/* * 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 : OTOWNIF.CPP //Description : Town interface routines #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //------------- Define coordinations -----------// enum { RACE_BROWSE_X1 = INFO_X1, RACE_BROWSE_Y1 = INFO_Y1+48, RACE_BROWSE_X2 = INFO_X2, RACE_BROWSE_Y2 = RACE_BROWSE_Y1+130, }; enum { BUTTON_X1 = INFO_X1, BUTTON_Y1 = RACE_BROWSE_Y2+28, BUTTON_X2 = INFO_X2, BUTTON_Y2 = BUTTON_Y1+50, }; //---------- Define constant ------------// enum { TOWN_MENU_MAIN, TOWN_MENU_TRAIN, TOWN_MENU_SPY, TOWN_MENU_VIEW_SECRET, TOWN_MENU_SET_AUTO_COLLECT_TAX, TOWN_MENU_SET_AUTO_GRANT, }; #define BUTTON_LOYALTY_COUNT 8 #define COUNT_BUTTON_OFFSET_X 165 #define COUNT_BUTTON_OFFSET_Y 5 #define COUNT_BUTTON_WIDTH 32 #define COUNT_BUTTON_HEIGHT 32 //----------- Define static variables ----------// static VBrowseIF browse_race, browse_spy; static Button3D button_recruit, button_train, button_tax, button_grant; static Button3D button_spy, button_cancel, button_spy_mobilize, button_spy_reward, button_spy_action, button_spy_view_secret; static Button3D button_cancel_training; static ButtonCustom button_cancel3; static Button button_loyalty_array[BUTTON_LOYALTY_COUNT]; static Button button_loyalty_disabled; static Button button_cancel2; static ButtonCustom button_skill[MAX_TRAINABLE_SKILL]; static ButtonCustom button_queue_skill[MAX_TRAINABLE_SKILL]; static short browse_race_recno=1, browse_race_town_recno=0; // the town which the browse_race displays its info static short recruit_race_count; static short spy_count; static short last_town_recno=0, last_rebel_recno=0; static char last_has_linked_own_camp; static char town_menu_mode=TOWN_MENU_MAIN; static char disable_refresh=0; static short action_spy_recno; // recno of the spy that is doing the bribing or viewing secret reports of other nations //-------- Define static class member var ------// short Town::if_town_recno = 0; //----------- Define static functions ----------// static int race_filter(int recNo=0); static int spy_filter(int recNo=0); static void put_race_rec(int recNo, int x, int y, int refreshFlag); static void put_spy_rec(int recNo, int x, int y, int refreshFlag); // ###### begin Gilbert 12/9 ########// static void i_disp_skill_button(ButtonCustom *button, int); static void i_disp_queue_skill_button(ButtonCustom *button, int); // ###### end Gilbert 12/9 ########// //--------- Begin of function Town::disp_info ---------// // void Town::disp_info(int refreshFlag) { if_town_recno = town_recno; if( town_recno != last_town_recno || (refreshFlag==INFO_REPAINT && !disable_refresh) ) { if( town_recno != last_town_recno ) browse_race_recno = 1; town_menu_mode = TOWN_MENU_MAIN; last_town_recno = town_recno; } //-----------------------------------------// int needRepaint=0; if( last_rebel_recno != rebel_recno ) { last_rebel_recno = rebel_recno; needRepaint = 1; } if( last_has_linked_own_camp != has_linked_own_camp ) { last_has_linked_own_camp = has_linked_own_camp; needRepaint = 1; } if( needRepaint && refreshFlag == INFO_UPDATE ) { info.disp(); return; } //-----------------------------------// switch( town_menu_mode ) { case TOWN_MENU_MAIN: disp_main_menu(refreshFlag); break; case TOWN_MENU_TRAIN: disp_train_menu(refreshFlag); break; case TOWN_MENU_SPY: disp_spy_menu(refreshFlag); break; case TOWN_MENU_VIEW_SECRET: spy_array.disp_view_secret_menu(action_spy_recno, refreshFlag); break; case TOWN_MENU_SET_AUTO_COLLECT_TAX: if( refreshFlag == INFO_REPAINT ) disp_auto_menu(1); break; case TOWN_MENU_SET_AUTO_GRANT: if( refreshFlag == INFO_REPAINT ) disp_auto_menu(0); break; } } //----------- End of function Town::disp_info -----------// //--------- Begin of function Town::detect_info ---------// // void Town::detect_info() { if_town_recno = town_recno; switch( town_menu_mode ) { case TOWN_MENU_MAIN: detect_main_menu(); break; case TOWN_MENU_TRAIN: detect_train_menu(); break; case TOWN_MENU_SPY: detect_spy_menu(); break; case TOWN_MENU_VIEW_SECRET: if( spy_array.detect_view_secret_menu(action_spy_recno, nation_recno) ) { town_menu_mode = TOWN_MENU_MAIN; info.disp(); } break; case TOWN_MENU_SET_AUTO_COLLECT_TAX: detect_auto_menu(1); break; case TOWN_MENU_SET_AUTO_GRANT: detect_auto_menu(0); break; } } //----------- End of function Town::detect_info -----------// //--------- Begin of function Town::disp_main_menu ---------// // void Town::disp_main_menu(int refreshFlag) { static short lastTownNationRecno; //--- if the town's owner nation has just been changed ---// if( lastTownNationRecno != nation_recno ) { lastTownNationRecno = nation_recno; info.disp(); return; } //--------- display basic info --------// disp_basic_info(refreshFlag); //---------- paint controls -----------// if( refreshFlag == INFO_REPAINT ) { recruit_race_count = race_filter(); //------ display browser field description -------// int x=RACE_BROWSE_X1+2; int y=RACE_BROWSE_Y1-23; vga.d3_panel_up( RACE_BROWSE_X1, y, RACE_BROWSE_X2, RACE_BROWSE_Y1-3 ); font_san.put( x+2 , y+4, "Population" ); font_san.put( x+70 , y+4, "Peasants" ); if( nation_recno ) // only display loyalty if this town is controlled by a nation font_san.put( x+132, y+4, "Loyalty" ); else { #ifdef GERMAN font_san.put( x+128, y+4, "Resistance" ); #else font_san.put( x+132, y+4, "Resistance" ); #endif } //------------ create browser ------------// browse_race.init( RACE_BROWSE_X1, RACE_BROWSE_Y1, RACE_BROWSE_X2, RACE_BROWSE_Y2, 0, 25, recruit_race_count, put_race_rec ); browse_race.open(browse_race_recno); browse_race_town_recno = town_recno; // the town which browse_race displays //---------- paint total section ----------// vga.d3_panel_up( RACE_BROWSE_X1, RACE_BROWSE_Y2+3, RACE_BROWSE_X2, RACE_BROWSE_Y2+23 ); font_san.put( RACE_BROWSE_X1+5, RACE_BROWSE_Y2+7, "Total" ); font_san.put( RACE_BROWSE_X1+128, RACE_BROWSE_Y2+7, "Avg" ); } else { //---------- update controls -----------// if( recruit_race_count != race_filter() ) { info.disp(); return; } browse_race.update(); } browse_race_recno = browse_race.recno(); //----------- display total -----------// font_mid.put( RACE_BROWSE_X1+52, RACE_BROWSE_Y2+6, population, 1 ); font_mid.put( RACE_BROWSE_X1+94, RACE_BROWSE_Y2+6, jobless_population, 1 ); if( nation_recno ) font_mid.put( RACE_BROWSE_X1+165, RACE_BROWSE_Y2+6, average_loyalty(), 1 ); else font_mid.put( RACE_BROWSE_X1+165, RACE_BROWSE_Y2+6, average_resistance(nation_array.player_recno), 1 ); //------ if this town is controlled by a rebel group -----// int x=BUTTON_X1, y=BUTTON_Y1; if( rebel_recno ) { if( refreshFlag == INFO_REPAINT ) font_san.d3_put( BUTTON_X1, y-1, BUTTON_X2, y+19, "Controlled by Rebels" ); y+=23; } //----------- create the paint button ----------// if( nation_recno==nation_array.player_recno ) { if( refreshFlag == INFO_REPAINT ) { button_recruit.paint( BUTTON_X1, y, 'A', "RECRUIT" ); if( has_linked_own_camp ) { button_train.paint( BUTTON_X1+BUTTON_ACTION_WIDTH, y, 'A', "TRAIN" ); button_tax.paint( BUTTON_X1+BUTTON_ACTION_WIDTH*2, y, 'A', "COLLTAX" ); button_grant.paint( BUTTON_X1+BUTTON_ACTION_WIDTH*3, y, 'A', "GRANT" ); disp_auto_loyalty(); } else { button_train.reset(); button_tax.reset(); button_grant.reset(); } #ifdef DEBUG if(debug2_enable_flag) { font_san.d3_put( INFO_X1, INFO_Y2-30, INFO_X2, INFO_Y2, "" ); font_san.field( INFO_X1+10, INFO_Y2-20, " ", INFO_X1+20, town_recno, 1, INFO_X2-10, refreshFlag); font_san.field( INFO_X1+40, INFO_Y2-20, " ", INFO_X1+50, loc_x1, 1, INFO_X2-10, refreshFlag); font_san.field( INFO_X1+70, INFO_Y2-20, " ", INFO_X1+80, loc_y1, 1, INFO_X2-10, refreshFlag); font_san.field( INFO_X1+100, INFO_Y2-20, " ", INFO_X1+110, ai_link_checked, 1, INFO_X2-10, refreshFlag); } #endif } if( has_linked_own_camp ) // a whole row is used for displaying buttons, so additional buttons will be displayed in the next row y += BUTTON_ACTION_HEIGHT; else x += BUTTON_ACTION_WIDTH; // only one button "Recruit", new button displayed next to it. //-------- enable/disable the train button -----------// int raceId = race_filter(browse_race.recno()); if( can_recruit(raceId) ) button_recruit.enable(); else button_recruit.disable(); if( button_train.init_flag ) { if( can_train(raceId) ) button_train.enable(); else button_train.disable(); } if( button_tax.init_flag ) { // ###### patch begin Gilbert 5/8 ######// // if( average_loyalty() >= 1 ) if( average_loyalty() > COLLECT_TAX_LOYALTY_DECREASE ) // ###### end begin Gilbert 5/8 ######// button_tax.enable(); else button_tax.disable(); } if( button_grant.init_flag ) { if( nation_array[nation_recno]->cash > 0 ) button_grant.enable(); else button_grant.disable(); } //--------- display train info --------// if( train_unit_recno ) // display the progress of the current training process disp_train_info(refreshFlag); } //------ grant to an independent town ------// else if( nation_array.player_recno && can_grant_to_non_own_town(nation_array.player_recno) ) { if( refreshFlag == INFO_REPAINT ) button_grant.paint( BUTTON_X1, y, 'A', "GRANT2" ); if( button_grant.init_flag ) { if( nation_array[nation_array.player_recno]->cash > 0 ) button_grant.enable(); else button_grant.disable(); } x += BUTTON_ACTION_WIDTH; } //---------- display the spy button ----------// int spyFlag = spy_filter() > 0; if( refreshFlag == INFO_REPAINT ) { if( spyFlag ) // only display the spy button for non-player towns button_spy.paint( x, y, 'A', "SPYMENU" ); else button_spy.reset(); } else { if( spyFlag != button_spy.init_flag ) // if the button availability has just changed { if(spyFlag) // only display the spy button for non-player towns button_spy.paint( x, y, 'A', "SPYMENU" ); else // remove the button from the screen button_spy.hide(); } } //-------- display debug info ----------// if( sys.debug_session || sys.testing_session ) disp_debug_resistance(refreshFlag); } //----------- End of function Town::disp_main_menu -----------// //--------- Begin of function Town::disp_auto_loyalty ---------// // void Town::disp_auto_loyalty() { if( auto_collect_tax_loyalty ) { vga_front.bar( button_tax.x1+8, button_tax.y1+10, button_tax.x2-12, button_tax.y2-15, V_WHITE ); vga_front.rect( button_tax.x1+8, button_tax.y1+10, button_tax.x2-12, button_tax.y2-15, 1, V_BLACK ); font_mid.center_put( button_tax.x1+8, button_tax.y1+10, button_tax.x2-12, button_tax.y2-15, m.format(auto_collect_tax_loyalty) ); } if( auto_grant_loyalty ) { vga_front.bar( button_grant.x1+8, button_grant.y1+10, button_grant.x2-12, button_grant.y2-15, V_WHITE ); vga_front.rect( button_grant.x1+8, button_grant.y1+10, button_grant.x2-12, button_grant.y2-15, 1, V_BLACK ); font_mid.center_put( button_grant.x1+8, button_grant.y1+10, button_grant.x2-12, button_grant.y2-15, m.format(auto_grant_loyalty) ); } } //----------- End of function Town::disp_auto_loyalty -----------// //--------- Begin of function Town::detect_main_menu ---------// // void Town::detect_main_menu() { //--- detect clicking on the name area to center the map on it ---// if( mouse.single_click(INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+21) ) { world.go_loc( center_x, center_y ); return; } //-------- detect browsers ---------// if( browse_race.detect() ) { browse_race_recno = browse_race.recno(); // ##### begin patch Gilbert 21/1 #######// if( sys.debug_session || sys.testing_session ) disp_debug_resistance(INFO_UPDATE); // ##### end patch Gilbert 21/1 #######// } if( button_spy.detect() ) // switch to the spy menu { town_menu_mode = TOWN_MENU_SPY; disable_refresh = 1; // static var for disp_info() only info.disp(); disable_refresh = 0; return; } //----- detect granting to an independent town ---// if( nation_array.player_recno && can_grant_to_non_own_town(nation_array.player_recno) ) { if( button_grant.detect() ) { se_ctrl.immediate_sound("TURN_ON"); grant_to_non_own_town(nation_array.player_recno, COMMAND_PLAYER); } } //---------- buttons for player town only --------// if( nation_recno!=nation_array.player_recno ) return; //------ update button status ------// if( browse_race.recno() > race_filter() ) return; int raceId = race_filter(browse_race.recno()); if( can_recruit(raceId) ) button_recruit.enable(); else button_recruit.disable(); if( can_train(raceId) ) button_train.enable(); else button_train.disable(); //------- detect buttons --------// if( button_recruit.detect() ) recruit(-1, 0, COMMAND_PLAYER); if( button_train.detect() ) { town_menu_mode = TOWN_MENU_TRAIN; disable_refresh = 1; // static var for disp_info() only info.disp(); disable_refresh = 0; return; } int rc; if( (rc=button_tax.detect(0, 0, 1)) > 0 ) // 1-detect right-clicking { disp_auto_loyalty(); // ##### begin Gilbert 26/9 ########// se_ctrl.immediate_sound("TURN_ON"); // ##### end Gilbert 26/9 ########// if( rc==1 ) { town_array[town_recno]->collect_tax(COMMAND_PLAYER); } else if( rc==2 ) // right click { town_menu_mode = TOWN_MENU_SET_AUTO_COLLECT_TAX; disable_refresh = 1; // static var for disp_info() only info.disp(); disable_refresh = 0; } } if( (rc=button_grant.detect(0, 0, 1)) > 0 ) { disp_auto_loyalty(); // ##### begin Gilbert 26/9 ########// se_ctrl.immediate_sound("TURN_ON"); // ##### end Gilbert 26/9 ########// if( rc==1 ) { town_array[town_recno]->reward(COMMAND_PLAYER); } else if( rc==2 ) // right click { town_menu_mode = TOWN_MENU_SET_AUTO_GRANT; disable_refresh = 1; // static var for disp_info() only info.disp(); disable_refresh = 0; } } if(train_unit_recno) { if((rc = button_cancel_training.detect())) { if( !remote.is_enable() ) { cancel_train_unit(); info.disp(); } else { short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_SKIP_RECRUIT, sizeof(short)); shortPtr[0] = town_recno; } } } } //----------- End of function Town::detect_main_menu -----------// //--------- Begin of function Town::disp_basic_info ---------// // void Town::disp_basic_info(int refreshFlag) { if( refreshFlag == INFO_REPAINT ) { vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+21 ); if( nation_recno ) { font_san.center_put( INFO_X1+21, INFO_Y1, INFO_X2-2, INFO_Y1+21, town_name() ); char *nationPict = image_button.get_ptr("V_COLCOD"); vga_front.put_bitmap_trans_remap_decompress(INFO_X1+3, INFO_Y1+2, nationPict, game.get_color_remap_table(nation_recno, 0) ); } else { font_san.center_put( INFO_X1, INFO_Y1, INFO_X2-2, INFO_Y1+21, town_name() ); } } } //----------- End of function Town::disp_basic_info -----------// //--------- Begin of function Town::disp_train_info ---------// // void Town::disp_train_info(int refreshFlag) { if( !train_unit_recno || nation_recno!=nation_array.player_recno ) return; int dispY1 = INFO_Y1+26; Unit* unitPtr = unit_array[train_unit_recno]; int x=MSG_X1+4, y=MSG_Y1+4; if( refreshFlag == INFO_REPAINT ) { vga.d3_panel_up( MSG_X1, MSG_Y1, MSG_X2, MSG_Y2 ); vga.d3_panel_down(x, y, x+RACE_ICON_WIDTH+3, y+RACE_ICON_HEIGHT+3 ); vga_front.put_bitmap(x+2, y+2, race_res[unitPtr->race_id]->icon_bitmap_ptr ); // vga.d3_panel_down(x+RACE_ICON_WIDTH+6, y, MSG_X2-4, MSG_Y2-4 ); } int totalDays; if( config.fast_build && nation_recno==nation_array.player_recno ) totalDays = TOTAL_TRAIN_DAYS/2; else totalDays = TOTAL_TRAIN_DAYS; vga_front.indicator( 0, x+RACE_ICON_WIDTH+6, y, float(sys.frame_count-start_train_frame_no), float(totalDays * FRAMES_PER_DAY), VGA_GRAY ); button_cancel_training.paint(MSG_X2-27, MSG_Y1+2, "V_X-U", "V_X-D"); button_cancel_training.set_help_code( "CANCELTRA" ); } //----------- End of function Town::disp_train_info -----------// //------ Begin of function Town::browse_selected_race_id ------// // // Return the id. of the race selected in the town's race browser. // int Town::browse_selected_race_id() { err_when( town_recno != town_array.selected_recno ); // the current town must be the selected one when this function is called if( browse_race_town_recno != town_recno ) // the browser still hasn't displayed this town yet. This happens when the selected town is just changed, and this function is called before the town interface is refreshed return 0; if( browse_race.none_record ) return 0; int raceCount = race_filter(); if( raceCount != browse_race.total_rec() || raceCount != recruit_race_count ) { info.disp(); } err_when( browse_race.recno() < 1 ); err_when( browse_race.recno() > raceCount ); err_when( browse_race.recno() > browse_race.total_rec() ); return race_filter(browse_race.recno()); } //------ End of function Town::browse_selected_race_id ------// //--------- Begin of function race_filter ---------// // // Filter those races that are in the town and can be trained. // static int race_filter(int recNo) { err_when( recNo && recNo < 1 ); err_when( recNo && recNo > recruit_race_count ); err_when( recNo && recNo > browse_race.total_rec() ); int i, recCount=0; Town* townPtr = town_array[Town::if_town_recno]; for( i=0 ; irace_pop_array[i] > 0 ) recCount++; if( recNo && recCount==recNo ) return i+1; } err_when( recNo ); return recCount; } //----------- End of function race_filter -----------// //-------- Begin of static function put_race_rec --------// // static void put_race_rec(int recNo, int x, int y, int refreshFlag) { //-------- display race icon -------// int raceId = race_filter(recNo); RaceInfo* raceInfo = race_res[raceId]; if( refreshFlag == INFO_REPAINT ) { vga.d3_panel_down(x+1, y+1, x+RACE_ICON_WIDTH+4, y+RACE_ICON_HEIGHT+4 ); vga_front.put_bitmap(x+3, y+3, raceInfo->icon_bitmap_ptr); } //--------- set help parameters --------// if( mouse.in_area(x+1, y+1, x+RACE_ICON_WIDTH+4, y+RACE_ICON_HEIGHT+4) ) help.set_unit_help( raceInfo->basic_unit_id, 0, x+1, y+1, x+RACE_ICON_WIDTH+4, y+RACE_ICON_HEIGHT+4 ); //-------- display race name --------// Town* townPtr = town_array[Town::if_town_recno]; font_mid.put( x+46, y+6, townPtr->race_pop_array[raceId-1],1, x+87 ); font_mid.put( x+88, y+6, townPtr->jobless_race_pop_array[raceId-1], 1, x+129 ); //---- only display loyalty if this town is controlled by a nation ----// int curLoyalty, targetLoyalty; int x2 = x+browse_race.rec_width-1; if( townPtr->nation_recno ) { curLoyalty = (int) townPtr->race_loyalty_array[raceId-1]; targetLoyalty = (int) townPtr->race_target_loyalty_array[raceId-1]; } else { curLoyalty = (int) townPtr->race_resistance_array[raceId-1][nation_array.player_recno-1]; targetLoyalty = (int) townPtr->race_target_resistance_array[raceId-1][nation_array.player_recno-1]; if( targetLoyalty > curLoyalty ) // resistance only decrease, won't increase targetLoyalty = -1; // don't display the decrease target } //---------- display loyalty/resistance ------------// int dispArrow=0; String str; if( curLoyalty == targetLoyalty || targetLoyalty == -1 ) // only display up and down arrow for independent town's resistance { str = curLoyalty; } else { str = curLoyalty; str += " "; str += targetLoyalty; dispArrow=1; } x2 = font_mid.center_put( x+110, y+6, x2, y+5+font_mid.height(), str, 1 ); //--------- display up/down arrow -----------// if( dispArrow ) { x = x2-font_mid.text_width( m.format(targetLoyalty) ) - 8; if( (int) targetLoyalty > (int) curLoyalty ) image_icon.put_join( x+1, y+9, "ARROWUP" ); else if( (int) targetLoyalty < (int) curLoyalty ) image_icon.put_join( x+1, y+9, "ARROWDWN" ); } } //----------- End of static function put_race_rec -----------// //--------- Begin of function Town::disp_train_menu ---------// // void Town::disp_train_menu(int refreshFlag) { // ####### begin Gilbert 13/9 ########// if( refreshFlag == INFO_UPDATE ) { for( int i=1; i<=MAX_TRAINABLE_SKILL; i++) { button_skill[i-1].paint(-1,0); // button_queue_skill[i] is called by automatically } } else if( refreshFlag == INFO_REPAINT ) { font_san.d3_put( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+18, "Train (Cost:$30, Skill:20)" ); int x=INFO_X1, y=INFO_Y1+24; for(int i=1; i<=MAX_TRAINABLE_SKILL; i++) { //disp_train_button(y, i, 1); button_queue_skill[i-1].create(INFO_X1+COUNT_BUTTON_OFFSET_X, y+COUNT_BUTTON_OFFSET_Y, INFO_X1+COUNT_BUTTON_OFFSET_X+COUNT_BUTTON_WIDTH-1, y+COUNT_BUTTON_OFFSET_Y+COUNT_BUTTON_HEIGHT-1, i_disp_queue_skill_button, ButtonCustomPara(this,i)); button_skill[i-1].paint(INFO_X1, y, INFO_X2, y+BUTTON_ACTION_HEIGHT-1, i_disp_skill_button, ButtonCustomPara(&button_queue_skill[i-1],i) ); y += BUTTON_ACTION_HEIGHT; } button_cancel3.paint( INFO_X1, y, INFO_X2, y+BUTTON_ACTION_HEIGHT*3/4-1, ButtonCustom::disp_text_button_func, ButtonCustomPara((void*)"Done",0) ); } // ####### end Gilbert 13/9 ########// } //----------- End of function Town::disp_train_menu -----------// // ######### begin Gilbert 13/9 #########// //-------- Begin of function i_disp_skill_button --------// // static void i_disp_skill_button(ButtonCustom *button, int repaintBody) { int x1 = button->x1; int y1 = button->y1; int x2 = button->x2; int y2 = button->y2; if( !button->pushed_flag ) { if( repaintBody ) { vga.blt_buf(x1, y1, x2, y2, 0); vga.d3_panel2_up( x1, y1, x2, y2, 1 ); } x2--; y2--; } else { if( repaintBody ) { vga.blt_buf(x1, y1, x2, y2, 0); vga.d3_panel2_down( x1, y1, x2, y2, 1 ); } x1++; y1++; } ButtonCustom *queueButton = (ButtonCustom *)button->custom_para.ptr; if( repaintBody) { // display skill large icon short skillId = button->custom_para.value; char str[9] = "U_"; strcat( str, Skill::skill_code_array[skillId-1] ); char *bitmapPtr = image_button.get_ptr(str); vga_front.put_bitmap_trans_decompress(x1, y1+4, bitmapPtr); // put name if( skillId == SKILL_MFT ) font_bible.put(x1+50, y1+11, "Manufacturing" ); // the string in skill_str_array[] is "Manufacture". else font_bible.put(x1+50, y1+11, Skill::skill_str_array[skillId-1]); } // display small button queueButton->paint(-1, repaintBody); } //--------- End of static function i_disp_skill_button ---------// /* //--------- Begin of function Town::disp_queue_button ---------// void Town::disp_queue_button(int y, int skillId, int buttonUp) { //----- count the no. of units queued for this ship ------// int x=INFO_X1+2+COUNT_BUTTON_OFFSET_X; int trainCount=0; for(int i=0; iskill.skill_id==skillId) trainCount++; } if(buttonUp) vga.d3_panel_up(x, y, x+COUNT_BUTTON_WIDTH-1, y+COUNT_BUTTON_HEIGHT-1); else { vga.d3_panel_down(x, y, x+COUNT_BUTTON_WIDTH-1, y+COUNT_BUTTON_HEIGHT-1); x++; y++; } font_san.center_put(x, y, x+COUNT_BUTTON_WIDTH-1 , y+COUNT_BUTTON_HEIGHT-1, m.format(trainCount)); } //----------- End of function Town::disp_queue_button -----------// */ //-------- Begin of static function i_disp_queue_skill_button --------// // static void i_disp_queue_skill_button(ButtonCustom *button, int repaintBody) { Town *townPtr= (Town *)button->custom_para.ptr; int x1 = button->x1; int y1 = button->y1; int x2 = button->x2; int y2 = button->y2; if( !button->pushed_flag ) { if( repaintBody ) { vga.blt_buf(x1, y1, x2, y2, 0); vga.d3_panel2_up( x1, y1, x2, y2, 1, 1); } x2--; y2--; } else { if( repaintBody ) { vga.blt_buf(x1, y1, x2, y2, 0); vga.d3_panel2_down( x1, y1, x2, y2, 1, 1); } x1++; y1++; } //----- count the no. of units queued for this skill ------// short skillId = button->custom_para.value; int queuedCount=0; for( int i=0 ; itrain_queue_count ; i++ ) { if( townPtr->train_queue_skill_array[i] == skillId ) queuedCount++; } if(townPtr->train_unit_recno) { Unit *unitPtr = unit_array[townPtr->train_unit_recno]; // ##### begin Gilbert 10/10 #######// if(unitPtr->skill.skill_id==skillId //### begin alex 17/3 ###// //|| (unitPtr->spy_recno && skillId == SKILL_SPYING) ) || (skillId == SKILL_SPYING && unitPtr->spy_recno && unitPtr->skill.skill_id == 0) ) // 0 for spying-training //#### end alex 17/3 ####// queuedCount++; // ##### end Gilbert 10/10 #######// } font_mid.center_put( x1+3, y1+3, x2-3, y2-3, m.format(queuedCount), 1); } //--------- End of static function i_disp_queue_skill_button ---------// // ######### end Gilbert 13/9 #########// //--------- Begin of function Town::detect_train_menu ---------// // void Town::detect_train_menu() { int x=INFO_X1+2, y=INFO_Y1+24, rc, quitFlag; for(int b=1; b<=MAX_TRAINABLE_SKILL; ++b) { // ###### begin Gilbert 10/9 ########// //------ detect pressing on the small queue count button -------// rc = 0; if( (rc = button_queue_skill[b-1].detect(0,0,2)) != 0) { quitFlag = 0; // don't quit the menu right after pressing the button } //------ detect pressing on the big button -------// else if( (rc= button_skill[b-1].detect(0,0,2)) != 0) { quitFlag = 1; // quit the menu right after pressing the button } // ###### end Gilbert 10/9 ########// //------- process the action --------// if( rc > 0 ) { if( rc==1 ) // left button { if( remote.is_enable() ) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_RECRUIT, 3*sizeof(short) ); shortPtr[0] = town_recno; shortPtr[1] = b; shortPtr[2] = race_filter(browse_race.recno()); } else add_queue(b, race_filter(browse_race.recno()) ); // ##### begin Gilbert 26/9 ########// se_ctrl.immediate_sound("TURN_ON"); // ##### end Gilbert 26/9 ########// } else // right button - remove queue { if( remote.is_enable() ) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_RECRUIT, 3*sizeof(short) ); shortPtr[0] = town_recno; shortPtr[1] = b; shortPtr[2] = -1; // -1 race_id represent remove queue } else remove_queue(b); // ##### begin Gilbert 26/9 ########// se_ctrl.immediate_sound("TURN_OFF"); // ##### end Gilbert 26/9 ########// } if( quitFlag ) info.disp(); // info.disp() will call put_info() which will switch mode back to the main menu mode // ####### begin Gilbert 10/9 ######// else // disp_queue_button(y+COUNT_BUTTON_OFFSET_Y, b, 1); info.update(); // ####### end Gilbert 10/9 ######// return; } y += BUTTON_ACTION_HEIGHT; } //------ detect the cancel button --------// if( button_cancel3.detect() || mouse.any_click(1) ) // press the cancel button or right click { // ##### begin Gilbert 26/9 ########// se_ctrl.immediate_sound("TURN_OFF"); // ##### end Gilbert 26/9 ########// town_menu_mode = TOWN_MENU_MAIN; info.disp(); } } //----------- End of function Town::detect_train_menu -----------// //--------- Begin of function Town::disp_auto_menu ---------// // void Town::disp_auto_menu(int modeCollectTax) { int curAutoLoyalty; Nation* nationPtr = nation_array[nation_recno]; if( modeCollectTax ) curAutoLoyalty = auto_collect_tax_loyalty; else curAutoLoyalty = auto_grant_loyalty; //---------- paint buttons ------------// char* headingStr; if( modeCollectTax ) headingStr = "Automatically Collect Tax from Villagers when their Loyalty reaches:"; else headingStr = "Automatically Grant Money to Villagers when their Loyalty drops below:"; char* clickStr = "(Left-click below to apply to this village. Right-click below to apply to all your villages.)"; vga.d3_panel_up( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+110 ); font_san.put_paragraph( INFO_X1+7, INFO_Y1+8, INFO_X2-7, INFO_Y2-5, headingStr ); font_san.put_paragraph( INFO_X1+7, INFO_Y1+58, INFO_X2-7, INFO_Y2-5, clickStr ); int i, loyaltyLevel, y=INFO_Y1+114; for( i=0, loyaltyLevel=30 ; i short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_AUTO_TAX, 2*sizeof(short) ); *shortPtr = town_recno; shortPtr[1] = loyaltyLevel; } } else { if( !remote.is_enable() ) { set_auto_grant_loyalty(loyaltyLevel); } else { // packet structure short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_AUTO_GRANT, 2*sizeof(short) ); *shortPtr = town_recno; shortPtr[1] = loyaltyLevel; } } } else if( rc==2 ) { // ####### begin Gilbert 11/9 ########// //----- set the national policy -----// if( !remote.is_enable() ) { Nation* nationPtr = nation_array[nation_recno]; if( modeCollectTax ) nationPtr->set_auto_collect_tax_loyalty(loyaltyLevel); else nationPtr->set_auto_grant_loyalty(loyaltyLevel); //----- update individual towns -----// Town* townPtr; for( i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i) ) continue; townPtr = town_array[i]; if( townPtr->nation_recno == nation_recno ) { if( modeCollectTax ) townPtr->set_auto_collect_tax_loyalty(loyaltyLevel); else townPtr->set_auto_grant_loyalty(loyaltyLevel); } } } else { err_when(!nation_recno); if( modeCollectTax ) { // packet structure <-nation recno> short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_AUTO_TAX, 2*sizeof(short) ); *shortPtr = -nation_recno; shortPtr[1] = loyaltyLevel; } else { // packet structure <-nation recno> short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_AUTO_GRANT, 2*sizeof(short) ); *shortPtr = -nation_recno; shortPtr[1] = loyaltyLevel; } } // ####### end Gilbert 11/9 ########// } //--------------------------------------// if( button_cancel2.detect() || rc ) { // ##### begin Gilbert 26/9 ########// se_ctrl.immediate_sound("TURN_OFF"); // ##### begin Gilbert 26/9 ########// town_menu_mode = TOWN_MENU_MAIN; info.disp(); } } //----------- End of function Town::detect_auto_menu -----------// //--------- Begin of function Town::disp_spy_menu ---------// // void Town::disp_spy_menu(int refreshFlag) { disp_basic_info(refreshFlag); //---------- paint controls -----------// if( refreshFlag == INFO_REPAINT ) { spy_count = spy_filter(); //------ display browser field description -------// int x=RACE_BROWSE_X1+2; int y=RACE_BROWSE_Y1-23; vga.d3_panel_up( RACE_BROWSE_X1, y, RACE_BROWSE_X2, RACE_BROWSE_Y1-3 ); font_san.put( x+4 , y+4, "Spy Skill" ); font_san.put( x+70 , y+4, "Loyalty" ); font_san.put( x+130, y+4, "Action" ); //------------ create browser ------------// browse_spy.init( RACE_BROWSE_X1, RACE_BROWSE_Y1, RACE_BROWSE_X2, RACE_BROWSE_Y2, 0, 25, spy_count, put_spy_rec ); browse_spy.open(1); } else { //---------- update controls -----------// if( spy_count != spy_filter() ) { spy_count = spy_filter(); if( spy_count>0 ) { disable_refresh = 1; // stay in the spy menu mode if disable_refresh is 1 info.disp(); disable_refresh = 0; } else info.disp(); // reset to the main menu mode if disable_refresh is 0 return; } else browse_spy.update(); } //----------- create the paint button ----------// if( refreshFlag == INFO_REPAINT ) { int x=BUTTON_X1, y=RACE_BROWSE_Y2+5; button_spy_mobilize.paint( x, y, 'A', "MOBILSPY" ); x+=BUTTON_ACTION_WIDTH; //--------- reward spy button --------// button_spy_reward.paint( x, y, 'A', "REWARD" ); x+=BUTTON_ACTION_WIDTH; if( nation_recno != nation_array.player_recno ) // if the spy is in another nation's town { button_spy_action.paint( x, y, 'A', "SPYCHACT" ); x+=BUTTON_ACTION_WIDTH; } if( nation_recno && nation_recno != nation_array.player_recno ) { button_spy_view_secret.paint( x, y, 'A', "VSECRET" ); x+=BUTTON_ACTION_WIDTH; if( x+BUTTON_ACTION_WIDTH-5 > INFO_X2 ) { x = BUTTON_X1; y += BUTTON_ACTION_HEIGHT; } } button_cancel.paint( x, y, 'A', "PREVMENU" ); } } //----------- End of function Town::disp_spy_menu -----------// //--------- Begin of function Town::detect_spy_menu ---------// // void Town::detect_spy_menu() { browse_spy.detect(); Spy* spyPtr = spy_array[ spy_filter( browse_spy.recno() ) ]; //------- mobilize spy --------// if( button_spy_mobilize.detect() ) { if( !remote.is_enable() ) { if( spyPtr->mobilize_town_spy() ) { spyPtr->notify_cloaked_nation_flag = 0; // reset it so the player can control it disp_spy_menu( INFO_UPDATE ); } } else { // packet structure short *shortPtr = (short *)remote.new_send_queue_msg(MSG_SPY_LEAVE_TOWN, sizeof(short) ); *shortPtr = spyPtr->spy_recno; } } //------ reward spy ---------// else if( button_spy_reward.detect() ) { spyPtr->reward(COMMAND_PLAYER); } //----- change spy action --------// if( nation_recno != nation_array.player_recno ) // if the spy is in another nation's town { if( button_spy_action.detect() ) // set action mode { if( !remote.is_enable() ) { spyPtr->set_next_action_mode(); disp_spy_menu( INFO_UPDATE ); } else { // packet structure short *shortPtr = (short *)remote.new_send_queue_msg(MSG_SPY_CYCLE_ACTION, sizeof(short) ); *shortPtr = spyPtr->spy_recno; } } } //----- view secret report ------/ if( nation_recno && nation_recno != nation_array.player_recno ) { if( button_spy_view_secret.detect() ) { action_spy_recno = spyPtr->spy_recno; town_menu_mode = TOWN_MENU_VIEW_SECRET; disable_refresh = 1; info.disp(); disable_refresh = 0; } } //--------- cancel -----------// if( button_cancel.detect() || mouse.any_click(1) ) // right click to cancel info.disp(); } //----------- End of function Town::detect_spy_menu -----------// //--------- Begin of function Town::has_player_spy ---------// // // Whether this town has any player spies. // int Town::has_player_spy() { int i; for( i=0 ; i 0 ) break; } if( i==MAX_RACE ) // no spies in this nation return 0; //----- look for player spy in the spy_array -----// Spy* spyPtr; for( i=spy_array.size() ; i>=1 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place==SPY_TOWN && spyPtr->spy_place_para==town_recno && spyPtr->true_nation_recno==nation_array.player_recno ) { return 1; } } return 0; } //----------- End of function Town::has_player_spy -----------// //--------- Begin of function spy_filter ---------// // static int spy_filter(int recNo) { Spy* spyPtr; int recCount=0; for( int i=spy_array.size() ; i>=1 ; i-- ) { if( spy_array.is_deleted(i) ) continue; spyPtr = spy_array[i]; if( spyPtr->spy_place==SPY_TOWN && spyPtr->spy_place_para==Town::if_town_recno && spyPtr->true_nation_recno==nation_array.player_recno ) { recCount++; } if( recNo && recCount==recNo ) return i; } err_when( recNo ); return recCount; } //----------- End of function spy_filter -----------// //-------- Begin of static function put_spy_rec --------// // static void put_spy_rec(int recNo, int x, int y, int refreshFlag) { int x2 = x+browse_spy.rec_width-1; //-------- display icon of the spy unit -----// Spy* spyPtr = spy_array[ spy_filter(recNo) ]; if( refreshFlag == INFO_REPAINT ) { vga.d3_panel_down(x+1, y+1, x+RACE_ICON_WIDTH+4, y+RACE_ICON_HEIGHT+4 ); vga_front.put_bitmap(x+3, y+3, race_res[spyPtr->race_id]->icon_bitmap_ptr); } //--------- set help parameters --------// if( mouse.in_area(x+1, y+1, x+RACE_ICON_WIDTH+4, y+RACE_ICON_HEIGHT+4) ) { int unitId = race_res[spyPtr->race_id]->basic_unit_id; help.set_unit_help( unitId, 0, x+1, y+1, x+RACE_ICON_WIDTH+4, y+RACE_ICON_HEIGHT+4 ); } //-------- display spy skill -------// font_san.put( x+40, y+6, spyPtr->spy_skill, 1, x+66 ); //-------- display spy loyalty -------// font_san.put( x+67, y+6, spyPtr->spy_loyalty, 1, x+94 ); //------ display the action mode of the spy ------// vga.blt_buf( x+95, y+6, x2, y+5+font_san.height(), 0 ); font_san.center_put( x+95, y+6, x2, y+5+font_san.height(), spyPtr->action_str() ); } //----------- End of static function put_spy_rec -----------// //--------- Begin of function Town::recruit ---------// // // trainSkillId = -1 - non-trained unit // >=1 - skill id. of the unit to be trained. // // [int] raceId = the race id. of the unit to be recruited // (default: the currently selected race) // // return: recno of the recruited unit // int Town::recruit(int trainSkillId, int raceId, char remoteAction) { //---- we can't train a new one when there is one currently under training ---// if( trainSkillId >= 1 && train_unit_recno ) return 0; //--------------------------------------------// if( !raceId ) { if( browse_race.recno() > race_filter() ) return 0; raceId = race_filter(browse_race.recno()); } if( !remoteAction && remote.is_enable() ) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_TOWN_RECRUIT, 3*sizeof(short)); shortPtr[0] = town_recno; shortPtr[1] = trainSkillId; shortPtr[2] = raceId; return 0; } //---- check if there are units of the race ready for training ----// int recruitableCount = recruitable_race_pop(raceId, 1); if( recruitableCount == 0 ) return 0; err_when( recruitableCount < 0 ); // 1-allow recruiting spies //-------- create an unit ------// int townRecno = town_recno; int nationRecno = nation_recno; // save this town's info that is needed as promote_pop() will delete Town if all population of the town are promoted //--- if there are spies in this town, chances are that they will be mobilized ---// int shouldTrainSpy = race_spy_count_array[raceId-1] >= m.random(recruitableCount)+1; // 1-allow recruiting spies //---- if we are trying to train an enemy to our spy, then... -----// if( shouldTrainSpy && trainSkillId == SKILL_SPYING ) { //-- if there are other non-spy units in the town, then train the other and don't train the spy --// if( recruitableCount > race_spy_count_array[raceId-1] ) { shouldTrainSpy = 0; } //--- if all remaining units are spies, when you try to train one, all of them will become mobilized ---// else { int spyRecno = spy_array.find_town_spy(town_recno, raceId, 1); err_when( !spyRecno ); Spy* spyPtr = spy_array[spyRecno]; if( !spyPtr->mobilize_town_spy() ) return 0; spyPtr->change_cloaked_nation( spyPtr->true_nation_recno ); return 0; } } //------- if we should train a spy --------// int unitRecno=0; if( shouldTrainSpy ) { int spyCount = spy_array.size(); int spyRecno = m.random(spyCount)+1; Spy* spyPtr; //-----------------------------------------------------// // Spies from other nations will first be mobilized, // when all peasants and spies are mobilized and // the only ones left in the town are spies from our // nation, then mobilize them finally. //-----------------------------------------------------// for( int mobileNationType=1 ; unitRecno==0 && mobileNationType<=2 ; mobileNationType++ ) { if( mobileNationType==2 ) // only mobilize our own spies are there are the only ones in the town { if( recruitable_race_pop(raceId,1) > race_spy_count_array[raceId-1] ) // 1-allow recruiting spies break; } for( int i=0 ; i spyCount ) spyRecno = 1; if( spy_array.is_deleted(spyRecno) ) continue; spyPtr = spy_array[spyRecno]; if( spyPtr->spy_place == SPY_TOWN && spyPtr->spy_place_para == town_recno // ##### patch begin Gilbert 9/4 ######// && spyPtr->race_id == raceId // ##### patch end Gilbert 9/4 ######// ) { if( mobileNationType==1 ) // only mobilize spies from other nations, don't mobilize spies of our own nation { if( spyPtr->true_nation_recno == nation_recno ) continue; } unitRecno = spyPtr->mobilize_town_spy(trainSkillId== -1); // the parameter is whether decreasing the population immediately, if decrease immediately in recruit mode, not in training mode, 1-mobilize spies break; } } } } //-------- mobilize normal peasant units -------// if( !unitRecno ) unitRecno = mobilize_town_people(raceId, trainSkillId== -1, 0 ); // the 2nd parameter is whether decreasing the population immediately, if decrease immediately in recruit mode, not in training mode, 2nd para 0-don't mobilize spies if( !unitRecno ) return 0; err_when(unitRecno<=0 || unit_array.is_deleted(unitRecno)); if( !unitRecno ) return 0; Unit* unitPtr = unit_array[unitRecno]; //-------- training skill -----------// if( trainSkillId > 0 ) { if( trainSkillId == SKILL_SPYING ) { unitPtr->spy_recno = spy_array.add_spy(unitRecno, TRAIN_SKILL_LEVEL); } else { if( trainSkillId == SKILL_LEADING ) // also increase the combat level for leadership skill training unitPtr->set_combat_level(TRAIN_SKILL_LEVEL); unitPtr->skill.skill_id = trainSkillId; unitPtr->skill.skill_level = TRAIN_SKILL_LEVEL; } nation_array[nationRecno]->add_expense( EXPENSE_TRAIN_UNIT, (float) TRAIN_SKILL_COST ); } else { //------ recruitment without training decreases loyalty --------// recruit_dec_loyalty(raceId); if( unitPtr->is_own() ) { se_res.far_sound(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), 1, 'S', unitPtr->sprite_id, "RDY" ); } } //---- training solider or skilled unit takes time ----// if( trainSkillId >= 0 ) { err_when(unitRecno<=0 || unit_array.is_deleted(unitRecno)); err_when( train_unit_recno ); // if there is already a unit under training train_unit_recno = unitRecno; start_train_frame_no = sys.frame_count; // as an offset for displaying the progress bar correctly unitPtr->deinit_sprite(); unitPtr->unit_mode = UNIT_MODE_UNDER_TRAINING; unitPtr->unit_mode_para = town_recno; } //--- mobilize_pop() will delete the current Town if population goes down to 0 ---// if( town_recno == town_array.selected_recno ) { if( town_array.is_deleted(townRecno) ) info.disp(); } return unitRecno; } //----------- End of function Town::recruit -----------// //--------- Begin of function Town::recruit_dec_loyalty ---------// // // Decrease loyalty when an unit is recruited. // This function is called by recruit() and Firm::pull_town_people() // // raceId - the race to be recruited // decNow - decrease now, if it is 0, just return the // loyalty to be decreased without actual decreasing. // (default: 1) // // return: - the loyalty decreased or to be decreased. // int Town::recruit_dec_loyalty(int raceId, int decNow) { float loyaltyDec = min( 5, (float) MAX_TOWN_POPULATION / race_pop_array[raceId-1] ); //------ recruitment without training decreases loyalty --------// if( decNow ) { loyaltyDec += accumulated_recruit_penalty/5; loyaltyDec = min(loyaltyDec, 10); accumulated_recruit_penalty += 5; //-------------------------------------// race_loyalty_array[raceId-1] -= loyaltyDec; if( race_loyalty_array[raceId-1] < 0 ) race_loyalty_array[raceId-1] = (float) 0; } return (int) loyaltyDec; } //----------- End of function Town::recruit_dec_loyalty -----------// //--------- Begin of function Town::process_train ---------// void Town::process_train() { err_when( !train_unit_recno ); Unit* unitPtr = unit_array[train_unit_recno]; int raceId = unitPtr->race_id; //---- if the unit being trained was killed -----// int cancelFlag = 0; err_when( jobless_race_pop_array[raceId-1] < 0 ); if( jobless_race_pop_array[raceId-1]==0 ) // the unit being trained was killed { cancelFlag = 1; } //-----------------------------------------------------------------// // // If after start training the unit (non-spy unit), a unit has been // mobilized, resulting that the spy count >= jobless_race, // we must cancel the training, otherwise when training finishes, // and dec_pop is called, spy count will > jobless count and cause error. // //-----------------------------------------------------------------// err_when( race_spy_count_array[raceId-1] > jobless_race_pop_array[raceId-1] ); if( race_spy_count_array[raceId-1] == jobless_race_pop_array[raceId-1] ) cancelFlag = 1; if( cancelFlag ) { unit_array.disappear_in_town(train_unit_recno, town_recno); train_unit_recno = 0; return; } //------------- process training ---------------// int totalDays; if( config.fast_build && nation_recno==nation_array.player_recno ) totalDays = TOTAL_TRAIN_DAYS/2; else totalDays = TOTAL_TRAIN_DAYS; if( (int)(sys.frame_count-start_train_frame_no) / FRAMES_PER_DAY >= totalDays ) { finish_train(unitPtr); } } //----------- End of function Town::process_train -----------// //--------- Begin of function Town::finish_train ---------// void Town::finish_train(Unit* unitPtr) { err_when(train_unit_recno<=0 || unit_array.is_deleted(train_unit_recno)); SpriteInfo* spriteInfo = unitPtr->sprite_info; int xLoc=loc_x1; // xLoc & yLoc are used for returning results int yLoc=loc_y1; if( !world.locate_space(xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height) ) return; unitPtr->init_sprite(xLoc, yLoc); if( unitPtr->is_own() ) se_res.far_sound( xLoc, yLoc, 1, 'S', unitPtr->sprite_id, "RDY"); unitPtr->unit_mode = 0; // reset it to 0 from UNIT_MODE_UNDER_TRAINING train_unit_recno = 0; int townRecno = town_recno; // save the recno as it can be deleted in dec_pop() dec_pop(unitPtr->race_id, 0); // decrease the population now as the recruit() does do so //---- if this trained unit is tied to an AI action ----// if( train_unit_action_id ) { nation_array[nation_recno]->process_action_id(train_unit_action_id); train_unit_action_id = 0; } //----- refresh if this town is currently selected ------// if(townRecno==town_array.selected_recno) { if(town_menu_mode==TOWN_MENU_MAIN) { info.disp(); } else { disable_refresh = 1; info.disp(); disable_refresh = 0; } } } //----------- End of function Town::finish_train -----------// //--------- Begin of function Town::process_queue ---------// void Town::process_queue() { if(train_queue_count==0) return; if(jobless_population==0) return; err_when(train_queue_count > MAX_TRAIN_QUEUE); char queueCount = train_queue_count; char skillId, raceId; char i; for(i=0; i MAX_TRAIN_QUEUE); memmove(train_queue_skill_array, train_queue_skill_array+i+1, sizeof(train_queue_skill_array[0])*(train_queue_count-i-1)); memmove(train_queue_race_array, train_queue_race_array+i+1, sizeof(train_queue_race_array[0])*(train_queue_count-i-1)); train_queue_count -= i+1; recruit(skillId, raceId, COMMAND_AUTO); break; } } if(i==queueCount) train_queue_count = 0; if(town_menu_mode==TOWN_MENU_MAIN) info.disp(); } //----------- End of function Town::process_queue -----------// //--------- Begin of function Town::add_queue ---------// void Town::add_queue(char skillId, char raceId) { if(train_queue_count+(train_unit_recno>0)==MAX_TRAIN_QUEUE) return; train_queue_skill_array[train_queue_count] = skillId; train_queue_race_array[train_queue_count++] = raceId; if( !train_unit_recno ) process_queue(); } //----------- End of function Town::add_queue -----------// //--------- Begin of function Town::remove_queue ---------// void Town::remove_queue(char skillId) { for(int i=train_queue_count-1; i>=0; i--) { if(train_queue_skill_array[i] == skillId) { err_when(train_queue_count > MAX_TRAIN_QUEUE); m.del_array_rec(train_queue_skill_array, train_queue_count, sizeof(train_queue_skill_array[0]), i+1); m.del_array_rec(train_queue_race_array, train_queue_count, sizeof(train_queue_race_array[0]), i+1); train_queue_count--; return; } } if(train_unit_recno) { Unit *unitPtr = unit_array[train_unit_recno]; if((unitPtr->skill).skill_id==skillId) cancel_train_unit(); } } //----------- End of function Town::remove_queue -----------// //--------- Begin of function Town::disp_debug_resistance ---------// // void Town::disp_debug_resistance(int refreshFlag) { if( nation_recno == nation_array.player_recno ) // not for player's own town return; if( refreshFlag==INFO_REPAINT ) vga.d3_panel_up( INFO_X1, INFO_Y2-50, INFO_X2, INFO_Y2 ); //------ display resistance (only for independent town) -----// int x=INFO_X1+10, y=INFO_Y2-47; if( nation_recno ==0 ) { int raceId = race_filter(browse_race.recno()); for( int i=1 ; i<=nation_array.size() ; i++, x+=28 ) { if( nation_array.is_deleted(i) ) continue; if( refreshFlag==INFO_REPAINT ) vga_front.bar( x, y, x+18, y+16, nation_array[i]->nation_color ); font_san.put( x, y+18, (int) race_resistance_array[raceId-1][i-1], 1, x+19 ); font_san.put( x, y+32, (int) race_target_resistance_array[raceId-1][i-1], 1, x+19 ); } } else { //------ if this town is the nation's base town -----// String str; str = "Base: "; str += is_base_town; font_san.put( INFO_X1+10, y, str ); str = "Town recno: "; str += town_recno; font_san.put( INFO_X1+70, y, str ); str = "no_neighbor_space: "; str += no_neighbor_space; font_san.put( INFO_X1+10, y+16, str ); str = "quality of life: "; str += quality_of_life; font_san.disp( INFO_X1+10, y+32, str, INFO_X2-10 ); } } //----------- End of function Town::disp_debug_resistance -----------// //--------- Begin of function Town::get_elected_race ---------// int Town::get_selected_race() { if(browse_race.recno() > race_filter()) return 0; return race_filter(browse_race.recno()); } //----------- End of function Town::get_elected_race -----------//