123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OF_INN.CPP
- //Description : Firm Military Inn
- #include <OINFO.h>
- #include <OBOX.h>
- #include <OVGA.h>
- #include <OSTR.h>
- #include <OFONT.h>
- #include <OMOUSE.h>
- #include <OHELP.h>
- #include <OVBROWIF.h>
- #include <OGAME.h>
- #include <OTOWN.h>
- #include <OBUTT3D.h>
- #include <ONATION.h>
- #include <ORAWRES.h>
- #include <ORACERES.h>
- #include <OWORLD.h>
- #include <OSPY.h>
- #include <OF_INN.h>
- #include <OREMOTE.h>
- #include <OSERES.h>
- //------------- Define coordinations -----------//
- enum { HIRE_BROWSE_X1 = INFO_X1,
- HIRE_BROWSE_Y1 = INFO_Y1+52,
- HIRE_BROWSE_X2 = INFO_X2,
- HIRE_BROWSE_Y2 = HIRE_BROWSE_Y1+144
- };
- enum { HIRE_DET_X1 = INFO_X1,
- HIRE_DET_Y1 = HIRE_BROWSE_Y2+5,
- HIRE_DET_X2 = INFO_X2,
- HIRE_DET_Y2 = HIRE_DET_Y1+54
- };
- //----------- Define static variables ----------//
- static VBrowseIF browse_hire;
- static Button3D button_hire;
- static int last_hire_count;
- static FirmInn* firm_inn_ptr;
- //----------- Define static functions ----------//
- static void put_hire_rec(int recNo, int x, int y, int refreshFlag);
- //--------- Begin of function FirmInn::FirmInn ---------//
- //
- FirmInn::FirmInn()
- {
- }
- //----------- End of function FirmInn::FirmInn -----------//
- //--------- Begin of function FirmInn::~FirmInn ---------//
- //
- FirmInn::~FirmInn()
- {
- }
- //----------- End of function FirmInn::~FirmInn -----------//
- //--------- Begin of function FirmInn::init_derived ---------//
- //
- void FirmInn::init_derived()
- {
- inn_unit_count = 0;
- next_skill_id = m.random(MAX_TRAINABLE_SKILL)+1;
- }
- //----------- End of function FirmInn::init_derived -----------//
- //--------- Begin of function FirmInn::assign_unit ---------//
- //
- void FirmInn::assign_unit(int unitRecno)
- {
- //------- if this is a construction worker -------//
- if( unit_array[unitRecno]->skill.skill_id == SKILL_CONSTRUCTION )
- {
- set_builder(unitRecno);
- return;
- }
- /*
- //--- can only assign if the unit is a spy cloaked into this firm's nation color ---//
- if( !unitPtr->spy_recno || unitPtr->nation_recno != nation_recno )
- return;
- //---------------------------------------------//
- if( inn_unit_count == MAX_INN_UNIT )
- return;
- err_when( inn_unit_count > MAX_INN_UNIT );
- err_when( !unitRecno );
- Unit* unitPtr = unit_array[unitRecno];
- //--------- add the InnUnit --------//
- InnUnit *innUnit = inn_unit_array+inn_unit_count;
- inn_unit_count++;
- //--------- set InnUnit vars -----------------//
- innUnit->unit_id = unitPtr->unit_id;
- innUnit->skill = unitPtr->skill;
- innUnit->spy_recno = unitPtr->spy_recno;
- innUnit->set_hire_cost();
- unitPtr->deinit_sprite();
- */
- }
- //----------- End of function FirmInn::assign_unit -----------//
- //--------- Begin of function FirmInn::put_info ---------//
- //
- void FirmInn::put_info(int refreshFlag)
- {
- firm_inn_ptr = this;
- disp_basic_info(INFO_Y1, refreshFlag);
- if( !should_show_info() )
- return;
- //----------- display browser -----------//
- if( refreshFlag == INFO_REPAINT )
- {
- browse_hire.init( HIRE_BROWSE_X1, HIRE_BROWSE_Y1, HIRE_BROWSE_X2, HIRE_BROWSE_Y2,
- 0, 25, inn_unit_count, put_hire_rec );
- browse_hire.open(1);
- }
- else
- {
- if( last_hire_count != inn_unit_count )
- {
- if( last_hire_count==0 || inn_unit_count==0 ) // repaint the whole area as the detail area needs to disappear
- {
- last_hire_count = inn_unit_count;
- info.disp();
- return;
- }
- last_hire_count = inn_unit_count;
- browse_hire.refresh(-1, inn_unit_count);
- if( last_hire_count==0 || inn_unit_count==0 )
- refreshFlag = INFO_REPAINT;
- }
- else
- browse_hire.update(); // update only
- }
- last_hire_count = inn_unit_count;
- put_det(refreshFlag);
- //---------- display spy button ----------//
- disp_spy_button(INFO_X1+BUTTON_ACTION_WIDTH, HIRE_DET_Y2+4, refreshFlag);
- }
- //----------- End of function FirmInn::put_info -----------//
- //--------- Begin of function FirmInn::detect_info ---------//
- //
- void FirmInn::detect_info()
- {
- firm_inn_ptr = this;
- if( detect_basic_info() )
- return;
- //-------- detect spy button ----------//
- if( !own_firm() )
- {
- detect_spy_button();
- return;
- }
- //-------------------------------------//
- if( browse_hire.detect() )
- {
- put_det(INFO_UPDATE);
- }
- if( button_hire.detect() && inn_unit_count > 0 )
- {
- // ###### begin Gilbert 31/7 #######//
- se_res.far_sound(center_x, center_y, 1, 'S',
- unit_res[inn_unit_array[browse_hire.recno()-1].unit_id]->sprite_id,
- "RDY" );
- // ###### end Gilbert 31/7 #######//
- if(remote.is_enable())
- {
- // packet structure : <firm recno>, <hire Id> <nation no>
- short *shortPtr=(short *)remote.new_send_queue_msg(MSG_F_INN_HIRE, 3*sizeof(short));
- shortPtr[0] = firm_recno;
- shortPtr[1] = browse_hire.recno();
- shortPtr[2] = nation_recno;
- }
- else
- {
- hire(browse_hire.recno());
- }
- }
- }
- //----------- End of function FirmInn::detect_info -----------//
- //--------- Begin of function FirmInn::hire ---------//
- //
- int FirmInn::hire(short recNo)
- {
- err_when( recNo < 1 );
- if( recNo > inn_unit_count ) // this may happen in a multiplayer game
- return 0;
- //--------- first check if you have enough money to hire ------//
- InnUnit* innUnit;
- Nation* nationPtr = nation_array[nation_recno];
- innUnit = inn_unit_array+recNo-1;
- if( nationPtr->cash < innUnit->hire_cost )
- return 0;
- //---------- add the unit now -----------//
- int unitRecno = create_unit( innUnit->unit_id );
- if(!unitRecno)
- return 0; // no space for creating the unit
- nationPtr->add_expense(EXPENSE_HIRE_UNIT, innUnit->hire_cost);
- //-------- set skills of the unit --------//
- Unit* unitPtr = unit_array[unitRecno];
- memcpy( &(unitPtr->skill), &(innUnit->skill), sizeof(Skill) );
- err_when( innUnit->skill.combat_level<=0 || innUnit->skill.combat_level>100 );
- unitPtr->set_combat_level( innUnit->skill.combat_level );
- //-------- if the unit's skill is spying -----//
- if( unitPtr->skill.skill_id == SKILL_SPYING )
- {
- unitPtr->spy_recno = spy_array.add_spy(unitRecno, unitPtr->skill.skill_level);
- unitPtr->skill.skill_id = 0; // reset its primary skill, its spying skill has been recorded in spy_array
- }
- //----------------------------------------//
- //
- // Loyalty of the hired unit
- //
- // = 30 + the nation's reputation / 2 + 30 if racially homogenous
- //
- //----------------------------------------//
- int unitLoyalty = 30 + (int)nationPtr->reputation/2;
- if( race_res.is_same_race(unitPtr->race_id, nationPtr->race_id) )
- unitLoyalty += 20;
- unitLoyalty = max( 40, unitLoyalty );
- unitLoyalty = min( 100, unitLoyalty );
- if( unitPtr->spy_recno )
- spy_array[unitPtr->spy_recno]->spy_loyalty = unitLoyalty;
- else
- unitPtr->loyalty = unitLoyalty;
- //---- remove the record from the hire list ----//
- del_inn_unit(recNo);
- if( firm_recno == firm_array.selected_recno &&
- nation_recno == nation_array.player_recno )
- {
- put_info(INFO_UPDATE);
- }
- return unitRecno;
- }
- //----------- End of function FirmInn::hire -----------//
- //--------- Begin of function FirmInn::put_det ---------//
- //
- void FirmInn::put_det(int refreshFlag)
- {
- if( browse_hire.none_record )
- {
- button_hire.reset();
- return;
- }
- //--------- display details ----------//
- InnUnit* innUnit = inn_unit_array+browse_hire.recno()-1;
- disp_unit_info(HIRE_DET_Y1, innUnit, refreshFlag );
- //------- paint buttons --------//
- if( own_firm() )
- {
- if( refreshFlag == INFO_REPAINT )
- {
- button_hire.paint( HIRE_DET_X1, HIRE_DET_Y2+4, 'A', "HIREUNIT" );
- }
- else
- {
- if( inn_unit_count > 0 &&
- (~nation_array)->cash >= inn_unit_array[browse_hire.recno()-1].hire_cost )
- {
- button_hire.enable();
- }
- else
- {
- button_hire.disable();
- }
- }
- }
- }
- //----------- End of function FirmInn::put_det -----------//
- //--------- Begin of function FirmInn::disp_unit_info ---------//
- //
- // Display the skill information of the people in the town.
- //
- // <int> dispY1 - the top y coordination of the info area
- // <InnUnit*> hireInfoPtr - pointer to a HireInfo structure
- // <int> refreshFlag - refresh flag
- //
- void FirmInn::disp_unit_info(int dispY1, InnUnit* hireInfoPtr, int refreshFlag)
- {
- Skill* skillPtr = &(hireInfoPtr->skill);
- //---------------- paint the panel --------------//
- if( refreshFlag == INFO_REPAINT )
- {
- vga.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+54 );
- }
- //------ display population composition of this resident town -----//
- int x=INFO_X1+4, y=dispY1+4, x1=x+100;
- String str;
- font_san.field( x, y, "Combat", x1, skillPtr->combat_level, 1, INFO_X2-10, refreshFlag );
- if( refreshFlag == INFO_REPAINT )
- {
- font_san.field( x, y+16, skillPtr->skill_des(), x1, skillPtr->skill_level , 1, INFO_X2-10, refreshFlag );
- }
- else
- {
- font_san.use_max_height();
- font_san.put( x+2, y+18, skillPtr->skill_des(), 1, x1-2 );
- font_san.use_std_height();
- font_san.update_field( x1, y+16, skillPtr->skill_level, 1, INFO_X2-10);
- }
- font_san.field( x, y+32, "Hiring Cost", x1, hireInfoPtr->hire_cost, 2, INFO_X2-10, refreshFlag);
- }
- //----------- End of function FirmInn::disp_unit_info -----------//
- //-------- Begin of static function put_hire_rec --------//
- //
- static void put_hire_rec(int recNo, int x, int y, int refreshFlag)
- {
- InnUnit* innUnit = firm_inn_ptr->inn_unit_array+recNo-1;
- //-------- display unit icon -------//
- vga_front.d3_panel_down(x+1, y+1, x+UNIT_SMALL_ICON_WIDTH+4, y+UNIT_SMALL_ICON_HEIGHT+4, 2, 0 );
- // ##### begin Gilbert 17/10 #######//
- vga_front.put_bitmap(x+3, y+3, unit_res[innUnit->unit_id]->get_small_icon_ptr(RANK_SOLDIER) );
- // ##### end Gilbert 17/10 #######//
- //--------- set help parameters --------//
- if( mouse.in_area(x+1, y+1, x+UNIT_SMALL_ICON_WIDTH+4, y+UNIT_SMALL_ICON_HEIGHT+4) )
- help.set_unit_help( innUnit->unit_id, 0, x+1, y+1, x+UNIT_SMALL_ICON_WIDTH+4, y+UNIT_SMALL_ICON_HEIGHT+4 );
- //---------- display info ----------//
- y+=6;
- font_san.use_max_height();
- if( innUnit->skill.skill_level > 0 )
- {
- font_san.put( x+32 , y, innUnit->skill.skill_des(1), 1, x+122 ); // 1-use short words
- font_san.put( x+116, y, innUnit->skill.skill_level, 1, x+146 );
- }
- else
- {
- font_san.put( x+32 , y, "Combat", 1, x+122 ); // 1-use short words
- font_san.put( x+116, y, innUnit->skill.combat_level, 1, x+146 );
- }
- font_san.use_std_height();
- font_san.put( x+140, y, m.format(innUnit->hire_cost,2), 1, x+browse_hire.rec_width-3 );
- }
- //----------- End of static function put_hire_rec -----------//
- //--------- Begin of function FirmInn::next_day ---------//
- //
- void FirmInn::next_day()
- {
- //----------- run next_day() of the base class -------------//
- Firm::next_day();
- //------------ update the hire list ------------//
- int updateInterveal = 10 + info.year_passed*2; // there will be less and less units to hire as the game passes
- if( info.game_date % updateInterveal == firm_recno % updateInterveal )
- update_add_hire_list();
- if( info.game_date % 10 == firm_recno % 10 )
- update_del_hire_list();
- }
- //----------- End of function FirmInn::next_day -----------//
- //---------- Begin of function FirmInn::update_add_hire_list --------//
- //
- void FirmInn::update_add_hire_list()
- {
- //-------- new units come by --------//
- if( inn_unit_count < MAX_INN_UNIT )
- {
- if( should_add_inn_unit() )
- {
- int unitId = race_res[m.random(MAX_RACE)+1]->basic_unit_id;
- if( unitId )
- add_inn_unit(unitId);
- }
- }
- }
- //----------- End of function FirmInn::update_add_hire_list ---------//
- //--------- Begin of function FirmInn::update_del_hire_list --------//
- //
- void FirmInn::update_del_hire_list()
- {
- //------- existing units leave -------//
- for( int i=inn_unit_count ; i>0 && inn_unit_count>0 ; i-- )
- {
- if( !inn_unit_array[i-1].spy_recno && --inn_unit_array[i-1].stay_count==0 )
- {
- del_inn_unit(i);
- if( firm_recno == firm_array.selected_recno )
- {
- if( browse_hire.recno() > i && browse_hire.recno() > 1 )
- browse_hire.refresh( browse_hire.recno()-1, inn_unit_count );
- }
- }
- }
- }
- //--------- End of function FirmInn::update_del_hire_list ---------//
- //-------- Begin of function FirmInn::should_add_inn_unit --------//
- //
- int FirmInn::should_add_inn_unit()
- {
- #define MAX_INN_UNIT_PER_REGION 10 // maximum no. of inn units in any single region
- FirmInn* firmInn;
- int totalInnUnit = inn_unit_count;
- for(int i=0; i<linked_firm_count; i++)
- {
- firmInn = (FirmInn*) firm_array[linked_firm_array[i]]; // links between inns are stored in linked_firm_array[] for quick scan only
- err_when( firmInn->firm_id != FIRM_INN );
- totalInnUnit += firmInn->inn_unit_count;
- }
- return totalInnUnit < MAX_INN_UNIT_PER_REGION;
- }
- //--------- End of function FirmInn::should_add_inn_unit ---------//
- //--------- Begin of function FirmInn::add_inn_unit ---------//
- void FirmInn::add_inn_unit(int unitId)
- {
- err_when( inn_unit_count >= MAX_INN_UNIT );
- InnUnit *innUnit = inn_unit_array+inn_unit_count;
- inn_unit_count++;
- innUnit->unit_id = unitId;
- //--------- set the skill now -----------------//
- char skillId = (char) next_skill_id;
- if( ++next_skill_id > MAX_TRAINABLE_SKILL )
- next_skill_id = 1;
- innUnit->skill.skill_id = skillId;
- if( skillId > 0 )
- innUnit->skill.skill_level = 30+m.random(70);
- else
- innUnit->skill.skill_level = 0;
- if( skillId==0 || skillId==SKILL_LEADING )
- innUnit->skill.combat_level = 30+m.random(70);
- else
- innUnit->skill.combat_level = 10;
- innUnit->set_hire_cost();
- innUnit->stay_count = 5 + m.random(5);
- innUnit->spy_recno = 0;
- }
- //----------- End of function FirmInn::add_inn_unit -----------//
- //--------- Begin of function InnUnit::set_hire_cost ---------//
- //
- void InnUnit::set_hire_cost()
- {
- hire_cost = skill.combat_level + (int)skill.skill_level*2;
- if( skill.skill_id==SKILL_LEADING ) // the cost of a leader unit is higher
- {
- hire_cost += skill.skill_level*2;
- for( int i=10 ; i<=100 ; i+=20 ) // increase the hiring cost with bigger steps when the skill level gets higher
- {
- if( i > skill.skill_level )
- hire_cost += i/5;
- }
- }
- else if( skill.skill_id==SKILL_SPYING ) // the cost of a leader unit is higher
- {
- hire_cost += skill.skill_level;
- }
- hire_cost *= 2;
- }
- //----------- End of function InnUnit::set_hire_cost -----------//
- //--------- Begin of function FirmInn::del_inn_unit ---------//
- void FirmInn::del_inn_unit(int recNo)
- {
- err_when( recNo<1 || recNo>MAX_INN_UNIT );
- err_when( inn_unit_count < 1 );
- err_when( inn_unit_count > MAX_INN_UNIT );
- m.del_array_rec(inn_unit_array, inn_unit_count, sizeof(InnUnit), recNo);
- inn_unit_count--;
- }
- //----------- End of function FirmInn::del_inn_unit -----------//
- //--------- Begin of function FirmInn::auto_defense ---------//
- void FirmInn::auto_defense(short targetRecno)
- {
- //---------- the area to check -----------//
- int xLoc1 = center_x - EFFECTIVE_FIRM_TOWN_DISTANCE;
- int yLoc1 = center_y - EFFECTIVE_FIRM_TOWN_DISTANCE;
- int xLoc2 = center_x + EFFECTIVE_FIRM_TOWN_DISTANCE;
- int yLoc2 = center_y + EFFECTIVE_FIRM_TOWN_DISTANCE;
- //----------- boundary checking ----------//
- if(xLoc1<0) xLoc1 = 0;
- if(yLoc1<0) yLoc1 = 0;
- if(xLoc2>=MAX_WORLD_X_LOC) xLoc2 = MAX_WORLD_X_LOC-1;
- if(yLoc2>=MAX_WORLD_Y_LOC) yLoc2 = MAX_WORLD_Y_LOC-1;
- int skipWidthDist = STD_TOWN_LOC_WIDTH;
- int skipHeightDist = STD_TOWN_LOC_HEIGHT;
- int xEnd, yEnd, xLimit, yLimit;
- int i, j, dist;
- Location *locPtr;
- Town *townPtr;
- //--------------------------------------------------//
- // check for our town in the effective area
- //--------------------------------------------------//
- xLimit = xLoc2+skipWidthDist-1;
- yLimit = yLoc2+skipHeightDist-1;
- for(xEnd=0, i=xLoc1; i<=xLimit && !xEnd; i+=skipWidthDist)
- {
- if(i>=xLoc2)
- {
- xEnd++; // final
- i = xLoc2;
- }
- for(yEnd=0, j=yLoc1; j<=yLimit && !yEnd; j+=skipHeightDist)
- {
- if(j>=yLoc2)
- {
- yEnd++; // final
- j = yLoc2;
- }
- err_when(i<xLoc1 || i>xLoc2 || j<yLoc1 || j>yLoc2);
- locPtr = world.get_loc(i, j);
- if(!locPtr->is_town())
- continue;
- err_when(!locPtr->town_recno() || town_array.is_deleted(locPtr->town_recno()));
- townPtr = town_array[locPtr->town_recno()];
- if(townPtr->nation_recno!=nation_recno)
- continue;
- dist = m.points_distance(center_x, center_y, townPtr->center_x, townPtr->center_y);
- if(dist <= EFFECTIVE_FIRM_TOWN_DISTANCE)
- townPtr->auto_defense(targetRecno);
- }
- }
- }
- //----------- End of function FirmInn::auto_defense -----------//
|