OFIRM.cpp 104 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OFIRM.CPP
  21. //Description : Object Firm
  22. #include <OVGA.h>
  23. #include <ODATE.h>
  24. #include <OMLINK.h>
  25. #include <OWORLD.h>
  26. #include <OPOWER.h>
  27. #include <OCONFIG.h>
  28. #include <OGAME.h>
  29. #include <OUNIT.h>
  30. #include <ONEWS.h>
  31. #include <OSYS.h>
  32. #include <OSPY.h>
  33. #include <OSITE.h>
  34. #include <OINFO.h>
  35. #include <ONEWS.h>
  36. #include <ONATION.h>
  37. #include <OFIRM.h>
  38. #include <ORACERES.h>
  39. #include <OTOWN.h>
  40. #include <OSPRITE.h>
  41. #include <OFIRMRES.h>
  42. #include <OF_MARK.h>
  43. #include <OREMOTE.h>
  44. #include <OF_CAMP.h>
  45. #include <OF_HARB.h>
  46. #include <OSERES.h>
  47. #include <OREBEL.h>
  48. // ###### begin Gilbert 2/10 ######//
  49. #include <OFIRMDIE.h>
  50. // ###### end Gilbert 2/10 ######//
  51. #include <OUNITRES.h>
  52. //---------- define static member vars -------------//
  53. char Firm::firm_menu_mode=FIRM_MENU_MAIN; // whether the firm is in spy menu mode
  54. short Firm::action_spy_recno;
  55. char Firm::bribe_result=BRIBE_NONE;
  56. char Firm::assassinate_result=0;
  57. //----------- define static parameters -------------//
  58. static int remove_firm = 0; // true only when the firm is to be removed from the firm_array
  59. //--------- Begin of function Firm::Firm --------//
  60. //
  61. // After created a Firm, you must either call Firm::set_world_matrix()
  62. // to set the record no. of the firm in the matrix or set it yourself
  63. //
  64. // NOTE : this function will be called by firm_array.read_file()
  65. // it CANNOT change any settings in nation_array
  66. //
  67. Firm::Firm()
  68. {
  69. //####### patch begin Gilbert 21/1 #######//
  70. // memset( (char *)this, 0, sizeof(Firm) );
  71. memset( (char *)this + sizeof(void *), 0, sizeof(Firm) - sizeof(void *) );
  72. //####### patch end Gilbert 21/1 #######//
  73. }
  74. //----------- End of function Firm::Firm ---------//
  75. //--------- Begin of function Firm::~Firm --------//
  76. //
  77. // Two ways to terminate a Firm :
  78. //
  79. // 1.call Firm::deinit() first and then delete the firm
  80. // 2.delete the firm directly
  81. //
  82. Firm::~Firm()
  83. {
  84. deinit();
  85. }
  86. //----------- End of function Firm::~Firm --------//
  87. //--------- Begin of function Firm::init --------//
  88. //
  89. // It will initialize vars, and set the world matrix.
  90. // Before calling init(), firm_recno should be set
  91. //
  92. // Note : it will set world matrix regardless the existing location content,
  93. // so you must ensure that the location is clean by calling
  94. // world.zoom_matrix->add_firm_test()
  95. //
  96. // <int> xLoc, yLoc = the location of firm in the world map
  97. // <int> nationRecno = the recno of nation which build this firm
  98. // <int> firmId = id(type) of the firm
  99. // [char*] buildCode = the build code of the firm, no need to give if the firm just have one build type
  100. // [short] builderRecno = recno of the builder unit
  101. //
  102. void Firm::init(int xLoc, int yLoc, int nationRecno, int firmId, char* buildCode, short builderRecno)
  103. {
  104. FirmInfo* firmInfo = firm_res[firmId];
  105. firm_id = firmId;
  106. if( buildCode )
  107. firm_build_id = firmInfo->get_build_id(buildCode);
  108. else
  109. firm_build_id = firmInfo->first_build_id;
  110. //----------- set vars -------------//
  111. nation_recno = nationRecno;
  112. setup_date = info.game_date;
  113. overseer_recno = 0;
  114. if( firmInfo->need_worker )
  115. worker_array = (Worker*) mem_add( MAX_WORKER * sizeof(Worker) );
  116. else
  117. worker_array = NULL;
  118. //----- set the firm's absolute positions on the map -----//
  119. FirmBuild* firmBuild = firm_res.get_build(firm_build_id);
  120. race_id = firmBuild->race_id;
  121. loc_x1 = xLoc;
  122. loc_y1 = yLoc;
  123. loc_x2 = loc_x1 + firmBuild->loc_width - 1;
  124. loc_y2 = loc_y1 + firmBuild->loc_height - 1;
  125. center_x = (loc_x1 + loc_x2) / 2;
  126. center_y = (loc_y1 + loc_y2) / 2;
  127. region_id = world.get_region_id( center_x, center_y );
  128. abs_x1 = xLoc * ZOOM_LOC_WIDTH + firmBuild->min_offset_x;
  129. abs_y1 = yLoc * ZOOM_LOC_HEIGHT + firmBuild->min_offset_y;
  130. abs_x2 = abs_x1 + firmBuild->max_bitmap_width - 1;
  131. abs_y2 = abs_y1 + firmBuild->max_bitmap_height - 1;
  132. //--------- set animation frame vars ---------//
  133. if( firmBuild->animate_full_size )
  134. cur_frame = 1;
  135. else
  136. {
  137. cur_frame = 2; // start with the 2nd frame as the 1st frame is the common frame
  138. err_when( firmBuild->frame_count <=2 ); // for segmented animation, the minimum no. of frames must be 3, as the first one is the common frame
  139. }
  140. remain_frame_delay = (char) firmBuild->frame_delay(cur_frame);
  141. //--------- initialize gaming vars ----------//
  142. hit_points = (float) 0;
  143. max_hit_points = firmInfo->max_hit_points;
  144. //------ set construction and builder -------//
  145. under_construction = firmInfo->buildable; // whether the firm is under construction, if the firm is not buildable it is completed in the first place
  146. if( !under_construction ) // if this firm doesn't been to be constructed, set its hit points to the maximum
  147. hit_points = max_hit_points;
  148. if( builderRecno )
  149. set_builder(builderRecno);
  150. else
  151. builder_recno = 0;
  152. //------ update firm counter -------//
  153. firmInfo->total_firm_count++;
  154. if( nation_recno )
  155. firmInfo->inc_nation_firm_count(nation_recno);
  156. //-------------------------------------------//
  157. if( nation_recno > 0 )
  158. {
  159. Nation* nationPtr = nation_array[nation_recno];
  160. firm_ai = nationPtr->is_ai();
  161. ai_processed = 1;
  162. //--------- increase firm counter -----------//
  163. nationPtr->nation_firm_count++;
  164. //-------- update last build date ------------//
  165. nationPtr->last_build_firm_date = info.game_date;
  166. }
  167. else
  168. {
  169. firm_ai = 0;
  170. ai_processed = 0;
  171. }
  172. ai_status = FIRM_WITHOUT_ACTION;
  173. ai_link_checked = 1; // check the connected firms if ai_link_checked = 0;
  174. //--------------------------------------------//
  175. setup_link();
  176. set_world_matrix();
  177. init_name();
  178. //----------- init AI -----------//
  179. if( firm_ai )
  180. nation_array[nation_recno]->add_firm_info(firm_id, firm_recno);
  181. //-------- init derived ---------//
  182. init_derived(); // init_derived() before set_world_matrix() so that init_derived has access to the original land info.
  183. }
  184. //----------- End of function Firm::init ---------//
  185. //--------- Begin of function Firm::deinit --------//
  186. //
  187. void Firm::deinit()
  188. {
  189. if( !firm_recno ) // already deleted
  190. return;
  191. deinit_derived();
  192. remove_firm = 1; // set static parameter
  193. //------- delete AI info ----------//
  194. if(firm_ai)
  195. {
  196. Nation* nationPtr = nation_array[nation_recno];
  197. if( should_close_flag )
  198. nationPtr->firm_should_close_array[firm_id-1]--;
  199. err_when( nationPtr->firm_should_close_array[firm_id-1] < 0 );
  200. nationPtr->del_firm_info(firm_id, firm_recno);
  201. }
  202. //--------- clean up related stuff -----------//
  203. restore_world_matrix();
  204. release_link();
  205. //------ all workers and the overseer resign ------//
  206. if( !sys.signal_exit_flag )
  207. {
  208. // ##### begin Gilbert 28/10 ########//
  209. if( !under_construction )
  210. {
  211. // -------- create a firm die record ------//
  212. // can be called as soon as restore_world_matrix
  213. FirmDie firmDie;
  214. firmDie.init(this);
  215. firm_die_array.add(&firmDie);
  216. }
  217. // ##### end Gilbert 28/10 ########//
  218. assign_overseer(0); // this function must be called before restore_world_matrix(), otherwise the power area can't be completely reset
  219. if( worker_array )
  220. {
  221. resign_all_worker(); // the workers in the firm will be killed if there is no space for creating the workers
  222. mem_del( worker_array );
  223. worker_array = NULL;
  224. }
  225. if(builder_recno)
  226. mobilize_builder(builder_recno);
  227. }
  228. else
  229. {
  230. if(builder_recno)
  231. kill_builder(builder_recno);
  232. kill_overseer();
  233. if(worker_array)
  234. {
  235. kill_all_worker();
  236. mem_del(worker_array);
  237. worker_array = NULL;
  238. }
  239. }
  240. //--------- decrease firm counter -----------//
  241. if( nation_recno )
  242. nation_array[nation_recno]->nation_firm_count--;
  243. //------ update firm counter -------//
  244. FirmInfo* firmInfo = firm_res[firm_id];
  245. firmInfo->total_firm_count--;
  246. if( nation_recno )
  247. firmInfo->dec_nation_firm_count(nation_recno);
  248. //------- update town border ---------//
  249. loc_x1 = -1; // mark deleted
  250. //------- if the current firm is the selected -----//
  251. if( firm_array.selected_recno == firm_recno )
  252. {
  253. firm_array.selected_recno = 0;
  254. info.disp();
  255. }
  256. //-------------------------------------------------//
  257. firm_recno = 0;
  258. remove_firm = 0; // reset static parameter
  259. }
  260. //----------- End of function Firm::deinit ---------//
  261. //--------- Begin of function Firm::init_name --------//
  262. //
  263. // Set the name of this firm. Name related vars are set.
  264. //
  265. void Firm::init_name()
  266. {
  267. char t=firm_res[firm_id]->short_name[0];
  268. if( t==' ' || !t ) // if this firm does not have any short name, display the full name without displaying the town name together
  269. return;
  270. //---- find the closest town and set closest_town_name_id -----//
  271. closest_town_name_id = get_closest_town_name_id();
  272. //--------- set firm_name_instance_id -----------//
  273. char usedInstanceArray[256];
  274. Firm* firmPtr;
  275. memset( usedInstanceArray, 0, sizeof(usedInstanceArray) );
  276. int i;
  277. for( i=firm_array.size() ; i>0 ; i-- )
  278. {
  279. if( firm_array.is_deleted(i) )
  280. continue;
  281. firmPtr = firm_array[i];
  282. if( firmPtr->firm_id == firm_id &&
  283. firmPtr->closest_town_name_id == closest_town_name_id &&
  284. firmPtr->firm_name_instance_id )
  285. {
  286. usedInstanceArray[firmPtr->firm_name_instance_id-1] = 1;
  287. }
  288. }
  289. for( i=0 ; i<256 ; i++ ) // get the smallest id. which are not used by existing firms
  290. {
  291. if( !usedInstanceArray[i] )
  292. {
  293. firm_name_instance_id = i+1;
  294. break;
  295. }
  296. }
  297. }
  298. //--------- End of function Firm::init_name --------//
  299. //------- Begin of function Firm::get_closest_town_name_id -----------//
  300. //
  301. // return the name id. of the closest town.
  302. //
  303. int Firm::get_closest_town_name_id()
  304. {
  305. //---- find the closest town and set closest_town_name_id -----//
  306. int townDistance, minTownDistance=0x7FFF;
  307. int closestTownNameId=0;
  308. Town* townPtr;
  309. for( int i=town_array.size() ; i>0 ; i-- )
  310. {
  311. if( town_array.is_deleted(i) )
  312. continue;
  313. townPtr = town_array[i];
  314. townDistance = m.points_distance( townPtr->center_x, townPtr->center_y,
  315. center_x, center_y );
  316. if( townDistance < minTownDistance )
  317. {
  318. minTownDistance = townDistance;
  319. closestTownNameId = townPtr->town_name_id;
  320. }
  321. }
  322. return closestTownNameId;
  323. }
  324. //--------- End of function Firm::get_closest_town_name_id -----------//
  325. //------- Begin of function Firm::firm_name -----------//
  326. //
  327. char* Firm::firm_name()
  328. {
  329. static String str;
  330. if( !closest_town_name_id )
  331. {
  332. str = firm_res[firm_id]->name;
  333. }
  334. else
  335. {
  336. #if(defined(SPANISH))
  337. str = firm_res[firm_id]->short_name;
  338. str += " de ";
  339. str += town_res.get_name(closest_town_name_id);
  340. #else
  341. // FRENCH, GERMAN and US
  342. str = town_res.get_name(closest_town_name_id);
  343. str += " ";
  344. str += firm_res[firm_id]->short_name;
  345. #endif
  346. if( firm_name_instance_id > 1 ) // don't display number for the first firm
  347. {
  348. str += " ";
  349. str += firm_name_instance_id;
  350. }
  351. }
  352. return str;
  353. }
  354. //--------- End of function Firm::firm_name -----------//
  355. //------- Begin of function Firm::complete_construction -----------//
  356. //
  357. // Complete construction instantly.
  358. //
  359. void Firm::complete_construction()
  360. {
  361. if( under_construction )
  362. {
  363. hit_points = max_hit_points;
  364. under_construction = 0;
  365. }
  366. }
  367. //--------- End of function Firm::complete_construction -----------//
  368. //------- Begin of function Firm::assign_unit -----------//
  369. //
  370. void Firm::assign_unit(int unitRecno)
  371. {
  372. err_when( !unitRecno );
  373. Unit* unitPtr = unit_array[unitRecno];
  374. //------- if this is a construction worker -------//
  375. if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION )
  376. {
  377. set_builder(unitRecno);
  378. return;
  379. }
  380. //---- if the unit does not belong to the firm's nation ----//
  381. if( unitPtr->nation_recno != nation_recno )
  382. {
  383. // can no longer capture a firm with a normal unit - must use spy
  384. //----- capture this firm if there is nobody here -----//
  385. /*
  386. if( worker_array && worker_count==0 && overseer_recno==0 && // if the firm is empty, assign to take over the firm
  387. unitPtr->skill.skill_id == firm_skill_id ) // the takeover unit must have the skill of this firm
  388. {
  389. change_nation(unitPtr->nation_recno);
  390. }
  391. else
  392. */ return; // if cannot capture, the nations are not the same, return now. This will happen if the unit's nation was changed during his moving to the firm.
  393. }
  394. //-- if there isn't any overseer in this firm or this unit's skill is higher than the current overseer's skill --//
  395. //### begin alex 18/10 ###//
  396. unitPtr->group_select_id = 0; // clear group select id
  397. //#### end alex 18/10 ####//
  398. FirmInfo* firmInfo = firm_res[firm_id];
  399. if( firmInfo->need_overseer &&
  400. ( !overseer_recno ||
  401. ( unitPtr->skill.skill_id == firm_skill_id &&
  402. unit_array[overseer_recno]->skill.skill_id != firm_skill_id ) || // the current overseer does not have the required skill
  403. ( unitPtr->skill.skill_id == firm_skill_id &&
  404. unitPtr->skill.skill_level > unit_array[overseer_recno]->skill.skill_level )
  405. ) )
  406. {
  407. assign_overseer(unitRecno);
  408. }
  409. else if( firmInfo->need_worker )
  410. {
  411. assign_worker(unitRecno);
  412. }
  413. }
  414. //--------- End of function Firm::assign_unit -----------//
  415. //--------- Begin of function Firm::assign_overseer --------//
  416. //
  417. // Assign an unit as the overseer of this firm
  418. //
  419. // <int> newOverseerRecno - recno of the new overseer unit.
  420. // 0 means resign the current overseer
  421. //
  422. // Note: If a new overseer is assigned to the firm, there should be
  423. // space for the old overseer to initialize and appear in the
  424. // map (the space the new overseer occupied).
  425. //
  426. // ** If the newOverseerRecno==0, there may be no space for
  427. // creating the old overseer. Then, the old overseer will be
  428. // deleted. **
  429. // ** else there must be space for creating the old overseer,
  430. // at least the space occupied by the new overseer **
  431. //
  432. void Firm::assign_overseer(int newOverseerRecno)
  433. {
  434. if( !firm_res[firm_id]->need_overseer )
  435. return;
  436. if( !newOverseerRecno && !overseer_recno )
  437. return;
  438. //--- if the new overseer's nation is not the same as the firm's nation, don't assign ---//
  439. if( newOverseerRecno && unit_array[newOverseerRecno]->nation_recno != nation_recno )
  440. return;
  441. //------------------------------------------//
  442. int oldOverseerRecno = overseer_recno;
  443. if(!newOverseerRecno)
  444. {
  445. //------------------------------------------------------------------------------------------------//
  446. // the old overseer may be kept in firm or killed if remove_firm is true
  447. //------------------------------------------------------------------------------------------------//
  448. err_when(!overseer_recno);
  449. Unit *oldUnitPtr = unit_array[overseer_recno];
  450. SpriteInfo *spriteInfo = sprite_res[unit_res[oldUnitPtr->unit_id]->sprite_id];
  451. int xLoc = loc_x1;
  452. int yLoc = loc_y1;
  453. if(!locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height))
  454. {
  455. if(remove_firm)
  456. kill_overseer();
  457. }
  458. else
  459. {
  460. //------ there should be space for creating the overseer -----//
  461. mobilize_overseer();
  462. /*
  463. //-- if the overseer is resigned without successor, mobilize a worker as overseer --//
  464. if(!newOverseerRecno && worker_array)
  465. {
  466. int bestWorkerId = best_worker_id(); // find the most skilled worker
  467. if( bestWorkerId )
  468. newOverseerRecno = mobilize_worker(bestWorkerId,1);
  469. }
  470. */
  471. }
  472. }
  473. else
  474. {
  475. //----------- there should be space for creating the overseer ---------//
  476. err_when(!newOverseerRecno);
  477. Unit *unitPtr = unit_array[newOverseerRecno];
  478. int originalXLoc = unitPtr->next_x_loc();
  479. int originalYLoc = unitPtr->next_y_loc();
  480. err_when( unitPtr->hit_points <= 0 );
  481. unitPtr->deinit_sprite();
  482. //----------------------------------------------------------------------------------------//
  483. // There should be at least one location (occupied by the new overseer) for creating the old
  484. // overseer.
  485. //
  486. // 1) If a town is already created, the new overseer settle down there, free its space for
  487. // creating the new overseer.
  488. // 2) If the overseer and the workers live in the firm, no town will be created. Thus, the
  489. // space occupied by the old overseer is free for creating the new overseer.
  490. // 3) If the overseer and the workers need live in town, and a town is created. i.e. there
  491. // is no overseer or worker in the firm, so just assign the new overseer in the firm
  492. //----------------------------------------------------------------------------------------//
  493. if(!overseer_recno && !worker_count)
  494. {
  495. //------------------------------------------------------------------------------------------------//
  496. // the firm is empty
  497. //------------------------------------------------------------------------------------------------//
  498. if(firm_res[firm_id]->live_in_town)
  499. {
  500. overseer_town_recno = assign_settle(unitPtr->race_id, unitPtr->loyalty, 1); // the overseer settles down
  501. if(!overseer_town_recno)
  502. return; // no space for creating the town, just return without assigning
  503. }
  504. //------- set the unit to overseer mode and deinit the sprite ------//
  505. overseer_recno = newOverseerRecno;
  506. Unit *unitPtr = unit_array[overseer_recno];
  507. unitPtr->set_mode(UNIT_MODE_OVERSEE, firm_recno);
  508. unitPtr->deinit_sprite(); // hide the unit from the world map
  509. //--------- if the unit is a spy -----------//
  510. if( unitPtr->spy_recno )
  511. spy_array[unitPtr->spy_recno]->set_place( SPY_FIRM, firm_recno );
  512. /*
  513. //------ capture the firm if the overseer is from another nation ---//
  514. if(unit_array[overseer_recno]->nation_recno != nation_recno)
  515. change_nation(unit_array[overseer_recno]->nation_recno);
  516. */
  517. }
  518. else
  519. {
  520. //------------------------------------------------------------------------------------------------//
  521. // a town should exist if the overseer need live in town
  522. //------------------------------------------------------------------------------------------------//
  523. if(firm_res[firm_id]->live_in_town)
  524. {
  525. overseer_town_recno = assign_settle(unitPtr->race_id, unitPtr->loyalty, 1); // the overseer settles down
  526. if(!overseer_town_recno)
  527. return; // reach max population and no space to create town, return without assigning
  528. }
  529. Unit *unitPtr = unit_array[newOverseerRecno];
  530. unitPtr->deinit_sprite();
  531. if(overseer_recno)
  532. mobilize_overseer();
  533. overseer_recno = newOverseerRecno;
  534. unitPtr->set_mode(UNIT_MODE_OVERSEE, firm_recno);
  535. //--------- if the unit is a spy -----------//
  536. if( unitPtr->spy_recno )
  537. spy_array[unitPtr->spy_recno]->set_place( SPY_FIRM, firm_recno );
  538. /*
  539. //------ capture the firm if the overseer is from another nation ---//
  540. if(unit_array[overseer_recno]->nation_recno != nation_recno)
  541. change_nation(unit_array[overseer_recno]->nation_recno);
  542. */
  543. }
  544. }
  545. //------- update loyalty -------//
  546. if( newOverseerRecno && !unit_array.is_deleted(newOverseerRecno) )
  547. unit_array[newOverseerRecno]->update_loyalty();
  548. //----------- refresh display if this firm is selected ----------//
  549. if(firm_array.selected_recno == firm_recno)
  550. info.disp();
  551. }
  552. //----------- End of function Firm::assign_overseer --------//
  553. //--------- Begin of function Firm::mobilize_overseer --------//
  554. //
  555. int Firm::mobilize_overseer()
  556. {
  557. if( !overseer_recno )
  558. return 0;
  559. //--------- restore overseer's harmony ---------//
  560. int overseerRecno = overseer_recno;
  561. Unit* unitPtr = unit_array[overseer_recno];
  562. //-------- if the overseer is a spy -------//
  563. if( unitPtr->spy_recno )
  564. spy_array[unitPtr->spy_recno]->set_place(SPY_MOBILE, unitPtr->sprite_recno);
  565. //---- cancel the overseer's presence in the town -----//
  566. if( firm_res[firm_id]->live_in_town )
  567. town_array[overseer_town_recno]->dec_pop(unitPtr->race_id, 1);
  568. //----- get this overseer out of the firm -----//
  569. SpriteInfo* spriteInfo = sprite_res[unit_res[unitPtr->unit_id]->sprite_id];
  570. int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
  571. int spaceFound = locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height);
  572. if(spaceFound)
  573. {
  574. unitPtr->init_sprite(xLoc, yLoc);
  575. unitPtr->set_mode(0); // reset overseen firm recno
  576. }
  577. else
  578. {
  579. unit_array.del(overseer_recno); // delete it when there is no space for the unit
  580. return 0;
  581. }
  582. //--------- reset overseer_recno -------------//
  583. overseer_recno = 0;
  584. overseer_town_recno = 0;
  585. //------- update loyalty -------//
  586. if( overseerRecno && !unit_array.is_deleted(overseerRecno) )
  587. unit_array[overseerRecno]->update_loyalty();
  588. return overseerRecno;
  589. }
  590. //----------- End of function Firm::mobilize_overseer --------//
  591. //--------- Begin of function Firm::mobilize_builder --------//
  592. int Firm::mobilize_builder(short recno)
  593. {
  594. //----------- mobilize the builder -------------//
  595. Unit* unitPtr = unit_array[recno];
  596. SpriteInfo *spriteInfo = unitPtr->sprite_info;
  597. int xLoc=loc_x1, yLoc=loc_y1;
  598. if(!locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height, UNIT_LAND, builder_region_id) &&
  599. !world.locate_space(xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height, UNIT_LAND, builder_region_id))
  600. {
  601. kill_builder(recno);
  602. return 0;
  603. }
  604. unitPtr->init_sprite(xLoc, yLoc);
  605. unitPtr->stop2(); // clear all previously defined action
  606. err_when(unitPtr->unit_mode != UNIT_MODE_CONSTRUCT);
  607. unitPtr->set_mode(0);
  608. return 1;
  609. }
  610. //----------- End of function Firm::mobilize_builder --------//
  611. //--------- Begin of function Firm::best_worker_id --------//
  612. //
  613. int Firm::best_worker_id()
  614. {
  615. int bestWorkerId=0, maxWorkerSkill=0;
  616. char rankId;
  617. int liveInTown = firm_res[firm_id]->live_in_town;
  618. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  619. for( int i=0 ; i<worker_count ; i++ )
  620. {
  621. //--- if the town the worker lives and the firm are of the same nation ---//
  622. if( !liveInTown || town_array[ worker_array[i].town_recno ]->nation_recno == nation_recno )
  623. {
  624. if(firm_id==FIRM_CAMP)
  625. {
  626. rankId = worker_array[i].rank_id;
  627. if(rankId!=RANK_GENERAL && rankId!=RANK_KING)
  628. continue;
  629. }
  630. if( worker_array[i].skill_level > maxWorkerSkill )
  631. {
  632. maxWorkerSkill = worker_array[i].skill_level;
  633. bestWorkerId = i+1;
  634. }
  635. }
  636. }
  637. return bestWorkerId;
  638. }
  639. //----------- End of function Firm::best_worker_id --------//
  640. //--------- Begin of function Firm::free_worker_room --------//
  641. //
  642. // Resign the worst worker from the firm to free up a room for
  643. // a new worker.
  644. //
  645. void Firm::free_worker_room()
  646. {
  647. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  648. //---- if there is space for one more worker, demote the overseer to worker ----//
  649. if( worker_count < MAX_WORKER || worker_count==0 )
  650. return;
  651. //---- if all worker space are full, resign the worst worker to release one worker space for the overseer ----//
  652. int worestWorkerId=0, minWorkerSkill=0x7FFF;
  653. for( int i=0 ; i<MAX_WORKER ; i++ )
  654. {
  655. if( worker_array[i].skill_level < minWorkerSkill )
  656. {
  657. minWorkerSkill = worker_array[i].skill_level;
  658. worestWorkerId = i+1;
  659. }
  660. }
  661. if( worestWorkerId )
  662. resign_worker(worestWorkerId);
  663. err_here();
  664. }
  665. //----------- End of function Firm::free_worker_room --------//
  666. //--------- Begin of function Firm::assign_worker --------//
  667. //
  668. // Assign an unit as one of the workers of this firm
  669. //
  670. void Firm::assign_worker(int workerUnitRecno)
  671. {
  672. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  673. //-- if the unit is a spy, only allow assign when there is room in the firm --//
  674. Unit* unitPtr = unit_array[workerUnitRecno];
  675. if( unitPtr->true_nation_recno() != nation_recno &&
  676. worker_count == MAX_WORKER )
  677. {
  678. return;
  679. }
  680. //---- if all worker space are full, resign the worst worker to release one worker space for the overseer ----//
  681. err_when( unitPtr->rank_id == RANK_KING );
  682. err_when( unitPtr->hit_points <= 0 );
  683. int unitXLoc= -1, unitYLoc;
  684. if( worker_count == MAX_WORKER )
  685. {
  686. int worstWorkerId=0, minWorkerSkill=0x7FFF, workerSkill;
  687. for(int i=0; i<MAX_WORKER; i++)
  688. {
  689. workerSkill = worker_array[i].skill_level;
  690. if( workerSkill < minWorkerSkill)
  691. {
  692. minWorkerSkill = workerSkill;
  693. worstWorkerId = i+1;
  694. }
  695. }
  696. err_when(worstWorkerId<1 || worstWorkerId>MAX_WORKER);
  697. unitXLoc = unitPtr->next_x_loc(); // save the location for later init_sprite() if the assign settle action failed
  698. unitYLoc = unitPtr->next_y_loc();
  699. unitPtr->deinit_sprite(); // free the location for creating the worst unit
  700. #ifdef DEBUG
  701. int oldWorkerCount = worker_count;
  702. int resignResult = resign_worker(worstWorkerId);
  703. err_when(!resignResult && oldWorkerCount==worker_count);
  704. #else
  705. resign_worker(worstWorkerId);
  706. #endif
  707. }
  708. // err_when( worker_count >= MAX_WORKER );
  709. //---------- there is room for the new worker ------------//
  710. Worker* workerPtr = worker_array + worker_count;
  711. memset( workerPtr, 0, sizeof(Worker) );
  712. if( firm_res[firm_id]->live_in_town )
  713. {
  714. workerPtr->town_recno = assign_settle(unitPtr->race_id, unitPtr->loyalty, 0); // the worker settles down
  715. if( !workerPtr->town_recno )
  716. {
  717. //--- the unit was deinit_sprite(), and now the assign settle action failed, we need to init_sprite() to restore it ---//
  718. if( unitXLoc>=0 && !unitPtr->is_visible() )
  719. unitPtr->init_sprite(unitXLoc, unitYLoc);
  720. return;
  721. }
  722. }
  723. else
  724. {
  725. workerPtr->town_recno = 0;
  726. workerPtr->worker_loyalty = unitPtr->loyalty;
  727. }
  728. //------- add the worker to the firm -------//
  729. worker_count++;
  730. err_when( worker_count > MAX_WORKER );
  731. workerPtr->name_id = unitPtr->name_id;
  732. workerPtr->race_id = unitPtr->race_id;
  733. workerPtr->unit_id = unitPtr->unit_id;
  734. workerPtr->rank_id = unitPtr->rank_id;
  735. workerPtr->skill_id = firm_skill_id;
  736. workerPtr->skill_level = unitPtr->skill.get_skill(firm_skill_id);
  737. if( workerPtr->skill_level == 0 )
  738. workerPtr->skill_level = CITIZEN_SKILL_LEVEL;
  739. err_when( workerPtr->skill_level<0 );
  740. err_when( workerPtr->skill_level>100 );
  741. /*#ifdef DEBUG2
  742. if(unit_res[unitPtr->unit_id]->unit_class==UNIT_CLASS_HUMAN)
  743. {
  744. unitPtr->skill.combat_level = 60;
  745. unitPtr->hit_points = unitPtr->skill.combat_level*2;
  746. unitPtr->max_hit_points = unitPtr->hit_points;
  747. }
  748. #endif*/
  749. workerPtr->combat_level = unitPtr->skill.combat_level;
  750. workerPtr->hit_points = (int) unitPtr->hit_points;
  751. err_when( workerPtr->combat_level <= 0 || workerPtr->combat_level > 100 );
  752. err_when( workerPtr->hit_points < 0 );
  753. if( workerPtr->hit_points == 0 ) // 0.? will become 0 in (float) to (int) conversion
  754. workerPtr->hit_points = 1;
  755. if( unit_res[unitPtr->unit_id]->unit_class == UNIT_CLASS_WEAPON )
  756. {
  757. workerPtr->extra_para = unitPtr->get_weapon_version();
  758. }
  759. else if( unitPtr->race_id )
  760. {
  761. workerPtr->extra_para = unitPtr->cur_power;
  762. }
  763. else
  764. {
  765. workerPtr->extra_para = 0;
  766. }
  767. workerPtr->init_potential();
  768. //------ if the recruited worker is a spy -----//
  769. if( unitPtr->spy_recno )
  770. {
  771. spy_array[unitPtr->spy_recno]->set_place( SPY_FIRM, firm_recno );
  772. workerPtr->spy_recno = unitPtr->spy_recno;
  773. unitPtr->spy_recno = 0; // reset it now so Unit::deinit() won't delete the Spy in spy_array
  774. }
  775. //--------- the unit disappear in firm -----//
  776. if( !firm_res[firm_id]->live_in_town ) // if the unit does not live in town, increase the unit count now
  777. unit_res[unitPtr->unit_id]->inc_nation_unit_count(nation_recno);
  778. unit_array.disappear_in_firm(workerUnitRecno);
  779. }
  780. //----------- End of function Firm::assign_worker --------//
  781. //--------- Begin of function Firm::assign_settle --------//
  782. //
  783. // The newly assigned overseer / worker settles down.
  784. //
  785. // <int> raceId - race id. of the unit
  786. // <int> unitLoyalty - loyalty of the unit
  787. // <int> isOverseer - whether the unit is an overseer, if not,
  788. // it is then a worker.
  789. //
  790. // return: <int> townRecno - the home town of the overseer/worker
  791. // 0 - no space to settle.
  792. //
  793. int Firm::assign_settle(int raceId, int unitLoyalty, int isOverseer)
  794. {
  795. err_when( !firm_res[firm_id]->live_in_town );
  796. err_when( unitLoyalty < 0 || unitLoyalty > 100 );
  797. //--- if there is a town of our nation within the effective distance ---//
  798. int townRecno = find_settle_town();
  799. if( townRecno )
  800. {
  801. town_array[townRecno]->inc_pop(raceId, 1, unitLoyalty);
  802. return townRecno;
  803. }
  804. //--- should create a town near the this firm, if there is no other town in the map ---//
  805. int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
  806. if( world.locate_space( xLoc, yLoc, loc_x2, loc_y2, STD_TOWN_LOC_WIDTH,
  807. STD_TOWN_LOC_HEIGHT, UNIT_LAND, region_id, 1 ) ) // the town must be in the same region as this firm.
  808. {
  809. if( m.points_distance( center_x, center_y, xLoc+(STD_TOWN_LOC_WIDTH-1)/2,
  810. yLoc+(STD_TOWN_LOC_HEIGHT-1)/2 ) <= EFFECTIVE_FIRM_TOWN_DISTANCE )
  811. {
  812. int townRecno = town_array.add_town( nation_recno, raceId, xLoc, yLoc );
  813. Town* townPtr = town_array[townRecno];
  814. townPtr->init_pop( raceId, 1, unitLoyalty, 1 ); // 1st 1 - population, 2nd 1 - the unit has a job already
  815. townPtr->auto_set_layout();
  816. return townRecno;
  817. }
  818. }
  819. //---- not able to find a space for a new town within the effective distance ----//
  820. return 0;
  821. }
  822. //----------- End of function Firm::assign_settle --------//
  823. //--------- Begin of function Firm::find_settle_town --------//
  824. //
  825. // Find a suitable town for the unit to settle.
  826. //
  827. int Firm::find_settle_town()
  828. {
  829. int townDistance, minDistance=0x7FFF, nearestTownRecno=0;
  830. Town* townPtr;
  831. Nation* nationPtr = nation_array[nation_recno];
  832. //-------- scan for our own town first -----------//
  833. for( int i=0 ; i<linked_town_count ; i++ )
  834. {
  835. townPtr = town_array[ linked_town_array[i] ];
  836. if( townPtr->population>=MAX_TOWN_POPULATION )
  837. continue;
  838. if( townPtr->nation_recno != nation_recno )
  839. continue;
  840. townDistance = m.points_distance( townPtr->center_x, townPtr->center_y, center_x, center_y );
  841. if( townDistance < minDistance )
  842. {
  843. minDistance = townDistance;
  844. nearestTownRecno = townPtr->town_recno;
  845. }
  846. }
  847. if( nearestTownRecno )
  848. return nearestTownRecno;
  849. else
  850. return 0;
  851. }
  852. //----------- End of function Firm::find_settle_town --------//
  853. //--------- Begin of function Firm::set_world_matrix --------//
  854. //
  855. // Set the cargo id of current firm int he world matrix
  856. //
  857. void Firm::set_world_matrix()
  858. {
  859. //--- if a nation set up a firm in a location that the player has explored, contact between the nation and the player is established ---//
  860. int xLoc, yLoc;
  861. for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
  862. {
  863. for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
  864. {
  865. world.get_loc(xLoc, yLoc)->set_firm(firm_recno);
  866. }
  867. }
  868. //--- if a nation set up a town in a location that the player has explored, contact between the nation and the player is established ---//
  869. establish_contact_with_player();
  870. //------------ reveal new land ----------//
  871. if( nation_recno == nation_array.player_recno ||
  872. (nation_recno && nation_array[nation_recno]->is_allied_with_player) )
  873. {
  874. world.unveil( loc_x1, loc_y1, loc_x2, loc_y2 );
  875. world.visit( loc_x1, loc_y1, loc_x2, loc_y2, EXPLORE_RANGE-1 );
  876. }
  877. //-------- set should_set_power --------//
  878. should_set_power = get_should_set_power();
  879. //---- set this town's influence on the map ----//
  880. if( should_set_power )
  881. world.set_power(loc_x1, loc_y1, loc_x2, loc_y2, nation_recno);
  882. //---- if the newly built firm is visual in the zoom window, redraw the zoom buffer ----//
  883. if( is_in_zoom_win() )
  884. sys.zoom_need_redraw = 1; // set the flag on so it will be redrawn in the next frame
  885. }
  886. //----------- End of function Firm::set_world_matrix --------//
  887. //--------- Begin of function Firm::get_should_set_power --------//
  888. //
  889. int Firm::get_should_set_power()
  890. {
  891. int shouldSetPower = 1;
  892. if( firm_id == FIRM_HARBOR ) // don't set power for harbors
  893. {
  894. shouldSetPower = 0;
  895. }
  896. else if( firm_id == FIRM_MARKET )
  897. {
  898. //--- don't set power for a market if it's linked to another nation's town ---//
  899. Town *townPtr;
  900. shouldSetPower = 0;
  901. //--- only set the shouldSetPower to 1 if the market is linked to a firm of ours ---//
  902. for( int i=0 ; i<linked_town_count ; i++ )
  903. {
  904. townPtr = town_array[ linked_town_array[i] ];
  905. if( townPtr->nation_recno == nation_recno )
  906. {
  907. shouldSetPower = 1;
  908. break;
  909. }
  910. }
  911. }
  912. return shouldSetPower;
  913. }
  914. //----------- End of function Firm::get_should_set_power --------//
  915. //------- Begin of function Firm::establish_contact_with_player --------//
  916. //
  917. // See if the town's location is an explored area, establish contact
  918. // with the player.
  919. //
  920. void Firm::establish_contact_with_player()
  921. {
  922. if( !nation_recno )
  923. return;
  924. int xLoc, yLoc;
  925. Location* locPtr;
  926. for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
  927. {
  928. for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
  929. {
  930. locPtr = world.get_loc(xLoc, yLoc);
  931. locPtr->set_firm(firm_recno);
  932. if( locPtr->explored() && nation_array.player_recno )
  933. {
  934. NationRelation *relation = (~nation_array)->get_relation(nation_recno);
  935. if( !remote.is_enable() )
  936. {
  937. relation->has_contact = 1;
  938. }
  939. else
  940. {
  941. if( !relation->has_contact && !relation->contact_msg_flag )
  942. {
  943. // packet structure : <player nation> <explored nation>
  944. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short));
  945. *shortPtr = nation_array.player_recno;
  946. shortPtr[1] = nation_recno;
  947. relation->contact_msg_flag = 1;
  948. }
  949. }
  950. }
  951. }
  952. }
  953. }
  954. //-------- End of function Firm::establish_contact_with_player --------//
  955. //--------- Begin of function Firm::restore_world_matrix --------//
  956. //
  957. // When the firm is destroyed, restore the original land id
  958. //
  959. void Firm::restore_world_matrix()
  960. {
  961. int xLoc, yLoc;
  962. for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
  963. {
  964. for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
  965. {
  966. err_when( world.get_loc(xLoc,yLoc)->firm_recno() != firm_recno );
  967. world.get_loc(xLoc,yLoc)->remove_firm();
  968. }
  969. }
  970. //---- restore this town's influence on the map ----//
  971. if( should_set_power ) // no power region for harbor as it build on coast which cannot be set with power region
  972. world.restore_power(loc_x1, loc_y1, loc_x2, loc_y2, 0, firm_recno);
  973. //---- if the newly built firm is visual in the zoom window, redraw the zoom buffer ----//
  974. if( is_in_zoom_win() )
  975. sys.zoom_need_redraw = 1;
  976. }
  977. //----------- End of function Firm::restore_world_matrix --------//
  978. //---------- Begin of function Firm::own_firm --------//
  979. //
  980. int Firm::own_firm()
  981. {
  982. return nation_recno == nation_array.player_recno;
  983. }
  984. //----------- End of function Firm::own_firm ---------//
  985. //---------- Begin of function Firm::process_animation --------//
  986. //
  987. void Firm::process_animation()
  988. {
  989. //-------- process animation ----------//
  990. FirmBuild* firmBuild = firm_res.get_build(firm_build_id);
  991. int frameCount = firmBuild->frame_count;
  992. if( frameCount==1 ) // no animation for this firm
  993. return;
  994. //---------- next frame -----------//
  995. if( --remain_frame_delay==0 ) // if it is in the delay between frames
  996. {
  997. remain_frame_delay = (char) firmBuild->frame_delay(cur_frame);
  998. if( ++cur_frame > frameCount )
  999. {
  1000. if( firmBuild->animate_full_size )
  1001. cur_frame = 1;
  1002. else
  1003. {
  1004. cur_frame = 2; // start with the 2nd frame as the 1st frame is the common frame
  1005. err_when( frameCount <=2 ); // for segmented animation, the minimum no. of frames must be 3, as the first one is the common frame
  1006. }
  1007. }
  1008. }
  1009. }
  1010. //---------- End of function Firm::process_animation --------//
  1011. //---------- Begin of function Firm::process_construction --------//
  1012. //
  1013. void Firm::process_construction()
  1014. {
  1015. err_when(firm_id!=FIRM_MONSTER && builder_recno<=0);
  1016. if(firm_id==FIRM_MONSTER)
  1017. {
  1018. //--------- process construction for monster firm ----------//
  1019. hit_points++;
  1020. #ifdef DEBUG
  1021. if( config.fast_build && nation_recno==nation_array.player_recno )
  1022. hit_points += 10;
  1023. #endif;
  1024. if(hit_points>=max_hit_points)
  1025. {
  1026. hit_points = max_hit_points;
  1027. under_construction = 0;
  1028. }
  1029. return;
  1030. }
  1031. err_when(firm_id==FIRM_MONSTER);
  1032. if( !under_construction )
  1033. return;
  1034. //--- can only do construction when the firm is not under attack ---//
  1035. if( info.game_date <= last_attacked_date+1 )
  1036. return;
  1037. if( sys.frame_count%2!=0 ) // one build every 2 frames
  1038. return;
  1039. //------ increase the construction progress ------//
  1040. Unit *unitPtr = unit_array[builder_recno];
  1041. if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION ) // if builder unit has construction skill
  1042. hit_points += 1+unitPtr->skill.skill_level/30;
  1043. else
  1044. hit_points++;
  1045. if( config.fast_build && nation_recno==nation_array.player_recno )
  1046. hit_points += 10;
  1047. //----- increase skill level of the builder unit -----//
  1048. if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION ) // if builder unit has construction skill
  1049. {
  1050. if( ++unitPtr->skill.skill_level_minor > 100 )
  1051. {
  1052. unitPtr->skill.skill_level_minor = 0;
  1053. if( unitPtr->skill.skill_level < 100 )
  1054. unitPtr->skill.skill_level++;
  1055. }
  1056. }
  1057. //------- when the construction is complete ----------//
  1058. if( hit_points >= max_hit_points ) // finished construction
  1059. {
  1060. hit_points = max_hit_points;
  1061. int needAssignUnit=0;
  1062. under_construction = 0;
  1063. // ##### begin Gilbert 10/10 #######//
  1064. if( nation_recno == nation_array.player_recno )
  1065. se_res.far_sound(center_x, center_y, 1, 'S', unitPtr->sprite_id,
  1066. "FINS", 'F', firm_id);
  1067. // ##### end Gilbert 10/10 #######//
  1068. err_when(builder_recno<=0 || unit_array.is_deleted(builder_recno));
  1069. err_when(unitPtr->nation_recno!=nation_recno);
  1070. FirmInfo* firmInfo=firm_res[firm_id];
  1071. if( (firmInfo->need_overseer || firmInfo->need_worker) &&
  1072. (firmInfo->firm_skill_id==0 || firmInfo->firm_skill_id == (unitPtr->skill).skill_id) ) // the builder with the skill required
  1073. {
  1074. unitPtr->set_mode(0); // reset it from UNIT_MODE_CONSTRUCT
  1075. needAssignUnit=1;
  1076. }
  1077. else
  1078. {
  1079. set_builder(0);
  1080. }
  1081. //---------------------------------------------------------------------------------------//
  1082. // should call assign_unit() first before calling action_finished(...UNDER_CONSTRUCTION)
  1083. //---------------------------------------------------------------------------------------//
  1084. if( needAssignUnit )
  1085. {
  1086. assign_unit(builder_recno);
  1087. //------------------------------------------------------------------------------//
  1088. // Note: there may be chance the unit cannot be assigned into the firm
  1089. //------------------------------------------------------------------------------//
  1090. if(!worker_count && !overseer_recno) // no assignment, can't assign
  1091. {
  1092. //------- init_sprite or delete the builder ---------//
  1093. int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
  1094. SpriteInfo *spriteInfo = unitPtr->sprite_info;
  1095. if(!locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height))
  1096. unit_array.disappear_in_firm(builder_recno); // kill the unit
  1097. else
  1098. unitPtr->init_sprite(xLoc, yLoc); // restore the unit
  1099. }
  1100. }
  1101. // ##### begin Gilbert 10/10 #######//
  1102. //if( nation_recno == nation_array.player_recno )
  1103. // se_res.far_sound(center_x, center_y, 1, 'S', unitPtr->sprite_id,
  1104. // "FINS", 'F', firm_id);
  1105. // ##### end Gilbert 10/10 #######//
  1106. builder_recno = 0;
  1107. }
  1108. err_when (hit_points < 0 || hit_points > max_hit_points );
  1109. }
  1110. //---------- End of function Firm::process_construction --------//
  1111. //---------- Begin of function Firm::set_builder --------//
  1112. //
  1113. // <short> newBuilderRecno - >0 the recno of the new builder unit.
  1114. // 0 just remove the existing builder, do not assign new one.
  1115. //
  1116. // return: <int> 0-the old builder is killed
  1117. // 1-the builder is changed successfully.
  1118. //
  1119. int Firm::set_builder(short newBuilderRecno)
  1120. {
  1121. err_when( under_construction && newBuilderRecno==0 ); // can't remove the construction worker when the firm is under construction
  1122. //------------------------------------//
  1123. short oldBuilderRecno = builder_recno; // store the old builder recno
  1124. builder_recno = newBuilderRecno;
  1125. //-------- assign the new builder ---------//
  1126. if(builder_recno)
  1127. {
  1128. Unit* unitPtr = unit_array[builder_recno];
  1129. //### begin alex 18/10 ###//
  1130. unitPtr->group_select_id = 0; // clear group select id
  1131. //#### end alex 18/10 ####//
  1132. if(unitPtr->is_visible()) // is visible if the unit is not inside the firm location
  1133. {
  1134. builder_region_id = world.get_region_id( unitPtr->cur_x_loc(), unitPtr->cur_y_loc() );
  1135. unitPtr->deinit_sprite();
  1136. if( unitPtr->selected_flag )
  1137. {
  1138. unitPtr->selected_flag = 0;
  1139. unit_array.selected_count--;
  1140. }
  1141. }
  1142. err_when( unitPtr->unit_mode != 0 );
  1143. unitPtr->set_mode( UNIT_MODE_CONSTRUCT, firm_recno );
  1144. }
  1145. if(oldBuilderRecno)
  1146. mobilize_builder(oldBuilderRecno);
  1147. return 1;
  1148. }
  1149. //---------- End of function Firm::set_builder --------//
  1150. //---------- Begin of function Firm::next_day --------//
  1151. //
  1152. void Firm::next_day()
  1153. {
  1154. if( !nation_recno )
  1155. return;
  1156. //------ think about updating link status -------//
  1157. //
  1158. // This part must be done here instead of in
  1159. // process_ai() because it will be too late to do
  1160. // it in process_ai() as the next_day() will call
  1161. // first and some wrong goods may be input to markets.
  1162. //
  1163. //-----------------------------------------------//
  1164. if( firm_ai )
  1165. {
  1166. if( info.game_date%30==firm_recno%30 || !ai_link_checked ) // once 30 days or when the link has been changed.
  1167. {
  1168. ai_update_link_status();
  1169. ai_link_checked = 1;
  1170. }
  1171. }
  1172. //-------- pay expenses ----------//
  1173. pay_expense();
  1174. //------- update loyalty --------//
  1175. if( info.game_date%30 == firm_recno%30 )
  1176. update_loyalty();
  1177. //-------- consume food --------//
  1178. if( !firm_res[firm_id]->live_in_town && worker_count>0 )
  1179. consume_food();
  1180. //------ think worker migration -------//
  1181. if( worker_array && info.game_date%30 == firm_recno%30 )
  1182. think_worker_migrate();
  1183. //--------- repairing ----------//
  1184. process_repair();
  1185. //------ catching spies -------//
  1186. if( info.game_date%30 == firm_recno%30 )
  1187. spy_array.catch_spy(SPY_FIRM, firm_recno);
  1188. //----- process workers from other town -----//
  1189. if( firm_res[firm_id]->live_in_town )
  1190. {
  1191. process_independent_town_worker();
  1192. }
  1193. //--- recheck no_neighbor_space after a period, there may be new space available now ---//
  1194. if( no_neighbor_space && info.game_date%180 == firm_recno%180 )
  1195. {
  1196. short buildXLoc, buildYLoc;
  1197. if( nation_array[nation_recno]->find_best_firm_loc(FIRM_INN, loc_x1, loc_y1, buildXLoc, buildYLoc) ) // whether it's FIRM_INN or not really doesn't matter, just any firm type will do
  1198. no_neighbor_space = 0;
  1199. }
  1200. //-------- debug code ---------//
  1201. #ifdef DEBUG
  1202. err_when( builder_recno && unit_array.is_deleted(builder_recno) );
  1203. if( worker_array )
  1204. {
  1205. for( int i=0 ; i<worker_count ; i++ )
  1206. err_when( worker_array[i].hit_points <= 0 );
  1207. }
  1208. if( overseer_recno )
  1209. {
  1210. err_when( unit_array[overseer_recno]->rank_id == RANK_SOLDIER );
  1211. }
  1212. #endif
  1213. }
  1214. //----------- End of function Firm::next_day ---------//
  1215. //---------- Begin of function Firm::next_month --------//
  1216. //
  1217. void Firm::next_month()
  1218. {
  1219. //------ update nation power recno ------//
  1220. int newShouldSetPower = get_should_set_power();
  1221. if( newShouldSetPower == should_set_power )
  1222. return;
  1223. if( should_set_power )
  1224. world.restore_power(loc_x1, loc_y1, loc_x2, loc_y2, 0, firm_recno);
  1225. should_set_power = newShouldSetPower;
  1226. if( should_set_power )
  1227. world.set_power(loc_x1, loc_y1, loc_x2, loc_y2, nation_recno);
  1228. }
  1229. //----------- End of function Firm::next_month ---------//
  1230. //---------- Begin of function Firm::next_year --------//
  1231. //
  1232. void Firm::next_year()
  1233. {
  1234. //------- post income data --------//
  1235. last_year_income = cur_year_income;
  1236. cur_year_income = (float) 0;
  1237. }
  1238. //----------- End of function Firm::next_year ---------//
  1239. //---------- Begin of function Firm::update_loyalty --------//
  1240. //
  1241. void Firm::update_loyalty()
  1242. {
  1243. if( firm_res[firm_id]->live_in_town ) // only for those who do not live in town
  1244. return;
  1245. //----- update loyalty of the soldiers -----//
  1246. Worker* workerPtr = worker_array;
  1247. for( int i=0 ; i<worker_count ; i++, workerPtr++ )
  1248. {
  1249. int targetLoyalty = workerPtr->target_loyalty(firm_recno);
  1250. if( targetLoyalty > workerPtr->worker_loyalty )
  1251. {
  1252. int incValue = (targetLoyalty - workerPtr->worker_loyalty)/10;
  1253. int newLoyalty = (int) workerPtr->worker_loyalty + max(1, incValue);
  1254. if( newLoyalty > targetLoyalty )
  1255. newLoyalty = targetLoyalty;
  1256. workerPtr->worker_loyalty = newLoyalty;
  1257. }
  1258. else if( targetLoyalty < workerPtr->worker_loyalty )
  1259. {
  1260. workerPtr->worker_loyalty--;
  1261. }
  1262. }
  1263. }
  1264. //----------- End of function Firm::update_loyalty ---------//
  1265. //---------- Begin of function Firm::process_repair --------//
  1266. //
  1267. void Firm::process_repair()
  1268. {
  1269. if( nation_array[nation_recno]->cash < 0 ) // if you don't have cash, the repair workers will not work
  1270. return;
  1271. if( !builder_recno )
  1272. return;
  1273. Unit *unitPtr = unit_array[builder_recno];
  1274. //--- can only do construction when the firm is not under attack ---//
  1275. if( info.game_date <= last_attacked_date+1 )
  1276. {
  1277. //---- if the construction worker is a spy, it will damage the building when the building is under attack ----//
  1278. if( unitPtr->spy_recno &&
  1279. unitPtr->true_nation_recno() != nation_recno )
  1280. {
  1281. hit_points -= (float) spy_array[unitPtr->spy_recno]->spy_skill / 30;
  1282. if( hit_points < 0 )
  1283. hit_points = (float) 0;
  1284. }
  1285. return;
  1286. }
  1287. //------- repair now - only process once every 3 days -----//
  1288. if( hit_points >= max_hit_points )
  1289. return;
  1290. err_when( unitPtr->skill.skill_id != SKILL_CONSTRUCTION );
  1291. int dayInterval = (100-unitPtr->skill.skill_level)/20+1; // repair once every 1 to 6 days, depending on the skill level of the construction worker
  1292. if( firm_recno % dayInterval == info.game_date % dayInterval )
  1293. {
  1294. hit_points++;
  1295. if( hit_points > max_hit_points )
  1296. hit_points = max_hit_points;
  1297. }
  1298. }
  1299. //----------- End of function Firm::process_repair ---------//
  1300. //---------- Begin of function Firm::pay_expense --------//
  1301. //
  1302. void Firm::pay_expense()
  1303. {
  1304. if( !nation_recno )
  1305. return;
  1306. Nation* nationPtr = nation_array[nation_recno];
  1307. //-------- fixed expenses ---------//
  1308. float dayExpense = (float) firm_res[firm_id]->year_cost / 365;
  1309. if( nationPtr->cash >= dayExpense )
  1310. {
  1311. nationPtr->add_expense( EXPENSE_FIRM, dayExpense, 1 );
  1312. }
  1313. else
  1314. {
  1315. if( hit_points > 0 )
  1316. hit_points--;
  1317. if( hit_points < 0 )
  1318. hit_points = (float) 0;
  1319. //--- when the hit points drop to zero and the firm is destroyed ---//
  1320. if( hit_points==0 && nation_recno == nation_array.player_recno )
  1321. news_array.firm_worn_out(firm_recno);
  1322. }
  1323. //----- paying salary to workers from other nations -----//
  1324. if( worker_array && firm_res[firm_id]->live_in_town )
  1325. {
  1326. int townNationRecno, payWorkerCount=0;
  1327. Worker* workerPtr;
  1328. for( int i=worker_count-1 ; i>=0 ; i-- )
  1329. {
  1330. workerPtr = worker_array+i;
  1331. townNationRecno = town_array[workerPtr->town_recno]->nation_recno;
  1332. if( townNationRecno != nation_recno )
  1333. {
  1334. //--- if we don't have cash to pay the foreign workers, resign them ---//
  1335. if( nationPtr->cash < 0 )
  1336. {
  1337. resign_worker(i+1);
  1338. }
  1339. else //----- pay salaries to the foreign workers now -----//
  1340. {
  1341. payWorkerCount++;
  1342. if( townNationRecno ) // the nation of the worker will get income
  1343. nation_array[townNationRecno]->add_income( INCOME_FOREIGN_WORKER, (float) WORKER_YEAR_SALARY / 365, 1 );
  1344. }
  1345. }
  1346. }
  1347. nationPtr->add_expense( EXPENSE_FOREIGN_WORKER, (float) WORKER_YEAR_SALARY * payWorkerCount / 365, 1 );
  1348. }
  1349. }
  1350. //----------- End of function Firm::pay_expense ---------//
  1351. //--------- Begin of function Firm::consume_food ---------//
  1352. //
  1353. void Firm::consume_food()
  1354. {
  1355. if( nation_array[nation_recno]->food > 0 )
  1356. {
  1357. int humanUnitCount=0;
  1358. for( int i=0 ; i<worker_count ; i++ )
  1359. {
  1360. if( worker_array[i].race_id )
  1361. humanUnitCount++;
  1362. }
  1363. nation_array[nation_recno]->consume_food((float) humanUnitCount * PERSON_FOOD_YEAR_CONSUMPTION / 365);
  1364. }
  1365. else //--- decrease loyalty if the food has been run out ---//
  1366. {
  1367. if( info.game_date%NO_FOOD_LOYALTY_DECREASE_INTERVAL == 0 ) // decrease 1 loyalty point every 2 days
  1368. {
  1369. for( int i=0 ; i<worker_count ; i++ )
  1370. {
  1371. if( worker_array[i].race_id )
  1372. worker_array[i].change_loyalty(-1);
  1373. }
  1374. }
  1375. }
  1376. }
  1377. //----------- End of function Firm::consume_food -----------//
  1378. //---------- Begin of function Firm::add_income --------//
  1379. //
  1380. void Firm::add_income(int incomeType, float incomeAmt)
  1381. {
  1382. cur_year_income += incomeAmt;
  1383. nation_array[nation_recno]->add_income(incomeType, incomeAmt, 1);
  1384. }
  1385. //----------- End of function Firm::add_income ---------//
  1386. //--------- Begin of function Firm::year_expense ---------//
  1387. //
  1388. // Return the yearly expense for this firm.
  1389. //
  1390. int Firm::year_expense()
  1391. {
  1392. int totalExpense = firm_res[firm_id]->year_cost;
  1393. //---- pay salary to workers from foreign towns ----//
  1394. int payWorkerCount=0;
  1395. if( worker_array && firm_res[firm_id]->live_in_town )
  1396. {
  1397. int payWorkerCount=0;
  1398. Worker* workerPtr = worker_array;
  1399. for( int i=0 ; i<worker_count ; i++, workerPtr++ )
  1400. {
  1401. if( town_array[workerPtr->town_recno]->nation_recno != nation_recno )
  1402. payWorkerCount++;
  1403. }
  1404. totalExpense += WORKER_YEAR_SALARY * payWorkerCount;
  1405. }
  1406. return totalExpense;
  1407. }
  1408. //----------- End of function Firm::year_expense -----------//
  1409. //--------- Begin of function Firm::sell_firm ---------//
  1410. void Firm::sell_firm(char remoteAction)
  1411. {
  1412. if( !remoteAction && remote.is_enable() )
  1413. {
  1414. // packet structure : <firm recno>
  1415. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_SELL, sizeof(short));
  1416. *shortPtr = firm_recno;
  1417. return;
  1418. }
  1419. //------- sell at 50% of the original cost -------//
  1420. Nation* nationPtr = nation_array[nation_recno];
  1421. int sellIncome = firm_res[firm_id]->setup_cost / 2 * (int) hit_points / (int) max_hit_points;
  1422. nationPtr->add_income(INCOME_SELL_FIRM, (float)sellIncome);
  1423. se_res.sound(center_x, center_y, 1, 'F', firm_id, "SELL" );
  1424. firm_array.del_firm(firm_recno);
  1425. }
  1426. //----------- End of function Firm::sell_firm -----------//
  1427. //--------- Begin of function Firm::destruct_firm ---------//
  1428. void Firm::destruct_firm(char remoteAction)
  1429. {
  1430. if( !remoteAction && remote.is_enable() )
  1431. {
  1432. // packet structure : <firm recno>
  1433. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_DESTRUCT, sizeof(short));
  1434. *shortPtr = firm_recno;
  1435. return;
  1436. }
  1437. se_res.sound(center_x, center_y, 1, 'F', firm_id, "DEST" );
  1438. firm_array.del_firm(firm_recno);
  1439. }
  1440. //----------- End of function Firm::destruct_firm -----------//
  1441. //--------- Begin of function Firm::cancel_construction ---------//
  1442. //
  1443. // Cancel construction
  1444. //
  1445. void Firm::cancel_construction(char remoteAction)
  1446. {
  1447. if( !remoteAction && remote.is_enable())
  1448. {
  1449. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_CANCEL, sizeof(short));
  1450. shortPtr[0] = firm_recno;
  1451. return;
  1452. }
  1453. //------ get half of the construction cost back -------//
  1454. Nation* nationPtr = nation_array[nation_recno];
  1455. nationPtr->add_expense( EXPENSE_FIRM, (float) -firm_res[firm_id]->setup_cost/2 );
  1456. firm_array.del_firm(firm_recno);
  1457. }
  1458. //----------- End of function Firm::cancel_construction -----------//
  1459. //---------- Begin of function Firm::recruit_worker --------//
  1460. //
  1461. void Firm::recruit_worker()
  1462. {
  1463. if( MAX_WORKER==worker_count )
  1464. return;
  1465. if( info.game_date%5 != firm_recno%5 ) // update population once 10 days
  1466. return;
  1467. err_when( worker_count > MAX_WORKER );
  1468. //-------- pull from neighbor towns --------//
  1469. int i;
  1470. Town* townPtr;
  1471. Nation* nationPtr = nation_array[nation_recno];
  1472. for( i=0 ; i<linked_town_count ; i++ )
  1473. {
  1474. if( linked_town_enable_array[i] != LINK_EE )
  1475. continue;
  1476. townPtr = town_array[linked_town_array[i]];
  1477. //--- don't hire foreign workers if we don't have cash to pay them ---//
  1478. if( nationPtr->cash < 0 && nation_recno != townPtr->nation_recno )
  1479. continue;
  1480. //-------- if the town has any unit ready for jobs -------//
  1481. if( townPtr->jobless_population == 0 )
  1482. continue;
  1483. //---- if nation of the town is not hositle to this firm's nation ---//
  1484. if( pull_town_people(townPtr->town_recno, COMMAND_AUTO) )
  1485. return;
  1486. }
  1487. }
  1488. //----------- End of function Firm::recruit_worker ---------//
  1489. //---------- Begin of function Firm::pull_town_people --------//
  1490. //
  1491. // Pull people from the town. Also called by Town::draw_detect_link_line()
  1492. //
  1493. // <int> townRecno - the town recno which the people are pulled from.
  1494. // [int] raceId - the race of the people to be pulled.
  1495. // if not given, pick one randomly.
  1496. // [int] forcePull - force pull people to to the firm.
  1497. // (default: 0)
  1498. //
  1499. int Firm::pull_town_people(int townRecno, char remoteAction, int raceId, int forcePull)
  1500. {
  1501. if( worker_count == MAX_WORKER ) // this can happen in a multiplayer game as Town::draw_detect_link_line() still have the old worker_count and thus allow this function being called.
  1502. return 0;
  1503. err_when( worker_count > MAX_WORKER );
  1504. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  1505. if(!remoteAction && remote.is_enable() )
  1506. {
  1507. // packet structure : <firm recno> <town recno> <race Id or 0> <force Pull>
  1508. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_PULL_TOWN_PEOPLE, 4*sizeof(short));
  1509. shortPtr[0] = firm_recno;
  1510. shortPtr[1] = townRecno;
  1511. shortPtr[2] = raceId;
  1512. // if raceId == 0, let each player choose the race by random number,
  1513. // to sychronize the random number
  1514. shortPtr[3] = forcePull;
  1515. return 0;
  1516. }
  1517. //---- people in the town go to work for the firm ---//
  1518. Town* townPtr = town_array[townRecno];
  1519. int i, popAdded=0;
  1520. //---- if doesn't specific a race, randomly pick one ----//
  1521. if( !raceId )
  1522. raceId = m.random(MAX_RACE)+1;
  1523. //----------- scan the races -----------//
  1524. for( i=0 ; i<MAX_RACE ; i++ ) // maximum 8 tries
  1525. {
  1526. //---- see if there is any population of this race to move to the firm ----//
  1527. int recruitableCount = townPtr->recruitable_race_pop(raceId,1); // 1-allow recruiting spies
  1528. if( recruitableCount > 0 )
  1529. {
  1530. //----- if the unit is forced to move to the firm ---//
  1531. if( forcePull ) // right-click to force pulling a worker from the village
  1532. {
  1533. if( townPtr->race_loyalty_array[raceId-1] < MIN_RECRUIT_LOYALTY )
  1534. return 0;
  1535. townPtr->recruit_dec_loyalty(raceId);
  1536. }
  1537. else //--- see if the unit will voluntarily move to the firm ---//
  1538. {
  1539. //--- the higher the loyalty is, the higher the chance of working for the firm ---//
  1540. if( townPtr->nation_recno )
  1541. {
  1542. if( m.random( (100-(int)townPtr->race_loyalty_array[raceId-1])/10 ) > 0 )
  1543. return 0;
  1544. }
  1545. else
  1546. {
  1547. if( m.random( (100-(int)townPtr->race_resistance_array[raceId-1][nation_recno-1])/10 ) > 0 )
  1548. return 0;
  1549. }
  1550. }
  1551. //----- get the chance of getting people to your command base is higher when the loyalty is higher ----//
  1552. if( firm_res[firm_id]->live_in_town )
  1553. {
  1554. townPtr->jobless_race_pop_array[raceId-1]--; // decrease the town's population
  1555. townPtr->jobless_population--;
  1556. err_when( townPtr->recruitable_race_pop(raceId,1) < 0 );
  1557. err_when( townPtr->jobless_population < 0 );
  1558. }
  1559. else
  1560. {
  1561. townPtr->dec_pop(raceId, 0);
  1562. }
  1563. //------- add the worker to the firm -----//
  1564. worker_count++;
  1565. err_when( worker_count > MAX_WORKER );
  1566. Worker* workerPtr = worker_array + worker_count - 1;
  1567. memset( workerPtr, 0, sizeof(Worker) );
  1568. workerPtr->race_id = raceId;
  1569. workerPtr->rank_id = RANK_SOLDIER;
  1570. workerPtr->unit_id = (char) race_res[raceId]->basic_unit_id;
  1571. workerPtr->worker_loyalty = (char) townPtr->race_loyalty_array[raceId-1];
  1572. if( firm_res[firm_id]->live_in_town )
  1573. workerPtr->town_recno = townRecno;
  1574. workerPtr->combat_level = CITIZEN_COMBAT_LEVEL;
  1575. workerPtr->hit_points = CITIZEN_HIT_POINTS;
  1576. workerPtr->skill_id = firm_skill_id;
  1577. workerPtr->skill_level = CITIZEN_SKILL_LEVEL;
  1578. workerPtr->init_potential();
  1579. //--------- if this is a military camp ---------//
  1580. //
  1581. // Increase armed unit count of the race of the worker assigned,
  1582. // as when a unit is assigned to a camp, Unit::deinit() will decrease
  1583. // the counter, so we need to increase it back here.
  1584. //
  1585. //---------------------------------------------------//
  1586. if( !firm_res[firm_id]->live_in_town )
  1587. unit_res[workerPtr->unit_id]->inc_nation_unit_count(nation_recno);
  1588. //------ if the recruited worker is a spy -----//
  1589. int spyCount = townPtr->race_spy_count_array[raceId-1];
  1590. if( spyCount >= m.random(recruitableCount)+1 )
  1591. {
  1592. int spyRecno = spy_array.find_town_spy(townRecno, raceId, m.random(spyCount)+1 ); // the 3rd parameter is which spy to recruit
  1593. err_when( !spyRecno );
  1594. workerPtr->spy_recno = spyRecno;
  1595. spy_array[spyRecno]->set_place(SPY_FIRM, firm_recno);
  1596. }
  1597. return 1;
  1598. }
  1599. if( ++raceId > MAX_RACE )
  1600. raceId = 1;
  1601. }
  1602. return 0;
  1603. }
  1604. //----------- End of function Firm::pull_town_people ---------//
  1605. //------ Begin of function Firm::process_independent_town_worker -----//
  1606. //
  1607. // Process workers from independent towns.
  1608. //
  1609. // When workers work for a foreign firm, the overall resistance of
  1610. // the worker's town towards that nation decreases.
  1611. //
  1612. void Firm::process_independent_town_worker()
  1613. {
  1614. if( firm_recno%15 != info.game_date%15 )
  1615. return;
  1616. #define RESISTANCE_DECREASE_PER_WORKER float(0.2) // resistance decrease per month every 15 days
  1617. Town* townPtr;
  1618. for( int i=0 ; i<worker_count ; i++ )
  1619. {
  1620. err_when( !worker_array[i].town_recno );
  1621. townPtr = town_array[ worker_array[i].town_recno ];
  1622. if( townPtr->nation_recno==0 ) // if it's an independent town
  1623. {
  1624. townPtr->race_resistance_array[worker_array[i].race_id-1][nation_recno-1] -= RESISTANCE_DECREASE_PER_WORKER;
  1625. if( townPtr->race_resistance_array[worker_array[i].race_id-1][nation_recno-1] < 0 )
  1626. townPtr->race_resistance_array[worker_array[i].race_id-1][nation_recno-1] = (float) 0;
  1627. }
  1628. }
  1629. }
  1630. //------- End of function Firm::process_independent_town_worker ------//
  1631. //---------- Begin of function Worker::init_potential --------//
  1632. //
  1633. void Worker::init_potential()
  1634. {
  1635. if( m.random(10)==0 ) // 1 out of 10 has a higher than normal potential in this skill
  1636. {
  1637. skill_potential = 50+m.random(51); // 50 to 100 potential
  1638. }
  1639. }
  1640. //----------- End of function Worker::init_potential ---------//
  1641. //---------- Begin of function Firm::calc_productivity --------//
  1642. //
  1643. // Calculate the productivity of the firm.
  1644. //
  1645. void Firm::calc_productivity()
  1646. {
  1647. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  1648. #define RACE_SKILL_MULTIPLE (float)2.0
  1649. productivity = (float) 0;
  1650. //------- calculate the productivity of the workers -----------//
  1651. int i;
  1652. float totalSkill=(float)0;
  1653. Worker* workerPtr = worker_array;
  1654. for( i=0 ; i<worker_count ; i++, workerPtr++ )
  1655. {
  1656. totalSkill += (int) workerPtr->skill_level
  1657. * workerPtr->hit_points / workerPtr->max_hit_points();
  1658. }
  1659. //----- include skill in the calculation ------//
  1660. productivity = totalSkill / MAX_WORKER - sabotage_level;
  1661. if( productivity < 0 )
  1662. productivity = (float) 0;
  1663. }
  1664. //----------- End of function Firm::calc_productivity ---------//
  1665. //---------- Begin of function Firm::average_worker_skill --------//
  1666. //
  1667. // Return the average skill level of the workers in this firm.
  1668. //
  1669. int Firm::average_worker_skill()
  1670. {
  1671. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  1672. if( worker_count==0 )
  1673. return 0;
  1674. //------- calculate the productivity of the workers -----------//
  1675. int i;
  1676. int totalSkill = 0;
  1677. Worker* workerPtr = worker_array;
  1678. for( i=0 ; i<worker_count ; i++, workerPtr++ )
  1679. totalSkill += workerPtr->skill_level;
  1680. //----- include skill in the calculation ------//
  1681. return totalSkill / worker_count;
  1682. }
  1683. //----------- End of function Firm::average_worker_skill ---------//
  1684. //---------- Begin of function Firm::update_worker --------//
  1685. //
  1686. void Firm::update_worker()
  1687. {
  1688. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  1689. if( info.game_date%15 != firm_recno%15 )
  1690. return;
  1691. if( worker_count==0 )
  1692. return;
  1693. //------- update the worker's para ---------//
  1694. int incValue, levelMinor;
  1695. Worker* workerPtr = worker_array;
  1696. for( int i=0 ; i<worker_count ; i++, workerPtr++ )
  1697. {
  1698. //------- increase worker skill -----------//
  1699. if( is_operating() && workerPtr->skill_level < 100 ) // only train when the workers are working
  1700. {
  1701. err_when(workerPtr->skill_level<0 || workerPtr->skill_level>100);
  1702. incValue = max(10, 100-workerPtr->skill_level)
  1703. * workerPtr->hit_points / workerPtr->max_hit_points()
  1704. * (100+workerPtr->skill_potential) / 100 / 2;
  1705. //-------- increase level minor now --------//
  1706. levelMinor = workerPtr->skill_level_minor + incValue * (75+m.random(50)) / 100; // with random factors, resulting in 75% to 125% of the original
  1707. int loopCount=0;
  1708. while( levelMinor >= 100 )
  1709. {
  1710. levelMinor -= 100;
  1711. workerPtr->skill_level++;
  1712. err_when( loopCount++ > 1000 );
  1713. }
  1714. workerPtr->skill_level_minor = levelMinor;
  1715. }
  1716. //------- increase worker hit points --------//
  1717. int maxHitPoints = workerPtr->max_hit_points();
  1718. err_when( maxHitPoints <= 0 );
  1719. if( workerPtr->hit_points < maxHitPoints )
  1720. {
  1721. workerPtr->hit_points += 2; // units in firms recover twice as fast as they are mobile
  1722. if( workerPtr->hit_points > maxHitPoints )
  1723. workerPtr->hit_points = maxHitPoints;
  1724. }
  1725. }
  1726. }
  1727. //----------- End of function Firm::update_worker ---------//
  1728. //---------- Begin of function Firm::create_unit --------//
  1729. //
  1730. // Create an unit and place it below the firm.
  1731. //
  1732. // <int> unitId - id. of the unit
  1733. // [int] townRecno - recno of the town from which the unit comes from
  1734. // if given, it means the unit comes from the town and
  1735. // should decrease the town population.
  1736. // (default: 0)
  1737. // [int] unitHasJob - whether the unit current has a job or not
  1738. // (default: 0)
  1739. //
  1740. // return : <int> unitRecno - the recno of the unit created
  1741. //
  1742. int Firm::create_unit(int unitId, int townRecno, int unitHasJob)
  1743. {
  1744. //----look for an empty locatino for the unit to stand ----//
  1745. //--- scan for the 5 rows right below the building ---//
  1746. SpriteInfo* spriteInfo = sprite_res[unit_res[unitId]->sprite_id];
  1747. int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
  1748. if(!locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height))
  1749. return 0;
  1750. //------------ add the unit now ----------------//
  1751. int unitNationRecno;
  1752. if( townRecno )
  1753. unitNationRecno = town_array[townRecno]->nation_recno;
  1754. else
  1755. unitNationRecno = nation_recno;
  1756. int unitRecno = unit_array.add_unit( unitId, unitNationRecno, RANK_SOLDIER, 0, xLoc, yLoc );
  1757. //----- update the population of the town ------//
  1758. if( townRecno )
  1759. town_array[townRecno]->dec_pop(unit_array[unitRecno]->race_id, unitHasJob);
  1760. return unitRecno;
  1761. }
  1762. //----------- End of function Firm::create_unit ---------//
  1763. //--------- Begin of function Firm::mobilize_worker ---------//
  1764. //
  1765. // Promote a firm worker as a unit.
  1766. //
  1767. // return: <int> the recno of the unit created.
  1768. //
  1769. int Firm::mobilize_worker(int workerId, char remoteAction)
  1770. {
  1771. if(!remoteAction && remote.is_enable() )
  1772. {
  1773. // packet strcture : <firm_recno> <workerId>
  1774. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_MOBL_WORKER, 2*sizeof(short) );
  1775. shortPtr[0] = firm_recno;
  1776. shortPtr[1] = workerId;
  1777. return 0;
  1778. }
  1779. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  1780. err_when( workerId<1 || workerId>worker_count );
  1781. //------------- resign worker --------------//
  1782. Worker thisWorker = worker_array[workerId-1];
  1783. int oldWorkerCount = worker_count;
  1784. int unitRecno2 = resign_worker(workerId);
  1785. if(!unitRecno2 && worker_count==oldWorkerCount)
  1786. return 0;
  1787. //------ create a mobile unit -------//
  1788. int unitRecno=0;
  1789. if( firm_res[firm_id]->live_in_town ) // if does not live_in_town, resign_worker() create the unit already, so don't create it again here.
  1790. {
  1791. unitRecno = create_worker_unit(thisWorker);
  1792. if( !unitRecno ) // no space for creating units
  1793. return 0;
  1794. }
  1795. //------------------------------------//
  1796. err_when( unitRecno2 && unitRecno ); // only one of them should have value
  1797. err_when( !unitRecno2 && !unitRecno ); // one of them must have a value
  1798. if( unitRecno )
  1799. return unitRecno;
  1800. else
  1801. return unitRecno2;
  1802. }
  1803. //----------- End of function Firm::mobilize_worker -----------//
  1804. //--------- Begin of function Firm::create_worker_unit ---------//
  1805. //
  1806. int Firm::create_worker_unit(Worker& thisWorker)
  1807. {
  1808. //--------- copy the worker's info --------//
  1809. int unitLoyalty = thisWorker.loyalty();
  1810. //------------ create an unit --------------//
  1811. int unitId = thisWorker.unit_id;
  1812. int unitRecno = create_unit( unitId, thisWorker.town_recno, 0 ); // this worker no longer has a job as it has been resigned
  1813. if( !unitRecno )
  1814. return 0;
  1815. Unit* unitPtr = unit_array[unitRecno];
  1816. UnitInfo *unitInfo = unit_res[unitId];
  1817. //------- set the unit's parameters --------//
  1818. unitPtr->skill.skill_id = thisWorker.skill_id;
  1819. unitPtr->skill.skill_level = thisWorker.skill_level;
  1820. unitPtr->skill.skill_level_minor = thisWorker.skill_level_minor;
  1821. err_when( unitPtr->skill.skill_level<0 || unitPtr->skill.skill_level>100 );
  1822. unitPtr->set_combat_level(thisWorker.combat_level);
  1823. unitPtr->skill.combat_level_minor = thisWorker.combat_level_minor;
  1824. err_when( unitPtr->skill.combat_level<=0 || unitPtr->skill.combat_level>100 );
  1825. unitPtr->loyalty = unitLoyalty;
  1826. unitPtr->hit_points = thisWorker.hit_points;
  1827. unitPtr->rank_id = thisWorker.rank_id;
  1828. if( unit_res[unitPtr->unit_id]->unit_class == UNIT_CLASS_WEAPON )
  1829. {
  1830. unitPtr->set_weapon_version( thisWorker.extra_para ); // restore nation contribution
  1831. }
  1832. else if( unitPtr->race_id )
  1833. {
  1834. unitPtr->cur_power = thisWorker.extra_para;
  1835. if( unitPtr->cur_power < 0 )
  1836. unitPtr->cur_power = 0;
  1837. if( unitPtr->cur_power > 150 )
  1838. unitPtr->cur_power = 150;
  1839. }
  1840. err_when( unitPtr->hit_points <= 0 );
  1841. unitPtr->fix_attack_info();
  1842. //if( unitInfo->unit_class == UNIT_CLASS_WEAPON )
  1843. //{
  1844. // switch( unitId )
  1845. // {
  1846. // case UNIT_BALLISTA:
  1847. // unitPtr->attack_count = 2;
  1848. // break;
  1849. // case UNIT_EXPLOSIVE_CART:
  1850. // unitPtr->attack_count = 0;
  1851. // break;
  1852. // default:
  1853. // unitPtr->attack_count = 1;
  1854. //}
  1855. // if( unitPtr->attack_count > 0)
  1856. // {
  1857. // unitPtr->attack_info_array = unit_res.attack_info_array
  1858. // + unitInfo->first_attack-1
  1859. // + (thisWorker.extra_para -1) * unitPtr->attack_count; // extra para keeps the weapon version
  1860. // }
  1861. // else
  1862. // {
  1863. // // no attack like explosive cart
  1864. // unitPtr->attack_info_array = NULL;
  1865. // }
  1866. // }
  1867. if( thisWorker.name_id && thisWorker.race_id ) // if this worker is formerly an unit who has a name
  1868. unitPtr->set_name(thisWorker.name_id);
  1869. err_when( !unitPtr->is_visible() );
  1870. //------ if the unit is a spy -------//
  1871. if( thisWorker.spy_recno )
  1872. {
  1873. Spy* spyPtr = spy_array[thisWorker.spy_recno];
  1874. unitPtr->spy_recno = thisWorker.spy_recno;
  1875. unitPtr->ai_unit = spyPtr->cloaked_nation_recno &&
  1876. nation_array[spyPtr->cloaked_nation_recno]->is_ai();
  1877. unitPtr->set_name(spyPtr->name_id); // set the name id. of this unit
  1878. spyPtr->set_place(SPY_MOBILE, unitRecno);
  1879. }
  1880. //--- decrease the nation unit count as the Unit has already increased it ----//
  1881. if( !firm_res[firm_id]->live_in_town ) // if the unit does not live in town, increase the unit count now
  1882. unit_res[unitPtr->unit_id]->dec_nation_unit_count(nation_recno);
  1883. return unitRecno;
  1884. }
  1885. //----------- End of function Firm::create_worker_unit -----------//
  1886. //--------- Begin of function Firm::mobilize_all_worker ---------//
  1887. //
  1888. // mobilize as many as workers if there is space for creating the
  1889. // workers
  1890. //
  1891. // [int] leaderUnitRecno - if given, the workers are assigned as
  1892. // a team and their leader_unit_recno are set.
  1893. // (default: 0)
  1894. //
  1895. void Firm::mobilize_all_worker(int leaderUnitRecno)
  1896. {
  1897. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  1898. //------- detect buttons on hiring firm workers -------//
  1899. int loopCount = 0;
  1900. short unitRecno;
  1901. err_when( worker_count > MAX_WORKER );
  1902. while( worker_count > 0 )
  1903. {
  1904. err_when(++loopCount > 100);
  1905. unitRecno = mobilize_worker(1, COMMAND_AUTO); // always record 1 as the workers info are moved forward from the back to the front
  1906. if(!unitRecno)
  1907. break; // keep the rest workers as there is no space for creating the unit
  1908. if( leaderUnitRecno )
  1909. {
  1910. Unit* unitPtr = unit_array[unitRecno];
  1911. unitPtr->team_id = unit_array.cur_team_id; // define it as a team
  1912. unitPtr->leader_unit_recno = leaderUnitRecno;
  1913. unitPtr->update_loyalty(); // the unit is just assigned to a new leader, set its target loyalty
  1914. err_when( unitPtr->rank_id != RANK_KING && unitPtr->rank_id != RANK_GENERAL );
  1915. if( nation_recno == nation_array.player_recno )
  1916. unitPtr->selected_flag = 1;
  1917. }
  1918. }
  1919. unit_array.cur_team_id++;
  1920. }
  1921. //----------- End of function Firm::mobilize_all_worker -----------//
  1922. //--------- Begin of function Firm::resign_all_worker ---------//
  1923. //
  1924. // Resign all workers in the firm.
  1925. //
  1926. // [int] disappearFlag - whether the worker should disappear after
  1927. // resigning, and does not go back to the town.
  1928. //
  1929. void Firm::resign_all_worker(int disappearFlag)
  1930. {
  1931. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  1932. //------- detect buttons on hiring firm workers -------//
  1933. int loopCount=0, townRecno, raceId;
  1934. int oldWorkerCount;
  1935. while( worker_count > 0 )
  1936. {
  1937. err_when(++loopCount > 100);
  1938. townRecno = worker_array[0].town_recno;
  1939. raceId = worker_array[0].race_id;
  1940. oldWorkerCount = worker_count;
  1941. if(!resign_worker(1))
  1942. {
  1943. if(oldWorkerCount==worker_count)
  1944. break; // no space to resign the worker, keep them in firm
  1945. }
  1946. if( disappearFlag && townRecno )
  1947. town_array[townRecno]->dec_pop(raceId, 0);
  1948. }
  1949. }
  1950. //----------- End of function Firm::resign_all_worker -----------//
  1951. //--------- Begin of function Firm::resign_worker ---------//
  1952. //
  1953. // Resign the worker from the firm.
  1954. //
  1955. // return: <int> recno of the mobile unit created if there is one created.
  1956. //
  1957. int Firm::resign_worker(int workerId)
  1958. {
  1959. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  1960. err_when( workerId<1 || workerId>worker_count );
  1961. //------- decrease worker no. and create an unit -----//
  1962. Worker* workerPtr = worker_array+workerId-1;
  1963. int unitRecno = 0;
  1964. if( workerPtr->race_id && workerPtr->name_id )
  1965. race_res[workerPtr->race_id]->free_name_id(workerPtr->name_id);
  1966. if( workerPtr->town_recno ) // town_recno is 0 if the workers in the firm do not live in towns
  1967. {
  1968. Town* townPtr = town_array[workerPtr->town_recno];
  1969. townPtr->jobless_race_pop_array[workerPtr->race_id-1]++; // decrease the town's population
  1970. townPtr->jobless_population++;
  1971. //------ put the spy in the town -------//
  1972. if( workerPtr->spy_recno )
  1973. spy_array[workerPtr->spy_recno]->set_place(SPY_TOWN, workerPtr->town_recno);
  1974. }
  1975. else
  1976. {
  1977. Worker thisWorker = worker_array[workerId-1];
  1978. unitRecno = create_worker_unit(thisWorker); // if he is a spy, create_worker_unit wil call set_place(SPY_MOBILE)
  1979. if(!unitRecno)
  1980. return 0; // return 0 eg there is no space to create the unit
  1981. }
  1982. //------- delete the record from the worker_array ------//
  1983. err_when( worker_count > MAX_WORKER );
  1984. err_when( selected_worker_id > worker_count );
  1985. m.del_array_rec(worker_array, worker_count, sizeof(Worker), workerId);
  1986. if( selected_worker_id > workerId || selected_worker_id == worker_count )
  1987. selected_worker_id--;
  1988. worker_count--;
  1989. err_when( worker_count < 0 );
  1990. err_when( selected_worker_id > worker_count );
  1991. return unitRecno;
  1992. }
  1993. //----------- End of function Firm::resign_worker -----------//
  1994. //------- Begin of function Firm::think_worker_migrate ---------//
  1995. //
  1996. // Let the workers think if they want to worker_migrate or not.
  1997. //
  1998. void Firm::think_worker_migrate()
  1999. {
  2000. #define MIN_MIGRATE_ATTRACT_LEVEL 30
  2001. if( worker_count==0 || !firm_res[firm_id]->live_in_town )
  2002. return;
  2003. int townPtrCount = town_array.size();
  2004. int townRecno = m.random(townPtrCount)+1;
  2005. int firmXLoc = center_x, firmYLoc = center_y;
  2006. int i, j, raceId, workerId;
  2007. Town *townPtr, *workerTownPtr;
  2008. Worker *workerPtr;
  2009. int curBaseAttractLevel, targetBaseAttractLevel, curAttractLevel, targetAttractLevel;
  2010. for( i=townPtrCount ; i>0 ; i-- )
  2011. {
  2012. if( ++townRecno > townPtrCount )
  2013. townRecno=1;
  2014. if( town_array.is_deleted(townRecno) )
  2015. continue;
  2016. townPtr = town_array[townRecno];
  2017. if(townPtr->population>=MAX_TOWN_POPULATION)
  2018. continue;
  2019. //------ check if this town is linked to the current firm -----//
  2020. for( j=townPtr->linked_firm_count-1 ; j>=0 ; j-- )
  2021. {
  2022. if( townPtr->linked_firm_array[j] == firm_recno &&
  2023. townPtr->linked_firm_enable_array[j] )
  2024. {
  2025. break;
  2026. }
  2027. }
  2028. if( j<0 )
  2029. continue;
  2030. //------------------------------------------------//
  2031. //
  2032. // Calculate the attractive factor, it is based on:
  2033. //
  2034. // - the reputation of the target nation (+0 to 100)
  2035. // - the racial harmony of the race in the target town (+0 to 100)
  2036. // - the no. of people of the race in the target town
  2037. // - distance between the current town and the target town (-0 to 100)
  2038. //
  2039. // Attractiveness level range: 0 to 200
  2040. //
  2041. //------------------------------------------------//
  2042. targetBaseAttractLevel = 0;
  2043. if( townPtr->nation_recno )
  2044. targetBaseAttractLevel += (int) nation_array[townPtr->nation_recno]->reputation;
  2045. //---- scan all workers, see if any of them want to worker_migrate ----//
  2046. workerId=m.random(worker_count)+1;
  2047. for(j=0 ; j<worker_count ; j++ )
  2048. {
  2049. if( ++workerId > worker_count )
  2050. workerId = 1;
  2051. workerPtr = worker_array+workerId-1;
  2052. if( workerPtr->town_recno == townRecno )
  2053. continue;
  2054. //-- do not migrate if the target town's population of that race is less than half of the population of the current town --//
  2055. raceId = workerPtr->race_id;
  2056. workerTownPtr = town_array[workerPtr->town_recno];
  2057. if( townPtr->race_pop_array[raceId-1] < workerTownPtr->race_pop_array[raceId-1]/2 )
  2058. continue;
  2059. //------ calc the current and target attractiveness level ------//
  2060. workerTownPtr = town_array[workerPtr->town_recno];
  2061. if( workerTownPtr->nation_recno )
  2062. curBaseAttractLevel = (int) nation_array[workerTownPtr->nation_recno]->reputation;
  2063. else
  2064. curBaseAttractLevel = 0;
  2065. targetAttractLevel = targetBaseAttractLevel +
  2066. townPtr->race_harmony(raceId);
  2067. if( targetAttractLevel < MIN_MIGRATE_ATTRACT_LEVEL )
  2068. continue;
  2069. curAttractLevel = curBaseAttractLevel +
  2070. workerTownPtr->race_harmony(raceId) +
  2071. ((int)workerPtr->loyalty() - 40); // loyalty > 40 is considered as positive force, < 40 is considered as negative force
  2072. if( targetAttractLevel > curAttractLevel )
  2073. {
  2074. int newLoyalty = max( REBEL_LOYALTY+1, targetAttractLevel/2 );
  2075. worker_migrate(workerId, townRecno, newLoyalty);
  2076. return;
  2077. }
  2078. }
  2079. }
  2080. }
  2081. //-------- End of function Firm::think_worker_migrate -----------//
  2082. //------- Begin of function Firm::worker_migrate ---------//
  2083. //
  2084. // Worker worker_migrate from one town to another.
  2085. //
  2086. // <int> workerId - id. of the worker
  2087. // <int> destTownRecno - recno of the destination town.
  2088. // <int> newLoyalty - loyalty of the unit in the target town.
  2089. //
  2090. void Firm::worker_migrate(int workerId, int destTownRecno, int newLoyalty)
  2091. {
  2092. err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
  2093. err_when( !firm_res[firm_id]->live_in_town );
  2094. Worker* workerPtr = worker_array+workerId-1;
  2095. int raceId = workerPtr->race_id;
  2096. Town* srcTown = town_array[workerPtr->town_recno];
  2097. Town* destTown = town_array[destTownRecno];
  2098. err_when( !raceId );
  2099. err_when( m.points_distance( center_x, center_y, destTown->center_x,
  2100. destTown->center_y ) > EFFECTIVE_FIRM_TOWN_DISTANCE );
  2101. //------------- add news --------------//
  2102. if( srcTown->nation_recno==nation_array.player_recno ||
  2103. destTown->nation_recno==nation_array.player_recno )
  2104. {
  2105. if( srcTown->nation_recno != destTown->nation_recno ) // don't add news for migrating between own towns
  2106. news_array.migrate(srcTown->town_recno, destTownRecno, raceId, 1, firm_recno);
  2107. }
  2108. //--------- migrate now ----------//
  2109. int keepJob = 1;
  2110. workerPtr->town_recno = destTownRecno;
  2111. //--------- decrease the population of the home town ------//
  2112. srcTown->dec_pop(raceId, keepJob);
  2113. //--------- increase the population of the target town ------//
  2114. destTown->inc_pop(raceId, keepJob, newLoyalty);
  2115. }
  2116. //-------- End of function Firm::worker_migrate -----------//
  2117. //-------- Begin of function Firm::set_worker_home_town --------//
  2118. //
  2119. // This function has two purposes.
  2120. //
  2121. // If the worker's home town is already the given one,
  2122. // then resign the worker.
  2123. //
  2124. // Otherwise, set the worker's home town to the new onel.
  2125. //
  2126. // <int> townRecno - the new home town recno
  2127. // [int] workerId - the id. of the worker to be set to a new home town
  2128. // (default: the currently selected worker, selected_worker_id)
  2129. //
  2130. void Firm::set_worker_home_town(int townRecno, char remoteAction, int workerId)
  2131. {
  2132. if( !workerId )
  2133. workerId = selected_worker_id;
  2134. if( !workerId || workerId > worker_count )
  2135. return;
  2136. if(!remoteAction && remote.is_enable() )
  2137. {
  2138. // packet structure : <firm recno> <town recno> <workderId>
  2139. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_SET_WORKER_HOME, 3*sizeof(short));
  2140. shortPtr[0] = firm_recno;
  2141. shortPtr[1] = townRecno;
  2142. shortPtr[2] = workerId;
  2143. return;
  2144. }
  2145. err_when( workerId<1 || workerId>worker_count );
  2146. //-------------------------------------------------//
  2147. Worker* workerPtr = worker_array+workerId-1;
  2148. err_when( !workerPtr->race_id );
  2149. if( workerPtr->town_recno == townRecno )
  2150. {
  2151. resign_worker(workerId);
  2152. }
  2153. //--- otherwise, set the worker's home town to the new one ---//
  2154. else if( workerPtr->is_nation(firm_recno, nation_recno) ) // only allow when the worker lives in a town belonging to the same nation
  2155. {
  2156. int workerLoyalty = workerPtr->loyalty();
  2157. town_array[workerPtr->town_recno]->dec_pop(workerPtr->race_id, 1);
  2158. town_array[townRecno]->inc_pop(workerPtr->race_id, 1, workerLoyalty);
  2159. workerPtr->town_recno = townRecno;
  2160. }
  2161. }
  2162. //-------- End of function Firm::set_worker_home_town --------//
  2163. //------- Begin of function Worker::loyalty ---------//
  2164. //
  2165. int Worker::loyalty()
  2166. {
  2167. if( town_recno ) // if the worker lives in a town
  2168. return (int) town_array[town_recno]->race_loyalty_array[race_id-1];
  2169. else
  2170. return (int) worker_loyalty;
  2171. }
  2172. //-------- End of function Worker::loyalty -----------//
  2173. //------- Begin of function Worker::target_loyalty ---------//
  2174. //
  2175. int Worker::target_loyalty(int firmRecno)
  2176. {
  2177. if( town_recno ) // if the worker lives in a town
  2178. {
  2179. return (int) town_array[town_recno]->race_loyalty_array[race_id-1];
  2180. }
  2181. else
  2182. {
  2183. Firm* firmPtr = firm_array[firmRecno];
  2184. if( firmPtr->overseer_recno )
  2185. {
  2186. Unit* overseerUnit = unit_array[firmPtr->overseer_recno];
  2187. int overseerSkill = overseerUnit->skill.get_skill(SKILL_LEADING);
  2188. int targetLoyalty = 30 + overseerSkill/2;
  2189. //---------------------------------------------------//
  2190. //
  2191. // Soldiers with higher combat and leadership skill
  2192. // will get discontented if they are led by a general
  2193. // with low leadership.
  2194. //
  2195. //---------------------------------------------------//
  2196. targetLoyalty -= combat_level/2;
  2197. if( skill_level > overseerSkill )
  2198. targetLoyalty -= skill_level - overseerSkill;
  2199. if( overseerUnit->rank_id == RANK_KING )
  2200. targetLoyalty += 20;
  2201. if( race_res.is_same_race(race_id, overseerUnit->race_id) )
  2202. targetLoyalty += 20;
  2203. if( targetLoyalty < 0 )
  2204. targetLoyalty = 0;
  2205. if( targetLoyalty > 100 )
  2206. targetLoyalty = 100;
  2207. return targetLoyalty;
  2208. }
  2209. else //-- if there is no overseer, just return the current loyalty --//
  2210. {
  2211. return worker_loyalty;
  2212. }
  2213. }
  2214. }
  2215. //-------- End of function Worker::target_loyalty -----------//
  2216. //------- Begin of function Firm::setup_link ---------//
  2217. //
  2218. void Firm::setup_link()
  2219. {
  2220. //-----------------------------------------------------------------------------//
  2221. // check the connected firms location and structure if ai_link_checked is true
  2222. //-----------------------------------------------------------------------------//
  2223. if(firm_ai)
  2224. ai_link_checked = 0;
  2225. //----- build firm-to-firm link relationship -------//
  2226. int firmRecno, defaultLinkStatus;
  2227. Firm* firmPtr;
  2228. FirmInfo* firmInfo = firm_res[firm_id];
  2229. linked_firm_count = 0;
  2230. for( firmRecno=firm_array.size() ; firmRecno>0 ; firmRecno-- )
  2231. {
  2232. if( firm_array.is_deleted(firmRecno) || firmRecno==firm_recno )
  2233. continue;
  2234. firmPtr = firm_array[firmRecno];
  2235. //---- do not allow links between firms of different nation ----//
  2236. if( firmPtr->nation_recno != nation_recno )
  2237. continue;
  2238. //---------- check if the firm is close enough to this firm -------//
  2239. if( m.points_distance( firmPtr->center_x, firmPtr->center_y,
  2240. center_x, center_y ) > EFFECTIVE_FIRM_FIRM_DISTANCE )
  2241. {
  2242. continue;
  2243. }
  2244. //------ check if both are on the same terrain type ------//
  2245. if( world.get_loc(firmPtr->center_x, firmPtr->center_y)->is_plateau()
  2246. != world.get_loc(center_x, center_y)->is_plateau() )
  2247. {
  2248. continue;
  2249. }
  2250. //----- if the firms are linkable to each other -----//
  2251. if( !firmInfo->is_linkable_to_firm(firmPtr->firm_id) )
  2252. continue;
  2253. //------- determine the default link status ------//
  2254. if( firmPtr->nation_recno == nation_recno ) // if the two firms are of the same nation, get the default link status which is based on the types of the firms
  2255. defaultLinkStatus = firmInfo->default_link_status(firmPtr->firm_id);
  2256. else
  2257. defaultLinkStatus = LINK_DD; // if the two firms are of different nations, default link status is both side disabled
  2258. //-------- add the link now -------//
  2259. if( linked_firm_count < MAX_LINKED_FIRM_FIRM )
  2260. {
  2261. linked_firm_array[linked_firm_count] = firmRecno;
  2262. linked_firm_enable_array[linked_firm_count] = defaultLinkStatus;
  2263. linked_firm_count++;
  2264. }
  2265. else // we must link it as it is linked both sides, if one side is linked and the other is not, that will cause a bug
  2266. {
  2267. err_here();
  2268. }
  2269. if( firmPtr->linked_firm_count < MAX_LINKED_FIRM_FIRM )
  2270. {
  2271. if( defaultLinkStatus==LINK_ED ) // Reverse the link status for the opposite linker
  2272. defaultLinkStatus=LINK_DE;
  2273. else if( defaultLinkStatus==LINK_DE )
  2274. defaultLinkStatus=LINK_ED;
  2275. firmPtr->linked_firm_array[firmPtr->linked_firm_count] = firm_recno;
  2276. firmPtr->linked_firm_enable_array[firmPtr->linked_firm_count] = defaultLinkStatus;
  2277. firmPtr->linked_firm_count++;
  2278. if(firmPtr->firm_ai)
  2279. firmPtr->ai_link_checked = 0;
  2280. if(firmPtr->firm_id==FIRM_HARBOR)
  2281. {
  2282. FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
  2283. harborPtr->link_checked = 0;
  2284. }
  2285. }
  2286. else
  2287. {
  2288. err_here();
  2289. }
  2290. }
  2291. //----- build firm-to-town link relationship -------//
  2292. linked_town_count = 0;
  2293. if( !firmInfo->is_linkable_to_town )
  2294. return;
  2295. int townRecno;
  2296. Town* townPtr;
  2297. for( townRecno=town_array.size() ; townRecno>0 ; townRecno-- )
  2298. {
  2299. if( town_array.is_deleted(townRecno) )
  2300. continue;
  2301. townPtr = town_array[townRecno];
  2302. //------ check if the town is close enough to this firm -------//
  2303. if( m.points_distance( townPtr->center_x, townPtr->center_y,
  2304. center_x, center_y ) > EFFECTIVE_FIRM_TOWN_DISTANCE )
  2305. {
  2306. continue;
  2307. }
  2308. //------ check if both are on the same terrain type ------//
  2309. if( (world.get_loc(townPtr->center_x, townPtr->center_y)->is_plateau()==1)
  2310. != (world.get_loc(center_x, center_y)->is_plateau()==1) )
  2311. {
  2312. continue;
  2313. }
  2314. //------- determine the default link status ------//
  2315. if( townPtr->nation_recno == nation_recno ) // if the two firms are of the same nation, get the default link status which is based on the types of the firms
  2316. defaultLinkStatus = LINK_EE;
  2317. else
  2318. defaultLinkStatus = LINK_DD; // if the two firms are of different nations, default link status is both side disabled
  2319. //---------------------------------------------------//
  2320. //
  2321. // If this is a camp, it can be linked to the town when
  2322. // either the town is an independent one or the town
  2323. // is not linked to any camps of its own.
  2324. //
  2325. //---------------------------------------------------//
  2326. if( firm_id==FIRM_CAMP )
  2327. {
  2328. if( townPtr->nation_recno==0 || !townPtr->has_linked_own_camp )
  2329. defaultLinkStatus = LINK_EE;
  2330. }
  2331. //-------- add the link now -------//
  2332. if( linked_town_count < MAX_LINKED_FIRM_TOWN )
  2333. {
  2334. linked_town_array[linked_town_count] = townRecno;
  2335. linked_town_enable_array[linked_town_count] = defaultLinkStatus;
  2336. linked_town_count++;
  2337. }
  2338. else
  2339. {
  2340. err_here();
  2341. }
  2342. if( townPtr->linked_firm_count < MAX_LINKED_FIRM_TOWN )
  2343. {
  2344. if( defaultLinkStatus==LINK_ED ) // Reverse the link status for the opposite linker
  2345. defaultLinkStatus=LINK_DE;
  2346. else if( defaultLinkStatus==LINK_DE )
  2347. defaultLinkStatus=LINK_ED;
  2348. townPtr->linked_firm_array[townPtr->linked_firm_count] = firm_recno;
  2349. townPtr->linked_firm_enable_array[townPtr->linked_firm_count] = defaultLinkStatus;
  2350. townPtr->linked_firm_count++;
  2351. if(townPtr->ai_town)
  2352. townPtr->ai_link_checked = 0;
  2353. }
  2354. else
  2355. {
  2356. err_here();
  2357. }
  2358. }
  2359. }
  2360. //-------- End of function Firm::setup_link -----------//
  2361. //------- Begin of function Firm::release_link ---------//
  2362. //
  2363. void Firm::release_link()
  2364. {
  2365. int i;
  2366. Firm *firmPtr;
  2367. Town *townPtr;
  2368. //------ release linked firms ------//
  2369. for( i=0 ; i<linked_firm_count ; i++ )
  2370. {
  2371. firmPtr = firm_array[linked_firm_array[i]];
  2372. firmPtr->release_firm_link(firm_recno);
  2373. if(firmPtr->firm_ai)
  2374. firmPtr->ai_link_checked = 0;
  2375. }
  2376. //------ release linked towns ------//
  2377. for( i=0 ; i<linked_town_count ; i++ )
  2378. {
  2379. townPtr = town_array[linked_town_array[i]];
  2380. townPtr->release_firm_link(firm_recno);
  2381. if(townPtr->ai_town)
  2382. townPtr->ai_link_checked = 0;
  2383. }
  2384. }
  2385. //-------- End of function Firm::release_link -----------//
  2386. //------- Begin of function Firm::release_firm_link ---------//
  2387. //
  2388. void Firm::release_firm_link(int releaseFirmRecno)
  2389. {
  2390. //-----------------------------------------------------------------------------//
  2391. // check the connected firms location and structure if ai_link_checked is true
  2392. //-----------------------------------------------------------------------------//
  2393. if(firm_ai)
  2394. ai_link_checked = 0;
  2395. for( int i=0 ; i<linked_firm_count ; i++ )
  2396. {
  2397. if( linked_firm_array[i] == releaseFirmRecno )
  2398. {
  2399. err_when( linked_firm_count > MAX_LINKED_FIRM_FIRM );
  2400. m.del_array_rec( linked_firm_array, linked_firm_count, sizeof(linked_firm_array[0]), i+1 );
  2401. m.del_array_rec( linked_firm_enable_array, linked_firm_count, sizeof(linked_firm_enable_array[0]), i+1 );
  2402. linked_firm_count--;
  2403. return;
  2404. }
  2405. }
  2406. err_here();
  2407. }
  2408. //------- End of function Firm::release_firm_link ---------//
  2409. //------- Begin of function Firm::release_town_link ---------//
  2410. //
  2411. void Firm::release_town_link(int releaseTownRecno)
  2412. {
  2413. //-----------------------------------------------------------------------------//
  2414. // check the connected firms location and structure if ai_link_checked is true
  2415. //-----------------------------------------------------------------------------//
  2416. if(firm_ai)
  2417. ai_link_checked = 0;
  2418. for( int i=0 ; i<linked_town_count ; i++ )
  2419. {
  2420. if( linked_town_array[i] == releaseTownRecno )
  2421. {
  2422. err_when( linked_town_count > MAX_LINKED_FIRM_TOWN );
  2423. m.del_array_rec( linked_town_array, linked_town_count, sizeof(linked_town_array[0]), i+1 );
  2424. m.del_array_rec( linked_town_enable_array, linked_town_count, sizeof(linked_town_enable_array[0]), i+1 );
  2425. linked_town_count--;
  2426. return;
  2427. }
  2428. }
  2429. err_here();
  2430. }
  2431. //------- End of function Firm::release_town_link ---------//
  2432. //--------- Begin of function Firm::capture_firm --------//
  2433. //
  2434. // The firm is being captured by another nation.
  2435. //
  2436. void Firm::capture_firm(int newNationRecno)
  2437. {
  2438. if( nation_recno == nation_array.player_recno )
  2439. news_array.firm_captured(firm_recno, newNationRecno, 0); // 0 - the capturer is not a spy
  2440. //-------- if this is an AI firm --------//
  2441. if( firm_ai )
  2442. ai_firm_captured(newNationRecno);
  2443. //------------------------------------------//
  2444. //
  2445. // If there is an overseer in this firm, then the only
  2446. // unit who can capture this firm will be the overseer only,
  2447. // so calling its betray() function will capture the whole
  2448. // firm already.
  2449. //
  2450. //------------------------------------------//
  2451. if( overseer_recno && unit_array[overseer_recno]->spy_recno )
  2452. unit_array[overseer_recno]->spy_change_nation(newNationRecno, COMMAND_AUTO);
  2453. else
  2454. change_nation(newNationRecno);
  2455. }
  2456. //--------- End of function Firm::capture_firm --------//
  2457. //------- Begin of function Firm::change_nation ---------//
  2458. //
  2459. void Firm::change_nation(int newNationRecno)
  2460. {
  2461. if( nation_recno == newNationRecno )
  2462. return;
  2463. //---------- stop all attack actions to this firm ----------//
  2464. unit_array.stop_attack_firm(firm_recno);
  2465. rebel_array.stop_attack_firm(firm_recno);
  2466. Nation *oldNationPtr = nation_array[nation_recno];
  2467. Nation *newNationPtr = nation_array[newNationRecno];
  2468. //------ if there is a builder in this firm, change its nation also ----//
  2469. if( builder_recno )
  2470. {
  2471. Unit* unitPtr = unit_array[builder_recno];
  2472. unitPtr->change_nation(newNationRecno);
  2473. //--- if this is a spy, chance its cloak ----//
  2474. if( unitPtr->spy_recno )
  2475. spy_array[unitPtr->spy_recno]->cloaked_nation_recno = newNationRecno;
  2476. }
  2477. //---------- stop all actions attacking this firm --------//
  2478. unit_array.stop_attack_firm(firm_recno);
  2479. //------ clear defense mode for military camp -----//
  2480. if(firm_id==FIRM_CAMP)
  2481. ((FirmCamp*)this)->clear_defense_mode();
  2482. //---- update nation_unit_count_array[] ----//
  2483. FirmInfo* firmInfo = firm_res[firm_id];
  2484. if( nation_recno )
  2485. firmInfo->dec_nation_firm_count(nation_recno);
  2486. if( newNationRecno )
  2487. firmInfo->inc_nation_firm_count(newNationRecno);
  2488. //---- reset should_close_flag -----//
  2489. if( firm_ai )
  2490. {
  2491. if( should_close_flag )
  2492. {
  2493. oldNationPtr->firm_should_close_array[firm_id-1]--;
  2494. should_close_flag = 0;
  2495. err_when( oldNationPtr->firm_should_close_array[firm_id-1] < 0 );
  2496. }
  2497. }
  2498. //------- update player_spy_count -------//
  2499. spy_array.update_firm_spy_count(firm_recno);
  2500. //--- update the cloaked_nation_recno of all spies in the firm ---//
  2501. spy_array.change_cloaked_nation(SPY_FIRM, firm_recno, nation_recno, newNationRecno); // check the cloaked nation recno of all spies in the firm
  2502. //-----------------------------------------//
  2503. if(firm_ai)
  2504. oldNationPtr->del_firm_info(firm_id, firm_recno);
  2505. //------ update power nation recno ----------//
  2506. if( should_set_power )
  2507. world.restore_power(loc_x1, loc_y1, loc_x2, loc_y2, 0, firm_recno);
  2508. should_set_power = get_should_set_power();
  2509. if( should_set_power )
  2510. world.set_power(loc_x1, loc_y1, loc_x2, loc_y2, newNationRecno); // set power of the new nation
  2511. //------------ update link --------------//
  2512. release_link(); // need to update link because firms are only linked to firms of the same nation
  2513. nation_recno = newNationRecno;
  2514. setup_link();
  2515. //---------------------------------------//
  2516. firm_ai = nation_array[nation_recno]->is_ai();
  2517. if(firm_ai)
  2518. newNationPtr->add_firm_info(firm_id, firm_recno);
  2519. //--- if a nation set up a town in a location that the player has explored, contact between the nation and the player is established ---//
  2520. establish_contact_with_player();
  2521. //---- reset the action mode of all spies in this town ----//
  2522. spy_array.set_action_mode( SPY_FIRM, firm_recno, SPY_IDLE ); // we need to reset it. e.g. when we have captured an enemy town, SPY_SOW_DISSENT action must be reset to SPY_IDLE
  2523. //-- refresh display if this firm is currently selected --//
  2524. if( firm_array.selected_recno == firm_recno )
  2525. info.disp();
  2526. }
  2527. //-------- End of function Firm::change_nation ---------//
  2528. //------- Begin of function Firm::toggle_firm_link ---------//
  2529. //
  2530. // Toggle the firm link of the current firm.
  2531. //
  2532. // <int> linkId - id. of the link
  2533. // <int> toggleFlag - 1-enable, 0-disable
  2534. // [int] setBoth - if this is 1, it will set the link to either LINK_EE or LINK_DD (and no LINK_ED or LINK_DD)
  2535. // if this is -1, the only one side will be set even though the nation recno of the firm and town are the same
  2536. // (default: 0)
  2537. //
  2538. void Firm::toggle_firm_link(int linkId, int toggleFlag, char remoteAction, int setBoth)
  2539. {
  2540. if( !remoteAction && remote.is_enable() )
  2541. {
  2542. // packet structure : <firm recno> <link Id> <toggle Flag>
  2543. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_TOGGLE_LINK_FIRM, 3*sizeof(short));
  2544. shortPtr[0] = firm_recno;
  2545. shortPtr[1] = linkId;
  2546. shortPtr[2] = toggleFlag;
  2547. return;
  2548. }
  2549. int linkedNationRecno = firm_array[linked_firm_array[linkId-1]]->nation_recno;
  2550. int sameNation = linkedNationRecno == nation_recno || // if one of the linked end is an indepdendent firm/nation, consider this link as a single nation link
  2551. linkedNationRecno == 0 ||
  2552. nation_recno == 0;
  2553. if( toggleFlag )
  2554. {
  2555. if( (sameNation && setBoth==0) || setBoth==1 )
  2556. linked_firm_enable_array[linkId-1] = LINK_EE;
  2557. else
  2558. linked_firm_enable_array[linkId-1] |= LINK_ED;
  2559. }
  2560. else
  2561. {
  2562. if( (sameNation && setBoth==0) || setBoth==1 )
  2563. linked_firm_enable_array[linkId-1] = LINK_DD;
  2564. else
  2565. linked_firm_enable_array[linkId-1] &= ~LINK_ED;
  2566. }
  2567. //---------- if this firm is harbor, set FirmHarbor's parameter link_checked to 0
  2568. if(firm_id == FIRM_HARBOR)
  2569. {
  2570. FirmHarbor *harborPtr = (FirmHarbor*) this;
  2571. harborPtr->link_checked = 0;
  2572. }
  2573. //------ set the linked flag of the opposite firm -----//
  2574. Firm* firmPtr = firm_array[ linked_firm_array[linkId-1] ];
  2575. //---------- if firm is harbor, set FirmHarbor's parameter link_checked to 0
  2576. if(firmPtr->firm_id==FIRM_HARBOR)
  2577. {
  2578. FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
  2579. harborPtr->link_checked = 0;
  2580. }
  2581. int i;
  2582. for( i=0 ; i<firmPtr->linked_firm_count ; i++ )
  2583. {
  2584. if( firmPtr->linked_firm_array[i] == firm_recno )
  2585. {
  2586. if( toggleFlag )
  2587. {
  2588. if( (sameNation && setBoth==0) || setBoth==1 )
  2589. firmPtr->linked_firm_enable_array[i] = LINK_EE;
  2590. else
  2591. firmPtr->linked_firm_enable_array[i] |= LINK_DE;
  2592. }
  2593. else
  2594. {
  2595. if( (sameNation && setBoth==0) || setBoth==1 )
  2596. firmPtr->linked_firm_enable_array[i] = LINK_DD;
  2597. else
  2598. firmPtr->linked_firm_enable_array[i] &= ~LINK_DE;
  2599. }
  2600. break;
  2601. }
  2602. }
  2603. }
  2604. //-------- End of function Firm::toggle_firm_link ---------//
  2605. //------- Begin of function Firm::toggle_town_link ---------//
  2606. //
  2607. // Toggle the town link of the current firm.
  2608. //
  2609. // <int> linkId - id. of the link
  2610. // <int> toggleFlag - 1-enable, 0-disable
  2611. // [int] setBoth - if this is 1, it will set the link to either LINK_EE or LINK_DD (and no LINK_ED or LINK_DD)
  2612. // if this is -1, the only one side will be set even though the nation recno of the firm and town are the same
  2613. // (default: 0)
  2614. //
  2615. void Firm::toggle_town_link(int linkId, int toggleFlag, char remoteAction, int setBoth)
  2616. {
  2617. if( !remoteAction && remote.is_enable() )
  2618. {
  2619. // packet structure : <firm recno> <link Id> <toggle Flag>
  2620. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_TOGGLE_LINK_TOWN, 3*sizeof(short));
  2621. shortPtr[0] = firm_recno;
  2622. shortPtr[1] = linkId;
  2623. shortPtr[2] = toggleFlag;
  2624. return;
  2625. }
  2626. int linkedNationRecno = town_array[linked_town_array[linkId-1]]->nation_recno;
  2627. int sameNation = linkedNationRecno == nation_recno || // if one of the linked end is an indepdendent firm/nation, consider this link as a single nation link
  2628. firm_id==FIRM_BASE; // town cannot decide whether it wants to link to Command Base or not, it is the Command Base which influences the town.
  2629. if( toggleFlag )
  2630. {
  2631. if( (sameNation && setBoth==0) || setBoth==1 )
  2632. linked_town_enable_array[linkId-1] = LINK_EE;
  2633. else
  2634. linked_town_enable_array[linkId-1] |= LINK_ED;
  2635. }
  2636. else
  2637. {
  2638. if( (sameNation && setBoth==0) || setBoth==1 )
  2639. linked_town_enable_array[linkId-1] = LINK_DD;
  2640. else
  2641. linked_town_enable_array[linkId-1] &= ~LINK_ED;
  2642. }
  2643. //------ set the linked flag of the opposite town -----//
  2644. Town* townPtr = town_array[ linked_town_array[linkId-1] ];
  2645. int i;
  2646. for( i=0 ; i<townPtr->linked_firm_count ; i++ )
  2647. {
  2648. if( townPtr->linked_firm_array[i] == firm_recno )
  2649. {
  2650. if( toggleFlag )
  2651. {
  2652. if( (sameNation && setBoth==0) || setBoth==1 )
  2653. townPtr->linked_firm_enable_array[i] = LINK_EE;
  2654. else
  2655. townPtr->linked_firm_enable_array[i] |= LINK_DE;
  2656. }
  2657. else
  2658. {
  2659. if( (sameNation && setBoth==0) || setBoth==1 )
  2660. townPtr->linked_firm_enable_array[i] = LINK_DD;
  2661. else
  2662. townPtr->linked_firm_enable_array[i] &= ~LINK_DE;
  2663. }
  2664. break;
  2665. }
  2666. }
  2667. //-------- update the town's influence --------//
  2668. if( townPtr->nation_recno==0 )
  2669. townPtr->update_target_resistance();
  2670. //--- redistribute demand if a link to market place has been toggled ---//
  2671. if( firm_id == FIRM_MARKET )
  2672. town_array.distribute_demand();
  2673. }
  2674. //-------- End of function Firm::toggle_town_link ---------//
  2675. //------- Begin of function Firm::auto_defense -----------//
  2676. void Firm::auto_defense(short targetRecno)
  2677. {
  2678. //--------------------------------------------------------//
  2679. // if the firm_id is FIRM_CAMP, send the units to defense
  2680. // the firm
  2681. //--------------------------------------------------------//
  2682. if(firm_id == FIRM_CAMP)
  2683. {
  2684. FirmCamp *campPtr = cast_to_FirmCamp();
  2685. campPtr->defend_target_recno = targetRecno;
  2686. campPtr->defense(targetRecno);
  2687. }
  2688. Town *townPtr;
  2689. for(int i=linked_town_count-1; i>=0; i--)
  2690. {
  2691. if(!linked_town_array[i] || town_array.is_deleted(linked_town_array[i]))
  2692. continue;
  2693. townPtr = town_array[linked_town_array[i]];
  2694. //-------------------------------------------------------//
  2695. // find whether military camp is linked to this town. If
  2696. // so, defense for this firm
  2697. //-------------------------------------------------------//
  2698. if(townPtr->nation_recno == nation_recno)
  2699. townPtr->auto_defense(targetRecno);
  2700. //-------------------------------------------------------//
  2701. // some linked town may be deleted after calling auto_defense().
  2702. // Also, the data in the linked_town_array may also be changed.
  2703. //-------------------------------------------------------//
  2704. if(i>linked_town_count)
  2705. i = linked_town_count;
  2706. }
  2707. }
  2708. //--------- End of function Firm::auto_defense -----------//
  2709. //------- Begin of function Worker::Worker -----------//
  2710. //
  2711. Worker::Worker()
  2712. {
  2713. memset( this, 0, sizeof(Worker) );
  2714. }
  2715. //--------- End of function Worker::Worker -----------//
  2716. //------- Begin of function Worker::max_hit_points -----------//
  2717. //
  2718. short Worker::max_hit_points()
  2719. {
  2720. err_when( combat_level <= 0 );
  2721. err_when( combat_level > 100 );
  2722. return (int) unit_res[unit_id]->hit_points * combat_level / 100;
  2723. }
  2724. //--------- End of function Worker::max_hit_points -----------//
  2725. //--------- Begin of function Worker::max_attack_range ---------//
  2726. int Worker::max_attack_range()
  2727. {
  2728. int maxRange=0;
  2729. AttackInfo *attackInfo = unit_res.get_attack_info(unit_res[unit_id]->first_attack);
  2730. int attackCount = unit_res[unit_id]->attack_count;
  2731. for(int i=0; i<attackCount; i++, attackInfo++)
  2732. {
  2733. if(combat_level >= attackInfo->combat_level &&
  2734. attackInfo->attack_range>maxRange)
  2735. maxRange = attackInfo->attack_range;
  2736. }
  2737. return maxRange;
  2738. }
  2739. //--------- End of function Worker::max_attack_range -----------//
  2740. //--------- Begin of function Worker::is_nation ---------//
  2741. //
  2742. // Whether this worker belongs to the specific nation.
  2743. //
  2744. // <int> firmRecno - the recno of the firm the worker works in
  2745. // <int> nationRecno - the recno of th nation to check against.
  2746. //
  2747. int Worker::is_nation(int firmRecno, int nationRecno)
  2748. {
  2749. if( spy_recno && spy_array[spy_recno]->true_nation_recno == nationRecno )
  2750. return 1;
  2751. if( town_recno )
  2752. return town_array[town_recno]->nation_recno == nationRecno;
  2753. else
  2754. return firm_array[firmRecno]->nation_recno == nationRecno;
  2755. }
  2756. //----------- End of function Worker::is_nation ---------//
  2757. //-------- Begin of function Firm::can_assign_capture ------//
  2758. //
  2759. // Return whether new units assigned to this firm can capture
  2760. // this firm.
  2761. //
  2762. int Firm::can_assign_capture()
  2763. {
  2764. return (overseer_recno==0 && worker_count==0);
  2765. }
  2766. //----------- End of function Worker::can_assign_capture ---------//
  2767. //-------- Begin of function Firm::should_show_info ------//
  2768. //
  2769. // Whether information of this firm should be shown.
  2770. //
  2771. int Firm::should_show_info()
  2772. {
  2773. if( config.show_ai_info || nation_recno==nation_array.player_recno ||
  2774. player_spy_count > 0 )
  2775. {
  2776. return 1;
  2777. }
  2778. //------ if the builder is a spy of the player ------//
  2779. if( builder_recno )
  2780. {
  2781. if( unit_array[builder_recno]->true_nation_recno() == nation_array.player_recno )
  2782. return 1;
  2783. }
  2784. //----- if any of the workers belong to the player, show the info of this firm -----//
  2785. Worker* workerPtr = worker_array;
  2786. for( int i=0 ; i<worker_count ; i++, workerPtr++ )
  2787. {
  2788. if( workerPtr->is_nation(firm_recno, nation_array.player_recno) )
  2789. return 1;
  2790. }
  2791. //---- if there is a phoenix of the player over this firm ----//
  2792. if( nation_array.player_recno && (~nation_array)->revealed_by_phoenix(loc_x1, loc_y1) )
  2793. return 1;
  2794. return 0;
  2795. }
  2796. //---------- End of function Firm::should_show_info --------//
  2797. //-------- Begin of function Firm::majority_race ------//
  2798. //
  2799. char Firm::majority_race()
  2800. {
  2801. //--- if there is a overseer, return the overseer's race ---//
  2802. if( overseer_recno )
  2803. return unit_array[overseer_recno]->race_id;
  2804. if( worker_count==0 )
  2805. return 0;
  2806. //----- count the no. people in each race ------//
  2807. char raceCountArray[MAX_RACE];
  2808. memset( raceCountArray, 0, sizeof(raceCountArray) );
  2809. int i;
  2810. for( i=0 ; i<worker_count ; i++ )
  2811. {
  2812. if( worker_array[i].race_id )
  2813. raceCountArray[ worker_array[i].race_id-1 ]++;
  2814. }
  2815. //---------------------------------------------//
  2816. int mostRaceCount=0, mostRaceId=0;
  2817. for( i=0 ; i<MAX_RACE ; i++ )
  2818. {
  2819. if( raceCountArray[i] > mostRaceCount )
  2820. {
  2821. mostRaceCount = raceCountArray[i];
  2822. mostRaceId = i+1;
  2823. }
  2824. }
  2825. return mostRaceId;
  2826. }
  2827. //---------- End of function Firm::majority_race --------//
  2828. //---------- Begin of function Worker::small_icon_ptr --------//
  2829. char* Worker::small_icon_ptr()
  2830. {
  2831. // ###### begin Gilbert 17/10 ########//
  2832. return unit_res[unit_id]->get_small_icon_ptr(rank_id);
  2833. // ###### end Gilbert 17/10 ########//
  2834. }
  2835. //---------- End of function Worker::small_icon_ptr --------//
  2836. //---------- Begin of function Worker::change_loyalty --------//
  2837. void Worker::change_loyalty(int loyaltyChange)
  2838. {
  2839. if( town_recno ) // for those live in town, their loyalty are based on town people loyalty.
  2840. return;
  2841. int newLoyalty = worker_loyalty + loyaltyChange;
  2842. newLoyalty = min( 100, newLoyalty );
  2843. worker_loyalty = max( 0, newLoyalty );
  2844. }
  2845. //---------- End of function Worker::change_loyalty --------//
  2846. //---------- Begin of function Worker::change_hit_points --------//
  2847. void Worker::change_hit_points(int changePoints)
  2848. {
  2849. err_when( town_recno ); // for those live in town, their loyalty are based on town people loyalty.
  2850. int newHitPoints = hit_points + changePoints;
  2851. int maxHitPoints = max_hit_points();
  2852. newHitPoints = min( maxHitPoints, newHitPoints );
  2853. hit_points = max( 0, newHitPoints );
  2854. }
  2855. //---------- End of function Worker::change_hit_points --------//
  2856. //-------- Begin of function Firm::is_worker_full ------//
  2857. //
  2858. int Firm::is_worker_full()
  2859. {
  2860. return worker_count == MAX_WORKER;
  2861. }
  2862. //----------- End of function Firm::is_worker_full ---------//
  2863. //--------- Begin of function Firm::reward ---------//
  2864. //
  2865. // Only military camp has the "reward" option and not the other firms also
  2866. // because workers in other firms live in the towns and their loyalty
  2867. // are based on the town they live. Military camp is not linked to a town.
  2868. //
  2869. // <int> workerId - 0 - commander, >0 - id. of the soldier
  2870. // <int> remoteAction - either COMMAND_PLAYER or COMMAND_REMOTE
  2871. //
  2872. void Firm::reward(int workerId, int remoteAction)
  2873. {
  2874. if( remoteAction==COMMAND_PLAYER && remote.is_enable() )
  2875. {
  2876. if( !remoteAction && remote.is_enable() )
  2877. {
  2878. // packet structure : <firm recno> <worker id>
  2879. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_REWARD, 2*sizeof(short) );
  2880. *shortPtr = firm_recno;
  2881. shortPtr[1] = workerId;
  2882. }
  2883. }
  2884. else
  2885. {
  2886. if( workerId == 0 )
  2887. {
  2888. if( overseer_recno )
  2889. unit_array[overseer_recno]->reward(nation_recno);
  2890. }
  2891. else
  2892. {
  2893. err_when( workerId < 1 || workerId > worker_count );
  2894. worker_array[workerId-1].change_loyalty( REWARD_LOYALTY_INCREASE );
  2895. nation_array[nation_recno]->add_expense( EXPENSE_REWARD_UNIT, (float)REWARD_COST);
  2896. }
  2897. }
  2898. }
  2899. //----------- End of function Firm::reward -----------//