OSYS.cpp 89 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OSYS.CPP
  21. //Description : System resource management object
  22. #include <RESOURCE.h>
  23. #include <stdio.h>
  24. #include <ALL.h>
  25. #include <OAUDIO.h>
  26. #include <ODATE.h>
  27. #include <OBOX.h>
  28. #include <OFONT.h>
  29. #include <OSTR.h>
  30. #include <OVGA.h>
  31. #include <OGAME.h>
  32. #include <ONEWS.h>
  33. #include <OTRANSL.h>
  34. #include <OGAMESET.h>
  35. #include <OGFILE.h>
  36. #include <OINFO.h>
  37. #include <OVBROWSE.h>
  38. #include <OIMGRES.h>
  39. #include <OMOUSE.h>
  40. #include <OMOUSE2.h>
  41. #include <KEY.h>
  42. #include <OMOUSECR.h>
  43. #include <OUNIT.h>
  44. #include <OSITE.h>
  45. #include <OSPATH.h>
  46. #include <OSPATHS2.h>
  47. #include <OSPREUSE.h>
  48. #include <OSPY.h>
  49. #include <OSYS.h>
  50. #include <OREMOTE.h>
  51. #include <OTECHRES.h>
  52. #include <OTALKRES.h>
  53. #include <OGODRES.h>
  54. #include <OHELP.h>
  55. #include <OTUTOR.h>
  56. #include <OF_BASE.h>
  57. #include <OTOWN.h>
  58. #include <OBULLET.h>
  59. #include <ONATION.h>
  60. #include <OFLAME.h>
  61. #include <OPOWER.h>
  62. #include <OTERRAIN.h>
  63. #include <OWORLD.h>
  64. #include <OANLINE.h>
  65. #include <OSE.h>
  66. #include <OLOG.h>
  67. #include <OERRCTRL.h>
  68. #include <OMUSIC.h>
  69. #include <OLZW.h>
  70. #include <OLONGLOG.h>
  71. #include <OVGALOCK.h>
  72. #include <OGRPSEL.h>
  73. #include <OCRC_STO.h>
  74. #include <OF_HARB.h>
  75. // ##### begin Gilbert 23/10 ######//
  76. #include <OOPTMENU.h>
  77. #include <OINGMENU.h>
  78. // ##### end Gilbert 23/10 ######//
  79. //----------- Declare static functions -----------//
  80. static long FAR PASCAL static_main_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
  81. //------- Define static functions -----------//
  82. LRESULT CALLBACK win_hook_proc(int nCode, WORD wParam, LONG lParam);
  83. static void test_lzw();
  84. static void locate_king_general(int rankId);
  85. static void locate_spy();
  86. static void locate_ship();
  87. static void locate_camp();
  88. static int locate_ship_in_harbor();
  89. static int locate_visible_ship();
  90. static int detect_scenario_cheat_key(unsigned scanCode, unsigned skeyState);
  91. static int get_mouse_loc_in_zoom_map(int &x, int &y);
  92. //----------- Define static variables ------------//
  93. static unsigned long last_frame_time=0, last_resend_time=0;
  94. static char remote_send_success_flag=1;
  95. static HHOOK win_hook_handle=NULL;
  96. static char scenario_cheat_flag=0;
  97. //----------- Begin of function Sys::Sys -----------//
  98. Sys::Sys()
  99. {
  100. memset(this, 0, sizeof(Sys) );
  101. common_data_buf = mem_add( COMMON_DATA_BUF_SIZE );
  102. view_mode = MODE_NORMAL; // the animation mode
  103. }
  104. //----------- End of function Sys::Sys -----------//
  105. //----------- Begin of function Sys::~Sys -----------//
  106. Sys::~Sys()
  107. {
  108. mem_del(common_data_buf);
  109. deinit();
  110. }
  111. //----------- End of function Sys::~Sys -----------//
  112. //------------ Begin of function Sys::init ----------//
  113. //
  114. int Sys::init( HINSTANCE hInstance )
  115. {
  116. err_when( init_flag );
  117. //------- initialize basic vars --------//
  118. app_hinstance = hInstance;
  119. #ifdef BETA
  120. debug_session = m.is_file_exist("DEBUG.SYS");
  121. testing_session = m.is_file_exist("TESTING.SYS");
  122. scenario_cheat_flag = m.is_file_exist("CHEAT.SYS");
  123. #endif
  124. #ifdef DEBUG
  125. debug_session = m.is_file_exist("DEBUG.SYS");
  126. testing_session = m.is_file_exist("TESTING.SYS");
  127. scenario_cheat_flag = m.is_file_exist("CHEAT.SYS");
  128. #endif
  129. // debug_session = m.is_file_exist("DEBUG.SYS");
  130. set_game_dir(); // set game directories names and game version
  131. //------- initialize more stuff ---------//
  132. if( !init_win() )
  133. return FALSE;
  134. if( !init_directx() )
  135. return FALSE;
  136. if( !init_objects() ) // initialize system objects which do not change from games to games.
  137. return FALSE;
  138. init_flag = 1;
  139. return TRUE;
  140. }
  141. //------------ End of function Sys::init ----------//
  142. //-------- Begin of function Sys::deinit --------//
  143. //
  144. // Finished with all objects we use; release them
  145. //
  146. void Sys::deinit()
  147. {
  148. if( !init_flag )
  149. return;
  150. game.deinit(); // actually game.deinit() will be called by main_win_proc() and calling it here will have no effect
  151. deinit_objects();
  152. //-------------------------------------//
  153. if( vga_back.buf_locked )
  154. vga_back.unlock_buf();
  155. if( vga_front.buf_locked )
  156. vga_front.unlock_buf();
  157. //-------------------------------------//
  158. /*
  159. extern char low_video_memory_flag;
  160. if( low_video_memory_flag )
  161. {
  162. ShowWindow(sys.main_hwnd, SW_MINIMIZE );
  163. unsigned curTime = m.get_time();
  164. while( m.get_time() < curTime + 4000 );
  165. }
  166. */
  167. //---------------------------------------//
  168. PostMessage(main_hwnd, WM_CLOSE, 0, 0);
  169. init_flag = 0;
  170. MSG msg;
  171. while( GetMessage(&msg, NULL, 0, 0) )
  172. {
  173. TranslateMessage(&msg);
  174. DispatchMessage(&msg);
  175. }
  176. }
  177. //--------- End of function Sys::deinit ---------//
  178. //-------- Begin of function Sys::init_win --------//
  179. //
  180. int Sys::init_win()
  181. {
  182. //--------- register window class --------//
  183. WNDCLASS wc;
  184. BOOL rc;
  185. wc.style = CS_DBLCLKS;
  186. wc.lpfnWndProc = static_main_win_proc;
  187. wc.cbClsExtra = 0;
  188. wc.cbWndExtra = 0;
  189. wc.hInstance = app_hinstance;
  190. wc.hIcon = LoadIcon( app_hinstance, MAKEINTATOM(IDI_ICON1));
  191. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  192. wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  193. wc.lpszMenuName = NULL;
  194. wc.lpszClassName = WIN_CLASS_NAME;
  195. rc = RegisterClass( &wc );
  196. if( !rc )
  197. return FALSE;
  198. //------ install keyboard hook ---------//
  199. /*
  200. win_hook_handle = SetWindowsHookEx(WH_CBT, (HOOKPROC) win_hook_proc, sys.app_hinstance, NULL);
  201. if( !win_hook_handle )
  202. err.run( "Failed installing keyboard hook." );
  203. */
  204. //--------- create window -----------//
  205. main_hwnd = CreateWindowEx(
  206. WS_EX_APPWINDOW | WS_EX_TOPMOST,
  207. WIN_CLASS_NAME,
  208. WIN_TITLE,
  209. WS_VISIBLE | // so we dont have to call ShowWindow
  210. WS_POPUP,
  211. 0,
  212. 0,
  213. GetSystemMetrics(SM_CXSCREEN),
  214. GetSystemMetrics(SM_CYSCREEN),
  215. NULL,
  216. NULL,
  217. app_hinstance,
  218. NULL );
  219. if( !main_hwnd )
  220. return FALSE;
  221. UpdateWindow( main_hwnd );
  222. SetFocus( main_hwnd );
  223. return TRUE;
  224. }
  225. //-------- End of function Sys::init_win --------//
  226. //------- Begin of function win_hook_proc --------//
  227. LRESULT CALLBACK win_hook_proc(int nCode, WORD wParam, LONG lParam)
  228. {
  229. static int lastnCode;
  230. int a=0;
  231. if( vga_true_front.dd_buf && vga_true_front.dd_buf->IsLost() )
  232. a = 1;
  233. lastnCode = nCode;
  234. if( sys.init_flag && nCode == HCBT_SETFOCUS )
  235. sys.pause();
  236. return CallNextHookEx(win_hook_handle, nCode, wParam, lParam);
  237. }
  238. //-------- End of function win_hook_proc --------//
  239. //-------- Begin of function Sys::init_directx --------//
  240. //
  241. int Sys::init_directx()
  242. {
  243. DEBUG_LOG("Attempt audio.init()");
  244. audio.init();
  245. DEBUG_LOG(audio.wav_init_flag);
  246. music.init();
  247. se_ctrl.init();
  248. //---------------------------------------//
  249. ShowCursor(FALSE);
  250. //-------- initialize DirectDraw --------//
  251. DEBUG_LOG("Attempt vga.init()");
  252. if( !vga.init() )
  253. return FALSE;
  254. DEBUG_LOG("vga.init() ok");
  255. DEBUG_LOG("Attempt vga.load_pal()");
  256. vga.load_pal(DIR_RES"PAL_STD.RES");
  257. DEBUG_LOG("vga.load_pal() finish");
  258. if( sys.debug_session ) // if we are currently in a debug session, don't lock the front buffer otherwise the system will hang up
  259. {
  260. DEBUG_LOG("Attempt vga_front.init_back()");
  261. vga_front.init_back( vga.dd_obj );
  262. vga_front.is_front = 1; // set it to 1, overriding the setting in init_back()
  263. DEBUG_LOG("Attempt vga_true_front.init_front()");
  264. vga_true_front.init_front( vga.dd_obj );
  265. DEBUG_LOG("Attempt vga.activate_pal()");
  266. vga.activate_pal(&vga_true_front);
  267. DEBUG_LOG("vga.activate_pal() finish");
  268. }
  269. else
  270. {
  271. vga_front.init_front( vga.dd_obj );
  272. vga.activate_pal(&vga_front);
  273. }
  274. DEBUG_LOG("Attempt vga_back.init_back()");
  275. vga_back.init_back( vga.dd_obj );
  276. DEBUG_LOG("vga_back.init_back() finish");
  277. DEBUG_LOG("Attempt vga_front.lock_buf()");
  278. vga_front.lock_buf();
  279. DEBUG_LOG("vga_front.lock_buf() finish");
  280. DEBUG_LOG("Attempt vga_back.lock_buf()");
  281. vga_back.lock_buf();
  282. DEBUG_LOG("vga_back.lock_buf() finish");
  283. return TRUE;
  284. }
  285. //-------- End of function Sys::init_directx --------//
  286. //-------- Begin of function Sys::deinit_directx --------//
  287. //
  288. void Sys::deinit_directx()
  289. {
  290. if( vga_back.dd_buf && vga_back.buf_locked )
  291. {
  292. DEBUG_LOG("Attempt vga_back.unlock_buf()");
  293. vga_back.unlock_buf();
  294. DEBUG_LOG("vga_back.unlock_buf() finish");
  295. }
  296. if( vga_front.dd_buf && vga_front.buf_locked )
  297. {
  298. DEBUG_LOG("Attempt vga_front.unlock_buf()");
  299. vga_front.unlock_buf();
  300. DEBUG_LOG("vga_front.unlock_buf() finish");
  301. }
  302. DEBUG_LOG("Attempt vga_back.deinit()");
  303. vga_back.deinit();
  304. DEBUG_LOG("vga_back.deinit() finish");
  305. if( sys.debug_session )
  306. {
  307. DEBUG_LOG("Attempt vga_true_front.deinit()");
  308. vga_true_front.deinit();
  309. DEBUG_LOG("vga_true_front.deinit() finish");
  310. }
  311. DEBUG_LOG("Attempt vga_front.deinit()");
  312. vga_front.deinit();
  313. DEBUG_LOG("Attempt vga_front.deinit() finish");
  314. DEBUG_LOG("Attempt vga.deinit()");
  315. vga.deinit();
  316. DEBUG_LOG("vga.deinit() finish");
  317. //------------------------------//
  318. se_ctrl.deinit();
  319. music.deinit();
  320. DEBUG_LOG("Attempt audio.deinit()");
  321. audio.deinit();
  322. DEBUG_LOG("audio.deinit() finish");
  323. }
  324. //--------- End of function Sys::deinit_directx ---------//
  325. //------- Begin of function Sys::init_objects -----------//
  326. //
  327. // Initialize system objects which do not change from games to games.
  328. //
  329. int Sys::init_objects()
  330. {
  331. //--------- init system class ----------//
  332. mouse_cursor.init();
  333. mouse_cursor.set_frame_border(ZOOM_X1,ZOOM_Y1,ZOOM_X2,ZOOM_Y2);
  334. mouse.init(app_hinstance, main_hwnd, NULL);
  335. //------- init resource class ----------//
  336. #if( defined(GERMAN) || defined(FRENCH) || defined(SPANISH) )
  337. font_std.init("SAN", 1);
  338. font_hall.init("HALL", 1);
  339. #else
  340. font_std.init("STD", 2);
  341. #endif
  342. font_san.init("SAN", 0); // 0-zero inter-character space
  343. font_mid.init("MID");
  344. font_small.init("SMAL");
  345. font_news.init("NEWS");
  346. font_hitpoint.init("HITP");
  347. font_bible.init("CASA", 1, 3);
  348. font_bard.init("CASA", 0);
  349. image_icon.init(DIR_RES"I_ICON.RES",1,0); // 1-read into buffer
  350. image_interface.init(DIR_RES"I_IF.RES",0,0); // 0-don't read into the buffer, don't use common buffer
  351. #ifndef DEMO // do not load these in the demo verison
  352. image_menu.init(DIR_RES"I_MENU.RES",0,0); // 0-don't read into the buffer, don't use common buffer
  353. image_encyc.init(DIR_RES"I_ENCYC.RES",0,0); // 0-don't read into the buffer, don't use common buffer
  354. #endif
  355. image_button.init(DIR_RES"I_BUTTON.RES",1,0);
  356. image_spict.init(DIR_RES"I_SPICT.RES",1,0);
  357. image_tutorial.init(DIR_RES"TUT_PICT.RES",0,0);
  358. #ifdef AMPLUS
  359. #ifndef DEMO // do not load these in the demo verison
  360. image_menu_plus.init(DIR_RES"I_MENU2.RES",0,0); // 0-don't read into the buffer, don't use common buffer
  361. #endif
  362. #endif
  363. seek_path.init(MAX_BACKGROUND_NODE);
  364. seek_path_s2.init(1);//seek_path_s2.init(MAX_BACKGROUND_NODE);
  365. seek_path_reuse.init(MAX_BACKGROUND_NODE);
  366. group_select.init();
  367. //------------ init flame ------------//
  368. for(int i = 0; i < FLAME_GROW_STEP; ++i)
  369. flame[i].init(Flame::default_width(i), Flame::default_height(i), Flame::base_width(i), FLAME_WIDE);
  370. //------------ init animated line drawer -------//
  371. anim_line.init(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2);
  372. //---------- init other objects ----------//
  373. game_set.init(); // this must be called before game.init() as game.init() assume game_set has been initialized
  374. help.init("HELP.RES");
  375. #if( defined(GERMAN) || defined(FRENCH) || defined(SPANISH) )
  376. translate.init();
  377. #endif
  378. tutor.init();
  379. game_file_array.init("*.SAV");
  380. //---------- init game_set -----------//
  381. DEBUG_LOG("Sys::init_objects finish");
  382. return TRUE;
  383. }
  384. //------- End of function Sys::init_objects -----------//
  385. //------- Begin of function Sys::deinit_objects -----------//
  386. void Sys::deinit_objects()
  387. {
  388. //--------- deinit system class ----------//
  389. mouse.deinit(); // mouse must be deinitialized first
  390. mouse_cursor.deinit();
  391. //------- deinit resource class ----------//
  392. font_std.deinit();
  393. font_san.deinit();
  394. font_mid.deinit();
  395. font_small.deinit();
  396. font_news.deinit();
  397. font_hitpoint.deinit();
  398. font_bible.deinit();
  399. font_bard.deinit();
  400. #if( defined(GERMAN) || defined(FRENCH) || defined(SPANISH) )
  401. font_hall.deinit();
  402. #endif
  403. image_icon.deinit();
  404. image_interface.deinit();
  405. image_menu.deinit();
  406. image_button.deinit();
  407. image_spict.deinit();
  408. image_encyc.deinit();
  409. image_tutorial.deinit();
  410. seek_path.deinit();
  411. seek_path_s2.deinit();
  412. seek_path_reuse.deinit();
  413. group_select.deinit();
  414. for(int i = 0; i < FLAME_GROW_STEP; ++i)
  415. flame[i].deinit();
  416. //--------- deinit other objects ----------//
  417. game_set.deinit();
  418. help.deinit();
  419. #if( defined(GERMAN) || defined(FRENCH) || defined(SPANISH) )
  420. translate.deinit();
  421. #endif
  422. tutor.deinit();
  423. config.deinit();
  424. game_file_array.deinit();
  425. }
  426. //------- End of function Sys::deinit_objects -----------//
  427. //-------- Begin of function Sys::run --------//
  428. //
  429. void Sys::run(int isLoadedGame)
  430. {
  431. //-*********** simulate aat ************-//
  432. #ifdef DEBUG
  433. //--------- enable only when simulation -------//
  434. debug_sim_game_type = (m.is_file_exist("sim.sys")) ? 2 : 0;
  435. #endif
  436. //-*********** simulate aat ************-//
  437. sys_flag = SYS_RUN;
  438. view_mode = MODE_NORMAL;
  439. //------- test LZW compression ---------//
  440. #ifdef DEBUG_LZW
  441. test_lzw();
  442. #endif
  443. //------ reset mouse ---------//
  444. mouse.reset_click();
  445. mouse_cursor.set_frame(0);
  446. //-- enable power after the game objets has been initialized --//
  447. power.enable(); // enable power, which handle mouse inputs
  448. //----- sys::disp_frame() will redraw everything when this flag is set to 1 ----//
  449. sys.need_redraw_flag = 1;
  450. option_menu.active_flag = 0;
  451. in_game_menu.active_flag = 0;
  452. sys.disp_frame();
  453. disp_view_mode();
  454. //----------- run the main loop -----------//
  455. main_loop(isLoadedGame);
  456. //-----------------------------------------//
  457. m.unlock_seed();
  458. }
  459. //--------- End of function Sys::run --------//
  460. //-------- Begin of static function test_lzw --------//
  461. //
  462. static void test_lzw()
  463. {
  464. // test lzw compress
  465. if( m.is_file_exist("NORMAL.SAV"))
  466. {
  467. File f,g;
  468. Lzw lzw_c, lzw_d; // one for compress, the other for decompress
  469. f.file_open("NORMAL.SAV");
  470. // read into buffer
  471. long fileSize = f.file_size();
  472. unsigned char *srcPtr = (unsigned char *) mem_add(fileSize);
  473. f.file_read(srcPtr, fileSize);
  474. // find compressed size to allocate space
  475. long compSize = lzw_c.compress(srcPtr, fileSize);
  476. unsigned char *destPtr = (unsigned char *) mem_add( compSize/8+ 4 ); // alloc 4 bytes more
  477. if( compSize != lzw_c.compress(srcPtr, fileSize, destPtr) )
  478. {
  479. err_here();
  480. }
  481. // decompress again
  482. long backSize = lzw_d.expand(destPtr, compSize, NULL);
  483. err_when(backSize != fileSize);
  484. unsigned char *backPtr = (unsigned char *) mem_add( backSize+4 );
  485. if( backSize != lzw_d.expand(destPtr, compSize, backPtr) )
  486. {
  487. err_here();
  488. }
  489. // finally compare srcPtr and backPtr
  490. err_when( memcmp(srcPtr, backPtr, fileSize) );
  491. f.file_close();
  492. // write it to a file
  493. {
  494. unsigned char *writePtr = destPtr;
  495. long writeSize = (compSize +7) / 8;
  496. g.file_create("NORMAL.LZ1");
  497. for( ; writeSize > 0; writeSize -= 0x4000)
  498. {
  499. g.file_write(writePtr, writeSize > 0x4000 ? 0x4000 : writeSize);
  500. writePtr += 0x4000;
  501. }
  502. g.file_close();
  503. }
  504. // test two, compress to a file
  505. g.file_create("NORMAL.LZW");
  506. compSize = lzw_c.compress(srcPtr, fileSize, &g);
  507. g.file_close();
  508. g.file_open("NORMAL.LZW");
  509. backSize = lzw_d.expand(&g, NULL);
  510. err_when(backSize != fileSize);
  511. backPtr = (unsigned char *) mem_resize(backPtr, backSize+4 );
  512. g.file_close();
  513. g.file_open("NORMAL.LZW");
  514. if( backSize != lzw_d.expand(&g, backPtr))
  515. {
  516. err_here();
  517. }
  518. err_when( memcmp(srcPtr,backPtr, fileSize) );
  519. mem_del(destPtr);
  520. mem_del(backPtr);
  521. mem_del(srcPtr);
  522. }
  523. }
  524. //--------- End of static function test_lzw --------//
  525. //-------- Begin of function Sys::main_loop --------//
  526. //
  527. void Sys::main_loop(int isLoadedGame)
  528. {
  529. MSG msg;
  530. // #### begin Gilbert 31/10 #####//
  531. // int rc;
  532. // #### end Gilbert 31/10 #####//
  533. //-------- reset day_frame_count -------//
  534. if( !isLoadedGame )
  535. {
  536. day_frame_count = 0; // for determining when the day counter should be increased.
  537. frame_count = 1;
  538. }
  539. //----- initialize these vars for every game -----//
  540. for( int i=nation_array.size() ; i>0 ; i-- )
  541. {
  542. if( !nation_array.is_deleted(i) )
  543. nation_array[i]->next_frame_ready = 0;
  544. }
  545. remote.packet_send_count = 0;
  546. remote.packet_receive_count = 0;
  547. last_frame_time = m.get_time()+60000; // plus 60 seconds buffer for game loading/starting time
  548. //frame_count = 1;
  549. is_sync_frame = 0;
  550. //----------------------------------------------//
  551. mp_clear_request_save();
  552. remote.enable_poll_msg();
  553. remote.enable_process_queue();
  554. remote_send_success_flag = 1;
  555. #ifdef DEBUG
  556. char longLogSuffix = 'A';
  557. if( remote.is_enable() )
  558. {
  559. if(long_log)
  560. delete long_log;
  561. long_log = new LongLog(longLogSuffix);
  562. }
  563. #endif
  564. //-*********** syn game test ***********-//
  565. #ifdef DEBUG
  566. if(debug_seed_status_flag==DEBUG_SYN_LOAD_AND_COMPARE_ONCE)
  567. sp_load_seed_file();
  568. #endif
  569. //-*********** syn game test ***********-//
  570. vga_front.unlock_buf();
  571. // ------- establish_contact again --------//
  572. // if the game saved after NationRelation::contact_msg_flag set, but
  573. // remote players may have not receive MSG_NATION_CONTACT
  574. //
  575. // send MSG_NATION_CONTACT now
  576. if( !config.explore_whole_map && nation_array.player_recno &&
  577. !nation_array.is_deleted(nation_array.player_recno) )
  578. {
  579. for(short nationRecno = 1; nationRecno <= nation_array.size(); ++nationRecno )
  580. {
  581. if( nationRecno == nation_array.player_recno ||
  582. nation_array.is_deleted(nationRecno) )
  583. continue;
  584. NationRelation *relation = (~nation_array)->get_relation(nationRecno);
  585. if( relation->contact_msg_flag && !relation->has_contact)
  586. {
  587. // packet structure : <player nation> <explored nation>
  588. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short));
  589. *shortPtr = nation_array.player_recno;
  590. shortPtr[1] = nationRecno;
  591. }
  592. }
  593. }
  594. // #### begin Gilbert 23/10 #######//
  595. option_menu.active_flag = 0;
  596. in_game_menu.active_flag = 0;
  597. // #### end Gilbert 23/10 #######//
  598. // ##### begin Gilbert 4/11 ######//
  599. DWORD lastDispFrameTime = m.get_time();
  600. // ##### end Gilbert 4/11 ######//
  601. // ##### patch begin Gilbert 17/11 #######//
  602. DWORD firstUnreadyTime = 0;
  603. // ##### patch end Gilbert 17/11 #######//
  604. while( 1 )
  605. {
  606. if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
  607. {
  608. if (!GetMessage( &msg, NULL, 0, 0))
  609. break;
  610. TranslateMessage(&msg);
  611. DispatchMessage(&msg);
  612. }
  613. else if ( !paused_flag && active_flag )
  614. {
  615. // #### begin Gilbert 31/10 ######//
  616. int rc = 0;
  617. // #### end Gilbert 31/10 ######//
  618. if( sys.signal_exit_flag )
  619. break;
  620. vga_front.lock_buf();
  621. yield(); // could be improved, give back the control to Windows, so it can do some OS management. Maybe call WaitMessage() here and set up a timer to get messages regularly.
  622. detect();
  623. //--------------------------------//
  624. // ###### begin Gilbert 4/11 ######//
  625. DWORD markTime = m.get_time(); // a time taken earlier than should_next_frame takes
  626. // ###### end Gilbert 4/11 ######//
  627. // ##### patch begin Gilbert 17/11 #######//
  628. int unreadyPlayerFlag = 0;
  629. // ##### patch end Gilbert 17/11 #######//
  630. if( config.frame_speed>0 ) // 0-frozen
  631. {
  632. if( remote.is_enable() ) // && is_sync_frame )
  633. {
  634. remote.poll_msg();
  635. m.unlock_seed();
  636. rc = is_mp_sync(&unreadyPlayerFlag); // if all players are synchronized
  637. m.lock_seed();
  638. }
  639. else
  640. rc = should_next_frame();
  641. if( rc )
  642. {
  643. LOG_BEGIN;
  644. m.unlock_seed();
  645. #ifdef DEBUG
  646. if( remote.is_enable() )
  647. {
  648. long_log->printf("begin process frame %d\n", frame_count);
  649. }
  650. #endif
  651. process();
  652. if(remote.is_enable() )
  653. m.lock_seed(); // such that random seed is unchanged outside sys::process()
  654. LOG_END;
  655. // -------- compare objects' crc --------- //
  656. // ###### patch begin Gilbert 20/1 ######//
  657. if( remote.is_enable() && (remote.sync_test_level & 2) &&(frame_count % (remote.get_process_frame_delay()+3)) == 0)
  658. {
  659. // cannot compare every frame, as PROCESS_FRAME_DELAY >= 1
  660. crc_store.record_all();
  661. crc_store.send_all();
  662. }
  663. // ###### patch end Gilbert 20/1 ######//
  664. }
  665. }
  666. // ###### begin Gilbert 4/11 #######//
  667. // ------- display graduately, keep on displaying --------- //
  668. if( rc )
  669. {
  670. lastDispFrameTime = m.get_time();
  671. // ####### patch begin Gilbert 17/11 ######//
  672. // reset firstUnreadyTime
  673. firstUnreadyTime = 0;
  674. // ####### patch end Gilbert 17/11 ######//
  675. }
  676. else
  677. {
  678. // ####### patch begin Gilbert 17/11 ######//
  679. // set firstUnreadyTime, begin of a delay
  680. if( !firstUnreadyTime )
  681. firstUnreadyTime = m.get_time();
  682. // ####### patch end Gilbert 17/11 ######//
  683. if( config.frame_speed == 0 || markTime-lastDispFrameTime >= DWORD(1000/config.frame_speed)
  684. #ifdef AMPLUS
  685. || zoom_need_redraw || map_need_redraw
  686. #endif
  687. )
  688. {
  689. // on second condition, it should be happened when
  690. // in multiplayer, where should_next_frame passed
  691. // but is_mp_sync not passed
  692. disp_frame();
  693. lastDispFrameTime = markTime;
  694. // ####### patch begin Gilbert 17/11 ######//
  695. // display player not ready
  696. if( firstUnreadyTime && m.get_time() - firstUnreadyTime > 5000 )
  697. {
  698. int y = ZOOM_Y1 + 10;
  699. int x = ZOOM_X1 + 10;
  700. for( int nationRecno = 1; nationRecno <= MAX_NATION; ++nationRecno )
  701. {
  702. if( unreadyPlayerFlag & (1 << (nationRecno-1)) )
  703. {
  704. if( !nation_array.is_deleted(nationRecno) )
  705. {
  706. int x2 = font_news.put( x, y, "Waiting for ");
  707. x2 = font_news.put( x2, y, nation_array[nationRecno]->nation_name() );
  708. y += font_news.height() + 5;
  709. }
  710. }
  711. }
  712. }
  713. // ####### patch end Gilbert 17/11 ######//
  714. }
  715. }
  716. // ###### end Gilbert 4/11 #######//
  717. // ----------- detect sond is ended, play another -----------//
  718. if( config.frame_speed == 0 || day_frame_count == 0)
  719. music.yield();
  720. #ifdef DEBUG
  721. if( rc && remote.is_enable() && day_frame_count == 0 )
  722. {
  723. if( long_log)
  724. delete long_log;
  725. if( ++longLogSuffix > 'Z' )
  726. {
  727. longLogSuffix = 'A';
  728. }
  729. long_log = new LongLog(longLogSuffix);
  730. long_log->printf("Game Date : %d/%d/%d\n", info.game_month, info.game_day, info.game_year);
  731. }
  732. #endif
  733. if(rc)
  734. {
  735. //-*********** syn game test ***********-//
  736. //-------------------------------------------------------------//
  737. // record random seed for comparison
  738. //-------------------------------------------------------------//
  739. #ifdef DEBUG
  740. if(debug_seed_status_flag==DEBUG_SYN_LOAD_AND_COMPARE_ONCE ||
  741. debug_seed_status_flag==DEBUG_SYN_AUTO_LOAD)
  742. sp_compare_seed();
  743. else if(debug_seed_status_flag==DEBUG_SYN_AUTO_SAVE)
  744. sp_record_seed();
  745. #endif
  746. //-*********** syn game test ***********-//
  747. //------ auto save -------//
  748. auto_save();
  749. }
  750. //------ detect save game triggered by remote player ------//
  751. if( mp_save_flag && mp_save_frame == frame_count )
  752. {
  753. mp_clear_request_save(); // clear request first before save game
  754. if( nation_array.player_recno ) // only save then the player is still in the game
  755. {
  756. game_file.save_game( remote.save_file_name );
  757. // ####### begin Gilbert 24/10 ######//
  758. //static String str;
  759. //str = "The current game has been saved to ";
  760. //str += remote.save_file_name;
  761. //str += ".";
  762. //box.msg( str );
  763. news_array.multi_save_game();
  764. // ####### end Gilbert 24/10 ######//
  765. }
  766. }
  767. vga_front.unlock_buf();
  768. if( sys.signal_exit_flag )
  769. break;
  770. }
  771. else
  772. {
  773. WaitMessage();
  774. }
  775. }
  776. // #### begin Gilbert 23/10 #######//
  777. in_game_menu.active_flag = 0;
  778. option_menu.active_flag = 0;
  779. // #### end Gilbert 23/10 #######//
  780. vga_front.lock_buf();
  781. #ifdef DEBUG
  782. if(remote.is_enable())
  783. {
  784. if(long_log)
  785. delete long_log;
  786. long_log = NULL;
  787. }
  788. #endif
  789. music.stop();
  790. remote.disable_process_queue();
  791. remote.disable_poll_msg();
  792. mp_clear_request_save();
  793. }
  794. //--------- End of function Sys::main_loop --------//
  795. //-------- Begin of function Sys::auto_save --------//
  796. //
  797. void Sys::auto_save()
  798. {
  799. if( nation_array.player_recno == 0 )
  800. return;
  801. //---------- single player auto save ----------//
  802. if( !remote.is_enable() && // no auto save in a multiplayer game
  803. info.game_month%2==0 && info.game_day==1 && day_frame_count==0)
  804. {
  805. #ifdef DEBUG2
  806. if(1)
  807. #else
  808. if( sys.debug_session || sys.testing_session )
  809. #endif
  810. {
  811. static int saveCount = 0;
  812. switch(saveCount)
  813. {
  814. case 0: game_file.save_game( "AUTO1.SAV" );
  815. break;
  816. case 1: game_file.save_game( "AUTO2.SAV" );
  817. break;
  818. case 2: game_file.save_game( "AUTO3.SAV" );
  819. break;
  820. }
  821. if( ++saveCount>3 )
  822. saveCount = 0;
  823. }
  824. else
  825. {
  826. //--- rename the existing AUTO.SAV to AUTO2.SAV and save a new game ---//
  827. if( m.is_file_exist( "AUTO.SAV" ) )
  828. {
  829. if( m.is_file_exist( "AUTO2.SAV" ) ) // if there is already an AUTO2.SAV, delete it
  830. remove( "AUTO2.SAV" );
  831. rename( "AUTO.SAV", "AUTO2.SAV" );
  832. }
  833. }
  834. game_file.save_game( "AUTO.SAV" );
  835. //-*********** syn game test ***********-//
  836. #ifdef DEBUG
  837. if(debug_seed_status_flag==DEBUG_SYN_AUTO_SAVE)
  838. {
  839. sp_write_seed();
  840. sp_close_seed_file();
  841. //if(info.game_date-info.game_start_date<=365)
  842. if(0)
  843. {
  844. sp_open_seed_file("nseed.rs");
  845. debug_seed_status_flag = DEBUG_SYN_AUTO_SAVE; // continue recording
  846. }
  847. else
  848. {
  849. debug_seed_status_flag = NO_DEBUG_SYN;
  850. //sp_load_seed_file();
  851. //SendMessage(main_hwnd, WM_KEYDOWN, 'L', 0);
  852. mouse.add_key_event(DIK_BACKSLASH, m.get_time()); // load file for comparison
  853. }
  854. }
  855. //debug_seed_status_flag = 2;
  856. //sp_seed_pos_reset();
  857. //sp_record_match_seed();
  858. #endif
  859. //-*********** syn game test ***********-//
  860. }
  861. // --------- multiplayer autosave game --------//
  862. // ###### patch begin Gilbert 23/1 #######//
  863. if( remote.is_enable() && remote.sync_test_level >= 0 && // disable autosave after un-sync
  864. day_frame_count==0 && info.game_day==1 && info.game_month%2==0 )
  865. // ###### patch end Gilbert 23/1 #######//
  866. {
  867. //--- rename the existing AUTO.SVM to AUTO2.SVM and save a new game ---//
  868. if( m.is_file_exist( "AUTO.SVM" ) )
  869. {
  870. if( m.is_file_exist( "AUTO2.SVM" ) ) // if there is already an AUTO2.SVM, delete it
  871. remove( "AUTO2.SVM" );
  872. rename( "AUTO.SVM", "AUTO2.SVM" );
  873. }
  874. game_file.save_game( "AUTO.SVM" );
  875. }
  876. }
  877. //-------- End of function Sys::auto_save --------//
  878. //-------- Begin of function Sys::pause --------//
  879. //
  880. void Sys::pause()
  881. {
  882. if( paused_flag )
  883. return;
  884. InvalidateRect(main_hwnd, NULL, TRUE);
  885. paused_flag = TRUE;
  886. }
  887. //--------- End of function Sys::pause ---------//
  888. //-------- Begin of function Sys::unpause --------//
  889. //
  890. void Sys::unpause()
  891. {
  892. if( !paused_flag )
  893. return;
  894. // ####### begin Gilbert 3/11 #######//
  895. //if( GetForegroundWindow() != main_hwnd )
  896. // return;
  897. // ####### end Gilbert 3/11 #######//
  898. if( !restore() )
  899. {
  900. //-----------------------------------------------------//
  901. // we are unable to restore, this can happen when
  902. // the screen resolution or bitdepth has changed
  903. // we just reload all the art again and re-create
  904. // the front and back buffers. this is a little
  905. // overkill we could handle a screen res change by
  906. // just recreating the front and back buffers we dont
  907. // need to redo the art, but this is way easier.
  908. //-----------------------------------------------------//
  909. if (init_directx())
  910. {
  911. if( !restore() ) // if still not successful, quit
  912. return;
  913. }
  914. }
  915. // ####### begin Gilbert 31/10 #######//
  916. mouse.update_skey_state(); // update ctrl/shift/alt key state after switch task
  917. // ####### end Gilbert 31/10 #######//
  918. //---- restore the saved screen before killing the focus ----//
  919. paused_flag = FALSE;
  920. }
  921. //--------- End of function Sys::unpause ---------//
  922. //-------- Begin of function Sys::restore --------//
  923. //
  924. int Sys::restore()
  925. {
  926. if( !vga_front.restore_buf() )
  927. return 0;
  928. if( !vga_back.restore_buf() )
  929. return 0;
  930. if( sys.debug_session )
  931. {
  932. if( !vga_true_front.restore_buf() )
  933. return 0;
  934. }
  935. // ####### begin Gilbert 16/9 ########//
  936. //else
  937. // vga_front.lock_buf();
  938. // ####### end Gilbert 16/9 ########//
  939. return 1;
  940. }
  941. //--------- End of function Sys::restore ---------//
  942. //-------- Begin of function Sys::yield --------//
  943. //
  944. void Sys::yield()
  945. {
  946. static int isYielding=0;
  947. if( isYielding )
  948. return;
  949. isYielding=1;
  950. handle_window_messages();
  951. mouse.poll_event();
  952. audio.yield();
  953. if( remote.is_enable() )
  954. {
  955. //yield_wsock_msg();
  956. remote.poll_msg();
  957. remote.process_specific_msg(MSG_SET_SPEED); // need to test it here for restoring the speed from frozen to normal
  958. if( config.frame_speed > 0 )
  959. {
  960. remote.process_specific_msg(MSG_TELL_SEND_TIME);
  961. remote.process_specific_msg(MSG_REQUEST_RESEND);
  962. }
  963. //-------- display debug info -----------//
  964. if( power.enable_flag && (testing_session || debug_session) )
  965. {
  966. String str;
  967. str = "Player: ";
  968. str += nation_array.player_recno;
  969. str += "/";
  970. str += nation_array.size();
  971. str += " Send:";
  972. str += remote.packet_send_count;
  973. str += " Recv:";
  974. str += remote.packet_receive_count;
  975. str += " Frame:";
  976. str += frame_count;
  977. font_san.disp( ZOOM_X1, 4, str, ZOOM_X1+300);
  978. }
  979. }
  980. isYielding=0;
  981. }
  982. //--------- End of function Sys::yield ---------//
  983. //-------- Begin of function Sys::yield_wsock_msg --------//
  984. //
  985. void Sys::yield_wsock_msg()
  986. {
  987. // MSG msg;
  988. //------ only get WinSock messages (WSA_ACCEPT & WSA_READ) ------//
  989. // if( PeekMessage(&msg, NULL, WSA_ACCEPT, WSA_READ, PM_NOREMOVE) )
  990. // {
  991. // if (!GetMessage( &msg, NULL, WSA_ACCEPT, WSA_READ))
  992. // return;
  993. // TranslateMessage(&msg);
  994. // DispatchMessage(&msg);
  995. //}
  996. }
  997. //--------- End of function Sys::yield_wsock_msg ---------//
  998. //-------- Begin of function Sys::is_mp_sync --------//
  999. //
  1000. // Multiplayer synchronization.
  1001. //
  1002. // Check all players are ready to proceed to the next frame.
  1003. //
  1004. int Sys::is_mp_sync(int *unreadyPlayerFlag)
  1005. {
  1006. #define RESEND_TIME_OUT 2000 // if the other machines still aren't ready after 2 seconds, send the notification again
  1007. #define RESEND_AGAIN_TIME_OUT 1000 // keep resending if no responses
  1008. #define CONNECTION_LOST_TIME_OUT 20000 // ask for connection lost handling aftering waiting for 5 seconds.
  1009. //---- if we haven't been ready for the next frame yet ----//
  1010. #ifdef DEBUG
  1011. int n;
  1012. DEBUG_LOG("begin nation's next_frame_ready");
  1013. for (n = 1; n <= nation_array.size(); ++n)
  1014. {
  1015. DEBUG_LOG(nation_array[n]->next_frame_ready);
  1016. }
  1017. DEBUG_LOG("end nation's next_frame_ready");
  1018. #endif
  1019. // ####### patch begin Gilbert 17/11 ######//
  1020. if( unreadyPlayerFlag )
  1021. *unreadyPlayerFlag = 0;
  1022. // ####### end begin Gilbert 17/11 ######//
  1023. // if last remote.send was fail, attempt to send it again
  1024. if( !nation_array.player_recno )
  1025. {
  1026. // observation mode
  1027. if( !should_next_frame() )
  1028. return 0;
  1029. remote_send_success_flag = 1;
  1030. }
  1031. else if( remote_send_success_flag
  1032. && remote.has_send_frame(nation_array.player_recno, frame_count)
  1033. && (~nation_array)->next_frame_ready==0 )
  1034. {
  1035. DEBUG_LOG("Local player not ready");
  1036. if( !should_next_frame() ) // not ready to proceed yet
  1037. return 0;
  1038. //------------ queue MSG_NEXT_FRAME ----------//
  1039. short* shortPtr = (short*) remote.new_send_queue_msg(MSG_NEXT_FRAME, sizeof(short));
  1040. shortPtr[0] = nation_array.player_recno; // short_para1 is the nation recno of the current player
  1041. //------------ queue MSG_QUEUE_TRAILER ----------//
  1042. shortPtr = (short*) remote.new_send_queue_msg(MSG_QUEUE_TRAILER, sizeof(short));
  1043. shortPtr[0] = nation_array.player_recno; // short_para1 is the nation recno of the current player
  1044. //------ copy all queued action to our own receive buffer to merge with other player's action ----//
  1045. remote.append_send_to_receive();
  1046. //--- copy the whole queue to a buffer in case of resend request from other players ---//
  1047. remote.copy_send_to_backup();
  1048. //----------- queue MSG_TELL_SEND_TIME ----------//
  1049. /*
  1050. unsigned long* longPtr = (unsigned long*) remote.new_send_queue_msg(MSG_TELL_SEND_TIME, sizeof(unsigned long));
  1051. longPtr[0] = m.get_time();
  1052. */
  1053. //---------- send out all messages in the queue ---------//
  1054. remote_send_success_flag = remote.send_queue_now(); // if not sent successfully, try again next time
  1055. if( remote_send_success_flag ) // still failed, try again next time
  1056. {
  1057. DEBUG_LOG("first send sucess" );
  1058. remote.init_send_queue(frame_count+1, nation_array.player_recno); // frame_count, initialize for next frame's send queue
  1059. // sent random seed
  1060. char *p = (char *)remote.new_send_queue_msg(MSG_TELL_RANDOM_SEED, sizeof(short)+sizeof(long));
  1061. *(short *)p = nation_array.player_recno;
  1062. p += sizeof(short);
  1063. *(long *)p = m.get_random_seed();
  1064. }
  1065. else
  1066. {
  1067. // re_transmit as quickly as possible
  1068. ec_remote.re_transmit(5);
  1069. }
  1070. }
  1071. else
  1072. {
  1073. DEBUG_LOG("Local player nation ready");
  1074. }
  1075. //----- if previous sending was not successful, send again now -----//
  1076. if( !remote_send_success_flag )
  1077. {
  1078. remote_send_success_flag = remote.send_queue_now(); // if not sent successfully, try again next time
  1079. if( remote_send_success_flag ) // still failed, try again next time
  1080. {
  1081. DEBUG_LOG("resending ok");
  1082. remote.init_send_queue(frame_count+1, nation_array.player_recno); // frame_count, initialize for next frame's send queue
  1083. // sent random seed
  1084. char *p = (char *)remote.new_send_queue_msg(MSG_TELL_RANDOM_SEED, sizeof(short)+sizeof(long));
  1085. *(short *)p = nation_array.player_recno;
  1086. p += sizeof(short);
  1087. *(long *)p = m.get_random_seed();
  1088. }
  1089. else
  1090. {
  1091. // re_transmit as quickly as possible
  1092. ec_remote.re_transmit(5);
  1093. DEBUG_LOG("resending not ok");
  1094. return 0;
  1095. }
  1096. }
  1097. //------ pre_process MSG_NEXT_FRAME in the queue -----//
  1098. remote.process_specific_msg(MSG_NEXT_FRAME);
  1099. #ifdef DEBUG
  1100. DEBUG_LOG("begin nation's next_frame_ready");
  1101. for (n = 1; n <= nation_array.size(); ++n)
  1102. {
  1103. DEBUG_LOG(nation_array[n]->next_frame_ready);
  1104. }
  1105. DEBUG_LOG("end nation's next_frame_ready");
  1106. #endif
  1107. //------ check if all remote players are ready to proceed -----//
  1108. int nationRecno;
  1109. Nation* nationPtr;
  1110. for( nationRecno=nation_array.size() ; nationRecno>0 ; nationRecno-- )
  1111. {
  1112. if( nation_array.is_deleted(nationRecno) )
  1113. continue;
  1114. nationPtr = nation_array[nationRecno];
  1115. //------- if some remote machines are not ready yet -------//
  1116. // ###### patch begin Gilbert 17/11 ######//
  1117. if( nationPtr->is_remote() &&
  1118. (remote.has_send_frame(nationRecno, frame_count) && !nationPtr->next_frame_ready) )
  1119. {
  1120. if( unreadyPlayerFlag )
  1121. *unreadyPlayerFlag |= ( 1 << (nationRecno-1) );
  1122. break;
  1123. }
  1124. // ###### end begin Gilbert 17/11 ######//
  1125. }
  1126. //------- if some remote machines are not ready yet -------//
  1127. if( nationRecno>0 )
  1128. {
  1129. DEBUG_LOG("a nation not ready");
  1130. DEBUG_LOG(nationRecno);
  1131. if( m.get_time() >= last_frame_time+RESEND_TIME_OUT )
  1132. {
  1133. //---- if it has been time out for too long, carry out connection lost handling ---//
  1134. if( // m.get_time() >= last_frame_time+CONNECTION_LOST_TIME_OUT ||
  1135. !ec_remote.is_player_valid(nationRecno))
  1136. {
  1137. DEBUG_LOG( "Connection Lost" );
  1138. // ###### begin Gilbert 24/10 ######//
  1139. // box.msg( "Connection Lost!" ); //**BUGHERE, should have a function to set all units, structures of this nation to AI
  1140. news_array.multi_connection_lost(nationRecno);
  1141. // may allow save game here, ask user whether to save the game
  1142. // ###### end Gilbert 24/10 ######//
  1143. nationPtr->nation_type = NATION_AI; // let computer take over the nation
  1144. nation_array.ai_nation_count++;
  1145. }
  1146. //------- re-send the message -------//
  1147. /* re-send is now done by ec_remote
  1148. else if( m.get_time() >= last_resend_time + RESEND_AGAIN_TIME_OUT ) // resent once per half second
  1149. {
  1150. DEBUG_LOG( "send retransmit request" );
  1151. RemoteMsg* remoteMsg = remote.new_msg(MSG_REQUEST_RESEND, sizeof(int) + sizeof(DWORD) );
  1152. DWORD* dwordPtr = (DWORD*) remoteMsg->data_buf;
  1153. dwordPtr[0] = (~nation_array)->player_id; // send to us
  1154. dwordPtr[1] = frame_count; // request it to send us queue of this frame
  1155. remote.send_free_msg( remoteMsg, nation_array[nationRecno]->player_id ); // send to that nationRecno only
  1156. last_resend_time = m.get_time();
  1157. }
  1158. */
  1159. }
  1160. return 0;
  1161. }
  1162. //--------------------------------------------------------//
  1163. //
  1164. // When all players are ready to proceed to the next frame
  1165. //
  1166. // As we have already know all players are ready, we can
  1167. // reset the next_frame_ready flag for all nations.
  1168. //
  1169. //--------------------------------------------------------//
  1170. DEBUG_LOG("all nation ready");
  1171. for( int i=nation_array.size() ; i>0 ; i-- )
  1172. {
  1173. if( nation_array.is_deleted(i) )
  1174. continue;
  1175. nation_array[i]->next_frame_ready=0; // -- instead of set to 0, set it may be 2 if it has just received an notifying signal for the further next frame from a player as it also sent out a next frame ready msg to all other players
  1176. }
  1177. //--------- process msgs in the receive queue ----------//
  1178. remote.process_receive_queue();
  1179. #ifdef DEBUG
  1180. DEBUG_LOG("begin nation's next_frame_ready");
  1181. for (n = 1; n <= nation_array.size(); ++n)
  1182. {
  1183. DEBUG_LOG(nation_array[n]->next_frame_ready);
  1184. }
  1185. DEBUG_LOG("end nation's next_frame_ready");
  1186. #endif
  1187. //-------- record this frame's time -------//
  1188. last_frame_time = m.get_time();
  1189. last_resend_time = 0;
  1190. return 1;
  1191. }
  1192. //---------- End of function Sys::is_mp_sync --------//
  1193. //-------- Begin of function Sys::should_next_frame --------//
  1194. //
  1195. // Check if it's now the time for processing the next frame.
  1196. //
  1197. int Sys::should_next_frame()
  1198. {
  1199. //----- special modes: 0-frozen, 9-fastest possible -----//
  1200. if( config.frame_speed==99 )
  1201. return 1;
  1202. if( config.frame_speed==0 )
  1203. return 0;
  1204. //---- check if it's now the time for processing the next frame ----//
  1205. DWORD curTime = m.get_time();
  1206. if( next_frame_time ) // if next_frame_time==0, it's the first frame of the game
  1207. {
  1208. if( next_frame_time < 1000 ) // the DWORD variable has been overflow
  1209. {
  1210. if( curTime < next_frame_time || curTime >= 1000 ) // >= 1000 if the curTime has been overflow yet, wait for it to overflow so we can compare it when next_frame_time
  1211. return 0;
  1212. }
  1213. else // normal non-overflow case
  1214. {
  1215. if( curTime < next_frame_time )
  1216. return 0;
  1217. }
  1218. }
  1219. //--- Time between frames = 1000 milliseconds / frames per second ---//
  1220. next_frame_time = curTime + 1000 / config.frame_speed;
  1221. return 1;
  1222. }
  1223. //--------- End of function Sys::should_next_frame ---------//
  1224. //-------- Begin of function Sys::main_win_proc --------//
  1225. //
  1226. long Sys::main_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1227. {
  1228. switch( message )
  1229. {
  1230. case WM_CREATE:
  1231. sys.main_hwnd = hWnd;
  1232. break;
  1233. case WM_ACTIVATEAPP:
  1234. // ####### begin Gilbert 3/11 #######//
  1235. // active_flag = (BOOL)wParam && GetForegroundWindow() == hWnd && !IsIconic(hWnd);
  1236. active_flag = (BOOL)wParam && !IsIconic(hWnd);
  1237. // ####### end Gilbert 3/11 #######//
  1238. //--------------------------------------------------------------//
  1239. // while we were not-active something bad happened that caused us
  1240. // to pause, like a surface restore failing or we got a palette
  1241. // changed, now that we are active try to fix things
  1242. //--------------------------------------------------------------//
  1243. if( active_flag )
  1244. {
  1245. unpause();
  1246. need_redraw_flag = 1; // for Sys::disp_frame to redraw the screen
  1247. }
  1248. else
  1249. pause();
  1250. break;
  1251. case WM_DESTROY:
  1252. main_hwnd = NULL;
  1253. // game.deinit(); // end of game
  1254. deinit_directx();
  1255. PostQuitMessage( 0 );
  1256. break;
  1257. case WM_ERASEBKGND:
  1258. // do not erase the background
  1259. return 1;
  1260. case WM_PALETTECHANGED:
  1261. // if we changed the palette, do nothing
  1262. if ((HWND)wParam == hWnd) break;
  1263. // we can't restore if dd_pal is not initialized
  1264. if (!vga.dd_pal) break;
  1265. // if we are temporarily overriding, then we should be okay
  1266. if (vga.back_up_pal) break;
  1267. // restore palette
  1268. vga.dd_pal->SetEntries(0, 0, 256, vga.pal_entry_buf);
  1269. break;
  1270. default:
  1271. break;
  1272. }
  1273. return DefWindowProc(hWnd, message, wParam, lParam);
  1274. }
  1275. //--------- End of function Sys::main_win_proc ---------//
  1276. //-------- Begin of function Sys::handle_window_messages --------//
  1277. void Sys::handle_window_messages()
  1278. {
  1279. static int lastTick;
  1280. int tick = GetTickCount();
  1281. if (lastTick == tick)
  1282. return;
  1283. lastTick = tick;
  1284. MSG msg;
  1285. while (PeekMessage(&msg, sys.main_hwnd, 0, 0, PM_NOREMOVE))
  1286. {
  1287. BOOL r;
  1288. r = GetMessage(&msg, sys.main_hwnd, 0, 0);
  1289. if (r == -1)
  1290. {
  1291. // not handled
  1292. return;
  1293. }
  1294. TranslateMessage(&msg);
  1295. DispatchMessage(&msg);
  1296. }
  1297. }
  1298. //-------- End of function Sys::handle_window_messages --------//
  1299. //-------- Begin of function Sys::process_key --------//
  1300. //
  1301. void Sys::process_key(unsigned scanCode, unsigned skeyState)
  1302. {
  1303. detect_function_key(scanCode, skeyState);
  1304. //----- don't detect letter keys when in chat mode ----//
  1305. if( !(view_mode == MODE_NATION &&
  1306. info.nation_report_mode == NATION_REPORT_CHAT) )
  1307. {
  1308. if( sys.debug_session || sys.testing_session || scenario_cheat_flag )
  1309. {
  1310. detect_cheat_key(scanCode, skeyState);
  1311. detect_debug_cheat_key(scanCode, skeyState);
  1312. if( detect_scenario_cheat_key(scanCode, skeyState) )
  1313. return;
  1314. }
  1315. else
  1316. {
  1317. if( nation_array.player_recno && !remote.is_enable() ) // not allowed in multiplayer mode
  1318. {
  1319. if( (~nation_array)->cheat_enabled_flag )
  1320. {
  1321. detect_cheat_key(scanCode, skeyState);
  1322. }
  1323. else
  1324. {
  1325. #ifdef GERMAN
  1326. if( detect_key_str(1, "!!!###") )
  1327. #else
  1328. if( detect_key_str(1, "!!!@@@###") )
  1329. #endif
  1330. {
  1331. box.msg( "Cheat Mode Enabled." );
  1332. (~nation_array)->cheat_enabled_flag = 1;
  1333. }
  1334. }
  1335. }
  1336. }
  1337. detect_letter_key(scanCode, skeyState);
  1338. detect_set_speed(scanCode, skeyState); // set the speed of the game
  1339. }
  1340. }
  1341. //--------- End of function Sys::process_key ---------//
  1342. //-------- Begin of function Sys::detect_letter_key --------//
  1343. //
  1344. void Sys::detect_letter_key(unsigned scanCode, unsigned skeyState)
  1345. {
  1346. int keyCode;
  1347. if((keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_IS_CTRL)))
  1348. {
  1349. int groupId;
  1350. switch(keyCode)
  1351. {
  1352. case '1': case '2': case '3': case '4': case '5':
  1353. case '6': case '7': case '8': case '9':
  1354. groupId = keyCode-'0';
  1355. group_select.group_units(groupId);
  1356. break;
  1357. }
  1358. }
  1359. if((keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_IS_ALT)))
  1360. {
  1361. int groupId;
  1362. switch(keyCode)
  1363. {
  1364. case '1': case '2': case '3': case '4': case '5':
  1365. case '6': case '7': case '8': case '9':
  1366. groupId = keyCode-'0';
  1367. group_select.select_grouped_units(groupId);
  1368. break;
  1369. }
  1370. }
  1371. if( (keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_UNIQUE_KEY)) )
  1372. {
  1373. keyCode = m.lower(keyCode);
  1374. switch(keyCode)
  1375. {
  1376. case KEY_ESC:
  1377. set_view_mode(MODE_NORMAL);
  1378. break;
  1379. //---- keys for toggling map mode ----//
  1380. case 'q':
  1381. world.map_matrix->toggle_map_mode(0);
  1382. break;
  1383. case 'w':
  1384. world.map_matrix->toggle_map_mode(1);
  1385. break;
  1386. case 'e':
  1387. world.map_matrix->toggle_map_mode(2);
  1388. break;
  1389. //--------- opaque report mode --------//
  1390. case 'p':
  1391. config.opaque_report = !config.opaque_report;
  1392. if( config.opaque_report )
  1393. box.msg( "Opaque report mode." );
  1394. else
  1395. box.msg( "Transparent report mode." );
  1396. break;
  1397. //------ clear news messages ------//
  1398. case 'x':
  1399. news_array.clear_news_disp();
  1400. break;
  1401. //------ jump to a location with natural resource ---//
  1402. case 'j':
  1403. site_array.go_to_a_raw_site();
  1404. break;
  1405. //--------- bring up the option menu ----------//
  1406. case 'o':
  1407. // ##### begin Gilbert 5/11 #######//
  1408. // game.in_game_option_menu();
  1409. option_menu.enter(!remote.is_enable());
  1410. // ##### end Gilbert 5/11 #######//
  1411. break;
  1412. //--------- forward/backward tutorial text block --------//
  1413. case ',':
  1414. if( game.game_mode == GAME_TUTORIAL )
  1415. tutor.prev_text_block();
  1416. break;
  1417. case '.':
  1418. if( game.game_mode == GAME_TUTORIAL )
  1419. tutor.next_text_block();
  1420. break;
  1421. //---- keys for saving and loading game -----//
  1422. case 's':
  1423. save_game();
  1424. break;
  1425. case 'l':
  1426. load_game();
  1427. break;
  1428. case KEY_UP:
  1429. world.disp_next(-1, 0); // previous same object type of any nation
  1430. break;
  1431. case KEY_DOWN:
  1432. world.disp_next(1, 0); // next same object type of any nation
  1433. break;
  1434. case KEY_LEFT:
  1435. world.disp_next(-1, 1); // prevous same object type of the same nation
  1436. break;
  1437. case KEY_RIGHT:
  1438. world.disp_next(1, 1); // next same object type of the same nation
  1439. break;
  1440. //---- key for quick locate -----//
  1441. case 'k':
  1442. locate_king_general(RANK_KING);
  1443. break;
  1444. case 'g':
  1445. locate_king_general(RANK_GENERAL);
  1446. break;
  1447. case 'y':
  1448. locate_spy();
  1449. break;
  1450. case 'h':
  1451. locate_ship();
  1452. break;
  1453. case 'f':
  1454. locate_camp();
  1455. break;
  1456. }
  1457. }
  1458. }
  1459. //--------- End of function Sys::detect_letter_key ---------//
  1460. //-------- Begin of function Sys::detect_function_key --------//
  1461. //
  1462. void Sys::detect_function_key(unsigned scanCode, unsigned skeyState)
  1463. {
  1464. int keyCode;
  1465. if( (keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_UNIQUE_KEY)) )
  1466. {
  1467. switch(keyCode)
  1468. {
  1469. case KEY_ESC:
  1470. set_view_mode(MODE_NORMAL);
  1471. break;
  1472. case KEY_F1:
  1473. if( view_mode==MODE_NATION )
  1474. set_view_mode(MODE_NORMAL);
  1475. else
  1476. set_view_mode(MODE_NATION);
  1477. break;
  1478. case KEY_F2:
  1479. if( view_mode==MODE_TOWN )
  1480. set_view_mode(MODE_NORMAL);
  1481. else
  1482. set_view_mode(MODE_TOWN);
  1483. break;
  1484. case KEY_F3:
  1485. if( view_mode==MODE_ECONOMY )
  1486. set_view_mode(MODE_NORMAL);
  1487. else
  1488. set_view_mode(MODE_ECONOMY);
  1489. break;
  1490. case KEY_F4:
  1491. if( view_mode==MODE_TRADE )
  1492. set_view_mode(MODE_NORMAL);
  1493. else
  1494. set_view_mode(MODE_TRADE);
  1495. break;
  1496. case KEY_F5:
  1497. if( view_mode==MODE_MILITARY )
  1498. set_view_mode(MODE_NORMAL);
  1499. else
  1500. set_view_mode(MODE_MILITARY);
  1501. break;
  1502. case KEY_F6:
  1503. if( view_mode==MODE_TECH )
  1504. set_view_mode(MODE_NORMAL);
  1505. else
  1506. set_view_mode(MODE_TECH);
  1507. break;
  1508. case KEY_F7:
  1509. if( view_mode==MODE_SPY )
  1510. set_view_mode(MODE_NORMAL);
  1511. else
  1512. set_view_mode(MODE_SPY);
  1513. break;
  1514. case KEY_F8:
  1515. if( view_mode==MODE_RANK )
  1516. set_view_mode(MODE_NORMAL);
  1517. else
  1518. set_view_mode(MODE_RANK);
  1519. break;
  1520. case KEY_F9:
  1521. if( view_mode==MODE_NEWS_LOG )
  1522. set_view_mode(MODE_NORMAL);
  1523. else
  1524. set_view_mode(MODE_NEWS_LOG);
  1525. break;
  1526. case KEY_F10:
  1527. // ##### begin Gilbert 5/11 ######//
  1528. //game.in_game_menu();
  1529. in_game_menu.enter(!remote.is_enable());
  1530. // ##### end Gilbert 5/11 ######//
  1531. break;
  1532. case KEY_F11:
  1533. capture_screen();
  1534. break;
  1535. case KEY_F12:
  1536. capture_minimap();
  1537. break;
  1538. }
  1539. }
  1540. }
  1541. //--------- End of function Sys::detect_function_key ---------//
  1542. //-------- Begin of function Sys::detect_cheat_key --------//
  1543. //
  1544. void Sys::detect_cheat_key(unsigned scanCode, unsigned skeyState)
  1545. {
  1546. if( remote.is_enable() ) // no cheat keys in multiplayer games
  1547. return;
  1548. int keyCode = mouse.is_key( scanCode, skeyState, (WORD) 0, K_CHAR_KEY );
  1549. if( !keyCode ) // since all keys concern are printable
  1550. return;
  1551. keyCode = m.lower(keyCode);
  1552. switch( keyCode )
  1553. {
  1554. //-------- cheat keys ---------//
  1555. case 'c': // add cash
  1556. if( nation_array.player_recno )
  1557. (~nation_array)->add_cheat((float)1000);
  1558. break;
  1559. case '\\': // add food
  1560. if( nation_array.player_recno )
  1561. (~nation_array)->add_food((float)1000);
  1562. break;
  1563. case 't':
  1564. tech_res.inc_all_tech_level(nation_array.player_recno);
  1565. god_res.enable_know_all(nation_array.player_recno);
  1566. box.msg( "Your technology has advanced.\nYou can now invoke all Greater Beings." );
  1567. break;
  1568. case 'm':
  1569. world.unveil(0, 0, MAX_WORLD_X_LOC-1, MAX_WORLD_Y_LOC-1);
  1570. world.visit(0, 0, MAX_WORLD_X_LOC-1, MAX_WORLD_Y_LOC-1, 0, 0);
  1571. break;
  1572. case ';': // increase town population
  1573. if( town_array.selected_recno )
  1574. {
  1575. Town* townPtr = town_array[town_array.selected_recno];
  1576. #ifdef DEBUG2
  1577. for(int di=0; di<MAX_RACE; di++)
  1578. {
  1579. if(townPtr->race_pop_array[di])
  1580. {
  1581. townPtr->init_pop(di+1, 10, 100);
  1582. break;
  1583. }
  1584. }
  1585. #else
  1586. townPtr->init_pop( m.random(MAX_RACE)+1, 10, 100 );
  1587. #endif
  1588. townPtr->auto_set_layout();
  1589. }
  1590. break;
  1591. case 'u':
  1592. config.king_undie_flag = !config.king_undie_flag;
  1593. if( config.king_undie_flag )
  1594. box.msg( "Your king is now immortal." );
  1595. else
  1596. box.msg( "King immortal mode is now disabled." );
  1597. break;
  1598. case '=':
  1599. if( firm_array.selected_recno )
  1600. {
  1601. Firm* firmPtr = firm_array[firm_array.selected_recno];
  1602. if( firmPtr->firm_id == FIRM_BASE )
  1603. {
  1604. ((FirmBase*)firmPtr)->pray_points = (float) MAX_PRAY_POINTS;
  1605. info.disp();
  1606. }
  1607. }
  1608. break;
  1609. case 'b': // finish building a firm instantly or increase the hit points of a firm to its max
  1610. if( firm_array.selected_recno )
  1611. {
  1612. Firm* firmPtr = firm_array[firm_array.selected_recno];
  1613. firmPtr->hit_points = firmPtr->max_hit_points;
  1614. }
  1615. break;
  1616. case 'z': // toggle fast_build
  1617. config.fast_build = !config.fast_build;
  1618. if( !config.fast_build )
  1619. box.msg( "Fast build is now disabled" );
  1620. else
  1621. box.msg( "Fast build is now enabled" );
  1622. break;
  1623. //----- increase the combat level -------//
  1624. case '[':
  1625. if( unit_array.selected_recno )
  1626. {
  1627. Unit* unitPtr = unit_array[unit_array.selected_recno];
  1628. unitPtr->set_combat_level( min(100, unitPtr->skill.combat_level+20) );
  1629. }
  1630. break;
  1631. //----- increase the skill level of the unit -------//
  1632. case ']':
  1633. if( unit_array.selected_recno )
  1634. {
  1635. Unit* unitPtr = unit_array[unit_array.selected_recno];
  1636. if( unitPtr->skill.skill_id )
  1637. unitPtr->skill.skill_level = min(100, unitPtr->skill.skill_level+20);
  1638. }
  1639. break;
  1640. //----- increase the spying skill -------//
  1641. case '\'':
  1642. if( unit_array.selected_recno )
  1643. {
  1644. Unit* unitPtr = unit_array[unit_array.selected_recno];
  1645. if( unitPtr->spy_recno )
  1646. {
  1647. Spy* spyPtr = spy_array[unitPtr->spy_recno];
  1648. spyPtr->spy_skill = min(100, spyPtr->spy_skill+20);
  1649. }
  1650. }
  1651. break;
  1652. }
  1653. }
  1654. //--------- End of function Sys::detect_cheat_key ---------//
  1655. //-------- Begin of function Sys::detect_debug_cheat_key --------//
  1656. //
  1657. void Sys::detect_debug_cheat_key(unsigned scanCode, unsigned skeyState)
  1658. {
  1659. if( remote.is_enable() ) // no cheat keys in multiplayer games
  1660. return;
  1661. int keyCode = mouse.is_key( scanCode, skeyState, (WORD) 0, K_UNIQUE_KEY );
  1662. if( !keyCode ) // since all keys concern are printable
  1663. return;
  1664. keyCode = m.lower(keyCode);
  1665. switch( keyCode )
  1666. {
  1667. /*
  1668. case 'j': // allow all nations to have all god creatures
  1669. for( i=1; i<=nation_array.size() ; i++ )
  1670. {
  1671. if( !nation_array.is_deleted(i) )
  1672. god_res.enable_know_all(i);
  1673. }
  1674. box.msg( "Now knowledge of seat of power is available to all nations." );
  1675. break;
  1676. */
  1677. case 'n':
  1678. config.blacken_map = !config.blacken_map;
  1679. config.fog_of_war = config.blacken_map;
  1680. break;
  1681. case 'r': // set default report nation
  1682. if( firm_array.selected_recno )
  1683. {
  1684. info.default_viewing_nation_recno = firm_array[firm_array.selected_recno]->nation_recno;
  1685. }
  1686. else if( town_array.selected_recno )
  1687. {
  1688. int nationRecno = town_array[town_array.selected_recno]->nation_recno;
  1689. if( nationRecno )
  1690. info.default_viewing_nation_recno = nationRecno;
  1691. }
  1692. else if( unit_array.selected_recno )
  1693. {
  1694. int nationRecno = unit_array[unit_array.selected_recno]->nation_recno;
  1695. if( nationRecno )
  1696. info.default_viewing_nation_recno = nationRecno;
  1697. }
  1698. break;
  1699. case 'a':
  1700. if( view_mode==MODE_AI_ACTION )
  1701. set_view_mode(MODE_NORMAL);
  1702. else
  1703. set_view_mode(MODE_AI_ACTION);
  1704. break;
  1705. //-----------------------------------//
  1706. /*
  1707. case 't': // next town layout
  1708. if( town_array.selected_recno )
  1709. town_array[town_array.selected_recno]->auto_set_layout();
  1710. break;
  1711. */
  1712. //-------------------------------//
  1713. case 'i':
  1714. config.disable_ai_flag = !config.disable_ai_flag;
  1715. if( config.disable_ai_flag )
  1716. box.msg( "AI is now disabled" );
  1717. else
  1718. box.msg( "AI is now enabled" );
  1719. break;
  1720. case 'd':
  1721. config.show_ai_info = !config.show_ai_info;
  1722. info.disp();
  1723. if( config.show_ai_info )
  1724. box.msg( "Now AI info will be displayed." );
  1725. else
  1726. box.msg( "Now AI info will not be displayed." );
  1727. break;
  1728. case '/':
  1729. config.show_all_unit_icon = !config.show_all_unit_icon;
  1730. if( config.show_all_unit_icon )
  1731. box.msg( "Now all unit icons will be displayed." );
  1732. else
  1733. box.msg( "Now all unit icons will not be displayed." );
  1734. break;
  1735. #ifdef DEBUG
  1736. case '~':
  1737. sys.testing_session = !sys.testing_session;
  1738. if( sys.testing_session )
  1739. box.msg( "sys.testing_session is now 1." );
  1740. else
  1741. box.msg( "sys.testing_session is now 0." );
  1742. break;
  1743. case '\r':
  1744. if(debug2_enable_flag)
  1745. debug2_enable_flag = 0;
  1746. else
  1747. debug2_enable_flag = 1;
  1748. break;
  1749. /* //-*********** syn game test ***********-//
  1750. case '\'':
  1751. //if(debug2_enable_flag && debug_sim_game_type)
  1752. //game_file_array[0]->load_game("syn.sav");
  1753. game_file.load_game("syn.sav");
  1754. sp_load_seed_file();
  1755. debug_seed_status_flag = DEBUG_SYN_AUTO_LOAD;
  1756. break;
  1757. case '[':
  1758. if(m.is_file_exist("SYN.SYS"))
  1759. {
  1760. debug_seed_status_flag = DEBUG_SYN_AUTO_SAVE;
  1761. sp_seed_pos_reset();
  1762. sp_record_match_seed();
  1763. sp_create_seed_file("nseed.rs");
  1764. game_file.save_game("syn.sav");
  1765. }
  1766. break;
  1767. case ']':
  1768. if(debug_seed_status_flag==NO_DEBUG_SYN)
  1769. {
  1770. if(m.is_file_exist("SYN.SYS"))
  1771. {
  1772. debug_seed_status_flag = DEBUG_SYN_LOAD_AND_COMPARE_ONCE;
  1773. game_file.load_game("syn.sav");
  1774. sp_load_seed_file();
  1775. }
  1776. else
  1777. debug_seed_status_flag = NO_DEBUG_SYN;
  1778. }
  1779. break;
  1780. */ //-*********** syn game test ***********-//
  1781. #endif
  1782. }
  1783. }
  1784. //--------- End of function Sys::detect_debug_cheat_key ---------//
  1785. //-------- Start of function detect_scenario_cheat_key -------------//
  1786. static int detect_scenario_cheat_key(unsigned scanCode, unsigned skeyState)
  1787. {
  1788. if( remote.is_enable() ) // no cheat keys in multiplayer games
  1789. return 0;
  1790. int keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_IS_CTRL);
  1791. if( !keyCode )
  1792. return 0;
  1793. //------------------------------------------//
  1794. int keyProcessed = 0;
  1795. Firm *firmPtr;
  1796. Unit *unitPtr;
  1797. Town *townPtr;
  1798. Nation *nationPtr;
  1799. Site *sitePtr;
  1800. Spy *spyPtr;
  1801. Location *locPtr;
  1802. int i, j, curXLoc, curYLoc;
  1803. switch(keyCode)
  1804. {
  1805. case 'p': //-------- get scroll of power for the race of selected unit --------//
  1806. if(unit_array.selected_recno)
  1807. {
  1808. unitPtr = unit_array[unit_array.selected_recno];
  1809. if(unitPtr->nation_recno==nation_array.player_recno && unitPtr->race_id)
  1810. {
  1811. god_res[unitPtr->race_id]->enable_know(unitPtr->nation_recno);
  1812. //box.msg( "Get Scroll of Power of selected unit for his race" );
  1813. keyProcessed++;
  1814. }
  1815. }
  1816. keyProcessed++;
  1817. break;
  1818. case 't': //-------- get all technology except scrolls of power -------//
  1819. tech_res.inc_all_tech_level(nation_array.player_recno);
  1820. //box.msg( "Your technology has advanced." );
  1821. keyProcessed++;
  1822. break;
  1823. case 'g': //------- get galleon and cannon technologies -------//
  1824. err_when(tech_res[4]->unit_id != UNIT_CANNON);
  1825. err_when(tech_res[7]->unit_id != UNIT_GALLEON);
  1826. i = tech_res[4]->get_nation_tech_level(nation_array.player_recno);
  1827. if(i < tech_res[4]->max_tech_level)
  1828. tech_res[4]->set_nation_tech_level(nation_array.player_recno, i+1);
  1829. i = tech_res[7]->get_nation_tech_level(nation_array.player_recno);
  1830. if(i < tech_res[7]->max_tech_level)
  1831. tech_res[7]->set_nation_tech_level(nation_array.player_recno, i+1);
  1832. //box.msg( "Get technologies of Galleon and Cannon." );
  1833. keyProcessed++;
  1834. break;
  1835. case 'q': //-- decrease population of a selected race in a selected village by 10 --//
  1836. if(town_array.selected_recno)
  1837. {
  1838. townPtr = town_array[town_array.selected_recno];
  1839. if(townPtr->nation_recno == nation_array.player_recno)
  1840. {
  1841. i = townPtr->get_selected_race();
  1842. if(i && townPtr->race_pop_array[i-1])
  1843. {
  1844. for(j=10; j>0 && !town_array.is_deleted(townPtr->town_recno); --j)
  1845. townPtr->kill_town_people(i);
  1846. //box.msg( "Population decrease by 10." );
  1847. keyProcessed++;
  1848. }
  1849. townPtr->auto_set_layout();
  1850. }
  1851. }
  1852. keyProcessed++;
  1853. break;
  1854. case 'w': //-- increase population of a selected race in a selected village by 10 --//
  1855. if(town_array.selected_recno)
  1856. {
  1857. townPtr = town_array[town_array.selected_recno];
  1858. if(townPtr->nation_recno == nation_array.player_recno)
  1859. {
  1860. i = townPtr->get_selected_race();
  1861. if(i && townPtr->race_pop_array[i-1])
  1862. {
  1863. townPtr->init_pop(i, 10, 100);
  1864. //box.msg( "Population increase by 10." );
  1865. keyProcessed++;
  1866. }
  1867. townPtr->auto_set_layout();
  1868. }
  1869. }
  1870. keyProcessed++;
  1871. break;
  1872. case 'e': //-------- decrease the reputation by 10 -----------//
  1873. nationPtr = nation_array[nation_array.player_recno];
  1874. nationPtr->reputation -= 10;
  1875. if(nationPtr->reputation < -100)
  1876. nationPtr->reputation = (float) -100;
  1877. //box.msg( "Reputation decrease by 10." );
  1878. keyProcessed++;
  1879. break;
  1880. case 'r': //-------- increase the reputation by 10 -----------//
  1881. nationPtr = nation_array[nation_array.player_recno];
  1882. nationPtr->reputation += 10;
  1883. if(nationPtr->reputation > 100)
  1884. nationPtr->reputation = (float) 100;
  1885. //box.msg( "Reputation increase by 10." );
  1886. keyProcessed++;
  1887. break;
  1888. case 'j': //--------- damage a building by 20 pt -----------//
  1889. if(firm_array.selected_recno)
  1890. {
  1891. firmPtr = firm_array[firm_array.selected_recno];
  1892. if(firmPtr->nation_recno==nation_array.player_recno)
  1893. {
  1894. firmPtr->hit_points -= 20;
  1895. if(firmPtr->hit_points < 1)
  1896. firmPtr->hit_points = (float) 1;
  1897. //box.msg( "damage firm by 20 points." );
  1898. keyProcessed++;
  1899. }
  1900. }
  1901. keyProcessed++;
  1902. break;
  1903. case 'k': //--------- repair a building by 20 pt -----------//
  1904. if(firm_array.selected_recno)
  1905. {
  1906. firmPtr = firm_array[firm_array.selected_recno];
  1907. if(firmPtr->nation_recno==nation_array.player_recno)
  1908. {
  1909. firmPtr->hit_points += 20;
  1910. if(firmPtr->hit_points > firmPtr->max_hit_points)
  1911. firmPtr->hit_points = firmPtr->max_hit_points;
  1912. //box.msg( "Repair firm by 20 points." );
  1913. keyProcessed++;
  1914. }
  1915. }
  1916. keyProcessed++;
  1917. break;
  1918. case 'x': //------ decrease cash by 1000 --------//
  1919. nationPtr = nation_array[nation_array.player_recno];
  1920. nationPtr->cash -= 1000;
  1921. if(nationPtr->cash < 0)
  1922. nationPtr->cash = (float) 0;
  1923. //box.msg( "Decrease cash by 1000." );
  1924. keyProcessed++;
  1925. break;
  1926. case 'c': //------ decrease food by 1000 --------//
  1927. nationPtr = nation_array[nation_array.player_recno];
  1928. nationPtr->food -= 1000;
  1929. if(nationPtr->food < 0)
  1930. nationPtr->food = (float) 0;
  1931. //box.msg( "Decrease food by 1000." );
  1932. keyProcessed++;
  1933. break;
  1934. case 'm': //----- add natural resource to cursor pos / remove existing resource ------//
  1935. if(get_mouse_loc_in_zoom_map(curXLoc, curYLoc))
  1936. {
  1937. locPtr = world.get_loc(curXLoc, curYLoc);
  1938. if(locPtr->has_site()) // remove site
  1939. {
  1940. i = locPtr->site_recno();
  1941. sitePtr = site_array[i];
  1942. if(!sitePtr->has_mine)
  1943. {
  1944. site_array.del_site(i);
  1945. //box.msg( "Site deleted." );
  1946. keyProcessed++;
  1947. }
  1948. }
  1949. else if(locPtr->can_build_site(1) && !locPtr->is_power_off()) // add site
  1950. {
  1951. i = MAX_RAW_RESERVE_QTY * (50 + m.random(50)) / 100;
  1952. site_array.add_site(curXLoc, curYLoc, SITE_RAW, m.random(MAX_RAW)+1, i);
  1953. //box.msg( "Site added." );
  1954. keyProcessed++;
  1955. }
  1956. }
  1957. keyProcessed++;
  1958. break;
  1959. case 'b': //------------ add reserve of natural resource by 100 ----------//
  1960. if(get_mouse_loc_in_zoom_map(curXLoc, curYLoc))
  1961. {
  1962. locPtr = world.get_loc(curXLoc, curYLoc);
  1963. if(locPtr->has_site())
  1964. {
  1965. i = locPtr->site_recno();
  1966. sitePtr = site_array[i];
  1967. if(!sitePtr->has_mine)
  1968. {
  1969. sitePtr->reserve_qty += 100;
  1970. //box.msg( "increase reserve by 100." );
  1971. keyProcessed++;
  1972. info.disp();
  1973. }
  1974. }
  1975. }
  1976. keyProcessed++;
  1977. break;
  1978. case 'v': //------------ reduce reserve of natural resource by 100 ----------//
  1979. if(get_mouse_loc_in_zoom_map(curXLoc, curYLoc))
  1980. {
  1981. locPtr = world.get_loc(curXLoc, curYLoc);
  1982. if(locPtr->has_site())
  1983. {
  1984. i = locPtr->site_recno();
  1985. sitePtr = site_array[i];
  1986. if(!sitePtr->has_mine && sitePtr->reserve_qty>100)
  1987. {
  1988. sitePtr->reserve_qty -= 100;
  1989. //box.msg( "reduce reserve by 100." );
  1990. keyProcessed++;
  1991. info.disp();
  1992. }
  1993. }
  1994. }
  1995. keyProcessed++;
  1996. break;
  1997. case 'h': //-------- hide map except for areas around your village, people --------//
  1998. if( config.explore_whole_map ) // no action if the setting of the map is explored
  1999. break;
  2000. vga_back.bar(MAP_X1, MAP_Y1, MAP_X2, MAP_Y2, UNEXPLORED_COLOR);
  2001. for(j=0; j<MAX_WORLD_Y_LOC; ++j)
  2002. {
  2003. locPtr = world.get_loc(0, j);
  2004. for(i=0; i<MAX_WORLD_X_LOC; ++i, locPtr++)
  2005. locPtr->explored_off();
  2006. }
  2007. for(i=town_array.size(); i>0; --i)
  2008. {
  2009. if(town_array.is_deleted(i))
  2010. continue;
  2011. townPtr = town_array[i];
  2012. if(townPtr->nation_recno == nation_array.player_recno)
  2013. world.unveil(townPtr->loc_x1, townPtr->loc_y1, townPtr->loc_x2, townPtr->loc_y2);
  2014. }
  2015. for(i=firm_array.size(); i>0; --i)
  2016. {
  2017. if(firm_array.is_deleted(i))
  2018. continue;
  2019. firmPtr = firm_array[i];
  2020. if(firmPtr->nation_recno == nation_array.player_recno)
  2021. world.unveil(firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->loc_x2, firmPtr->loc_y2);
  2022. }
  2023. for(i=unit_array.size(); i>0; --i)
  2024. {
  2025. if(unit_array.is_deleted(i))
  2026. continue;
  2027. unitPtr = unit_array[i];
  2028. if(unitPtr->nation_recno == nation_array.player_recno)
  2029. world.unveil(unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->next_x_loc(), unitPtr->next_y_loc());
  2030. }
  2031. for(i=spy_array.size(); i>0; --i)
  2032. {
  2033. if(spy_array.is_deleted(i))
  2034. continue;
  2035. spyPtr = spy_array[i];
  2036. if(spyPtr->true_nation_recno!=nation_array.player_recno)
  2037. continue;
  2038. if(spyPtr->spy_place == SPY_FIRM)
  2039. {
  2040. if(!firm_array.is_deleted(spyPtr->spy_place_para))
  2041. {
  2042. firmPtr = firm_array[spyPtr->spy_place_para];
  2043. world.unveil(firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->loc_x2, firmPtr->loc_y2);
  2044. }
  2045. }
  2046. else if(spyPtr->spy_place == SPY_TOWN)
  2047. {
  2048. if(!town_array.is_deleted(spyPtr->spy_place_para))
  2049. {
  2050. townPtr = town_array[spyPtr->spy_place_para];
  2051. world.unveil(townPtr->loc_x1, townPtr->loc_y1, townPtr->loc_x2, townPtr->loc_y2);
  2052. }
  2053. }
  2054. }
  2055. for(i=2; i<=nation_array.size(); ++i) // assume player_nation_recno = 1
  2056. {
  2057. if( nation_array.is_deleted(i) )
  2058. continue;
  2059. (~nation_array)->init_relation(i);
  2060. nation_array[i]->init_relation(1);
  2061. }
  2062. keyProcessed++;
  2063. break;
  2064. case 'z': //------------ put the selected unit to the cursor position ------------//
  2065. if(unit_array.selected_recno)
  2066. {
  2067. unitPtr = unit_array[unit_array.selected_recno];
  2068. if(get_mouse_loc_in_zoom_map(curXLoc, curYLoc))
  2069. {
  2070. if(unitPtr->mobile_type!=UNIT_LAND)
  2071. {
  2072. curXLoc = (curXLoc/2) * 2;
  2073. curYLoc = (curYLoc/2) * 2;
  2074. }
  2075. locPtr = world.get_loc(curXLoc, curYLoc);
  2076. if(locPtr->can_move(unitPtr->mobile_type))
  2077. {
  2078. world.set_unit_recno(unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->mobile_type, 0);
  2079. unitPtr->stop2();
  2080. unitPtr->next_x = curXLoc << ZOOM_X_SHIFT_COUNT;
  2081. unitPtr->next_y = curYLoc << ZOOM_Y_SHIFT_COUNT;
  2082. unitPtr->cur_x = unitPtr->go_x = unitPtr->next_x;
  2083. unitPtr->cur_y = unitPtr->go_y = unitPtr->next_y;
  2084. unitPtr->move_to_x_loc = curXLoc;
  2085. unitPtr->move_to_y_loc = curYLoc;
  2086. world.set_unit_recno(curXLoc, curYLoc, unitPtr->mobile_type, unitPtr->sprite_recno);
  2087. //box.msg( "move unit." );
  2088. keyProcessed++;
  2089. }
  2090. }
  2091. }
  2092. keyProcessed++;
  2093. break;
  2094. case 's':
  2095. if( info.default_viewing_nation_recno &&
  2096. nation_array.player_recno &&
  2097. nation_array[info.default_viewing_nation_recno]->is_ai() )
  2098. {
  2099. nation_array[info.default_viewing_nation_recno]->surrender(nation_array.player_recno);
  2100. }
  2101. keyProcessed++;
  2102. break;
  2103. }
  2104. return keyProcessed;
  2105. }
  2106. //--------- End of function detect_scenario_cheat_key ---------------//
  2107. //-------- Begin of function Sys::detect_set_speed --------//
  2108. //
  2109. int Sys::detect_set_speed(unsigned scanCode, unsigned skeyState)
  2110. {
  2111. int keyCode = mouse.is_key( scanCode, skeyState, (WORD) 0, K_CHAR_KEY );
  2112. if( !keyCode ) // since all keys concern are printable
  2113. return 0;
  2114. //------- determine the speed to set of the key pressed -------//
  2115. if( keyCode >= '0' && keyCode <= '8' )
  2116. {
  2117. set_speed( (keyCode-'0') * 3 );
  2118. return 1;
  2119. }
  2120. else if( keyCode == '9' )
  2121. {
  2122. set_speed( 99 ); // highest possible speed
  2123. return 1;
  2124. }
  2125. return 0;
  2126. }
  2127. //--------- End of function Sys::detect_set_speed ---------//
  2128. //--------- Begin of function Sys::detect_key_str --------//
  2129. //
  2130. // Detect for continous input of a string from the keyboard
  2131. //
  2132. // <int> keyStrId = the id. of the key string
  2133. // each id has its individual key_str_pos
  2134. // <char*> keyStr = the string to detect
  2135. //
  2136. // return : <int> 1 - complete string detected
  2137. // 0 - not detected
  2138. //
  2139. int Sys::detect_key_str(int keyStrId, char* keyStr)
  2140. {
  2141. err_when( keyStrId < 0 || keyStrId >= MAX_KEY_STR );
  2142. unsigned char* keyStr2 = (unsigned char*) keyStr;
  2143. if( mouse.key_code == keyStr2[key_str_pos[keyStrId]] )
  2144. key_str_pos[keyStrId]++;
  2145. else
  2146. key_str_pos[keyStrId]=0; // when one key unmatched, reset the counter
  2147. if( key_str_pos[keyStrId] >= (int) strlen(keyStr) )
  2148. {
  2149. key_str_pos[keyStrId]=0; // the full string has been entered successfully without any mistakes
  2150. return 1;
  2151. }
  2152. else
  2153. return 0;
  2154. }
  2155. //----------- End of function Sys::detect_key_str --------//
  2156. //-------- Begin of function Sys::set_speed --------//
  2157. //
  2158. void Sys::set_speed(int frameSpeed, int remoteCall)
  2159. {
  2160. //--------- if multiplayer, update remote players setting -------//
  2161. if( remote.is_enable() && !remoteCall )
  2162. {
  2163. RemoteMsg *remoteMsg = remote.new_msg(MSG_SET_SPEED, sizeof(short));
  2164. *((short*)remoteMsg->data_buf) = frameSpeed;
  2165. remote.send_free_msg( remoteMsg ); // send out the message and free it after finishing sending
  2166. }
  2167. //---------- set the speed now ----------//
  2168. if( config.frame_speed==0 ) // if it's currently frozen, set last_frame_time to avoid incorrect timeout
  2169. last_frame_time = m.get_time();
  2170. config.frame_speed = frameSpeed;
  2171. }
  2172. //--------- End of function Sys::set_speed ---------//
  2173. //-------- Begin of function Sys::capture_screen --------//
  2174. //
  2175. void Sys::capture_screen()
  2176. {
  2177. String str;
  2178. int i;
  2179. for (i = 0; i <= 999; i++)
  2180. {
  2181. str = m.format(info.random_seed, 1);
  2182. str += "_";
  2183. if (i < 100) str += "0";
  2184. if (i < 10) str += "0";
  2185. str += i;
  2186. str += ".BMP";
  2187. if( !m.is_file_exist(str) )
  2188. break;
  2189. }
  2190. if (i > 999) // all file names from DWORLD000 to DWORLD999 have been occupied
  2191. return;
  2192. if( sys.debug_session ) // in debug session, the buffer is not locked, we need to lock it for capturing the screen
  2193. {
  2194. vga_true_front.lock_buf();
  2195. vga_true_front.write_bmp_file(str);
  2196. vga_true_front.unlock_buf();
  2197. }
  2198. else
  2199. {
  2200. vga_front.write_bmp_file(str);
  2201. }
  2202. //------ display msg --------//
  2203. String str2;
  2204. #if(defined(SPANISH))
  2205. str2 = "Pantalla actual guardada en el archivo ";
  2206. str2 += str;
  2207. str2 += ".";
  2208. #elif(defined(FRENCH))
  2209. str2 = "Cet écran a été sauvegardé dans le fichier ";
  2210. str2 += str;
  2211. str2 += ".";
  2212. #else
  2213. str2 = "The current screen has been written to file ";
  2214. str2 += str;
  2215. str2 += ".";
  2216. #endif
  2217. box.msg( str2 );
  2218. }
  2219. //--------- End of function Sys::capture_screen ---------//
  2220. //-------- Begin of function Sys::capture_minimap --------//
  2221. //
  2222. void Sys::capture_minimap()
  2223. {
  2224. String str;
  2225. int i;
  2226. for (i = 0; i <= 999; i++)
  2227. {
  2228. str = m.format(info.random_seed, 1);
  2229. str += "_";
  2230. if (i < 100) str += "0";
  2231. if (i < 10) str += "0";
  2232. str += i;
  2233. str += ".BMP";
  2234. if( !m.is_file_exist(str) )
  2235. break;
  2236. }
  2237. if (i > 999) // all file names from DWORLD000 to DWORLD999 have been occupied
  2238. return;
  2239. if( sys.debug_session ) // in debug session, the buffer is not locked, we need to lock it for capturing the screen
  2240. {
  2241. vga_true_front.lock_buf();
  2242. vga_true_front.write_bmp_file(str, 588, 56, 200, 200);
  2243. vga_true_front.unlock_buf();
  2244. }
  2245. else
  2246. {
  2247. vga_front.write_bmp_file(str, 588, 56, 200, 200);
  2248. }
  2249. //------ display msg --------//
  2250. String str2;
  2251. str2 = "The current minimap has been written to file ";
  2252. str2 += str;
  2253. str2 += ".";
  2254. box.msg( str2 );
  2255. }
  2256. //--------- End of function Sys::capture_minimap ---------//
  2257. //--------- Begin of static function static_main_win_proc --------//
  2258. //
  2259. // Callback for all Windows messages
  2260. //
  2261. static long FAR PASCAL static_main_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2262. {
  2263. return sys.main_win_proc(hWnd, message, wParam, lParam);
  2264. }
  2265. //--------- End of static function static_main_win_proc --------//
  2266. //-------- Begin of function Sys::load_game --------//
  2267. //
  2268. void Sys::load_game()
  2269. {
  2270. //--- load game not enabled in multiplayer game ---//
  2271. if( remote.is_enable() )
  2272. return;
  2273. signal_exit_flag=1; // for deinit functions to recognize that this is an end game deinitialization instead of a normal deinitialization
  2274. int rc=0;
  2275. game_file_array.init("*.SAV"); // reload any save game file
  2276. game_file_array.menu(-2); // save screen area to back buffer
  2277. switch( game_file_array.menu(2) )
  2278. {
  2279. case 1:
  2280. rc = 1; // fall through to case 0
  2281. case 0:
  2282. signal_exit_flag = 0;
  2283. break;
  2284. // case -1 and otherwise, left sys.signal_exit_flag 1 to exit the game
  2285. }
  2286. game_file_array.menu(-1); // restore screen area from back buffer
  2287. //-----------------------------------//
  2288. if( rc == -1)
  2289. {
  2290. box.msg( "Fail Loading Game" );
  2291. return;
  2292. }
  2293. if( rc ) // if rc==0, leave signal_exit_flag 1, which the game will then quit
  2294. {
  2295. need_redraw_flag = 1;
  2296. disp_frame();
  2297. // #### begin Gilbert 22/10 ######//
  2298. disp_view_mode();
  2299. // #### end Gilbert 22/10 ######//
  2300. box.msg( "Game Loaded Successfully" );
  2301. signal_exit_flag=0;
  2302. info.disp();
  2303. }
  2304. }
  2305. //--------- End of function Sys::load_game ---------//
  2306. //-------- Begin of function Sys::save_game --------//
  2307. //
  2308. void Sys::save_game()
  2309. {
  2310. if( nation_array.player_recno==0 ) // cannot save game when the player's kingdom has been destroyed
  2311. return;
  2312. if( remote.is_enable() )
  2313. {
  2314. DWORD *dwordPtr = (DWORD *)remote.new_send_queue_msg( MSG_REQUEST_SAVE, sizeof(DWORD) );
  2315. *dwordPtr = remote.next_send_frame(nation_array.player_recno, sys.frame_count+remote.process_frame_delay)+2;
  2316. return;
  2317. }
  2318. game_file_array.init("*.SAV"); // reload any save game file
  2319. game_file_array.menu(-2); // save screen area to back buffer
  2320. if( game_file_array.menu(1) == 1 )
  2321. {
  2322. if( GameFile::last_read_success_flag )
  2323. box.msg( "Game Saved Successfully" );
  2324. }
  2325. game_file_array.menu(-1); // restore screen area from back buffer
  2326. // ##### patch begin Gilbert 16/3 #######//
  2327. info.disp();
  2328. // ##### patch end Gilbert 16/3 #######//
  2329. }
  2330. //-------- End of function Sys::save_game --------//
  2331. // --------- begin of function Sys::mp_request_save ----------//
  2332. void Sys::mp_request_save(DWORD frame)
  2333. {
  2334. if( !mp_save_flag )
  2335. {
  2336. mp_save_flag = 1;
  2337. mp_save_frame = frame;
  2338. }
  2339. }
  2340. // --------- end of function Sys::mp_request_save ----------//
  2341. // --------- begin of function Sys::mp_clear_request_save ----------//
  2342. void Sys::mp_clear_request_save()
  2343. {
  2344. mp_save_flag = 0;
  2345. mp_save_frame = 0;
  2346. }
  2347. // --------- end of function Sys::mp_clear_request_save ----------//
  2348. //-------- Begin of function Sys::set_game_dir ----------//
  2349. //
  2350. // Set all game directories.
  2351. //
  2352. void Sys::set_game_dir()
  2353. {
  2354. //------- If it should run from the CDROM ------//
  2355. get_cdrom_drive();
  2356. set_one_dir( "IMAGE\\HALLFAME.ICN" , "IMAGE\\", dir_image );
  2357. set_one_dir( "ENCYC\\SEAT\\NORMAN.ICN", "ENCYC\\", dir_encyc );
  2358. #ifdef AMPLUS
  2359. set_one_dir( "ENCYC2\\SEAT\\EGYPTIAN.ICN", "ENCYC2\\", dir_encyc2 );
  2360. #endif
  2361. set_one_dir( "MOVIE\\INTRO.AVI" , "MOVIE\\", dir_movie );
  2362. #ifdef DEMO
  2363. set_one_dir( "MUSIC\\DEMO.WAV" , "MUSIC\\", dir_music );
  2364. set_one_dir( "TUTORIAL\\STANDARD.TUT" , "TUTORIAL\\", dir_tutorial );
  2365. set_one_dir( "SCENARIO\\DEMO.SCN" , "SCENARIO\\", dir_scenario );
  2366. #else
  2367. set_one_dir( "MUSIC\\NORMAN.WAV" , "MUSIC\\", dir_music );
  2368. set_one_dir( "TUTORIAL\\1BAS_MIL.TUT" , "TUTORIAL\\", dir_tutorial );
  2369. set_one_dir( "SCENARIO\\7FOR7.SCN" , "SCENARIO\\", dir_scenario );
  2370. #endif
  2371. #if(MAX_SCENARIO_PATH >= 2)
  2372. set_one_dir( "SCENARI2\\SCN_01.SCN" , "SCENARI2\\", dir_scenario_path[1] );
  2373. #endif
  2374. //-------- set game version ---------//
  2375. #ifdef BETA
  2376. game_version = VERSION_FULL;
  2377. #else
  2378. #ifdef DEMO
  2379. game_version = VERSION_DEMO;
  2380. #else
  2381. if( 1 ) // no longer checkcd if( cdrom_drive )
  2382. game_version = VERSION_FULL; // single player game is not available when game_version == VERSION_FULL
  2383. else
  2384. game_version = VERSION_MULTIPLAYER_ONLY;
  2385. #endif
  2386. #endif
  2387. }
  2388. //----------- End of function Sys::set_game_dir ----------//
  2389. //-------- Begin of function Sys::set_one_dir ----------//
  2390. //
  2391. int Sys::set_one_dir( char* checkFileName, char* defaultDir, char* trueDir )
  2392. {
  2393. if( m.is_file_exist( checkFileName ) )
  2394. {
  2395. strcpy( trueDir, defaultDir );
  2396. }
  2397. else
  2398. {
  2399. if( cdrom_drive )
  2400. {
  2401. strcpy( trueDir, "D:\\" );
  2402. strcat( trueDir, defaultDir );
  2403. trueDir[0] = cdrom_drive;
  2404. }
  2405. else
  2406. {
  2407. strcpy( trueDir, "" );
  2408. return 0;
  2409. }
  2410. }
  2411. return 1;
  2412. }
  2413. //----------- End of function Sys::set_one_dir ----------//
  2414. //-------- Start of function Sys::get_cdrom_drive -------------//
  2415. //
  2416. // Get the drive letter of the CDROM and restore the result in cdrom_drive.
  2417. //
  2418. void Sys::get_cdrom_drive()
  2419. {
  2420. unsigned char i;
  2421. char driveStr[4];
  2422. static char checkFileName[30] = "D:\\7K.EXE"; // check this file to identify the disc
  2423. cdrom_drive = 0;
  2424. driveStr[1] = ':';
  2425. driveStr[2] = '\\';
  2426. driveStr[3] = 0;
  2427. // ##### patch begin Gilbert 14/10 ######//
  2428. for(i='C'; i<='Z'; i++)
  2429. // ##### patch end Gilbert 14/10 ######//
  2430. {
  2431. checkFileName[0] = i;
  2432. driveStr[0] = i;
  2433. if(GetDriveType(driveStr) == DRIVE_CDROM)
  2434. {
  2435. if( m.is_file_exist(checkFileName) )
  2436. {
  2437. cdrom_drive = i;
  2438. break;
  2439. }
  2440. }
  2441. }
  2442. }
  2443. //--------- End of function Sys::get_cdrom_drive ---------------//
  2444. //-------- Start of function locate_king_general -------------//
  2445. //
  2446. static void locate_king_general(int rankId)
  2447. {
  2448. if( !nation_array.player_recno )
  2449. return;
  2450. int unitRecno = 0;
  2451. if(unit_array.selected_recno)
  2452. unitRecno = unit_array.selected_recno;
  2453. else if(rankId!=RANK_KING && firm_array.selected_recno)
  2454. {
  2455. Firm *firmPtr = firm_array[firm_array.selected_recno];
  2456. if((firmPtr->firm_id==FIRM_CAMP || firmPtr->firm_id==FIRM_BASE) && firmPtr->overseer_recno)
  2457. unitRecno = firmPtr->overseer_recno;
  2458. }
  2459. for( int i=unit_array.size() ; i>0 ; i-- )
  2460. {
  2461. if( ++unitRecno > unit_array.size() )
  2462. unitRecno = 1;
  2463. if( unit_array.is_deleted(unitRecno) )
  2464. continue;
  2465. Unit* unitPtr = unit_array[unitRecno];
  2466. if( unitPtr->nation_recno == nation_array.player_recno &&
  2467. unitPtr->rank_id == rankId )
  2468. {
  2469. short xLoc, yLoc;
  2470. if( unitPtr->get_cur_loc(xLoc, yLoc) )
  2471. {
  2472. world.go_loc(xLoc, yLoc, 1);
  2473. return;
  2474. }
  2475. }
  2476. }
  2477. }
  2478. //--------- End of function locate_king_general ---------------//
  2479. //-------- Start of function locate_spy -------------//
  2480. //
  2481. static void locate_spy()
  2482. {
  2483. if( !nation_array.player_recno )
  2484. return;
  2485. int unitRecno = unit_array.selected_recno;
  2486. for( int i=unit_array.size() ; i>0 ; i-- )
  2487. {
  2488. if( ++unitRecno > unit_array.size() )
  2489. unitRecno = 1;
  2490. if( unit_array.is_deleted(unitRecno) )
  2491. continue;
  2492. Unit* unitPtr = unit_array[unitRecno];
  2493. if( unitPtr->true_nation_recno() == nation_array.player_recno &&
  2494. unitPtr->spy_recno && unitPtr->is_visible() )
  2495. {
  2496. short xLoc, yLoc;
  2497. if( unitPtr->get_cur_loc(xLoc, yLoc) )
  2498. {
  2499. world.go_loc(xLoc, yLoc, 1);
  2500. return;
  2501. }
  2502. }
  2503. }
  2504. }
  2505. //--------- End of function locate_spy ---------------//
  2506. //-------- Start of function locate_ship -------------//
  2507. //
  2508. static void locate_ship()
  2509. {
  2510. if( !nation_array.player_recno )
  2511. return;
  2512. //----------------------------------------------------------------------------//
  2513. // The order is
  2514. // 1) visible ships by their sprite_recno in ascending order
  2515. // 2) FirmHarbors with ships (num of ships >= 1) by their firm_recno in ascending
  2516. // order
  2517. //
  2518. // Start the scaning in one of the following cases
  2519. // 1) a unit is selected
  2520. // 2) a firm is selected
  2521. // 3) neither unit or firm is selected
  2522. //----------------------------------------------------------------------------//
  2523. if(firm_array.selected_recno)
  2524. {
  2525. if(!locate_ship_in_harbor()) // harbor first, then unit
  2526. locate_visible_ship();
  2527. }
  2528. else // if(unit_array.selected_recno) or neither of them is selected
  2529. {
  2530. if(!locate_visible_ship()) // unit first, then harbor
  2531. locate_ship_in_harbor();
  2532. }
  2533. }
  2534. //--------- End of function locate_ship ---------------//
  2535. //-------- Start of function locate_ship_in_harbor -------------//
  2536. // return 1 if found
  2537. // return 0 otherwise
  2538. //
  2539. static int locate_ship_in_harbor()
  2540. {
  2541. int firmRecno = firm_array.selected_recno;
  2542. int checkSize = firm_array.size();
  2543. if(firmRecno)
  2544. checkSize--; // not include the selected firm
  2545. for( int i=checkSize ; i>0 ; i-- )
  2546. {
  2547. if( ++firmRecno > firm_array.size() )
  2548. firmRecno = 1;
  2549. if( firm_array.is_deleted(firmRecno) )
  2550. continue;
  2551. Firm* firmPtr = firm_array[firmRecno];
  2552. if(firmPtr->firm_id!=FIRM_HARBOR ||
  2553. firmPtr->nation_recno != nation_array.player_recno)
  2554. continue;
  2555. if(((FirmHarbor*)firmPtr)->ship_count==0)
  2556. continue; // not interested
  2557. world.go_loc(firmPtr->center_x, firmPtr->center_y, 1);
  2558. return 1;
  2559. }
  2560. return 0;
  2561. }
  2562. //--------- End of function locate_ship_in_harbor ---------------//
  2563. //-------- Start of function locate_visible_ship -------------//
  2564. // return 1 if found
  2565. // return 0 otherwise
  2566. //
  2567. static int locate_visible_ship()
  2568. {
  2569. int unitRecno = unit_array.selected_recno;
  2570. int checkSize = unit_array.size();
  2571. if(unitRecno)
  2572. checkSize--; // not include the selected unit
  2573. for( int i=checkSize ; i>0 ; i-- )
  2574. {
  2575. if( ++unitRecno > unit_array.size() )
  2576. unitRecno = 1;
  2577. if( unit_array.is_deleted(unitRecno) )
  2578. continue;
  2579. Unit* unitPtr = unit_array[unitRecno];
  2580. if(!unitPtr->is_visible()) // skip the case unit_mode==UNIT_MODE_IN_HARBOR in calling Unit::get_cur_loc()
  2581. continue;
  2582. if( unitPtr->nation_recno == nation_array.player_recno &&
  2583. unit_res[unitPtr->unit_id]->unit_class == UNIT_CLASS_SHIP )
  2584. {
  2585. short xLoc, yLoc;
  2586. if( unitPtr->get_cur_loc(xLoc, yLoc) )
  2587. {
  2588. world.go_loc(xLoc, yLoc, 1);
  2589. return 1;
  2590. }
  2591. }
  2592. }
  2593. return 0;
  2594. }
  2595. //--------- End of function locate_visible_ship ---------------//
  2596. //-------- Start of function locate_camp -------------//
  2597. //
  2598. static void locate_camp()
  2599. {
  2600. if( !nation_array.player_recno )
  2601. return;
  2602. int firmRecno = firm_array.selected_recno;
  2603. for( int i=firm_array.size() ; i>0 ; i-- )
  2604. {
  2605. if( ++firmRecno > firm_array.size() )
  2606. firmRecno = 1;
  2607. if( firm_array.is_deleted(firmRecno) )
  2608. continue;
  2609. Firm* firmPtr = firm_array[firmRecno];
  2610. if( firmPtr->nation_recno == nation_array.player_recno &&
  2611. firmPtr->firm_id == FIRM_CAMP )
  2612. {
  2613. world.go_loc(firmPtr->center_x, firmPtr->center_y, 1);
  2614. return;
  2615. }
  2616. }
  2617. }
  2618. //--------- End of function locate_camp ---------------//
  2619. //-------- Start of function get_mouse_loc_in_zoom_map -------------//
  2620. static int get_mouse_loc_in_zoom_map(int &x, int &y)
  2621. {
  2622. int mouseX = mouse.cur_x;
  2623. int mouseY = mouse.cur_y;
  2624. if(mouseX >= ZOOM_X1 && mouseX <= ZOOM_X2 && mouseY >= ZOOM_Y1 && mouseY <= ZOOM_Y2)
  2625. {
  2626. x = world.zoom_matrix->top_x_loc + (mouseX-ZOOM_X1)/ZOOM_LOC_WIDTH;
  2627. y = world.zoom_matrix->top_y_loc + (mouseY-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
  2628. return 1;
  2629. }
  2630. return 0; // out of zoom map boundary
  2631. }
  2632. //--------- End of function get_mouse_loc_in_zoom_map ---------------//