/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OSYS.CPP //Description : System resource management object #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ##### begin Gilbert 23/10 ######// #include #include // ##### end Gilbert 23/10 ######// //----------- Declare static functions -----------// static long FAR PASCAL static_main_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); //------- Define static functions -----------// LRESULT CALLBACK win_hook_proc(int nCode, WORD wParam, LONG lParam); static void test_lzw(); static void locate_king_general(int rankId); static void locate_spy(); static void locate_ship(); static void locate_camp(); static int locate_ship_in_harbor(); static int locate_visible_ship(); static int detect_scenario_cheat_key(unsigned scanCode, unsigned skeyState); static int get_mouse_loc_in_zoom_map(int &x, int &y); //----------- Define static variables ------------// static unsigned long last_frame_time=0, last_resend_time=0; static char remote_send_success_flag=1; static HHOOK win_hook_handle=NULL; static char scenario_cheat_flag=0; //----------- Begin of function Sys::Sys -----------// Sys::Sys() { memset(this, 0, sizeof(Sys) ); common_data_buf = mem_add( COMMON_DATA_BUF_SIZE ); view_mode = MODE_NORMAL; // the animation mode } //----------- End of function Sys::Sys -----------// //----------- Begin of function Sys::~Sys -----------// Sys::~Sys() { mem_del(common_data_buf); deinit(); } //----------- End of function Sys::~Sys -----------// //------------ Begin of function Sys::init ----------// // int Sys::init( HINSTANCE hInstance ) { err_when( init_flag ); //------- initialize basic vars --------// app_hinstance = hInstance; #ifdef BETA debug_session = m.is_file_exist("DEBUG.SYS"); testing_session = m.is_file_exist("TESTING.SYS"); scenario_cheat_flag = m.is_file_exist("CHEAT.SYS"); #endif #ifdef DEBUG debug_session = m.is_file_exist("DEBUG.SYS"); testing_session = m.is_file_exist("TESTING.SYS"); scenario_cheat_flag = m.is_file_exist("CHEAT.SYS"); #endif // debug_session = m.is_file_exist("DEBUG.SYS"); set_game_dir(); // set game directories names and game version //------- initialize more stuff ---------// if( !init_win() ) return FALSE; if( !init_directx() ) return FALSE; if( !init_objects() ) // initialize system objects which do not change from games to games. return FALSE; init_flag = 1; return TRUE; } //------------ End of function Sys::init ----------// //-------- Begin of function Sys::deinit --------// // // Finished with all objects we use; release them // void Sys::deinit() { if( !init_flag ) return; game.deinit(); // actually game.deinit() will be called by main_win_proc() and calling it here will have no effect deinit_objects(); //-------------------------------------// if( vga_back.buf_locked ) vga_back.unlock_buf(); if( vga_front.buf_locked ) vga_front.unlock_buf(); //-------------------------------------// /* extern char low_video_memory_flag; if( low_video_memory_flag ) { ShowWindow(sys.main_hwnd, SW_MINIMIZE ); unsigned curTime = m.get_time(); while( m.get_time() < curTime + 4000 ); } */ //---------------------------------------// PostMessage(main_hwnd, WM_CLOSE, 0, 0); init_flag = 0; MSG msg; while( GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } } //--------- End of function Sys::deinit ---------// //-------- Begin of function Sys::init_win --------// // int Sys::init_win() { //--------- register window class --------// WNDCLASS wc; BOOL rc; wc.style = CS_DBLCLKS; wc.lpfnWndProc = static_main_win_proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = app_hinstance; wc.hIcon = LoadIcon( app_hinstance, MAKEINTATOM(IDI_ICON1)); wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = WIN_CLASS_NAME; rc = RegisterClass( &wc ); if( !rc ) return FALSE; //------ install keyboard hook ---------// /* win_hook_handle = SetWindowsHookEx(WH_CBT, (HOOKPROC) win_hook_proc, sys.app_hinstance, NULL); if( !win_hook_handle ) err.run( "Failed installing keyboard hook." ); */ //--------- create window -----------// main_hwnd = CreateWindowEx( WS_EX_APPWINDOW | WS_EX_TOPMOST, WIN_CLASS_NAME, WIN_TITLE, WS_VISIBLE | // so we dont have to call ShowWindow WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, app_hinstance, NULL ); if( !main_hwnd ) return FALSE; UpdateWindow( main_hwnd ); SetFocus( main_hwnd ); return TRUE; } //-------- End of function Sys::init_win --------// //------- Begin of function win_hook_proc --------// LRESULT CALLBACK win_hook_proc(int nCode, WORD wParam, LONG lParam) { static int lastnCode; int a=0; if( vga_true_front.dd_buf && vga_true_front.dd_buf->IsLost() ) a = 1; lastnCode = nCode; if( sys.init_flag && nCode == HCBT_SETFOCUS ) sys.pause(); return CallNextHookEx(win_hook_handle, nCode, wParam, lParam); } //-------- End of function win_hook_proc --------// //-------- Begin of function Sys::init_directx --------// // int Sys::init_directx() { DEBUG_LOG("Attempt audio.init()"); audio.init(); DEBUG_LOG(audio.wav_init_flag); music.init(); se_ctrl.init(); //---------------------------------------// ShowCursor(FALSE); //-------- initialize DirectDraw --------// DEBUG_LOG("Attempt vga.init()"); if( !vga.init() ) return FALSE; DEBUG_LOG("vga.init() ok"); DEBUG_LOG("Attempt vga.load_pal()"); vga.load_pal(DIR_RES"PAL_STD.RES"); DEBUG_LOG("vga.load_pal() finish"); if( sys.debug_session ) // if we are currently in a debug session, don't lock the front buffer otherwise the system will hang up { DEBUG_LOG("Attempt vga_front.init_back()"); vga_front.init_back( vga.dd_obj ); vga_front.is_front = 1; // set it to 1, overriding the setting in init_back() DEBUG_LOG("Attempt vga_true_front.init_front()"); vga_true_front.init_front( vga.dd_obj ); DEBUG_LOG("Attempt vga.activate_pal()"); vga.activate_pal(&vga_true_front); DEBUG_LOG("vga.activate_pal() finish"); } else { vga_front.init_front( vga.dd_obj ); vga.activate_pal(&vga_front); } DEBUG_LOG("Attempt vga_back.init_back()"); vga_back.init_back( vga.dd_obj ); DEBUG_LOG("vga_back.init_back() finish"); DEBUG_LOG("Attempt vga_front.lock_buf()"); vga_front.lock_buf(); DEBUG_LOG("vga_front.lock_buf() finish"); DEBUG_LOG("Attempt vga_back.lock_buf()"); vga_back.lock_buf(); DEBUG_LOG("vga_back.lock_buf() finish"); return TRUE; } //-------- End of function Sys::init_directx --------// //-------- Begin of function Sys::deinit_directx --------// // void Sys::deinit_directx() { if( vga_back.dd_buf && vga_back.buf_locked ) { DEBUG_LOG("Attempt vga_back.unlock_buf()"); vga_back.unlock_buf(); DEBUG_LOG("vga_back.unlock_buf() finish"); } if( vga_front.dd_buf && vga_front.buf_locked ) { DEBUG_LOG("Attempt vga_front.unlock_buf()"); vga_front.unlock_buf(); DEBUG_LOG("vga_front.unlock_buf() finish"); } DEBUG_LOG("Attempt vga_back.deinit()"); vga_back.deinit(); DEBUG_LOG("vga_back.deinit() finish"); if( sys.debug_session ) { DEBUG_LOG("Attempt vga_true_front.deinit()"); vga_true_front.deinit(); DEBUG_LOG("vga_true_front.deinit() finish"); } DEBUG_LOG("Attempt vga_front.deinit()"); vga_front.deinit(); DEBUG_LOG("Attempt vga_front.deinit() finish"); DEBUG_LOG("Attempt vga.deinit()"); vga.deinit(); DEBUG_LOG("vga.deinit() finish"); //------------------------------// se_ctrl.deinit(); music.deinit(); DEBUG_LOG("Attempt audio.deinit()"); audio.deinit(); DEBUG_LOG("audio.deinit() finish"); } //--------- End of function Sys::deinit_directx ---------// //------- Begin of function Sys::init_objects -----------// // // Initialize system objects which do not change from games to games. // int Sys::init_objects() { //--------- init system class ----------// mouse_cursor.init(); mouse_cursor.set_frame_border(ZOOM_X1,ZOOM_Y1,ZOOM_X2,ZOOM_Y2); mouse.init(app_hinstance, main_hwnd, NULL); //------- init resource class ----------// #if( defined(GERMAN) || defined(FRENCH) || defined(SPANISH) ) font_std.init("SAN", 1); font_hall.init("HALL", 1); #else font_std.init("STD", 2); #endif font_san.init("SAN", 0); // 0-zero inter-character space font_mid.init("MID"); font_small.init("SMAL"); font_news.init("NEWS"); font_hitpoint.init("HITP"); font_bible.init("CASA", 1, 3); font_bard.init("CASA", 0); image_icon.init(DIR_RES"I_ICON.RES",1,0); // 1-read into buffer image_interface.init(DIR_RES"I_IF.RES",0,0); // 0-don't read into the buffer, don't use common buffer #ifndef DEMO // do not load these in the demo verison image_menu.init(DIR_RES"I_MENU.RES",0,0); // 0-don't read into the buffer, don't use common buffer image_encyc.init(DIR_RES"I_ENCYC.RES",0,0); // 0-don't read into the buffer, don't use common buffer #endif image_button.init(DIR_RES"I_BUTTON.RES",1,0); image_spict.init(DIR_RES"I_SPICT.RES",1,0); image_tutorial.init(DIR_RES"TUT_PICT.RES",0,0); #ifdef AMPLUS #ifndef DEMO // do not load these in the demo verison image_menu_plus.init(DIR_RES"I_MENU2.RES",0,0); // 0-don't read into the buffer, don't use common buffer #endif #endif seek_path.init(MAX_BACKGROUND_NODE); seek_path_s2.init(1);//seek_path_s2.init(MAX_BACKGROUND_NODE); seek_path_reuse.init(MAX_BACKGROUND_NODE); group_select.init(); //------------ init flame ------------// for(int i = 0; i < FLAME_GROW_STEP; ++i) flame[i].init(Flame::default_width(i), Flame::default_height(i), Flame::base_width(i), FLAME_WIDE); //------------ init animated line drawer -------// anim_line.init(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2); //---------- init other objects ----------// game_set.init(); // this must be called before game.init() as game.init() assume game_set has been initialized help.init("HELP.RES"); #if( defined(GERMAN) || defined(FRENCH) || defined(SPANISH) ) translate.init(); #endif tutor.init(); game_file_array.init("*.SAV"); //---------- init game_set -----------// DEBUG_LOG("Sys::init_objects finish"); return TRUE; } //------- End of function Sys::init_objects -----------// //------- Begin of function Sys::deinit_objects -----------// void Sys::deinit_objects() { //--------- deinit system class ----------// mouse.deinit(); // mouse must be deinitialized first mouse_cursor.deinit(); //------- deinit resource class ----------// font_std.deinit(); font_san.deinit(); font_mid.deinit(); font_small.deinit(); font_news.deinit(); font_hitpoint.deinit(); font_bible.deinit(); font_bard.deinit(); #if( defined(GERMAN) || defined(FRENCH) || defined(SPANISH) ) font_hall.deinit(); #endif image_icon.deinit(); image_interface.deinit(); image_menu.deinit(); image_button.deinit(); image_spict.deinit(); image_encyc.deinit(); image_tutorial.deinit(); seek_path.deinit(); seek_path_s2.deinit(); seek_path_reuse.deinit(); group_select.deinit(); for(int i = 0; i < FLAME_GROW_STEP; ++i) flame[i].deinit(); //--------- deinit other objects ----------// game_set.deinit(); help.deinit(); #if( defined(GERMAN) || defined(FRENCH) || defined(SPANISH) ) translate.deinit(); #endif tutor.deinit(); config.deinit(); game_file_array.deinit(); } //------- End of function Sys::deinit_objects -----------// //-------- Begin of function Sys::run --------// // void Sys::run(int isLoadedGame) { //-*********** simulate aat ************-// #ifdef DEBUG //--------- enable only when simulation -------// debug_sim_game_type = (m.is_file_exist("sim.sys")) ? 2 : 0; #endif //-*********** simulate aat ************-// sys_flag = SYS_RUN; view_mode = MODE_NORMAL; //------- test LZW compression ---------// #ifdef DEBUG_LZW test_lzw(); #endif //------ reset mouse ---------// mouse.reset_click(); mouse_cursor.set_frame(0); //-- enable power after the game objets has been initialized --// power.enable(); // enable power, which handle mouse inputs //----- sys::disp_frame() will redraw everything when this flag is set to 1 ----// sys.need_redraw_flag = 1; option_menu.active_flag = 0; in_game_menu.active_flag = 0; sys.disp_frame(); disp_view_mode(); //----------- run the main loop -----------// main_loop(isLoadedGame); //-----------------------------------------// m.unlock_seed(); } //--------- End of function Sys::run --------// //-------- Begin of static function test_lzw --------// // static void test_lzw() { // test lzw compress if( m.is_file_exist("NORMAL.SAV")) { File f,g; Lzw lzw_c, lzw_d; // one for compress, the other for decompress f.file_open("NORMAL.SAV"); // read into buffer long fileSize = f.file_size(); unsigned char *srcPtr = (unsigned char *) mem_add(fileSize); f.file_read(srcPtr, fileSize); // find compressed size to allocate space long compSize = lzw_c.compress(srcPtr, fileSize); unsigned char *destPtr = (unsigned char *) mem_add( compSize/8+ 4 ); // alloc 4 bytes more if( compSize != lzw_c.compress(srcPtr, fileSize, destPtr) ) { err_here(); } // decompress again long backSize = lzw_d.expand(destPtr, compSize, NULL); err_when(backSize != fileSize); unsigned char *backPtr = (unsigned char *) mem_add( backSize+4 ); if( backSize != lzw_d.expand(destPtr, compSize, backPtr) ) { err_here(); } // finally compare srcPtr and backPtr err_when( memcmp(srcPtr, backPtr, fileSize) ); f.file_close(); // write it to a file { unsigned char *writePtr = destPtr; long writeSize = (compSize +7) / 8; g.file_create("NORMAL.LZ1"); for( ; writeSize > 0; writeSize -= 0x4000) { g.file_write(writePtr, writeSize > 0x4000 ? 0x4000 : writeSize); writePtr += 0x4000; } g.file_close(); } // test two, compress to a file g.file_create("NORMAL.LZW"); compSize = lzw_c.compress(srcPtr, fileSize, &g); g.file_close(); g.file_open("NORMAL.LZW"); backSize = lzw_d.expand(&g, NULL); err_when(backSize != fileSize); backPtr = (unsigned char *) mem_resize(backPtr, backSize+4 ); g.file_close(); g.file_open("NORMAL.LZW"); if( backSize != lzw_d.expand(&g, backPtr)) { err_here(); } err_when( memcmp(srcPtr,backPtr, fileSize) ); mem_del(destPtr); mem_del(backPtr); mem_del(srcPtr); } } //--------- End of static function test_lzw --------// //-------- Begin of function Sys::main_loop --------// // void Sys::main_loop(int isLoadedGame) { MSG msg; // #### begin Gilbert 31/10 #####// // int rc; // #### end Gilbert 31/10 #####// //-------- reset day_frame_count -------// if( !isLoadedGame ) { day_frame_count = 0; // for determining when the day counter should be increased. frame_count = 1; } //----- initialize these vars for every game -----// for( int i=nation_array.size() ; i>0 ; i-- ) { if( !nation_array.is_deleted(i) ) nation_array[i]->next_frame_ready = 0; } remote.packet_send_count = 0; remote.packet_receive_count = 0; last_frame_time = m.get_time()+60000; // plus 60 seconds buffer for game loading/starting time //frame_count = 1; is_sync_frame = 0; //----------------------------------------------// mp_clear_request_save(); remote.enable_poll_msg(); remote.enable_process_queue(); remote_send_success_flag = 1; #ifdef DEBUG char longLogSuffix = 'A'; if( remote.is_enable() ) { if(long_log) delete long_log; long_log = new LongLog(longLogSuffix); } #endif //-*********** syn game test ***********-// #ifdef DEBUG if(debug_seed_status_flag==DEBUG_SYN_LOAD_AND_COMPARE_ONCE) sp_load_seed_file(); #endif //-*********** syn game test ***********-// vga_front.unlock_buf(); // ------- establish_contact again --------// // if the game saved after NationRelation::contact_msg_flag set, but // remote players may have not receive MSG_NATION_CONTACT // // send MSG_NATION_CONTACT now if( !config.explore_whole_map && nation_array.player_recno && !nation_array.is_deleted(nation_array.player_recno) ) { for(short nationRecno = 1; nationRecno <= nation_array.size(); ++nationRecno ) { if( nationRecno == nation_array.player_recno || nation_array.is_deleted(nationRecno) ) continue; NationRelation *relation = (~nation_array)->get_relation(nationRecno); if( relation->contact_msg_flag && !relation->has_contact) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short)); *shortPtr = nation_array.player_recno; shortPtr[1] = nationRecno; } } } // #### begin Gilbert 23/10 #######// option_menu.active_flag = 0; in_game_menu.active_flag = 0; // #### end Gilbert 23/10 #######// // ##### begin Gilbert 4/11 ######// DWORD lastDispFrameTime = m.get_time(); // ##### end Gilbert 4/11 ######// // ##### patch begin Gilbert 17/11 #######// DWORD firstUnreadyTime = 0; // ##### patch end Gilbert 17/11 #######// while( 1 ) { if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) { if (!GetMessage( &msg, NULL, 0, 0)) break; TranslateMessage(&msg); DispatchMessage(&msg); } else if ( !paused_flag && active_flag ) { // #### begin Gilbert 31/10 ######// int rc = 0; // #### end Gilbert 31/10 ######// if( sys.signal_exit_flag ) break; vga_front.lock_buf(); 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. detect(); //--------------------------------// // ###### begin Gilbert 4/11 ######// DWORD markTime = m.get_time(); // a time taken earlier than should_next_frame takes // ###### end Gilbert 4/11 ######// // ##### patch begin Gilbert 17/11 #######// int unreadyPlayerFlag = 0; // ##### patch end Gilbert 17/11 #######// if( config.frame_speed>0 ) // 0-frozen { if( remote.is_enable() ) // && is_sync_frame ) { remote.poll_msg(); m.unlock_seed(); rc = is_mp_sync(&unreadyPlayerFlag); // if all players are synchronized m.lock_seed(); } else rc = should_next_frame(); if( rc ) { LOG_BEGIN; m.unlock_seed(); #ifdef DEBUG if( remote.is_enable() ) { long_log->printf("begin process frame %d\n", frame_count); } #endif process(); if(remote.is_enable() ) m.lock_seed(); // such that random seed is unchanged outside sys::process() LOG_END; // -------- compare objects' crc --------- // // ###### patch begin Gilbert 20/1 ######// if( remote.is_enable() && (remote.sync_test_level & 2) &&(frame_count % (remote.get_process_frame_delay()+3)) == 0) { // cannot compare every frame, as PROCESS_FRAME_DELAY >= 1 crc_store.record_all(); crc_store.send_all(); } // ###### patch end Gilbert 20/1 ######// } } // ###### begin Gilbert 4/11 #######// // ------- display graduately, keep on displaying --------- // if( rc ) { lastDispFrameTime = m.get_time(); // ####### patch begin Gilbert 17/11 ######// // reset firstUnreadyTime firstUnreadyTime = 0; // ####### patch end Gilbert 17/11 ######// } else { // ####### patch begin Gilbert 17/11 ######// // set firstUnreadyTime, begin of a delay if( !firstUnreadyTime ) firstUnreadyTime = m.get_time(); // ####### patch end Gilbert 17/11 ######// if( config.frame_speed == 0 || markTime-lastDispFrameTime >= DWORD(1000/config.frame_speed) #ifdef AMPLUS || zoom_need_redraw || map_need_redraw #endif ) { // on second condition, it should be happened when // in multiplayer, where should_next_frame passed // but is_mp_sync not passed disp_frame(); lastDispFrameTime = markTime; // ####### patch begin Gilbert 17/11 ######// // display player not ready if( firstUnreadyTime && m.get_time() - firstUnreadyTime > 5000 ) { int y = ZOOM_Y1 + 10; int x = ZOOM_X1 + 10; for( int nationRecno = 1; nationRecno <= MAX_NATION; ++nationRecno ) { if( unreadyPlayerFlag & (1 << (nationRecno-1)) ) { if( !nation_array.is_deleted(nationRecno) ) { int x2 = font_news.put( x, y, "Waiting for "); x2 = font_news.put( x2, y, nation_array[nationRecno]->nation_name() ); y += font_news.height() + 5; } } } } // ####### patch end Gilbert 17/11 ######// } } // ###### end Gilbert 4/11 #######// // ----------- detect sond is ended, play another -----------// if( config.frame_speed == 0 || day_frame_count == 0) music.yield(); #ifdef DEBUG if( rc && remote.is_enable() && day_frame_count == 0 ) { if( long_log) delete long_log; if( ++longLogSuffix > 'Z' ) { longLogSuffix = 'A'; } long_log = new LongLog(longLogSuffix); long_log->printf("Game Date : %d/%d/%d\n", info.game_month, info.game_day, info.game_year); } #endif if(rc) { //-*********** syn game test ***********-// //-------------------------------------------------------------// // record random seed for comparison //-------------------------------------------------------------// #ifdef DEBUG if(debug_seed_status_flag==DEBUG_SYN_LOAD_AND_COMPARE_ONCE || debug_seed_status_flag==DEBUG_SYN_AUTO_LOAD) sp_compare_seed(); else if(debug_seed_status_flag==DEBUG_SYN_AUTO_SAVE) sp_record_seed(); #endif //-*********** syn game test ***********-// //------ auto save -------// auto_save(); } //------ detect save game triggered by remote player ------// if( mp_save_flag && mp_save_frame == frame_count ) { mp_clear_request_save(); // clear request first before save game if( nation_array.player_recno ) // only save then the player is still in the game { game_file.save_game( remote.save_file_name ); // ####### begin Gilbert 24/10 ######// //static String str; //str = "The current game has been saved to "; //str += remote.save_file_name; //str += "."; //box.msg( str ); news_array.multi_save_game(); // ####### end Gilbert 24/10 ######// } } vga_front.unlock_buf(); if( sys.signal_exit_flag ) break; } else { WaitMessage(); } } // #### begin Gilbert 23/10 #######// in_game_menu.active_flag = 0; option_menu.active_flag = 0; // #### end Gilbert 23/10 #######// vga_front.lock_buf(); #ifdef DEBUG if(remote.is_enable()) { if(long_log) delete long_log; long_log = NULL; } #endif music.stop(); remote.disable_process_queue(); remote.disable_poll_msg(); mp_clear_request_save(); } //--------- End of function Sys::main_loop --------// //-------- Begin of function Sys::auto_save --------// // void Sys::auto_save() { if( nation_array.player_recno == 0 ) return; //---------- single player auto save ----------// if( !remote.is_enable() && // no auto save in a multiplayer game info.game_month%2==0 && info.game_day==1 && day_frame_count==0) { #ifdef DEBUG2 if(1) #else if( sys.debug_session || sys.testing_session ) #endif { static int saveCount = 0; switch(saveCount) { case 0: game_file.save_game( "AUTO1.SAV" ); break; case 1: game_file.save_game( "AUTO2.SAV" ); break; case 2: game_file.save_game( "AUTO3.SAV" ); break; } if( ++saveCount>3 ) saveCount = 0; } else { //--- rename the existing AUTO.SAV to AUTO2.SAV and save a new game ---// if( m.is_file_exist( "AUTO.SAV" ) ) { if( m.is_file_exist( "AUTO2.SAV" ) ) // if there is already an AUTO2.SAV, delete it remove( "AUTO2.SAV" ); rename( "AUTO.SAV", "AUTO2.SAV" ); } } game_file.save_game( "AUTO.SAV" ); //-*********** syn game test ***********-// #ifdef DEBUG if(debug_seed_status_flag==DEBUG_SYN_AUTO_SAVE) { sp_write_seed(); sp_close_seed_file(); //if(info.game_date-info.game_start_date<=365) if(0) { sp_open_seed_file("nseed.rs"); debug_seed_status_flag = DEBUG_SYN_AUTO_SAVE; // continue recording } else { debug_seed_status_flag = NO_DEBUG_SYN; //sp_load_seed_file(); //SendMessage(main_hwnd, WM_KEYDOWN, 'L', 0); mouse.add_key_event(DIK_BACKSLASH, m.get_time()); // load file for comparison } } //debug_seed_status_flag = 2; //sp_seed_pos_reset(); //sp_record_match_seed(); #endif //-*********** syn game test ***********-// } // --------- multiplayer autosave game --------// // ###### patch begin Gilbert 23/1 #######// if( remote.is_enable() && remote.sync_test_level >= 0 && // disable autosave after un-sync day_frame_count==0 && info.game_day==1 && info.game_month%2==0 ) // ###### patch end Gilbert 23/1 #######// { //--- rename the existing AUTO.SVM to AUTO2.SVM and save a new game ---// if( m.is_file_exist( "AUTO.SVM" ) ) { if( m.is_file_exist( "AUTO2.SVM" ) ) // if there is already an AUTO2.SVM, delete it remove( "AUTO2.SVM" ); rename( "AUTO.SVM", "AUTO2.SVM" ); } game_file.save_game( "AUTO.SVM" ); } } //-------- End of function Sys::auto_save --------// //-------- Begin of function Sys::pause --------// // void Sys::pause() { if( paused_flag ) return; InvalidateRect(main_hwnd, NULL, TRUE); paused_flag = TRUE; } //--------- End of function Sys::pause ---------// //-------- Begin of function Sys::unpause --------// // void Sys::unpause() { if( !paused_flag ) return; // ####### begin Gilbert 3/11 #######// //if( GetForegroundWindow() != main_hwnd ) // return; // ####### end Gilbert 3/11 #######// if( !restore() ) { //-----------------------------------------------------// // we are unable to restore, this can happen when // the screen resolution or bitdepth has changed // we just reload all the art again and re-create // the front and back buffers. this is a little // overkill we could handle a screen res change by // just recreating the front and back buffers we dont // need to redo the art, but this is way easier. //-----------------------------------------------------// if (init_directx()) { if( !restore() ) // if still not successful, quit return; } } // ####### begin Gilbert 31/10 #######// mouse.update_skey_state(); // update ctrl/shift/alt key state after switch task // ####### end Gilbert 31/10 #######// //---- restore the saved screen before killing the focus ----// paused_flag = FALSE; } //--------- End of function Sys::unpause ---------// //-------- Begin of function Sys::restore --------// // int Sys::restore() { if( !vga_front.restore_buf() ) return 0; if( !vga_back.restore_buf() ) return 0; if( sys.debug_session ) { if( !vga_true_front.restore_buf() ) return 0; } // ####### begin Gilbert 16/9 ########// //else // vga_front.lock_buf(); // ####### end Gilbert 16/9 ########// return 1; } //--------- End of function Sys::restore ---------// //-------- Begin of function Sys::yield --------// // void Sys::yield() { static int isYielding=0; if( isYielding ) return; isYielding=1; handle_window_messages(); mouse.poll_event(); audio.yield(); if( remote.is_enable() ) { //yield_wsock_msg(); remote.poll_msg(); remote.process_specific_msg(MSG_SET_SPEED); // need to test it here for restoring the speed from frozen to normal if( config.frame_speed > 0 ) { remote.process_specific_msg(MSG_TELL_SEND_TIME); remote.process_specific_msg(MSG_REQUEST_RESEND); } //-------- display debug info -----------// if( power.enable_flag && (testing_session || debug_session) ) { String str; str = "Player: "; str += nation_array.player_recno; str += "/"; str += nation_array.size(); str += " Send:"; str += remote.packet_send_count; str += " Recv:"; str += remote.packet_receive_count; str += " Frame:"; str += frame_count; font_san.disp( ZOOM_X1, 4, str, ZOOM_X1+300); } } isYielding=0; } //--------- End of function Sys::yield ---------// //-------- Begin of function Sys::yield_wsock_msg --------// // void Sys::yield_wsock_msg() { // MSG msg; //------ only get WinSock messages (WSA_ACCEPT & WSA_READ) ------// // if( PeekMessage(&msg, NULL, WSA_ACCEPT, WSA_READ, PM_NOREMOVE) ) // { // if (!GetMessage( &msg, NULL, WSA_ACCEPT, WSA_READ)) // return; // TranslateMessage(&msg); // DispatchMessage(&msg); //} } //--------- End of function Sys::yield_wsock_msg ---------// //-------- Begin of function Sys::is_mp_sync --------// // // Multiplayer synchronization. // // Check all players are ready to proceed to the next frame. // int Sys::is_mp_sync(int *unreadyPlayerFlag) { #define RESEND_TIME_OUT 2000 // if the other machines still aren't ready after 2 seconds, send the notification again #define RESEND_AGAIN_TIME_OUT 1000 // keep resending if no responses #define CONNECTION_LOST_TIME_OUT 20000 // ask for connection lost handling aftering waiting for 5 seconds. //---- if we haven't been ready for the next frame yet ----// #ifdef DEBUG int n; DEBUG_LOG("begin nation's next_frame_ready"); for (n = 1; n <= nation_array.size(); ++n) { DEBUG_LOG(nation_array[n]->next_frame_ready); } DEBUG_LOG("end nation's next_frame_ready"); #endif // ####### patch begin Gilbert 17/11 ######// if( unreadyPlayerFlag ) *unreadyPlayerFlag = 0; // ####### end begin Gilbert 17/11 ######// // if last remote.send was fail, attempt to send it again if( !nation_array.player_recno ) { // observation mode if( !should_next_frame() ) return 0; remote_send_success_flag = 1; } else if( remote_send_success_flag && remote.has_send_frame(nation_array.player_recno, frame_count) && (~nation_array)->next_frame_ready==0 ) { DEBUG_LOG("Local player not ready"); if( !should_next_frame() ) // not ready to proceed yet return 0; //------------ queue MSG_NEXT_FRAME ----------// short* shortPtr = (short*) remote.new_send_queue_msg(MSG_NEXT_FRAME, sizeof(short)); shortPtr[0] = nation_array.player_recno; // short_para1 is the nation recno of the current player //------------ queue MSG_QUEUE_TRAILER ----------// shortPtr = (short*) remote.new_send_queue_msg(MSG_QUEUE_TRAILER, sizeof(short)); shortPtr[0] = nation_array.player_recno; // short_para1 is the nation recno of the current player //------ copy all queued action to our own receive buffer to merge with other player's action ----// remote.append_send_to_receive(); //--- copy the whole queue to a buffer in case of resend request from other players ---// remote.copy_send_to_backup(); //----------- queue MSG_TELL_SEND_TIME ----------// /* unsigned long* longPtr = (unsigned long*) remote.new_send_queue_msg(MSG_TELL_SEND_TIME, sizeof(unsigned long)); longPtr[0] = m.get_time(); */ //---------- send out all messages in the queue ---------// remote_send_success_flag = remote.send_queue_now(); // if not sent successfully, try again next time if( remote_send_success_flag ) // still failed, try again next time { DEBUG_LOG("first send sucess" ); remote.init_send_queue(frame_count+1, nation_array.player_recno); // frame_count, initialize for next frame's send queue // sent random seed char *p = (char *)remote.new_send_queue_msg(MSG_TELL_RANDOM_SEED, sizeof(short)+sizeof(long)); *(short *)p = nation_array.player_recno; p += sizeof(short); *(long *)p = m.get_random_seed(); } else { // re_transmit as quickly as possible ec_remote.re_transmit(5); } } else { DEBUG_LOG("Local player nation ready"); } //----- if previous sending was not successful, send again now -----// if( !remote_send_success_flag ) { remote_send_success_flag = remote.send_queue_now(); // if not sent successfully, try again next time if( remote_send_success_flag ) // still failed, try again next time { DEBUG_LOG("resending ok"); remote.init_send_queue(frame_count+1, nation_array.player_recno); // frame_count, initialize for next frame's send queue // sent random seed char *p = (char *)remote.new_send_queue_msg(MSG_TELL_RANDOM_SEED, sizeof(short)+sizeof(long)); *(short *)p = nation_array.player_recno; p += sizeof(short); *(long *)p = m.get_random_seed(); } else { // re_transmit as quickly as possible ec_remote.re_transmit(5); DEBUG_LOG("resending not ok"); return 0; } } //------ pre_process MSG_NEXT_FRAME in the queue -----// remote.process_specific_msg(MSG_NEXT_FRAME); #ifdef DEBUG DEBUG_LOG("begin nation's next_frame_ready"); for (n = 1; n <= nation_array.size(); ++n) { DEBUG_LOG(nation_array[n]->next_frame_ready); } DEBUG_LOG("end nation's next_frame_ready"); #endif //------ check if all remote players are ready to proceed -----// int nationRecno; Nation* nationPtr; for( nationRecno=nation_array.size() ; nationRecno>0 ; nationRecno-- ) { if( nation_array.is_deleted(nationRecno) ) continue; nationPtr = nation_array[nationRecno]; //------- if some remote machines are not ready yet -------// // ###### patch begin Gilbert 17/11 ######// if( nationPtr->is_remote() && (remote.has_send_frame(nationRecno, frame_count) && !nationPtr->next_frame_ready) ) { if( unreadyPlayerFlag ) *unreadyPlayerFlag |= ( 1 << (nationRecno-1) ); break; } // ###### end begin Gilbert 17/11 ######// } //------- if some remote machines are not ready yet -------// if( nationRecno>0 ) { DEBUG_LOG("a nation not ready"); DEBUG_LOG(nationRecno); if( m.get_time() >= last_frame_time+RESEND_TIME_OUT ) { //---- if it has been time out for too long, carry out connection lost handling ---// if( // m.get_time() >= last_frame_time+CONNECTION_LOST_TIME_OUT || !ec_remote.is_player_valid(nationRecno)) { DEBUG_LOG( "Connection Lost" ); // ###### begin Gilbert 24/10 ######// // box.msg( "Connection Lost!" ); //**BUGHERE, should have a function to set all units, structures of this nation to AI news_array.multi_connection_lost(nationRecno); // may allow save game here, ask user whether to save the game // ###### end Gilbert 24/10 ######// nationPtr->nation_type = NATION_AI; // let computer take over the nation nation_array.ai_nation_count++; } //------- re-send the message -------// /* re-send is now done by ec_remote else if( m.get_time() >= last_resend_time + RESEND_AGAIN_TIME_OUT ) // resent once per half second { DEBUG_LOG( "send retransmit request" ); RemoteMsg* remoteMsg = remote.new_msg(MSG_REQUEST_RESEND, sizeof(int) + sizeof(DWORD) ); DWORD* dwordPtr = (DWORD*) remoteMsg->data_buf; dwordPtr[0] = (~nation_array)->player_id; // send to us dwordPtr[1] = frame_count; // request it to send us queue of this frame remote.send_free_msg( remoteMsg, nation_array[nationRecno]->player_id ); // send to that nationRecno only last_resend_time = m.get_time(); } */ } return 0; } //--------------------------------------------------------// // // When all players are ready to proceed to the next frame // // As we have already know all players are ready, we can // reset the next_frame_ready flag for all nations. // //--------------------------------------------------------// DEBUG_LOG("all nation ready"); for( int i=nation_array.size() ; i>0 ; i-- ) { if( nation_array.is_deleted(i) ) continue; 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 } //--------- process msgs in the receive queue ----------// remote.process_receive_queue(); #ifdef DEBUG DEBUG_LOG("begin nation's next_frame_ready"); for (n = 1; n <= nation_array.size(); ++n) { DEBUG_LOG(nation_array[n]->next_frame_ready); } DEBUG_LOG("end nation's next_frame_ready"); #endif //-------- record this frame's time -------// last_frame_time = m.get_time(); last_resend_time = 0; return 1; } //---------- End of function Sys::is_mp_sync --------// //-------- Begin of function Sys::should_next_frame --------// // // Check if it's now the time for processing the next frame. // int Sys::should_next_frame() { //----- special modes: 0-frozen, 9-fastest possible -----// if( config.frame_speed==99 ) return 1; if( config.frame_speed==0 ) return 0; //---- check if it's now the time for processing the next frame ----// DWORD curTime = m.get_time(); if( next_frame_time ) // if next_frame_time==0, it's the first frame of the game { if( next_frame_time < 1000 ) // the DWORD variable has been overflow { 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 return 0; } else // normal non-overflow case { if( curTime < next_frame_time ) return 0; } } //--- Time between frames = 1000 milliseconds / frames per second ---// next_frame_time = curTime + 1000 / config.frame_speed; return 1; } //--------- End of function Sys::should_next_frame ---------// //-------- Begin of function Sys::main_win_proc --------// // long Sys::main_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch( message ) { case WM_CREATE: sys.main_hwnd = hWnd; break; case WM_ACTIVATEAPP: // ####### begin Gilbert 3/11 #######// // active_flag = (BOOL)wParam && GetForegroundWindow() == hWnd && !IsIconic(hWnd); active_flag = (BOOL)wParam && !IsIconic(hWnd); // ####### end Gilbert 3/11 #######// //--------------------------------------------------------------// // while we were not-active something bad happened that caused us // to pause, like a surface restore failing or we got a palette // changed, now that we are active try to fix things //--------------------------------------------------------------// if( active_flag ) { unpause(); need_redraw_flag = 1; // for Sys::disp_frame to redraw the screen } else pause(); break; case WM_DESTROY: main_hwnd = NULL; // game.deinit(); // end of game deinit_directx(); PostQuitMessage( 0 ); break; case WM_ERASEBKGND: // do not erase the background return 1; case WM_PALETTECHANGED: // if we changed the palette, do nothing if ((HWND)wParam == hWnd) break; // we can't restore if dd_pal is not initialized if (!vga.dd_pal) break; // if we are temporarily overriding, then we should be okay if (vga.back_up_pal) break; // restore palette vga.dd_pal->SetEntries(0, 0, 256, vga.pal_entry_buf); break; default: break; } return DefWindowProc(hWnd, message, wParam, lParam); } //--------- End of function Sys::main_win_proc ---------// //-------- Begin of function Sys::handle_window_messages --------// void Sys::handle_window_messages() { static int lastTick; int tick = GetTickCount(); if (lastTick == tick) return; lastTick = tick; MSG msg; while (PeekMessage(&msg, sys.main_hwnd, 0, 0, PM_NOREMOVE)) { BOOL r; r = GetMessage(&msg, sys.main_hwnd, 0, 0); if (r == -1) { // not handled return; } TranslateMessage(&msg); DispatchMessage(&msg); } } //-------- End of function Sys::handle_window_messages --------// //-------- Begin of function Sys::process_key --------// // void Sys::process_key(unsigned scanCode, unsigned skeyState) { detect_function_key(scanCode, skeyState); //----- don't detect letter keys when in chat mode ----// if( !(view_mode == MODE_NATION && info.nation_report_mode == NATION_REPORT_CHAT) ) { if( sys.debug_session || sys.testing_session || scenario_cheat_flag ) { detect_cheat_key(scanCode, skeyState); detect_debug_cheat_key(scanCode, skeyState); if( detect_scenario_cheat_key(scanCode, skeyState) ) return; } else { if( nation_array.player_recno && !remote.is_enable() ) // not allowed in multiplayer mode { if( (~nation_array)->cheat_enabled_flag ) { detect_cheat_key(scanCode, skeyState); } else { #ifdef GERMAN if( detect_key_str(1, "!!!###") ) #else if( detect_key_str(1, "!!!@@@###") ) #endif { box.msg( "Cheat Mode Enabled." ); (~nation_array)->cheat_enabled_flag = 1; } } } } detect_letter_key(scanCode, skeyState); detect_set_speed(scanCode, skeyState); // set the speed of the game } } //--------- End of function Sys::process_key ---------// //-------- Begin of function Sys::detect_letter_key --------// // void Sys::detect_letter_key(unsigned scanCode, unsigned skeyState) { int keyCode; if((keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_IS_CTRL))) { int groupId; switch(keyCode) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': groupId = keyCode-'0'; group_select.group_units(groupId); break; } } if((keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_IS_ALT))) { int groupId; switch(keyCode) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': groupId = keyCode-'0'; group_select.select_grouped_units(groupId); break; } } if( (keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_UNIQUE_KEY)) ) { keyCode = m.lower(keyCode); switch(keyCode) { case KEY_ESC: set_view_mode(MODE_NORMAL); break; //---- keys for toggling map mode ----// case 'q': world.map_matrix->toggle_map_mode(0); break; case 'w': world.map_matrix->toggle_map_mode(1); break; case 'e': world.map_matrix->toggle_map_mode(2); break; //--------- opaque report mode --------// case 'p': config.opaque_report = !config.opaque_report; if( config.opaque_report ) box.msg( "Opaque report mode." ); else box.msg( "Transparent report mode." ); break; //------ clear news messages ------// case 'x': news_array.clear_news_disp(); break; //------ jump to a location with natural resource ---// case 'j': site_array.go_to_a_raw_site(); break; //--------- bring up the option menu ----------// case 'o': // ##### begin Gilbert 5/11 #######// // game.in_game_option_menu(); option_menu.enter(!remote.is_enable()); // ##### end Gilbert 5/11 #######// break; //--------- forward/backward tutorial text block --------// case ',': if( game.game_mode == GAME_TUTORIAL ) tutor.prev_text_block(); break; case '.': if( game.game_mode == GAME_TUTORIAL ) tutor.next_text_block(); break; //---- keys for saving and loading game -----// case 's': save_game(); break; case 'l': load_game(); break; case KEY_UP: world.disp_next(-1, 0); // previous same object type of any nation break; case KEY_DOWN: world.disp_next(1, 0); // next same object type of any nation break; case KEY_LEFT: world.disp_next(-1, 1); // prevous same object type of the same nation break; case KEY_RIGHT: world.disp_next(1, 1); // next same object type of the same nation break; //---- key for quick locate -----// case 'k': locate_king_general(RANK_KING); break; case 'g': locate_king_general(RANK_GENERAL); break; case 'y': locate_spy(); break; case 'h': locate_ship(); break; case 'f': locate_camp(); break; } } } //--------- End of function Sys::detect_letter_key ---------// //-------- Begin of function Sys::detect_function_key --------// // void Sys::detect_function_key(unsigned scanCode, unsigned skeyState) { int keyCode; if( (keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_UNIQUE_KEY)) ) { switch(keyCode) { case KEY_ESC: set_view_mode(MODE_NORMAL); break; case KEY_F1: if( view_mode==MODE_NATION ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_NATION); break; case KEY_F2: if( view_mode==MODE_TOWN ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_TOWN); break; case KEY_F3: if( view_mode==MODE_ECONOMY ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_ECONOMY); break; case KEY_F4: if( view_mode==MODE_TRADE ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_TRADE); break; case KEY_F5: if( view_mode==MODE_MILITARY ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_MILITARY); break; case KEY_F6: if( view_mode==MODE_TECH ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_TECH); break; case KEY_F7: if( view_mode==MODE_SPY ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_SPY); break; case KEY_F8: if( view_mode==MODE_RANK ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_RANK); break; case KEY_F9: if( view_mode==MODE_NEWS_LOG ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_NEWS_LOG); break; case KEY_F10: // ##### begin Gilbert 5/11 ######// //game.in_game_menu(); in_game_menu.enter(!remote.is_enable()); // ##### end Gilbert 5/11 ######// break; case KEY_F11: capture_screen(); break; case KEY_F12: capture_minimap(); break; } } } //--------- End of function Sys::detect_function_key ---------// //-------- Begin of function Sys::detect_cheat_key --------// // void Sys::detect_cheat_key(unsigned scanCode, unsigned skeyState) { if( remote.is_enable() ) // no cheat keys in multiplayer games return; int keyCode = mouse.is_key( scanCode, skeyState, (WORD) 0, K_CHAR_KEY ); if( !keyCode ) // since all keys concern are printable return; keyCode = m.lower(keyCode); switch( keyCode ) { //-------- cheat keys ---------// case 'c': // add cash if( nation_array.player_recno ) (~nation_array)->add_cheat((float)1000); break; case '\\': // add food if( nation_array.player_recno ) (~nation_array)->add_food((float)1000); break; case 't': tech_res.inc_all_tech_level(nation_array.player_recno); god_res.enable_know_all(nation_array.player_recno); box.msg( "Your technology has advanced.\nYou can now invoke all Greater Beings." ); break; case 'm': world.unveil(0, 0, MAX_WORLD_X_LOC-1, MAX_WORLD_Y_LOC-1); world.visit(0, 0, MAX_WORLD_X_LOC-1, MAX_WORLD_Y_LOC-1, 0, 0); break; case ';': // increase town population if( town_array.selected_recno ) { Town* townPtr = town_array[town_array.selected_recno]; #ifdef DEBUG2 for(int di=0; dirace_pop_array[di]) { townPtr->init_pop(di+1, 10, 100); break; } } #else townPtr->init_pop( m.random(MAX_RACE)+1, 10, 100 ); #endif townPtr->auto_set_layout(); } break; case 'u': config.king_undie_flag = !config.king_undie_flag; if( config.king_undie_flag ) box.msg( "Your king is now immortal." ); else box.msg( "King immortal mode is now disabled." ); break; case '=': if( firm_array.selected_recno ) { Firm* firmPtr = firm_array[firm_array.selected_recno]; if( firmPtr->firm_id == FIRM_BASE ) { ((FirmBase*)firmPtr)->pray_points = (float) MAX_PRAY_POINTS; info.disp(); } } break; case 'b': // finish building a firm instantly or increase the hit points of a firm to its max if( firm_array.selected_recno ) { Firm* firmPtr = firm_array[firm_array.selected_recno]; firmPtr->hit_points = firmPtr->max_hit_points; } break; case 'z': // toggle fast_build config.fast_build = !config.fast_build; if( !config.fast_build ) box.msg( "Fast build is now disabled" ); else box.msg( "Fast build is now enabled" ); break; //----- increase the combat level -------// case '[': if( unit_array.selected_recno ) { Unit* unitPtr = unit_array[unit_array.selected_recno]; unitPtr->set_combat_level( min(100, unitPtr->skill.combat_level+20) ); } break; //----- increase the skill level of the unit -------// case ']': if( unit_array.selected_recno ) { Unit* unitPtr = unit_array[unit_array.selected_recno]; if( unitPtr->skill.skill_id ) unitPtr->skill.skill_level = min(100, unitPtr->skill.skill_level+20); } break; //----- increase the spying skill -------// case '\'': if( unit_array.selected_recno ) { Unit* unitPtr = unit_array[unit_array.selected_recno]; if( unitPtr->spy_recno ) { Spy* spyPtr = spy_array[unitPtr->spy_recno]; spyPtr->spy_skill = min(100, spyPtr->spy_skill+20); } } break; } } //--------- End of function Sys::detect_cheat_key ---------// //-------- Begin of function Sys::detect_debug_cheat_key --------// // void Sys::detect_debug_cheat_key(unsigned scanCode, unsigned skeyState) { if( remote.is_enable() ) // no cheat keys in multiplayer games return; int keyCode = mouse.is_key( scanCode, skeyState, (WORD) 0, K_UNIQUE_KEY ); if( !keyCode ) // since all keys concern are printable return; keyCode = m.lower(keyCode); switch( keyCode ) { /* case 'j': // allow all nations to have all god creatures for( i=1; i<=nation_array.size() ; i++ ) { if( !nation_array.is_deleted(i) ) god_res.enable_know_all(i); } box.msg( "Now knowledge of seat of power is available to all nations." ); break; */ case 'n': config.blacken_map = !config.blacken_map; config.fog_of_war = config.blacken_map; break; case 'r': // set default report nation if( firm_array.selected_recno ) { info.default_viewing_nation_recno = firm_array[firm_array.selected_recno]->nation_recno; } else if( town_array.selected_recno ) { int nationRecno = town_array[town_array.selected_recno]->nation_recno; if( nationRecno ) info.default_viewing_nation_recno = nationRecno; } else if( unit_array.selected_recno ) { int nationRecno = unit_array[unit_array.selected_recno]->nation_recno; if( nationRecno ) info.default_viewing_nation_recno = nationRecno; } break; case 'a': if( view_mode==MODE_AI_ACTION ) set_view_mode(MODE_NORMAL); else set_view_mode(MODE_AI_ACTION); break; //-----------------------------------// /* case 't': // next town layout if( town_array.selected_recno ) town_array[town_array.selected_recno]->auto_set_layout(); break; */ //-------------------------------// case 'i': config.disable_ai_flag = !config.disable_ai_flag; if( config.disable_ai_flag ) box.msg( "AI is now disabled" ); else box.msg( "AI is now enabled" ); break; case 'd': config.show_ai_info = !config.show_ai_info; info.disp(); if( config.show_ai_info ) box.msg( "Now AI info will be displayed." ); else box.msg( "Now AI info will not be displayed." ); break; case '/': config.show_all_unit_icon = !config.show_all_unit_icon; if( config.show_all_unit_icon ) box.msg( "Now all unit icons will be displayed." ); else box.msg( "Now all unit icons will not be displayed." ); break; #ifdef DEBUG case '~': sys.testing_session = !sys.testing_session; if( sys.testing_session ) box.msg( "sys.testing_session is now 1." ); else box.msg( "sys.testing_session is now 0." ); break; case '\r': if(debug2_enable_flag) debug2_enable_flag = 0; else debug2_enable_flag = 1; break; /* //-*********** syn game test ***********-// case '\'': //if(debug2_enable_flag && debug_sim_game_type) //game_file_array[0]->load_game("syn.sav"); game_file.load_game("syn.sav"); sp_load_seed_file(); debug_seed_status_flag = DEBUG_SYN_AUTO_LOAD; break; case '[': if(m.is_file_exist("SYN.SYS")) { debug_seed_status_flag = DEBUG_SYN_AUTO_SAVE; sp_seed_pos_reset(); sp_record_match_seed(); sp_create_seed_file("nseed.rs"); game_file.save_game("syn.sav"); } break; case ']': if(debug_seed_status_flag==NO_DEBUG_SYN) { if(m.is_file_exist("SYN.SYS")) { debug_seed_status_flag = DEBUG_SYN_LOAD_AND_COMPARE_ONCE; game_file.load_game("syn.sav"); sp_load_seed_file(); } else debug_seed_status_flag = NO_DEBUG_SYN; } break; */ //-*********** syn game test ***********-// #endif } } //--------- End of function Sys::detect_debug_cheat_key ---------// //-------- Start of function detect_scenario_cheat_key -------------// static int detect_scenario_cheat_key(unsigned scanCode, unsigned skeyState) { if( remote.is_enable() ) // no cheat keys in multiplayer games return 0; int keyCode = mouse.is_key(scanCode, skeyState, (WORD) 0, K_IS_CTRL); if( !keyCode ) return 0; //------------------------------------------// int keyProcessed = 0; Firm *firmPtr; Unit *unitPtr; Town *townPtr; Nation *nationPtr; Site *sitePtr; Spy *spyPtr; Location *locPtr; int i, j, curXLoc, curYLoc; switch(keyCode) { case 'p': //-------- get scroll of power for the race of selected unit --------// if(unit_array.selected_recno) { unitPtr = unit_array[unit_array.selected_recno]; if(unitPtr->nation_recno==nation_array.player_recno && unitPtr->race_id) { god_res[unitPtr->race_id]->enable_know(unitPtr->nation_recno); //box.msg( "Get Scroll of Power of selected unit for his race" ); keyProcessed++; } } keyProcessed++; break; case 't': //-------- get all technology except scrolls of power -------// tech_res.inc_all_tech_level(nation_array.player_recno); //box.msg( "Your technology has advanced." ); keyProcessed++; break; case 'g': //------- get galleon and cannon technologies -------// err_when(tech_res[4]->unit_id != UNIT_CANNON); err_when(tech_res[7]->unit_id != UNIT_GALLEON); i = tech_res[4]->get_nation_tech_level(nation_array.player_recno); if(i < tech_res[4]->max_tech_level) tech_res[4]->set_nation_tech_level(nation_array.player_recno, i+1); i = tech_res[7]->get_nation_tech_level(nation_array.player_recno); if(i < tech_res[7]->max_tech_level) tech_res[7]->set_nation_tech_level(nation_array.player_recno, i+1); //box.msg( "Get technologies of Galleon and Cannon." ); keyProcessed++; break; case 'q': //-- decrease population of a selected race in a selected village by 10 --// if(town_array.selected_recno) { townPtr = town_array[town_array.selected_recno]; if(townPtr->nation_recno == nation_array.player_recno) { i = townPtr->get_selected_race(); if(i && townPtr->race_pop_array[i-1]) { for(j=10; j>0 && !town_array.is_deleted(townPtr->town_recno); --j) townPtr->kill_town_people(i); //box.msg( "Population decrease by 10." ); keyProcessed++; } townPtr->auto_set_layout(); } } keyProcessed++; break; case 'w': //-- increase population of a selected race in a selected village by 10 --// if(town_array.selected_recno) { townPtr = town_array[town_array.selected_recno]; if(townPtr->nation_recno == nation_array.player_recno) { i = townPtr->get_selected_race(); if(i && townPtr->race_pop_array[i-1]) { townPtr->init_pop(i, 10, 100); //box.msg( "Population increase by 10." ); keyProcessed++; } townPtr->auto_set_layout(); } } keyProcessed++; break; case 'e': //-------- decrease the reputation by 10 -----------// nationPtr = nation_array[nation_array.player_recno]; nationPtr->reputation -= 10; if(nationPtr->reputation < -100) nationPtr->reputation = (float) -100; //box.msg( "Reputation decrease by 10." ); keyProcessed++; break; case 'r': //-------- increase the reputation by 10 -----------// nationPtr = nation_array[nation_array.player_recno]; nationPtr->reputation += 10; if(nationPtr->reputation > 100) nationPtr->reputation = (float) 100; //box.msg( "Reputation increase by 10." ); keyProcessed++; break; case 'j': //--------- damage a building by 20 pt -----------// if(firm_array.selected_recno) { firmPtr = firm_array[firm_array.selected_recno]; if(firmPtr->nation_recno==nation_array.player_recno) { firmPtr->hit_points -= 20; if(firmPtr->hit_points < 1) firmPtr->hit_points = (float) 1; //box.msg( "damage firm by 20 points." ); keyProcessed++; } } keyProcessed++; break; case 'k': //--------- repair a building by 20 pt -----------// if(firm_array.selected_recno) { firmPtr = firm_array[firm_array.selected_recno]; if(firmPtr->nation_recno==nation_array.player_recno) { firmPtr->hit_points += 20; if(firmPtr->hit_points > firmPtr->max_hit_points) firmPtr->hit_points = firmPtr->max_hit_points; //box.msg( "Repair firm by 20 points." ); keyProcessed++; } } keyProcessed++; break; case 'x': //------ decrease cash by 1000 --------// nationPtr = nation_array[nation_array.player_recno]; nationPtr->cash -= 1000; if(nationPtr->cash < 0) nationPtr->cash = (float) 0; //box.msg( "Decrease cash by 1000." ); keyProcessed++; break; case 'c': //------ decrease food by 1000 --------// nationPtr = nation_array[nation_array.player_recno]; nationPtr->food -= 1000; if(nationPtr->food < 0) nationPtr->food = (float) 0; //box.msg( "Decrease food by 1000." ); keyProcessed++; break; case 'm': //----- add natural resource to cursor pos / remove existing resource ------// if(get_mouse_loc_in_zoom_map(curXLoc, curYLoc)) { locPtr = world.get_loc(curXLoc, curYLoc); if(locPtr->has_site()) // remove site { i = locPtr->site_recno(); sitePtr = site_array[i]; if(!sitePtr->has_mine) { site_array.del_site(i); //box.msg( "Site deleted." ); keyProcessed++; } } else if(locPtr->can_build_site(1) && !locPtr->is_power_off()) // add site { i = MAX_RAW_RESERVE_QTY * (50 + m.random(50)) / 100; site_array.add_site(curXLoc, curYLoc, SITE_RAW, m.random(MAX_RAW)+1, i); //box.msg( "Site added." ); keyProcessed++; } } keyProcessed++; break; case 'b': //------------ add reserve of natural resource by 100 ----------// if(get_mouse_loc_in_zoom_map(curXLoc, curYLoc)) { locPtr = world.get_loc(curXLoc, curYLoc); if(locPtr->has_site()) { i = locPtr->site_recno(); sitePtr = site_array[i]; if(!sitePtr->has_mine) { sitePtr->reserve_qty += 100; //box.msg( "increase reserve by 100." ); keyProcessed++; info.disp(); } } } keyProcessed++; break; case 'v': //------------ reduce reserve of natural resource by 100 ----------// if(get_mouse_loc_in_zoom_map(curXLoc, curYLoc)) { locPtr = world.get_loc(curXLoc, curYLoc); if(locPtr->has_site()) { i = locPtr->site_recno(); sitePtr = site_array[i]; if(!sitePtr->has_mine && sitePtr->reserve_qty>100) { sitePtr->reserve_qty -= 100; //box.msg( "reduce reserve by 100." ); keyProcessed++; info.disp(); } } } keyProcessed++; break; case 'h': //-------- hide map except for areas around your village, people --------// if( config.explore_whole_map ) // no action if the setting of the map is explored break; vga_back.bar(MAP_X1, MAP_Y1, MAP_X2, MAP_Y2, UNEXPLORED_COLOR); for(j=0; jexplored_off(); } for(i=town_array.size(); i>0; --i) { if(town_array.is_deleted(i)) continue; townPtr = town_array[i]; if(townPtr->nation_recno == nation_array.player_recno) world.unveil(townPtr->loc_x1, townPtr->loc_y1, townPtr->loc_x2, townPtr->loc_y2); } for(i=firm_array.size(); i>0; --i) { if(firm_array.is_deleted(i)) continue; firmPtr = firm_array[i]; if(firmPtr->nation_recno == nation_array.player_recno) world.unveil(firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->loc_x2, firmPtr->loc_y2); } for(i=unit_array.size(); i>0; --i) { if(unit_array.is_deleted(i)) continue; unitPtr = unit_array[i]; if(unitPtr->nation_recno == nation_array.player_recno) world.unveil(unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->next_x_loc(), unitPtr->next_y_loc()); } for(i=spy_array.size(); i>0; --i) { if(spy_array.is_deleted(i)) continue; spyPtr = spy_array[i]; if(spyPtr->true_nation_recno!=nation_array.player_recno) continue; if(spyPtr->spy_place == SPY_FIRM) { if(!firm_array.is_deleted(spyPtr->spy_place_para)) { firmPtr = firm_array[spyPtr->spy_place_para]; world.unveil(firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->loc_x2, firmPtr->loc_y2); } } else if(spyPtr->spy_place == SPY_TOWN) { if(!town_array.is_deleted(spyPtr->spy_place_para)) { townPtr = town_array[spyPtr->spy_place_para]; world.unveil(townPtr->loc_x1, townPtr->loc_y1, townPtr->loc_x2, townPtr->loc_y2); } } } for(i=2; i<=nation_array.size(); ++i) // assume player_nation_recno = 1 { if( nation_array.is_deleted(i) ) continue; (~nation_array)->init_relation(i); nation_array[i]->init_relation(1); } keyProcessed++; break; case 'z': //------------ put the selected unit to the cursor position ------------// if(unit_array.selected_recno) { unitPtr = unit_array[unit_array.selected_recno]; if(get_mouse_loc_in_zoom_map(curXLoc, curYLoc)) { if(unitPtr->mobile_type!=UNIT_LAND) { curXLoc = (curXLoc/2) * 2; curYLoc = (curYLoc/2) * 2; } locPtr = world.get_loc(curXLoc, curYLoc); if(locPtr->can_move(unitPtr->mobile_type)) { world.set_unit_recno(unitPtr->next_x_loc(), unitPtr->next_y_loc(), unitPtr->mobile_type, 0); unitPtr->stop2(); unitPtr->next_x = curXLoc << ZOOM_X_SHIFT_COUNT; unitPtr->next_y = curYLoc << ZOOM_Y_SHIFT_COUNT; unitPtr->cur_x = unitPtr->go_x = unitPtr->next_x; unitPtr->cur_y = unitPtr->go_y = unitPtr->next_y; unitPtr->move_to_x_loc = curXLoc; unitPtr->move_to_y_loc = curYLoc; world.set_unit_recno(curXLoc, curYLoc, unitPtr->mobile_type, unitPtr->sprite_recno); //box.msg( "move unit." ); keyProcessed++; } } } keyProcessed++; break; case 's': if( info.default_viewing_nation_recno && nation_array.player_recno && nation_array[info.default_viewing_nation_recno]->is_ai() ) { nation_array[info.default_viewing_nation_recno]->surrender(nation_array.player_recno); } keyProcessed++; break; } return keyProcessed; } //--------- End of function detect_scenario_cheat_key ---------------// //-------- Begin of function Sys::detect_set_speed --------// // int Sys::detect_set_speed(unsigned scanCode, unsigned skeyState) { int keyCode = mouse.is_key( scanCode, skeyState, (WORD) 0, K_CHAR_KEY ); if( !keyCode ) // since all keys concern are printable return 0; //------- determine the speed to set of the key pressed -------// if( keyCode >= '0' && keyCode <= '8' ) { set_speed( (keyCode-'0') * 3 ); return 1; } else if( keyCode == '9' ) { set_speed( 99 ); // highest possible speed return 1; } return 0; } //--------- End of function Sys::detect_set_speed ---------// //--------- Begin of function Sys::detect_key_str --------// // // Detect for continous input of a string from the keyboard // // keyStrId = the id. of the key string // each id has its individual key_str_pos // keyStr = the string to detect // // return : 1 - complete string detected // 0 - not detected // int Sys::detect_key_str(int keyStrId, char* keyStr) { err_when( keyStrId < 0 || keyStrId >= MAX_KEY_STR ); unsigned char* keyStr2 = (unsigned char*) keyStr; if( mouse.key_code == keyStr2[key_str_pos[keyStrId]] ) key_str_pos[keyStrId]++; else key_str_pos[keyStrId]=0; // when one key unmatched, reset the counter if( key_str_pos[keyStrId] >= (int) strlen(keyStr) ) { key_str_pos[keyStrId]=0; // the full string has been entered successfully without any mistakes return 1; } else return 0; } //----------- End of function Sys::detect_key_str --------// //-------- Begin of function Sys::set_speed --------// // void Sys::set_speed(int frameSpeed, int remoteCall) { //--------- if multiplayer, update remote players setting -------// if( remote.is_enable() && !remoteCall ) { RemoteMsg *remoteMsg = remote.new_msg(MSG_SET_SPEED, sizeof(short)); *((short*)remoteMsg->data_buf) = frameSpeed; remote.send_free_msg( remoteMsg ); // send out the message and free it after finishing sending } //---------- set the speed now ----------// if( config.frame_speed==0 ) // if it's currently frozen, set last_frame_time to avoid incorrect timeout last_frame_time = m.get_time(); config.frame_speed = frameSpeed; } //--------- End of function Sys::set_speed ---------// //-------- Begin of function Sys::capture_screen --------// // void Sys::capture_screen() { String str; int i; for (i = 0; i <= 999; i++) { str = m.format(info.random_seed, 1); str += "_"; if (i < 100) str += "0"; if (i < 10) str += "0"; str += i; str += ".BMP"; if( !m.is_file_exist(str) ) break; } if (i > 999) // all file names from DWORLD000 to DWORLD999 have been occupied return; if( sys.debug_session ) // in debug session, the buffer is not locked, we need to lock it for capturing the screen { vga_true_front.lock_buf(); vga_true_front.write_bmp_file(str); vga_true_front.unlock_buf(); } else { vga_front.write_bmp_file(str); } //------ display msg --------// String str2; #if(defined(SPANISH)) str2 = "Pantalla actual guardada en el archivo "; str2 += str; str2 += "."; #elif(defined(FRENCH)) str2 = "Cet écran a été sauvegardé dans le fichier "; str2 += str; str2 += "."; #else str2 = "The current screen has been written to file "; str2 += str; str2 += "."; #endif box.msg( str2 ); } //--------- End of function Sys::capture_screen ---------// //-------- Begin of function Sys::capture_minimap --------// // void Sys::capture_minimap() { String str; int i; for (i = 0; i <= 999; i++) { str = m.format(info.random_seed, 1); str += "_"; if (i < 100) str += "0"; if (i < 10) str += "0"; str += i; str += ".BMP"; if( !m.is_file_exist(str) ) break; } if (i > 999) // all file names from DWORLD000 to DWORLD999 have been occupied return; if( sys.debug_session ) // in debug session, the buffer is not locked, we need to lock it for capturing the screen { vga_true_front.lock_buf(); vga_true_front.write_bmp_file(str, 588, 56, 200, 200); vga_true_front.unlock_buf(); } else { vga_front.write_bmp_file(str, 588, 56, 200, 200); } //------ display msg --------// String str2; str2 = "The current minimap has been written to file "; str2 += str; str2 += "."; box.msg( str2 ); } //--------- End of function Sys::capture_minimap ---------// //--------- Begin of static function static_main_win_proc --------// // // Callback for all Windows messages // static long FAR PASCAL static_main_win_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return sys.main_win_proc(hWnd, message, wParam, lParam); } //--------- End of static function static_main_win_proc --------// //-------- Begin of function Sys::load_game --------// // void Sys::load_game() { //--- load game not enabled in multiplayer game ---// if( remote.is_enable() ) return; signal_exit_flag=1; // for deinit functions to recognize that this is an end game deinitialization instead of a normal deinitialization int rc=0; game_file_array.init("*.SAV"); // reload any save game file game_file_array.menu(-2); // save screen area to back buffer switch( game_file_array.menu(2) ) { case 1: rc = 1; // fall through to case 0 case 0: signal_exit_flag = 0; break; // case -1 and otherwise, left sys.signal_exit_flag 1 to exit the game } game_file_array.menu(-1); // restore screen area from back buffer //-----------------------------------// if( rc == -1) { box.msg( "Fail Loading Game" ); return; } if( rc ) // if rc==0, leave signal_exit_flag 1, which the game will then quit { need_redraw_flag = 1; disp_frame(); // #### begin Gilbert 22/10 ######// disp_view_mode(); // #### end Gilbert 22/10 ######// box.msg( "Game Loaded Successfully" ); signal_exit_flag=0; info.disp(); } } //--------- End of function Sys::load_game ---------// //-------- Begin of function Sys::save_game --------// // void Sys::save_game() { if( nation_array.player_recno==0 ) // cannot save game when the player's kingdom has been destroyed return; if( remote.is_enable() ) { DWORD *dwordPtr = (DWORD *)remote.new_send_queue_msg( MSG_REQUEST_SAVE, sizeof(DWORD) ); *dwordPtr = remote.next_send_frame(nation_array.player_recno, sys.frame_count+remote.process_frame_delay)+2; return; } game_file_array.init("*.SAV"); // reload any save game file game_file_array.menu(-2); // save screen area to back buffer if( game_file_array.menu(1) == 1 ) { if( GameFile::last_read_success_flag ) box.msg( "Game Saved Successfully" ); } game_file_array.menu(-1); // restore screen area from back buffer // ##### patch begin Gilbert 16/3 #######// info.disp(); // ##### patch end Gilbert 16/3 #######// } //-------- End of function Sys::save_game --------// // --------- begin of function Sys::mp_request_save ----------// void Sys::mp_request_save(DWORD frame) { if( !mp_save_flag ) { mp_save_flag = 1; mp_save_frame = frame; } } // --------- end of function Sys::mp_request_save ----------// // --------- begin of function Sys::mp_clear_request_save ----------// void Sys::mp_clear_request_save() { mp_save_flag = 0; mp_save_frame = 0; } // --------- end of function Sys::mp_clear_request_save ----------// //-------- Begin of function Sys::set_game_dir ----------// // // Set all game directories. // void Sys::set_game_dir() { //------- If it should run from the CDROM ------// get_cdrom_drive(); set_one_dir( "IMAGE\\HALLFAME.ICN" , "IMAGE\\", dir_image ); set_one_dir( "ENCYC\\SEAT\\NORMAN.ICN", "ENCYC\\", dir_encyc ); #ifdef AMPLUS set_one_dir( "ENCYC2\\SEAT\\EGYPTIAN.ICN", "ENCYC2\\", dir_encyc2 ); #endif set_one_dir( "MOVIE\\INTRO.AVI" , "MOVIE\\", dir_movie ); #ifdef DEMO set_one_dir( "MUSIC\\DEMO.WAV" , "MUSIC\\", dir_music ); set_one_dir( "TUTORIAL\\STANDARD.TUT" , "TUTORIAL\\", dir_tutorial ); set_one_dir( "SCENARIO\\DEMO.SCN" , "SCENARIO\\", dir_scenario ); #else set_one_dir( "MUSIC\\NORMAN.WAV" , "MUSIC\\", dir_music ); set_one_dir( "TUTORIAL\\1BAS_MIL.TUT" , "TUTORIAL\\", dir_tutorial ); set_one_dir( "SCENARIO\\7FOR7.SCN" , "SCENARIO\\", dir_scenario ); #endif #if(MAX_SCENARIO_PATH >= 2) set_one_dir( "SCENARI2\\SCN_01.SCN" , "SCENARI2\\", dir_scenario_path[1] ); #endif //-------- set game version ---------// #ifdef BETA game_version = VERSION_FULL; #else #ifdef DEMO game_version = VERSION_DEMO; #else if( 1 ) // no longer checkcd if( cdrom_drive ) game_version = VERSION_FULL; // single player game is not available when game_version == VERSION_FULL else game_version = VERSION_MULTIPLAYER_ONLY; #endif #endif } //----------- End of function Sys::set_game_dir ----------// //-------- Begin of function Sys::set_one_dir ----------// // int Sys::set_one_dir( char* checkFileName, char* defaultDir, char* trueDir ) { if( m.is_file_exist( checkFileName ) ) { strcpy( trueDir, defaultDir ); } else { if( cdrom_drive ) { strcpy( trueDir, "D:\\" ); strcat( trueDir, defaultDir ); trueDir[0] = cdrom_drive; } else { strcpy( trueDir, "" ); return 0; } } return 1; } //----------- End of function Sys::set_one_dir ----------// //-------- Start of function Sys::get_cdrom_drive -------------// // // Get the drive letter of the CDROM and restore the result in cdrom_drive. // void Sys::get_cdrom_drive() { unsigned char i; char driveStr[4]; static char checkFileName[30] = "D:\\7K.EXE"; // check this file to identify the disc cdrom_drive = 0; driveStr[1] = ':'; driveStr[2] = '\\'; driveStr[3] = 0; // ##### patch begin Gilbert 14/10 ######// for(i='C'; i<='Z'; i++) // ##### patch end Gilbert 14/10 ######// { checkFileName[0] = i; driveStr[0] = i; if(GetDriveType(driveStr) == DRIVE_CDROM) { if( m.is_file_exist(checkFileName) ) { cdrom_drive = i; break; } } } } //--------- End of function Sys::get_cdrom_drive ---------------// //-------- Start of function locate_king_general -------------// // static void locate_king_general(int rankId) { if( !nation_array.player_recno ) return; int unitRecno = 0; if(unit_array.selected_recno) unitRecno = unit_array.selected_recno; else if(rankId!=RANK_KING && firm_array.selected_recno) { Firm *firmPtr = firm_array[firm_array.selected_recno]; if((firmPtr->firm_id==FIRM_CAMP || firmPtr->firm_id==FIRM_BASE) && firmPtr->overseer_recno) unitRecno = firmPtr->overseer_recno; } for( int i=unit_array.size() ; i>0 ; i-- ) { if( ++unitRecno > unit_array.size() ) unitRecno = 1; if( unit_array.is_deleted(unitRecno) ) continue; Unit* unitPtr = unit_array[unitRecno]; if( unitPtr->nation_recno == nation_array.player_recno && unitPtr->rank_id == rankId ) { short xLoc, yLoc; if( unitPtr->get_cur_loc(xLoc, yLoc) ) { world.go_loc(xLoc, yLoc, 1); return; } } } } //--------- End of function locate_king_general ---------------// //-------- Start of function locate_spy -------------// // static void locate_spy() { if( !nation_array.player_recno ) return; int unitRecno = unit_array.selected_recno; for( int i=unit_array.size() ; i>0 ; i-- ) { if( ++unitRecno > unit_array.size() ) unitRecno = 1; if( unit_array.is_deleted(unitRecno) ) continue; Unit* unitPtr = unit_array[unitRecno]; if( unitPtr->true_nation_recno() == nation_array.player_recno && unitPtr->spy_recno && unitPtr->is_visible() ) { short xLoc, yLoc; if( unitPtr->get_cur_loc(xLoc, yLoc) ) { world.go_loc(xLoc, yLoc, 1); return; } } } } //--------- End of function locate_spy ---------------// //-------- Start of function locate_ship -------------// // static void locate_ship() { if( !nation_array.player_recno ) return; //----------------------------------------------------------------------------// // The order is // 1) visible ships by their sprite_recno in ascending order // 2) FirmHarbors with ships (num of ships >= 1) by their firm_recno in ascending // order // // Start the scaning in one of the following cases // 1) a unit is selected // 2) a firm is selected // 3) neither unit or firm is selected //----------------------------------------------------------------------------// if(firm_array.selected_recno) { if(!locate_ship_in_harbor()) // harbor first, then unit locate_visible_ship(); } else // if(unit_array.selected_recno) or neither of them is selected { if(!locate_visible_ship()) // unit first, then harbor locate_ship_in_harbor(); } } //--------- End of function locate_ship ---------------// //-------- Start of function locate_ship_in_harbor -------------// // return 1 if found // return 0 otherwise // static int locate_ship_in_harbor() { int firmRecno = firm_array.selected_recno; int checkSize = firm_array.size(); if(firmRecno) checkSize--; // not include the selected firm for( int i=checkSize ; i>0 ; i-- ) { if( ++firmRecno > firm_array.size() ) firmRecno = 1; if( firm_array.is_deleted(firmRecno) ) continue; Firm* firmPtr = firm_array[firmRecno]; if(firmPtr->firm_id!=FIRM_HARBOR || firmPtr->nation_recno != nation_array.player_recno) continue; if(((FirmHarbor*)firmPtr)->ship_count==0) continue; // not interested world.go_loc(firmPtr->center_x, firmPtr->center_y, 1); return 1; } return 0; } //--------- End of function locate_ship_in_harbor ---------------// //-------- Start of function locate_visible_ship -------------// // return 1 if found // return 0 otherwise // static int locate_visible_ship() { int unitRecno = unit_array.selected_recno; int checkSize = unit_array.size(); if(unitRecno) checkSize--; // not include the selected unit for( int i=checkSize ; i>0 ; i-- ) { if( ++unitRecno > unit_array.size() ) unitRecno = 1; if( unit_array.is_deleted(unitRecno) ) continue; Unit* unitPtr = unit_array[unitRecno]; if(!unitPtr->is_visible()) // skip the case unit_mode==UNIT_MODE_IN_HARBOR in calling Unit::get_cur_loc() continue; if( unitPtr->nation_recno == nation_array.player_recno && unit_res[unitPtr->unit_id]->unit_class == UNIT_CLASS_SHIP ) { short xLoc, yLoc; if( unitPtr->get_cur_loc(xLoc, yLoc) ) { world.go_loc(xLoc, yLoc, 1); return 1; } } } return 0; } //--------- End of function locate_visible_ship ---------------// //-------- Start of function locate_camp -------------// // static void locate_camp() { if( !nation_array.player_recno ) return; int firmRecno = firm_array.selected_recno; for( int i=firm_array.size() ; i>0 ; i-- ) { if( ++firmRecno > firm_array.size() ) firmRecno = 1; if( firm_array.is_deleted(firmRecno) ) continue; Firm* firmPtr = firm_array[firmRecno]; if( firmPtr->nation_recno == nation_array.player_recno && firmPtr->firm_id == FIRM_CAMP ) { world.go_loc(firmPtr->center_x, firmPtr->center_y, 1); return; } } } //--------- End of function locate_camp ---------------// //-------- Start of function get_mouse_loc_in_zoom_map -------------// static int get_mouse_loc_in_zoom_map(int &x, int &y) { int mouseX = mouse.cur_x; int mouseY = mouse.cur_y; if(mouseX >= ZOOM_X1 && mouseX <= ZOOM_X2 && mouseY >= ZOOM_Y1 && mouseY <= ZOOM_Y2) { x = world.zoom_matrix->top_x_loc + (mouseX-ZOOM_X1)/ZOOM_LOC_WIDTH; y = world.zoom_matrix->top_y_loc + (mouseY-ZOOM_Y1)/ZOOM_LOC_HEIGHT; return 1; } return 0; // out of zoom map boundary } //--------- End of function get_mouse_loc_in_zoom_map ---------------//