1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832 |
- /*
- * Seven Kingdoms: Ancient Adversaries
- *
- * Copyright 1997,1998 Enlight Software Ltd.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OFIRM.CPP
- //Description : Object Firm
- #include <OVGA.h>
- #include <ODATE.h>
- #include <OMLINK.h>
- #include <OWORLD.h>
- #include <OPOWER.h>
- #include <OCONFIG.h>
- #include <OGAME.h>
- #include <OUNIT.h>
- #include <ONEWS.h>
- #include <OSYS.h>
- #include <OSPY.h>
- #include <OSITE.h>
- #include <OINFO.h>
- #include <ONEWS.h>
- #include <ONATION.h>
- #include <OFIRM.h>
- #include <ORACERES.h>
- #include <OTOWN.h>
- #include <OSPRITE.h>
- #include <OFIRMRES.h>
- #include <OF_MARK.h>
- #include <OREMOTE.h>
- #include <OF_CAMP.h>
- #include <OF_HARB.h>
- #include <OSERES.h>
- #include <OREBEL.h>
- // ###### begin Gilbert 2/10 ######//
- #include <OFIRMDIE.h>
- // ###### end Gilbert 2/10 ######//
- #include <OUNITRES.h>
- //---------- define static member vars -------------//
- char Firm::firm_menu_mode=FIRM_MENU_MAIN; // whether the firm is in spy menu mode
- short Firm::action_spy_recno;
- char Firm::bribe_result=BRIBE_NONE;
- char Firm::assassinate_result=0;
- //----------- define static parameters -------------//
- static int remove_firm = 0; // true only when the firm is to be removed from the firm_array
- //--------- Begin of function Firm::Firm --------//
- //
- // After created a Firm, you must either call Firm::set_world_matrix()
- // to set the record no. of the firm in the matrix or set it yourself
- //
- // NOTE : this function will be called by firm_array.read_file()
- // it CANNOT change any settings in nation_array
- //
- Firm::Firm()
- {
- //####### patch begin Gilbert 21/1 #######//
- // memset( (char *)this, 0, sizeof(Firm) );
- memset( (char *)this + sizeof(void *), 0, sizeof(Firm) - sizeof(void *) );
- //####### patch end Gilbert 21/1 #######//
- }
- //----------- End of function Firm::Firm ---------//
- //--------- Begin of function Firm::~Firm --------//
- //
- // Two ways to terminate a Firm :
- //
- // 1.call Firm::deinit() first and then delete the firm
- // 2.delete the firm directly
- //
- Firm::~Firm()
- {
- deinit();
- }
- //----------- End of function Firm::~Firm --------//
- //--------- Begin of function Firm::init --------//
- //
- // It will initialize vars, and set the world matrix.
- // Before calling init(), firm_recno should be set
- //
- // Note : it will set world matrix regardless the existing location content,
- // so you must ensure that the location is clean by calling
- // world.zoom_matrix->add_firm_test()
- //
- // <int> xLoc, yLoc = the location of firm in the world map
- // <int> nationRecno = the recno of nation which build this firm
- // <int> firmId = id(type) of the firm
- // [char*] buildCode = the build code of the firm, no need to give if the firm just have one build type
- // [short] builderRecno = recno of the builder unit
- //
- void Firm::init(int xLoc, int yLoc, int nationRecno, int firmId, char* buildCode, short builderRecno)
- {
- FirmInfo* firmInfo = firm_res[firmId];
- firm_id = firmId;
- if( buildCode )
- firm_build_id = firmInfo->get_build_id(buildCode);
- else
- firm_build_id = firmInfo->first_build_id;
- //----------- set vars -------------//
- nation_recno = nationRecno;
- setup_date = info.game_date;
- overseer_recno = 0;
- if( firmInfo->need_worker )
- worker_array = (Worker*) mem_add( MAX_WORKER * sizeof(Worker) );
- else
- worker_array = NULL;
- //----- set the firm's absolute positions on the map -----//
- FirmBuild* firmBuild = firm_res.get_build(firm_build_id);
- race_id = firmBuild->race_id;
- loc_x1 = xLoc;
- loc_y1 = yLoc;
- loc_x2 = loc_x1 + firmBuild->loc_width - 1;
- loc_y2 = loc_y1 + firmBuild->loc_height - 1;
- center_x = (loc_x1 + loc_x2) / 2;
- center_y = (loc_y1 + loc_y2) / 2;
- region_id = world.get_region_id( center_x, center_y );
- abs_x1 = xLoc * ZOOM_LOC_WIDTH + firmBuild->min_offset_x;
- abs_y1 = yLoc * ZOOM_LOC_HEIGHT + firmBuild->min_offset_y;
- abs_x2 = abs_x1 + firmBuild->max_bitmap_width - 1;
- abs_y2 = abs_y1 + firmBuild->max_bitmap_height - 1;
- //--------- set animation frame vars ---------//
- if( firmBuild->animate_full_size )
- cur_frame = 1;
- else
- {
- cur_frame = 2; // start with the 2nd frame as the 1st frame is the common frame
- 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
- }
- remain_frame_delay = (char) firmBuild->frame_delay(cur_frame);
- //--------- initialize gaming vars ----------//
- hit_points = (float) 0;
- max_hit_points = firmInfo->max_hit_points;
- //------ set construction and builder -------//
- under_construction = firmInfo->buildable; // whether the firm is under construction, if the firm is not buildable it is completed in the first place
- if( !under_construction ) // if this firm doesn't been to be constructed, set its hit points to the maximum
- hit_points = max_hit_points;
- if( builderRecno )
- set_builder(builderRecno);
- else
- builder_recno = 0;
- //------ update firm counter -------//
- firmInfo->total_firm_count++;
-
- if( nation_recno )
- firmInfo->inc_nation_firm_count(nation_recno);
- //-------------------------------------------//
- if( nation_recno > 0 )
- {
- Nation* nationPtr = nation_array[nation_recno];
- firm_ai = nationPtr->is_ai();
- ai_processed = 1;
- //--------- increase firm counter -----------//
- nationPtr->nation_firm_count++;
- //-------- update last build date ------------//
- nationPtr->last_build_firm_date = info.game_date;
- }
- else
- {
- firm_ai = 0;
- ai_processed = 0;
- }
- ai_status = FIRM_WITHOUT_ACTION;
- ai_link_checked = 1; // check the connected firms if ai_link_checked = 0;
- //--------------------------------------------//
- setup_link();
- set_world_matrix();
- init_name();
- //----------- init AI -----------//
- if( firm_ai )
- nation_array[nation_recno]->add_firm_info(firm_id, firm_recno);
- //-------- init derived ---------//
- init_derived(); // init_derived() before set_world_matrix() so that init_derived has access to the original land info.
- }
- //----------- End of function Firm::init ---------//
- //--------- Begin of function Firm::deinit --------//
- //
- void Firm::deinit()
- {
- if( !firm_recno ) // already deleted
- return;
- deinit_derived();
- remove_firm = 1; // set static parameter
- //------- delete AI info ----------//
- if(firm_ai)
- {
- Nation* nationPtr = nation_array[nation_recno];
- if( should_close_flag )
- nationPtr->firm_should_close_array[firm_id-1]--;
- err_when( nationPtr->firm_should_close_array[firm_id-1] < 0 );
- nationPtr->del_firm_info(firm_id, firm_recno);
- }
- //--------- clean up related stuff -----------//
- restore_world_matrix();
- release_link();
- //------ all workers and the overseer resign ------//
- if( !sys.signal_exit_flag )
- {
- // ##### begin Gilbert 28/10 ########//
- if( !under_construction )
- {
- // -------- create a firm die record ------//
- // can be called as soon as restore_world_matrix
- FirmDie firmDie;
- firmDie.init(this);
- firm_die_array.add(&firmDie);
- }
- // ##### end Gilbert 28/10 ########//
- assign_overseer(0); // this function must be called before restore_world_matrix(), otherwise the power area can't be completely reset
- if( worker_array )
- {
- resign_all_worker(); // the workers in the firm will be killed if there is no space for creating the workers
- mem_del( worker_array );
- worker_array = NULL;
- }
- if(builder_recno)
- mobilize_builder(builder_recno);
- }
- else
- {
- if(builder_recno)
- kill_builder(builder_recno);
- kill_overseer();
- if(worker_array)
- {
- kill_all_worker();
- mem_del(worker_array);
- worker_array = NULL;
- }
- }
- //--------- decrease firm counter -----------//
- if( nation_recno )
- nation_array[nation_recno]->nation_firm_count--;
- //------ update firm counter -------//
- FirmInfo* firmInfo = firm_res[firm_id];
- firmInfo->total_firm_count--;
- if( nation_recno )
- firmInfo->dec_nation_firm_count(nation_recno);
- //------- update town border ---------//
- loc_x1 = -1; // mark deleted
- //------- if the current firm is the selected -----//
- if( firm_array.selected_recno == firm_recno )
- {
- firm_array.selected_recno = 0;
- info.disp();
- }
- //-------------------------------------------------//
- firm_recno = 0;
- remove_firm = 0; // reset static parameter
- }
- //----------- End of function Firm::deinit ---------//
- //--------- Begin of function Firm::init_name --------//
- //
- // Set the name of this firm. Name related vars are set.
- //
- void Firm::init_name()
- {
- char t=firm_res[firm_id]->short_name[0];
- if( t==' ' || !t ) // if this firm does not have any short name, display the full name without displaying the town name together
- return;
- //---- find the closest town and set closest_town_name_id -----//
- closest_town_name_id = get_closest_town_name_id();
- //--------- set firm_name_instance_id -----------//
- char usedInstanceArray[256];
- Firm* firmPtr;
- memset( usedInstanceArray, 0, sizeof(usedInstanceArray) );
- int i;
- for( i=firm_array.size() ; i>0 ; i-- )
- {
- if( firm_array.is_deleted(i) )
- continue;
- firmPtr = firm_array[i];
- if( firmPtr->firm_id == firm_id &&
- firmPtr->closest_town_name_id == closest_town_name_id &&
- firmPtr->firm_name_instance_id )
- {
- usedInstanceArray[firmPtr->firm_name_instance_id-1] = 1;
- }
- }
- for( i=0 ; i<256 ; i++ ) // get the smallest id. which are not used by existing firms
- {
- if( !usedInstanceArray[i] )
- {
- firm_name_instance_id = i+1;
- break;
- }
- }
- }
- //--------- End of function Firm::init_name --------//
- //------- Begin of function Firm::get_closest_town_name_id -----------//
- //
- // return the name id. of the closest town.
- //
- int Firm::get_closest_town_name_id()
- {
- //---- find the closest town and set closest_town_name_id -----//
- int townDistance, minTownDistance=0x7FFF;
- int closestTownNameId=0;
- Town* townPtr;
- for( int i=town_array.size() ; i>0 ; i-- )
- {
- if( town_array.is_deleted(i) )
- continue;
- townPtr = town_array[i];
- townDistance = m.points_distance( townPtr->center_x, townPtr->center_y,
- center_x, center_y );
- if( townDistance < minTownDistance )
- {
- minTownDistance = townDistance;
- closestTownNameId = townPtr->town_name_id;
- }
- }
- return closestTownNameId;
- }
- //--------- End of function Firm::get_closest_town_name_id -----------//
- //------- Begin of function Firm::firm_name -----------//
- //
- char* Firm::firm_name()
- {
- static String str;
- if( !closest_town_name_id )
- {
- str = firm_res[firm_id]->name;
- }
- else
- {
- #if(defined(SPANISH))
- str = firm_res[firm_id]->short_name;
- str += " de ";
- str += town_res.get_name(closest_town_name_id);
- #else
- // FRENCH, GERMAN and US
- str = town_res.get_name(closest_town_name_id);
- str += " ";
- str += firm_res[firm_id]->short_name;
- #endif
- if( firm_name_instance_id > 1 ) // don't display number for the first firm
- {
- str += " ";
- str += firm_name_instance_id;
- }
- }
- return str;
- }
- //--------- End of function Firm::firm_name -----------//
- //------- Begin of function Firm::complete_construction -----------//
- //
- // Complete construction instantly.
- //
- void Firm::complete_construction()
- {
- if( under_construction )
- {
- hit_points = max_hit_points;
- under_construction = 0;
- }
- }
- //--------- End of function Firm::complete_construction -----------//
- //------- Begin of function Firm::assign_unit -----------//
- //
- void Firm::assign_unit(int unitRecno)
- {
- err_when( !unitRecno );
- Unit* unitPtr = unit_array[unitRecno];
- //------- if this is a construction worker -------//
- if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION )
- {
- set_builder(unitRecno);
- return;
- }
- //---- if the unit does not belong to the firm's nation ----//
- if( unitPtr->nation_recno != nation_recno )
- {
- // can no longer capture a firm with a normal unit - must use spy
- //----- capture this firm if there is nobody here -----//
- /*
- if( worker_array && worker_count==0 && overseer_recno==0 && // if the firm is empty, assign to take over the firm
- unitPtr->skill.skill_id == firm_skill_id ) // the takeover unit must have the skill of this firm
- {
- change_nation(unitPtr->nation_recno);
- }
- else
- */ 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.
- }
- //-- if there isn't any overseer in this firm or this unit's skill is higher than the current overseer's skill --//
- //### begin alex 18/10 ###//
- unitPtr->group_select_id = 0; // clear group select id
- //#### end alex 18/10 ####//
- FirmInfo* firmInfo = firm_res[firm_id];
- if( firmInfo->need_overseer &&
- ( !overseer_recno ||
- ( unitPtr->skill.skill_id == firm_skill_id &&
- unit_array[overseer_recno]->skill.skill_id != firm_skill_id ) || // the current overseer does not have the required skill
- ( unitPtr->skill.skill_id == firm_skill_id &&
- unitPtr->skill.skill_level > unit_array[overseer_recno]->skill.skill_level )
- ) )
- {
- assign_overseer(unitRecno);
- }
- else if( firmInfo->need_worker )
- {
- assign_worker(unitRecno);
- }
- }
- //--------- End of function Firm::assign_unit -----------//
- //--------- Begin of function Firm::assign_overseer --------//
- //
- // Assign an unit as the overseer of this firm
- //
- // <int> newOverseerRecno - recno of the new overseer unit.
- // 0 means resign the current overseer
- //
- // Note: If a new overseer is assigned to the firm, there should be
- // space for the old overseer to initialize and appear in the
- // map (the space the new overseer occupied).
- //
- // ** If the newOverseerRecno==0, there may be no space for
- // creating the old overseer. Then, the old overseer will be
- // deleted. **
- // ** else there must be space for creating the old overseer,
- // at least the space occupied by the new overseer **
- //
- void Firm::assign_overseer(int newOverseerRecno)
- {
- if( !firm_res[firm_id]->need_overseer )
- return;
- if( !newOverseerRecno && !overseer_recno )
- return;
- //--- if the new overseer's nation is not the same as the firm's nation, don't assign ---//
- if( newOverseerRecno && unit_array[newOverseerRecno]->nation_recno != nation_recno )
- return;
- //------------------------------------------//
- int oldOverseerRecno = overseer_recno;
- if(!newOverseerRecno)
- {
- //------------------------------------------------------------------------------------------------//
- // the old overseer may be kept in firm or killed if remove_firm is true
- //------------------------------------------------------------------------------------------------//
- err_when(!overseer_recno);
- Unit *oldUnitPtr = unit_array[overseer_recno];
- SpriteInfo *spriteInfo = sprite_res[unit_res[oldUnitPtr->unit_id]->sprite_id];
- int xLoc = loc_x1;
- int yLoc = loc_y1;
- if(!locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height))
- {
- if(remove_firm)
- kill_overseer();
- }
- else
- {
- //------ there should be space for creating the overseer -----//
- mobilize_overseer();
- /*
- //-- if the overseer is resigned without successor, mobilize a worker as overseer --//
- if(!newOverseerRecno && worker_array)
- {
- int bestWorkerId = best_worker_id(); // find the most skilled worker
- if( bestWorkerId )
- newOverseerRecno = mobilize_worker(bestWorkerId,1);
- }
- */
- }
- }
- else
- {
- //----------- there should be space for creating the overseer ---------//
- err_when(!newOverseerRecno);
- Unit *unitPtr = unit_array[newOverseerRecno];
- int originalXLoc = unitPtr->next_x_loc();
- int originalYLoc = unitPtr->next_y_loc();
- err_when( unitPtr->hit_points <= 0 );
- unitPtr->deinit_sprite();
- //----------------------------------------------------------------------------------------//
- // There should be at least one location (occupied by the new overseer) for creating the old
- // overseer.
- //
- // 1) If a town is already created, the new overseer settle down there, free its space for
- // creating the new overseer.
- // 2) If the overseer and the workers live in the firm, no town will be created. Thus, the
- // space occupied by the old overseer is free for creating the new overseer.
- // 3) If the overseer and the workers need live in town, and a town is created. i.e. there
- // is no overseer or worker in the firm, so just assign the new overseer in the firm
- //----------------------------------------------------------------------------------------//
-
- if(!overseer_recno && !worker_count)
- {
- //------------------------------------------------------------------------------------------------//
- // the firm is empty
- //------------------------------------------------------------------------------------------------//
- if(firm_res[firm_id]->live_in_town)
- {
- overseer_town_recno = assign_settle(unitPtr->race_id, unitPtr->loyalty, 1); // the overseer settles down
- if(!overseer_town_recno)
- return; // no space for creating the town, just return without assigning
- }
- //------- set the unit to overseer mode and deinit the sprite ------//
- overseer_recno = newOverseerRecno;
- Unit *unitPtr = unit_array[overseer_recno];
- unitPtr->set_mode(UNIT_MODE_OVERSEE, firm_recno);
- unitPtr->deinit_sprite(); // hide the unit from the world map
- //--------- if the unit is a spy -----------//
- if( unitPtr->spy_recno )
- spy_array[unitPtr->spy_recno]->set_place( SPY_FIRM, firm_recno );
- /*
- //------ capture the firm if the overseer is from another nation ---//
- if(unit_array[overseer_recno]->nation_recno != nation_recno)
- change_nation(unit_array[overseer_recno]->nation_recno);
- */
- }
- else
- {
- //------------------------------------------------------------------------------------------------//
- // a town should exist if the overseer need live in town
- //------------------------------------------------------------------------------------------------//
- if(firm_res[firm_id]->live_in_town)
- {
- overseer_town_recno = assign_settle(unitPtr->race_id, unitPtr->loyalty, 1); // the overseer settles down
- if(!overseer_town_recno)
- return; // reach max population and no space to create town, return without assigning
- }
- Unit *unitPtr = unit_array[newOverseerRecno];
- unitPtr->deinit_sprite();
- if(overseer_recno)
- mobilize_overseer();
- overseer_recno = newOverseerRecno;
- unitPtr->set_mode(UNIT_MODE_OVERSEE, firm_recno);
- //--------- if the unit is a spy -----------//
- if( unitPtr->spy_recno )
- spy_array[unitPtr->spy_recno]->set_place( SPY_FIRM, firm_recno );
- /*
- //------ capture the firm if the overseer is from another nation ---//
- if(unit_array[overseer_recno]->nation_recno != nation_recno)
- change_nation(unit_array[overseer_recno]->nation_recno);
- */
- }
- }
- //------- update loyalty -------//
- if( newOverseerRecno && !unit_array.is_deleted(newOverseerRecno) )
- unit_array[newOverseerRecno]->update_loyalty();
- //----------- refresh display if this firm is selected ----------//
- if(firm_array.selected_recno == firm_recno)
- info.disp();
- }
- //----------- End of function Firm::assign_overseer --------//
- //--------- Begin of function Firm::mobilize_overseer --------//
- //
- int Firm::mobilize_overseer()
- {
- if( !overseer_recno )
- return 0;
- //--------- restore overseer's harmony ---------//
- int overseerRecno = overseer_recno;
- Unit* unitPtr = unit_array[overseer_recno];
- //-------- if the overseer is a spy -------//
- if( unitPtr->spy_recno )
- spy_array[unitPtr->spy_recno]->set_place(SPY_MOBILE, unitPtr->sprite_recno);
- //---- cancel the overseer's presence in the town -----//
- if( firm_res[firm_id]->live_in_town )
- town_array[overseer_town_recno]->dec_pop(unitPtr->race_id, 1);
- //----- get this overseer out of the firm -----//
- SpriteInfo* spriteInfo = sprite_res[unit_res[unitPtr->unit_id]->sprite_id];
- int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
- int spaceFound = locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height);
- if(spaceFound)
- {
- unitPtr->init_sprite(xLoc, yLoc);
- unitPtr->set_mode(0); // reset overseen firm recno
- }
- else
- {
- unit_array.del(overseer_recno); // delete it when there is no space for the unit
- return 0;
- }
- //--------- reset overseer_recno -------------//
- overseer_recno = 0;
- overseer_town_recno = 0;
- //------- update loyalty -------//
- if( overseerRecno && !unit_array.is_deleted(overseerRecno) )
- unit_array[overseerRecno]->update_loyalty();
- return overseerRecno;
- }
- //----------- End of function Firm::mobilize_overseer --------//
- //--------- Begin of function Firm::mobilize_builder --------//
- int Firm::mobilize_builder(short recno)
- {
- //----------- mobilize the builder -------------//
- Unit* unitPtr = unit_array[recno];
- SpriteInfo *spriteInfo = unitPtr->sprite_info;
- int xLoc=loc_x1, yLoc=loc_y1;
- if(!locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height, UNIT_LAND, builder_region_id) &&
- !world.locate_space(xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height, UNIT_LAND, builder_region_id))
- {
- kill_builder(recno);
- return 0;
- }
- unitPtr->init_sprite(xLoc, yLoc);
- unitPtr->stop2(); // clear all previously defined action
- err_when(unitPtr->unit_mode != UNIT_MODE_CONSTRUCT);
- unitPtr->set_mode(0);
- return 1;
- }
- //----------- End of function Firm::mobilize_builder --------//
- //--------- Begin of function Firm::best_worker_id --------//
- //
- int Firm::best_worker_id()
- {
- int bestWorkerId=0, maxWorkerSkill=0;
- char rankId;
- int liveInTown = firm_res[firm_id]->live_in_town;
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- for( int i=0 ; i<worker_count ; i++ )
- {
- //--- if the town the worker lives and the firm are of the same nation ---//
- if( !liveInTown || town_array[ worker_array[i].town_recno ]->nation_recno == nation_recno )
- {
- if(firm_id==FIRM_CAMP)
- {
- rankId = worker_array[i].rank_id;
- if(rankId!=RANK_GENERAL && rankId!=RANK_KING)
- continue;
- }
- if( worker_array[i].skill_level > maxWorkerSkill )
- {
- maxWorkerSkill = worker_array[i].skill_level;
- bestWorkerId = i+1;
- }
- }
- }
- return bestWorkerId;
- }
- //----------- End of function Firm::best_worker_id --------//
- //--------- Begin of function Firm::free_worker_room --------//
- //
- // Resign the worst worker from the firm to free up a room for
- // a new worker.
- //
- void Firm::free_worker_room()
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- //---- if there is space for one more worker, demote the overseer to worker ----//
- if( worker_count < MAX_WORKER || worker_count==0 )
- return;
- //---- if all worker space are full, resign the worst worker to release one worker space for the overseer ----//
- int worestWorkerId=0, minWorkerSkill=0x7FFF;
- for( int i=0 ; i<MAX_WORKER ; i++ )
- {
- if( worker_array[i].skill_level < minWorkerSkill )
- {
- minWorkerSkill = worker_array[i].skill_level;
- worestWorkerId = i+1;
- }
- }
- if( worestWorkerId )
- resign_worker(worestWorkerId);
- err_here();
- }
- //----------- End of function Firm::free_worker_room --------//
- //--------- Begin of function Firm::assign_worker --------//
- //
- // Assign an unit as one of the workers of this firm
- //
- void Firm::assign_worker(int workerUnitRecno)
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- //-- if the unit is a spy, only allow assign when there is room in the firm --//
- Unit* unitPtr = unit_array[workerUnitRecno];
- if( unitPtr->true_nation_recno() != nation_recno &&
- worker_count == MAX_WORKER )
- {
- return;
- }
- //---- if all worker space are full, resign the worst worker to release one worker space for the overseer ----//
- err_when( unitPtr->rank_id == RANK_KING );
- err_when( unitPtr->hit_points <= 0 );
- int unitXLoc= -1, unitYLoc;
- if( worker_count == MAX_WORKER )
- {
- int worstWorkerId=0, minWorkerSkill=0x7FFF, workerSkill;
- for(int i=0; i<MAX_WORKER; i++)
- {
- workerSkill = worker_array[i].skill_level;
- if( workerSkill < minWorkerSkill)
- {
- minWorkerSkill = workerSkill;
- worstWorkerId = i+1;
- }
- }
- err_when(worstWorkerId<1 || worstWorkerId>MAX_WORKER);
- unitXLoc = unitPtr->next_x_loc(); // save the location for later init_sprite() if the assign settle action failed
- unitYLoc = unitPtr->next_y_loc();
- unitPtr->deinit_sprite(); // free the location for creating the worst unit
- #ifdef DEBUG
- int oldWorkerCount = worker_count;
- int resignResult = resign_worker(worstWorkerId);
- err_when(!resignResult && oldWorkerCount==worker_count);
- #else
- resign_worker(worstWorkerId);
- #endif
- }
- // err_when( worker_count >= MAX_WORKER );
- //---------- there is room for the new worker ------------//
- Worker* workerPtr = worker_array + worker_count;
- memset( workerPtr, 0, sizeof(Worker) );
- if( firm_res[firm_id]->live_in_town )
- {
- workerPtr->town_recno = assign_settle(unitPtr->race_id, unitPtr->loyalty, 0); // the worker settles down
- if( !workerPtr->town_recno )
- {
- //--- the unit was deinit_sprite(), and now the assign settle action failed, we need to init_sprite() to restore it ---//
- if( unitXLoc>=0 && !unitPtr->is_visible() )
- unitPtr->init_sprite(unitXLoc, unitYLoc);
- return;
- }
- }
- else
- {
- workerPtr->town_recno = 0;
- workerPtr->worker_loyalty = unitPtr->loyalty;
- }
- //------- add the worker to the firm -------//
- worker_count++;
- err_when( worker_count > MAX_WORKER );
- workerPtr->name_id = unitPtr->name_id;
- workerPtr->race_id = unitPtr->race_id;
- workerPtr->unit_id = unitPtr->unit_id;
- workerPtr->rank_id = unitPtr->rank_id;
- workerPtr->skill_id = firm_skill_id;
- workerPtr->skill_level = unitPtr->skill.get_skill(firm_skill_id);
- if( workerPtr->skill_level == 0 )
- workerPtr->skill_level = CITIZEN_SKILL_LEVEL;
- err_when( workerPtr->skill_level<0 );
- err_when( workerPtr->skill_level>100 );
- /*#ifdef DEBUG2
- if(unit_res[unitPtr->unit_id]->unit_class==UNIT_CLASS_HUMAN)
- {
- unitPtr->skill.combat_level = 60;
- unitPtr->hit_points = unitPtr->skill.combat_level*2;
- unitPtr->max_hit_points = unitPtr->hit_points;
- }
- #endif*/
- workerPtr->combat_level = unitPtr->skill.combat_level;
- workerPtr->hit_points = (int) unitPtr->hit_points;
- err_when( workerPtr->combat_level <= 0 || workerPtr->combat_level > 100 );
- err_when( workerPtr->hit_points < 0 );
- if( workerPtr->hit_points == 0 ) // 0.? will become 0 in (float) to (int) conversion
- workerPtr->hit_points = 1;
- if( unit_res[unitPtr->unit_id]->unit_class == UNIT_CLASS_WEAPON )
- {
- workerPtr->extra_para = unitPtr->get_weapon_version();
- }
- else if( unitPtr->race_id )
- {
- workerPtr->extra_para = unitPtr->cur_power;
- }
- else
- {
- workerPtr->extra_para = 0;
- }
- workerPtr->init_potential();
- //------ if the recruited worker is a spy -----//
- if( unitPtr->spy_recno )
- {
- spy_array[unitPtr->spy_recno]->set_place( SPY_FIRM, firm_recno );
- workerPtr->spy_recno = unitPtr->spy_recno;
- unitPtr->spy_recno = 0; // reset it now so Unit::deinit() won't delete the Spy in spy_array
- }
- //--------- the unit disappear in firm -----//
- if( !firm_res[firm_id]->live_in_town ) // if the unit does not live in town, increase the unit count now
- unit_res[unitPtr->unit_id]->inc_nation_unit_count(nation_recno);
- unit_array.disappear_in_firm(workerUnitRecno);
- }
- //----------- End of function Firm::assign_worker --------//
- //--------- Begin of function Firm::assign_settle --------//
- //
- // The newly assigned overseer / worker settles down.
- //
- // <int> raceId - race id. of the unit
- // <int> unitLoyalty - loyalty of the unit
- // <int> isOverseer - whether the unit is an overseer, if not,
- // it is then a worker.
- //
- // return: <int> townRecno - the home town of the overseer/worker
- // 0 - no space to settle.
- //
- int Firm::assign_settle(int raceId, int unitLoyalty, int isOverseer)
- {
- err_when( !firm_res[firm_id]->live_in_town );
- err_when( unitLoyalty < 0 || unitLoyalty > 100 );
- //--- if there is a town of our nation within the effective distance ---//
- int townRecno = find_settle_town();
- if( townRecno )
- {
- town_array[townRecno]->inc_pop(raceId, 1, unitLoyalty);
- return townRecno;
- }
- //--- should create a town near the this firm, if there is no other town in the map ---//
- int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
- if( world.locate_space( xLoc, yLoc, loc_x2, loc_y2, STD_TOWN_LOC_WIDTH,
- STD_TOWN_LOC_HEIGHT, UNIT_LAND, region_id, 1 ) ) // the town must be in the same region as this firm.
- {
- if( m.points_distance( center_x, center_y, xLoc+(STD_TOWN_LOC_WIDTH-1)/2,
- yLoc+(STD_TOWN_LOC_HEIGHT-1)/2 ) <= EFFECTIVE_FIRM_TOWN_DISTANCE )
- {
- int townRecno = town_array.add_town( nation_recno, raceId, xLoc, yLoc );
- Town* townPtr = town_array[townRecno];
- townPtr->init_pop( raceId, 1, unitLoyalty, 1 ); // 1st 1 - population, 2nd 1 - the unit has a job already
- townPtr->auto_set_layout();
- return townRecno;
- }
- }
- //---- not able to find a space for a new town within the effective distance ----//
- return 0;
- }
- //----------- End of function Firm::assign_settle --------//
- //--------- Begin of function Firm::find_settle_town --------//
- //
- // Find a suitable town for the unit to settle.
- //
- int Firm::find_settle_town()
- {
- int townDistance, minDistance=0x7FFF, nearestTownRecno=0;
- Town* townPtr;
- Nation* nationPtr = nation_array[nation_recno];
- //-------- scan for our own town first -----------//
- for( int i=0 ; i<linked_town_count ; i++ )
- {
- townPtr = town_array[ linked_town_array[i] ];
- if( townPtr->population>=MAX_TOWN_POPULATION )
- continue;
- if( townPtr->nation_recno != nation_recno )
- continue;
- townDistance = m.points_distance( townPtr->center_x, townPtr->center_y, center_x, center_y );
- if( townDistance < minDistance )
- {
- minDistance = townDistance;
- nearestTownRecno = townPtr->town_recno;
- }
- }
- if( nearestTownRecno )
- return nearestTownRecno;
- else
- return 0;
- }
- //----------- End of function Firm::find_settle_town --------//
- //--------- Begin of function Firm::set_world_matrix --------//
- //
- // Set the cargo id of current firm int he world matrix
- //
- void Firm::set_world_matrix()
- {
- //--- if a nation set up a firm in a location that the player has explored, contact between the nation and the player is established ---//
- int xLoc, yLoc;
- for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
- {
- for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
- {
- world.get_loc(xLoc, yLoc)->set_firm(firm_recno);
- }
- }
- //--- if a nation set up a town in a location that the player has explored, contact between the nation and the player is established ---//
- establish_contact_with_player();
- //------------ reveal new land ----------//
- if( nation_recno == nation_array.player_recno ||
- (nation_recno && nation_array[nation_recno]->is_allied_with_player) )
- {
- world.unveil( loc_x1, loc_y1, loc_x2, loc_y2 );
- world.visit( loc_x1, loc_y1, loc_x2, loc_y2, EXPLORE_RANGE-1 );
- }
- //-------- set should_set_power --------//
- should_set_power = get_should_set_power();
- //---- set this town's influence on the map ----//
- if( should_set_power )
- world.set_power(loc_x1, loc_y1, loc_x2, loc_y2, nation_recno);
- //---- if the newly built firm is visual in the zoom window, redraw the zoom buffer ----//
- if( is_in_zoom_win() )
- sys.zoom_need_redraw = 1; // set the flag on so it will be redrawn in the next frame
- }
- //----------- End of function Firm::set_world_matrix --------//
- //--------- Begin of function Firm::get_should_set_power --------//
- //
- int Firm::get_should_set_power()
- {
- int shouldSetPower = 1;
- if( firm_id == FIRM_HARBOR ) // don't set power for harbors
- {
- shouldSetPower = 0;
- }
- else if( firm_id == FIRM_MARKET )
- {
- //--- don't set power for a market if it's linked to another nation's town ---//
- Town *townPtr;
- shouldSetPower = 0;
- //--- only set the shouldSetPower to 1 if the market is linked to a firm of ours ---//
- for( int i=0 ; i<linked_town_count ; i++ )
- {
- townPtr = town_array[ linked_town_array[i] ];
- if( townPtr->nation_recno == nation_recno )
- {
- shouldSetPower = 1;
- break;
- }
- }
- }
- return shouldSetPower;
- }
- //----------- End of function Firm::get_should_set_power --------//
- //------- Begin of function Firm::establish_contact_with_player --------//
- //
- // See if the town's location is an explored area, establish contact
- // with the player.
- //
- void Firm::establish_contact_with_player()
- {
- if( !nation_recno )
- return;
- int xLoc, yLoc;
- Location* locPtr;
- for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
- {
- for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
- {
- locPtr = world.get_loc(xLoc, yLoc);
- locPtr->set_firm(firm_recno);
- if( locPtr->explored() && nation_array.player_recno )
- {
- NationRelation *relation = (~nation_array)->get_relation(nation_recno);
- if( !remote.is_enable() )
- {
- relation->has_contact = 1;
- }
- else
- {
- if( !relation->has_contact && !relation->contact_msg_flag )
- {
- // packet structure : <player nation> <explored nation>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short));
- *shortPtr = nation_array.player_recno;
- shortPtr[1] = nation_recno;
- relation->contact_msg_flag = 1;
- }
- }
- }
- }
- }
- }
- //-------- End of function Firm::establish_contact_with_player --------//
- //--------- Begin of function Firm::restore_world_matrix --------//
- //
- // When the firm is destroyed, restore the original land id
- //
- void Firm::restore_world_matrix()
- {
- int xLoc, yLoc;
- for( yLoc=loc_y1 ; yLoc<=loc_y2 ; yLoc++ )
- {
- for( xLoc=loc_x1 ; xLoc<=loc_x2 ; xLoc++ )
- {
- err_when( world.get_loc(xLoc,yLoc)->firm_recno() != firm_recno );
- world.get_loc(xLoc,yLoc)->remove_firm();
- }
- }
- //---- restore this town's influence on the map ----//
- if( should_set_power ) // no power region for harbor as it build on coast which cannot be set with power region
- world.restore_power(loc_x1, loc_y1, loc_x2, loc_y2, 0, firm_recno);
- //---- if the newly built firm is visual in the zoom window, redraw the zoom buffer ----//
- if( is_in_zoom_win() )
- sys.zoom_need_redraw = 1;
- }
- //----------- End of function Firm::restore_world_matrix --------//
- //---------- Begin of function Firm::own_firm --------//
- //
- int Firm::own_firm()
- {
- return nation_recno == nation_array.player_recno;
- }
- //----------- End of function Firm::own_firm ---------//
- //---------- Begin of function Firm::process_animation --------//
- //
- void Firm::process_animation()
- {
- //-------- process animation ----------//
- FirmBuild* firmBuild = firm_res.get_build(firm_build_id);
- int frameCount = firmBuild->frame_count;
- if( frameCount==1 ) // no animation for this firm
- return;
- //---------- next frame -----------//
- if( --remain_frame_delay==0 ) // if it is in the delay between frames
- {
- remain_frame_delay = (char) firmBuild->frame_delay(cur_frame);
- if( ++cur_frame > frameCount )
- {
- if( firmBuild->animate_full_size )
- cur_frame = 1;
- else
- {
- cur_frame = 2; // start with the 2nd frame as the 1st frame is the common frame
- err_when( frameCount <=2 ); // for segmented animation, the minimum no. of frames must be 3, as the first one is the common frame
- }
- }
- }
- }
- //---------- End of function Firm::process_animation --------//
- //---------- Begin of function Firm::process_construction --------//
- //
- void Firm::process_construction()
- {
- err_when(firm_id!=FIRM_MONSTER && builder_recno<=0);
- if(firm_id==FIRM_MONSTER)
- {
- //--------- process construction for monster firm ----------//
- hit_points++;
- #ifdef DEBUG
- if( config.fast_build && nation_recno==nation_array.player_recno )
- hit_points += 10;
- #endif;
- if(hit_points>=max_hit_points)
- {
- hit_points = max_hit_points;
- under_construction = 0;
- }
- return;
- }
- err_when(firm_id==FIRM_MONSTER);
- if( !under_construction )
- return;
- //--- can only do construction when the firm is not under attack ---//
- if( info.game_date <= last_attacked_date+1 )
- return;
- if( sys.frame_count%2!=0 ) // one build every 2 frames
- return;
- //------ increase the construction progress ------//
- Unit *unitPtr = unit_array[builder_recno];
- if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION ) // if builder unit has construction skill
- hit_points += 1+unitPtr->skill.skill_level/30;
- else
- hit_points++;
- if( config.fast_build && nation_recno==nation_array.player_recno )
- hit_points += 10;
- //----- increase skill level of the builder unit -----//
- if( unitPtr->skill.skill_id == SKILL_CONSTRUCTION ) // if builder unit has construction skill
- {
- if( ++unitPtr->skill.skill_level_minor > 100 )
- {
- unitPtr->skill.skill_level_minor = 0;
- if( unitPtr->skill.skill_level < 100 )
- unitPtr->skill.skill_level++;
- }
- }
- //------- when the construction is complete ----------//
- if( hit_points >= max_hit_points ) // finished construction
- {
- hit_points = max_hit_points;
- int needAssignUnit=0;
- under_construction = 0;
- // ##### begin Gilbert 10/10 #######//
- if( nation_recno == nation_array.player_recno )
- se_res.far_sound(center_x, center_y, 1, 'S', unitPtr->sprite_id,
- "FINS", 'F', firm_id);
- // ##### end Gilbert 10/10 #######//
- err_when(builder_recno<=0 || unit_array.is_deleted(builder_recno));
- err_when(unitPtr->nation_recno!=nation_recno);
- FirmInfo* firmInfo=firm_res[firm_id];
- if( (firmInfo->need_overseer || firmInfo->need_worker) &&
- (firmInfo->firm_skill_id==0 || firmInfo->firm_skill_id == (unitPtr->skill).skill_id) ) // the builder with the skill required
- {
- unitPtr->set_mode(0); // reset it from UNIT_MODE_CONSTRUCT
- needAssignUnit=1;
- }
- else
- {
- set_builder(0);
- }
- //---------------------------------------------------------------------------------------//
- // should call assign_unit() first before calling action_finished(...UNDER_CONSTRUCTION)
- //---------------------------------------------------------------------------------------//
- if( needAssignUnit )
- {
- assign_unit(builder_recno);
- //------------------------------------------------------------------------------//
- // Note: there may be chance the unit cannot be assigned into the firm
- //------------------------------------------------------------------------------//
- if(!worker_count && !overseer_recno) // no assignment, can't assign
- {
- //------- init_sprite or delete the builder ---------//
- int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
- SpriteInfo *spriteInfo = unitPtr->sprite_info;
- if(!locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height))
- unit_array.disappear_in_firm(builder_recno); // kill the unit
- else
- unitPtr->init_sprite(xLoc, yLoc); // restore the unit
- }
- }
- // ##### begin Gilbert 10/10 #######//
- //if( nation_recno == nation_array.player_recno )
- // se_res.far_sound(center_x, center_y, 1, 'S', unitPtr->sprite_id,
- // "FINS", 'F', firm_id);
- // ##### end Gilbert 10/10 #######//
- builder_recno = 0;
- }
- err_when (hit_points < 0 || hit_points > max_hit_points );
- }
- //---------- End of function Firm::process_construction --------//
- //---------- Begin of function Firm::set_builder --------//
- //
- // <short> newBuilderRecno - >0 the recno of the new builder unit.
- // 0 just remove the existing builder, do not assign new one.
- //
- // return: <int> 0-the old builder is killed
- // 1-the builder is changed successfully.
- //
- int Firm::set_builder(short newBuilderRecno)
- {
- err_when( under_construction && newBuilderRecno==0 ); // can't remove the construction worker when the firm is under construction
- //------------------------------------//
- short oldBuilderRecno = builder_recno; // store the old builder recno
- builder_recno = newBuilderRecno;
- //-------- assign the new builder ---------//
- if(builder_recno)
- {
- Unit* unitPtr = unit_array[builder_recno];
- //### begin alex 18/10 ###//
- unitPtr->group_select_id = 0; // clear group select id
- //#### end alex 18/10 ####//
- if(unitPtr->is_visible()) // is visible if the unit is not inside the firm location
- {
- builder_region_id = world.get_region_id( unitPtr->cur_x_loc(), unitPtr->cur_y_loc() );
- unitPtr->deinit_sprite();
- if( unitPtr->selected_flag )
- {
- unitPtr->selected_flag = 0;
- unit_array.selected_count--;
- }
- }
- err_when( unitPtr->unit_mode != 0 );
- unitPtr->set_mode( UNIT_MODE_CONSTRUCT, firm_recno );
- }
- if(oldBuilderRecno)
- mobilize_builder(oldBuilderRecno);
- return 1;
- }
- //---------- End of function Firm::set_builder --------//
- //---------- Begin of function Firm::next_day --------//
- //
- void Firm::next_day()
- {
- if( !nation_recno )
- return;
- //------ think about updating link status -------//
- //
- // This part must be done here instead of in
- // process_ai() because it will be too late to do
- // it in process_ai() as the next_day() will call
- // first and some wrong goods may be input to markets.
- //
- //-----------------------------------------------//
- if( firm_ai )
- {
- if( info.game_date%30==firm_recno%30 || !ai_link_checked ) // once 30 days or when the link has been changed.
- {
- ai_update_link_status();
- ai_link_checked = 1;
- }
- }
- //-------- pay expenses ----------//
- pay_expense();
- //------- update loyalty --------//
- if( info.game_date%30 == firm_recno%30 )
- update_loyalty();
- //-------- consume food --------//
- if( !firm_res[firm_id]->live_in_town && worker_count>0 )
- consume_food();
- //------ think worker migration -------//
- if( worker_array && info.game_date%30 == firm_recno%30 )
- think_worker_migrate();
- //--------- repairing ----------//
- process_repair();
- //------ catching spies -------//
- if( info.game_date%30 == firm_recno%30 )
- spy_array.catch_spy(SPY_FIRM, firm_recno);
- //----- process workers from other town -----//
- if( firm_res[firm_id]->live_in_town )
- {
- process_independent_town_worker();
- }
- //--- recheck no_neighbor_space after a period, there may be new space available now ---//
- if( no_neighbor_space && info.game_date%180 == firm_recno%180 )
- {
- short buildXLoc, buildYLoc;
- 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
- no_neighbor_space = 0;
- }
- //-------- debug code ---------//
- #ifdef DEBUG
- err_when( builder_recno && unit_array.is_deleted(builder_recno) );
-
- if( worker_array )
- {
- for( int i=0 ; i<worker_count ; i++ )
- err_when( worker_array[i].hit_points <= 0 );
- }
- if( overseer_recno )
- {
- err_when( unit_array[overseer_recno]->rank_id == RANK_SOLDIER );
- }
- #endif
- }
- //----------- End of function Firm::next_day ---------//
- //---------- Begin of function Firm::next_month --------//
- //
- void Firm::next_month()
- {
- //------ update nation power recno ------//
- int newShouldSetPower = get_should_set_power();
- if( newShouldSetPower == should_set_power )
- return;
- if( should_set_power )
- world.restore_power(loc_x1, loc_y1, loc_x2, loc_y2, 0, firm_recno);
- should_set_power = newShouldSetPower;
- if( should_set_power )
- world.set_power(loc_x1, loc_y1, loc_x2, loc_y2, nation_recno);
- }
- //----------- End of function Firm::next_month ---------//
- //---------- Begin of function Firm::next_year --------//
- //
- void Firm::next_year()
- {
- //------- post income data --------//
- last_year_income = cur_year_income;
- cur_year_income = (float) 0;
- }
- //----------- End of function Firm::next_year ---------//
- //---------- Begin of function Firm::update_loyalty --------//
- //
- void Firm::update_loyalty()
- {
- if( firm_res[firm_id]->live_in_town ) // only for those who do not live in town
- return;
- //----- update loyalty of the soldiers -----//
- Worker* workerPtr = worker_array;
- for( int i=0 ; i<worker_count ; i++, workerPtr++ )
- {
- int targetLoyalty = workerPtr->target_loyalty(firm_recno);
- if( targetLoyalty > workerPtr->worker_loyalty )
- {
- int incValue = (targetLoyalty - workerPtr->worker_loyalty)/10;
- int newLoyalty = (int) workerPtr->worker_loyalty + max(1, incValue);
- if( newLoyalty > targetLoyalty )
- newLoyalty = targetLoyalty;
- workerPtr->worker_loyalty = newLoyalty;
- }
- else if( targetLoyalty < workerPtr->worker_loyalty )
- {
- workerPtr->worker_loyalty--;
- }
- }
- }
- //----------- End of function Firm::update_loyalty ---------//
- //---------- Begin of function Firm::process_repair --------//
- //
- void Firm::process_repair()
- {
- if( nation_array[nation_recno]->cash < 0 ) // if you don't have cash, the repair workers will not work
- return;
- if( !builder_recno )
- return;
- Unit *unitPtr = unit_array[builder_recno];
- //--- can only do construction when the firm is not under attack ---//
- if( info.game_date <= last_attacked_date+1 )
- {
- //---- if the construction worker is a spy, it will damage the building when the building is under attack ----//
- if( unitPtr->spy_recno &&
- unitPtr->true_nation_recno() != nation_recno )
- {
- hit_points -= (float) spy_array[unitPtr->spy_recno]->spy_skill / 30;
- if( hit_points < 0 )
- hit_points = (float) 0;
- }
- return;
- }
- //------- repair now - only process once every 3 days -----//
- if( hit_points >= max_hit_points )
- return;
- err_when( unitPtr->skill.skill_id != SKILL_CONSTRUCTION );
- 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
- if( firm_recno % dayInterval == info.game_date % dayInterval )
- {
- hit_points++;
- if( hit_points > max_hit_points )
- hit_points = max_hit_points;
- }
- }
- //----------- End of function Firm::process_repair ---------//
- //---------- Begin of function Firm::pay_expense --------//
- //
- void Firm::pay_expense()
- {
- if( !nation_recno )
- return;
- Nation* nationPtr = nation_array[nation_recno];
- //-------- fixed expenses ---------//
- float dayExpense = (float) firm_res[firm_id]->year_cost / 365;
- if( nationPtr->cash >= dayExpense )
- {
- nationPtr->add_expense( EXPENSE_FIRM, dayExpense, 1 );
- }
- else
- {
- if( hit_points > 0 )
- hit_points--;
- if( hit_points < 0 )
- hit_points = (float) 0;
- //--- when the hit points drop to zero and the firm is destroyed ---//
- if( hit_points==0 && nation_recno == nation_array.player_recno )
- news_array.firm_worn_out(firm_recno);
- }
- //----- paying salary to workers from other nations -----//
- if( worker_array && firm_res[firm_id]->live_in_town )
- {
- int townNationRecno, payWorkerCount=0;
- Worker* workerPtr;
- for( int i=worker_count-1 ; i>=0 ; i-- )
- {
- workerPtr = worker_array+i;
- townNationRecno = town_array[workerPtr->town_recno]->nation_recno;
- if( townNationRecno != nation_recno )
- {
- //--- if we don't have cash to pay the foreign workers, resign them ---//
- if( nationPtr->cash < 0 )
- {
- resign_worker(i+1);
- }
- else //----- pay salaries to the foreign workers now -----//
- {
- payWorkerCount++;
- if( townNationRecno ) // the nation of the worker will get income
- nation_array[townNationRecno]->add_income( INCOME_FOREIGN_WORKER, (float) WORKER_YEAR_SALARY / 365, 1 );
- }
- }
- }
- nationPtr->add_expense( EXPENSE_FOREIGN_WORKER, (float) WORKER_YEAR_SALARY * payWorkerCount / 365, 1 );
- }
- }
- //----------- End of function Firm::pay_expense ---------//
- //--------- Begin of function Firm::consume_food ---------//
- //
- void Firm::consume_food()
- {
- if( nation_array[nation_recno]->food > 0 )
- {
- int humanUnitCount=0;
- for( int i=0 ; i<worker_count ; i++ )
- {
- if( worker_array[i].race_id )
- humanUnitCount++;
- }
- nation_array[nation_recno]->consume_food((float) humanUnitCount * PERSON_FOOD_YEAR_CONSUMPTION / 365);
- }
- else //--- decrease loyalty if the food has been run out ---//
- {
- if( info.game_date%NO_FOOD_LOYALTY_DECREASE_INTERVAL == 0 ) // decrease 1 loyalty point every 2 days
- {
- for( int i=0 ; i<worker_count ; i++ )
- {
- if( worker_array[i].race_id )
- worker_array[i].change_loyalty(-1);
- }
- }
- }
- }
- //----------- End of function Firm::consume_food -----------//
- //---------- Begin of function Firm::add_income --------//
- //
- void Firm::add_income(int incomeType, float incomeAmt)
- {
- cur_year_income += incomeAmt;
- nation_array[nation_recno]->add_income(incomeType, incomeAmt, 1);
- }
- //----------- End of function Firm::add_income ---------//
- //--------- Begin of function Firm::year_expense ---------//
- //
- // Return the yearly expense for this firm.
- //
- int Firm::year_expense()
- {
- int totalExpense = firm_res[firm_id]->year_cost;
- //---- pay salary to workers from foreign towns ----//
- int payWorkerCount=0;
- if( worker_array && firm_res[firm_id]->live_in_town )
- {
- int payWorkerCount=0;
- Worker* workerPtr = worker_array;
- for( int i=0 ; i<worker_count ; i++, workerPtr++ )
- {
- if( town_array[workerPtr->town_recno]->nation_recno != nation_recno )
- payWorkerCount++;
- }
- totalExpense += WORKER_YEAR_SALARY * payWorkerCount;
- }
- return totalExpense;
- }
- //----------- End of function Firm::year_expense -----------//
- //--------- Begin of function Firm::sell_firm ---------//
- void Firm::sell_firm(char remoteAction)
- {
- if( !remoteAction && remote.is_enable() )
- {
- // packet structure : <firm recno>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_SELL, sizeof(short));
- *shortPtr = firm_recno;
- return;
- }
- //------- sell at 50% of the original cost -------//
- Nation* nationPtr = nation_array[nation_recno];
- int sellIncome = firm_res[firm_id]->setup_cost / 2 * (int) hit_points / (int) max_hit_points;
- nationPtr->add_income(INCOME_SELL_FIRM, (float)sellIncome);
- se_res.sound(center_x, center_y, 1, 'F', firm_id, "SELL" );
- firm_array.del_firm(firm_recno);
- }
- //----------- End of function Firm::sell_firm -----------//
- //--------- Begin of function Firm::destruct_firm ---------//
- void Firm::destruct_firm(char remoteAction)
- {
- if( !remoteAction && remote.is_enable() )
- {
- // packet structure : <firm recno>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_DESTRUCT, sizeof(short));
- *shortPtr = firm_recno;
- return;
- }
- se_res.sound(center_x, center_y, 1, 'F', firm_id, "DEST" );
-
- firm_array.del_firm(firm_recno);
- }
- //----------- End of function Firm::destruct_firm -----------//
- //--------- Begin of function Firm::cancel_construction ---------//
- //
- // Cancel construction
- //
- void Firm::cancel_construction(char remoteAction)
- {
- if( !remoteAction && remote.is_enable())
- {
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_CANCEL, sizeof(short));
- shortPtr[0] = firm_recno;
- return;
- }
- //------ get half of the construction cost back -------//
- Nation* nationPtr = nation_array[nation_recno];
- nationPtr->add_expense( EXPENSE_FIRM, (float) -firm_res[firm_id]->setup_cost/2 );
- firm_array.del_firm(firm_recno);
- }
- //----------- End of function Firm::cancel_construction -----------//
- //---------- Begin of function Firm::recruit_worker --------//
- //
- void Firm::recruit_worker()
- {
- if( MAX_WORKER==worker_count )
- return;
- if( info.game_date%5 != firm_recno%5 ) // update population once 10 days
- return;
- err_when( worker_count > MAX_WORKER );
- //-------- pull from neighbor towns --------//
- int i;
- Town* townPtr;
- Nation* nationPtr = nation_array[nation_recno];
- for( i=0 ; i<linked_town_count ; i++ )
- {
- if( linked_town_enable_array[i] != LINK_EE )
- continue;
- townPtr = town_array[linked_town_array[i]];
- //--- don't hire foreign workers if we don't have cash to pay them ---//
- if( nationPtr->cash < 0 && nation_recno != townPtr->nation_recno )
- continue;
- //-------- if the town has any unit ready for jobs -------//
- if( townPtr->jobless_population == 0 )
- continue;
- //---- if nation of the town is not hositle to this firm's nation ---//
- if( pull_town_people(townPtr->town_recno, COMMAND_AUTO) )
- return;
- }
- }
- //----------- End of function Firm::recruit_worker ---------//
- //---------- Begin of function Firm::pull_town_people --------//
- //
- // Pull people from the town. Also called by Town::draw_detect_link_line()
- //
- // <int> townRecno - the town recno which the people are pulled from.
- // [int] raceId - the race of the people to be pulled.
- // if not given, pick one randomly.
- // [int] forcePull - force pull people to to the firm.
- // (default: 0)
- //
- int Firm::pull_town_people(int townRecno, char remoteAction, int raceId, int forcePull)
- {
- 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.
- return 0;
- err_when( worker_count > MAX_WORKER );
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- if(!remoteAction && remote.is_enable() )
- {
- // packet structure : <firm recno> <town recno> <race Id or 0> <force Pull>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_PULL_TOWN_PEOPLE, 4*sizeof(short));
- shortPtr[0] = firm_recno;
- shortPtr[1] = townRecno;
- shortPtr[2] = raceId;
- // if raceId == 0, let each player choose the race by random number,
- // to sychronize the random number
- shortPtr[3] = forcePull;
- return 0;
- }
- //---- people in the town go to work for the firm ---//
- Town* townPtr = town_array[townRecno];
- int i, popAdded=0;
- //---- if doesn't specific a race, randomly pick one ----//
- if( !raceId )
- raceId = m.random(MAX_RACE)+1;
- //----------- scan the races -----------//
- for( i=0 ; i<MAX_RACE ; i++ ) // maximum 8 tries
- {
- //---- see if there is any population of this race to move to the firm ----//
- int recruitableCount = townPtr->recruitable_race_pop(raceId,1); // 1-allow recruiting spies
- if( recruitableCount > 0 )
- {
- //----- if the unit is forced to move to the firm ---//
- if( forcePull ) // right-click to force pulling a worker from the village
- {
- if( townPtr->race_loyalty_array[raceId-1] < MIN_RECRUIT_LOYALTY )
- return 0;
- townPtr->recruit_dec_loyalty(raceId);
- }
- else //--- see if the unit will voluntarily move to the firm ---//
- {
- //--- the higher the loyalty is, the higher the chance of working for the firm ---//
- if( townPtr->nation_recno )
- {
- if( m.random( (100-(int)townPtr->race_loyalty_array[raceId-1])/10 ) > 0 )
- return 0;
- }
- else
- {
- if( m.random( (100-(int)townPtr->race_resistance_array[raceId-1][nation_recno-1])/10 ) > 0 )
- return 0;
- }
- }
- //----- get the chance of getting people to your command base is higher when the loyalty is higher ----//
- if( firm_res[firm_id]->live_in_town )
- {
- townPtr->jobless_race_pop_array[raceId-1]--; // decrease the town's population
- townPtr->jobless_population--;
- err_when( townPtr->recruitable_race_pop(raceId,1) < 0 );
- err_when( townPtr->jobless_population < 0 );
- }
- else
- {
- townPtr->dec_pop(raceId, 0);
- }
- //------- add the worker to the firm -----//
- worker_count++;
- err_when( worker_count > MAX_WORKER );
- Worker* workerPtr = worker_array + worker_count - 1;
- memset( workerPtr, 0, sizeof(Worker) );
- workerPtr->race_id = raceId;
- workerPtr->rank_id = RANK_SOLDIER;
- workerPtr->unit_id = (char) race_res[raceId]->basic_unit_id;
- workerPtr->worker_loyalty = (char) townPtr->race_loyalty_array[raceId-1];
- if( firm_res[firm_id]->live_in_town )
- workerPtr->town_recno = townRecno;
- workerPtr->combat_level = CITIZEN_COMBAT_LEVEL;
- workerPtr->hit_points = CITIZEN_HIT_POINTS;
- workerPtr->skill_id = firm_skill_id;
- workerPtr->skill_level = CITIZEN_SKILL_LEVEL;
- workerPtr->init_potential();
- //--------- if this is a military camp ---------//
- //
- // Increase armed unit count of the race of the worker assigned,
- // as when a unit is assigned to a camp, Unit::deinit() will decrease
- // the counter, so we need to increase it back here.
- //
- //---------------------------------------------------//
- if( !firm_res[firm_id]->live_in_town )
- unit_res[workerPtr->unit_id]->inc_nation_unit_count(nation_recno);
- //------ if the recruited worker is a spy -----//
- int spyCount = townPtr->race_spy_count_array[raceId-1];
- if( spyCount >= m.random(recruitableCount)+1 )
- {
- int spyRecno = spy_array.find_town_spy(townRecno, raceId, m.random(spyCount)+1 ); // the 3rd parameter is which spy to recruit
- err_when( !spyRecno );
- workerPtr->spy_recno = spyRecno;
- spy_array[spyRecno]->set_place(SPY_FIRM, firm_recno);
- }
- return 1;
- }
- if( ++raceId > MAX_RACE )
- raceId = 1;
- }
- return 0;
- }
- //----------- End of function Firm::pull_town_people ---------//
- //------ Begin of function Firm::process_independent_town_worker -----//
- //
- // Process workers from independent towns.
- //
- // When workers work for a foreign firm, the overall resistance of
- // the worker's town towards that nation decreases.
- //
- void Firm::process_independent_town_worker()
- {
- if( firm_recno%15 != info.game_date%15 )
- return;
- #define RESISTANCE_DECREASE_PER_WORKER float(0.2) // resistance decrease per month every 15 days
- Town* townPtr;
- for( int i=0 ; i<worker_count ; i++ )
- {
- err_when( !worker_array[i].town_recno );
- townPtr = town_array[ worker_array[i].town_recno ];
- if( townPtr->nation_recno==0 ) // if it's an independent town
- {
- townPtr->race_resistance_array[worker_array[i].race_id-1][nation_recno-1] -= RESISTANCE_DECREASE_PER_WORKER;
- if( townPtr->race_resistance_array[worker_array[i].race_id-1][nation_recno-1] < 0 )
- townPtr->race_resistance_array[worker_array[i].race_id-1][nation_recno-1] = (float) 0;
- }
- }
- }
- //------- End of function Firm::process_independent_town_worker ------//
- //---------- Begin of function Worker::init_potential --------//
- //
- void Worker::init_potential()
- {
- if( m.random(10)==0 ) // 1 out of 10 has a higher than normal potential in this skill
- {
- skill_potential = 50+m.random(51); // 50 to 100 potential
- }
- }
- //----------- End of function Worker::init_potential ---------//
- //---------- Begin of function Firm::calc_productivity --------//
- //
- // Calculate the productivity of the firm.
- //
- void Firm::calc_productivity()
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- #define RACE_SKILL_MULTIPLE (float)2.0
- productivity = (float) 0;
- //------- calculate the productivity of the workers -----------//
- int i;
- float totalSkill=(float)0;
- Worker* workerPtr = worker_array;
- for( i=0 ; i<worker_count ; i++, workerPtr++ )
- {
- totalSkill += (int) workerPtr->skill_level
- * workerPtr->hit_points / workerPtr->max_hit_points();
- }
- //----- include skill in the calculation ------//
- productivity = totalSkill / MAX_WORKER - sabotage_level;
- if( productivity < 0 )
- productivity = (float) 0;
- }
- //----------- End of function Firm::calc_productivity ---------//
- //---------- Begin of function Firm::average_worker_skill --------//
- //
- // Return the average skill level of the workers in this firm.
- //
- int Firm::average_worker_skill()
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- if( worker_count==0 )
- return 0;
- //------- calculate the productivity of the workers -----------//
- int i;
- int totalSkill = 0;
- Worker* workerPtr = worker_array;
- for( i=0 ; i<worker_count ; i++, workerPtr++ )
- totalSkill += workerPtr->skill_level;
- //----- include skill in the calculation ------//
- return totalSkill / worker_count;
- }
- //----------- End of function Firm::average_worker_skill ---------//
- //---------- Begin of function Firm::update_worker --------//
- //
- void Firm::update_worker()
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- if( info.game_date%15 != firm_recno%15 )
- return;
- if( worker_count==0 )
- return;
- //------- update the worker's para ---------//
- int incValue, levelMinor;
- Worker* workerPtr = worker_array;
- for( int i=0 ; i<worker_count ; i++, workerPtr++ )
- {
- //------- increase worker skill -----------//
- if( is_operating() && workerPtr->skill_level < 100 ) // only train when the workers are working
- {
- err_when(workerPtr->skill_level<0 || workerPtr->skill_level>100);
- incValue = max(10, 100-workerPtr->skill_level)
- * workerPtr->hit_points / workerPtr->max_hit_points()
- * (100+workerPtr->skill_potential) / 100 / 2;
- //-------- increase level minor now --------//
- levelMinor = workerPtr->skill_level_minor + incValue * (75+m.random(50)) / 100; // with random factors, resulting in 75% to 125% of the original
- int loopCount=0;
- while( levelMinor >= 100 )
- {
- levelMinor -= 100;
- workerPtr->skill_level++;
- err_when( loopCount++ > 1000 );
- }
- workerPtr->skill_level_minor = levelMinor;
- }
- //------- increase worker hit points --------//
- int maxHitPoints = workerPtr->max_hit_points();
- err_when( maxHitPoints <= 0 );
- if( workerPtr->hit_points < maxHitPoints )
- {
- workerPtr->hit_points += 2; // units in firms recover twice as fast as they are mobile
- if( workerPtr->hit_points > maxHitPoints )
- workerPtr->hit_points = maxHitPoints;
- }
- }
- }
- //----------- End of function Firm::update_worker ---------//
- //---------- Begin of function Firm::create_unit --------//
- //
- // Create an unit and place it below the firm.
- //
- // <int> unitId - id. of the unit
- // [int] townRecno - recno of the town from which the unit comes from
- // if given, it means the unit comes from the town and
- // should decrease the town population.
- // (default: 0)
- // [int] unitHasJob - whether the unit current has a job or not
- // (default: 0)
- //
- // return : <int> unitRecno - the recno of the unit created
- //
- int Firm::create_unit(int unitId, int townRecno, int unitHasJob)
- {
- //----look for an empty locatino for the unit to stand ----//
- //--- scan for the 5 rows right below the building ---//
- SpriteInfo* spriteInfo = sprite_res[unit_res[unitId]->sprite_id];
- int xLoc=loc_x1, yLoc=loc_y1; // xLoc & yLoc are used for returning results
- if(!locate_space(remove_firm, xLoc, yLoc, loc_x2, loc_y2, spriteInfo->loc_width, spriteInfo->loc_height))
- return 0;
- //------------ add the unit now ----------------//
- int unitNationRecno;
- if( townRecno )
- unitNationRecno = town_array[townRecno]->nation_recno;
- else
- unitNationRecno = nation_recno;
- int unitRecno = unit_array.add_unit( unitId, unitNationRecno, RANK_SOLDIER, 0, xLoc, yLoc );
- //----- update the population of the town ------//
- if( townRecno )
- town_array[townRecno]->dec_pop(unit_array[unitRecno]->race_id, unitHasJob);
- return unitRecno;
- }
- //----------- End of function Firm::create_unit ---------//
- //--------- Begin of function Firm::mobilize_worker ---------//
- //
- // Promote a firm worker as a unit.
- //
- // return: <int> the recno of the unit created.
- //
- int Firm::mobilize_worker(int workerId, char remoteAction)
- {
- if(!remoteAction && remote.is_enable() )
- {
- // packet strcture : <firm_recno> <workerId>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_MOBL_WORKER, 2*sizeof(short) );
- shortPtr[0] = firm_recno;
- shortPtr[1] = workerId;
- return 0;
- }
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- err_when( workerId<1 || workerId>worker_count );
- //------------- resign worker --------------//
- Worker thisWorker = worker_array[workerId-1];
- int oldWorkerCount = worker_count;
- int unitRecno2 = resign_worker(workerId);
- if(!unitRecno2 && worker_count==oldWorkerCount)
- return 0;
- //------ create a mobile unit -------//
- int unitRecno=0;
- 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.
- {
- unitRecno = create_worker_unit(thisWorker);
- if( !unitRecno ) // no space for creating units
- return 0;
- }
- //------------------------------------//
- err_when( unitRecno2 && unitRecno ); // only one of them should have value
- err_when( !unitRecno2 && !unitRecno ); // one of them must have a value
- if( unitRecno )
- return unitRecno;
- else
- return unitRecno2;
- }
- //----------- End of function Firm::mobilize_worker -----------//
- //--------- Begin of function Firm::create_worker_unit ---------//
- //
- int Firm::create_worker_unit(Worker& thisWorker)
- {
- //--------- copy the worker's info --------//
- int unitLoyalty = thisWorker.loyalty();
- //------------ create an unit --------------//
- int unitId = thisWorker.unit_id;
- int unitRecno = create_unit( unitId, thisWorker.town_recno, 0 ); // this worker no longer has a job as it has been resigned
- if( !unitRecno )
- return 0;
- Unit* unitPtr = unit_array[unitRecno];
- UnitInfo *unitInfo = unit_res[unitId];
- //------- set the unit's parameters --------//
- unitPtr->skill.skill_id = thisWorker.skill_id;
- unitPtr->skill.skill_level = thisWorker.skill_level;
- unitPtr->skill.skill_level_minor = thisWorker.skill_level_minor;
- err_when( unitPtr->skill.skill_level<0 || unitPtr->skill.skill_level>100 );
- unitPtr->set_combat_level(thisWorker.combat_level);
- unitPtr->skill.combat_level_minor = thisWorker.combat_level_minor;
- err_when( unitPtr->skill.combat_level<=0 || unitPtr->skill.combat_level>100 );
- unitPtr->loyalty = unitLoyalty;
- unitPtr->hit_points = thisWorker.hit_points;
- unitPtr->rank_id = thisWorker.rank_id;
- if( unit_res[unitPtr->unit_id]->unit_class == UNIT_CLASS_WEAPON )
- {
- unitPtr->set_weapon_version( thisWorker.extra_para ); // restore nation contribution
- }
- else if( unitPtr->race_id )
- {
- unitPtr->cur_power = thisWorker.extra_para;
- if( unitPtr->cur_power < 0 )
- unitPtr->cur_power = 0;
- if( unitPtr->cur_power > 150 )
- unitPtr->cur_power = 150;
- }
- err_when( unitPtr->hit_points <= 0 );
- unitPtr->fix_attack_info();
- //if( unitInfo->unit_class == UNIT_CLASS_WEAPON )
- //{
- // switch( unitId )
- // {
- // case UNIT_BALLISTA:
- // unitPtr->attack_count = 2;
- // break;
- // case UNIT_EXPLOSIVE_CART:
- // unitPtr->attack_count = 0;
- // break;
- // default:
- // unitPtr->attack_count = 1;
- //}
- // if( unitPtr->attack_count > 0)
- // {
- // unitPtr->attack_info_array = unit_res.attack_info_array
- // + unitInfo->first_attack-1
- // + (thisWorker.extra_para -1) * unitPtr->attack_count; // extra para keeps the weapon version
- // }
- // else
- // {
- // // no attack like explosive cart
- // unitPtr->attack_info_array = NULL;
- // }
- // }
- if( thisWorker.name_id && thisWorker.race_id ) // if this worker is formerly an unit who has a name
- unitPtr->set_name(thisWorker.name_id);
- err_when( !unitPtr->is_visible() );
- //------ if the unit is a spy -------//
- if( thisWorker.spy_recno )
- {
- Spy* spyPtr = spy_array[thisWorker.spy_recno];
- unitPtr->spy_recno = thisWorker.spy_recno;
- unitPtr->ai_unit = spyPtr->cloaked_nation_recno &&
- nation_array[spyPtr->cloaked_nation_recno]->is_ai();
- unitPtr->set_name(spyPtr->name_id); // set the name id. of this unit
- spyPtr->set_place(SPY_MOBILE, unitRecno);
- }
- //--- decrease the nation unit count as the Unit has already increased it ----//
- if( !firm_res[firm_id]->live_in_town ) // if the unit does not live in town, increase the unit count now
- unit_res[unitPtr->unit_id]->dec_nation_unit_count(nation_recno);
- return unitRecno;
- }
- //----------- End of function Firm::create_worker_unit -----------//
- //--------- Begin of function Firm::mobilize_all_worker ---------//
- //
- // mobilize as many as workers if there is space for creating the
- // workers
- //
- // [int] leaderUnitRecno - if given, the workers are assigned as
- // a team and their leader_unit_recno are set.
- // (default: 0)
- //
- void Firm::mobilize_all_worker(int leaderUnitRecno)
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- //------- detect buttons on hiring firm workers -------//
- int loopCount = 0;
- short unitRecno;
- err_when( worker_count > MAX_WORKER );
- while( worker_count > 0 )
- {
- err_when(++loopCount > 100);
- unitRecno = mobilize_worker(1, COMMAND_AUTO); // always record 1 as the workers info are moved forward from the back to the front
- if(!unitRecno)
- break; // keep the rest workers as there is no space for creating the unit
- if( leaderUnitRecno )
- {
- Unit* unitPtr = unit_array[unitRecno];
- unitPtr->team_id = unit_array.cur_team_id; // define it as a team
- unitPtr->leader_unit_recno = leaderUnitRecno;
- unitPtr->update_loyalty(); // the unit is just assigned to a new leader, set its target loyalty
- err_when( unitPtr->rank_id != RANK_KING && unitPtr->rank_id != RANK_GENERAL );
- if( nation_recno == nation_array.player_recno )
- unitPtr->selected_flag = 1;
- }
- }
- unit_array.cur_team_id++;
- }
- //----------- End of function Firm::mobilize_all_worker -----------//
- //--------- Begin of function Firm::resign_all_worker ---------//
- //
- // Resign all workers in the firm.
- //
- // [int] disappearFlag - whether the worker should disappear after
- // resigning, and does not go back to the town.
- //
- void Firm::resign_all_worker(int disappearFlag)
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- //------- detect buttons on hiring firm workers -------//
- int loopCount=0, townRecno, raceId;
- int oldWorkerCount;
- while( worker_count > 0 )
- {
- err_when(++loopCount > 100);
- townRecno = worker_array[0].town_recno;
- raceId = worker_array[0].race_id;
- oldWorkerCount = worker_count;
- if(!resign_worker(1))
- {
- if(oldWorkerCount==worker_count)
- break; // no space to resign the worker, keep them in firm
- }
- if( disappearFlag && townRecno )
- town_array[townRecno]->dec_pop(raceId, 0);
- }
- }
- //----------- End of function Firm::resign_all_worker -----------//
- //--------- Begin of function Firm::resign_worker ---------//
- //
- // Resign the worker from the firm.
- //
- // return: <int> recno of the mobile unit created if there is one created.
- //
- int Firm::resign_worker(int workerId)
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- err_when( workerId<1 || workerId>worker_count );
- //------- decrease worker no. and create an unit -----//
- Worker* workerPtr = worker_array+workerId-1;
- int unitRecno = 0;
- if( workerPtr->race_id && workerPtr->name_id )
- race_res[workerPtr->race_id]->free_name_id(workerPtr->name_id);
- if( workerPtr->town_recno ) // town_recno is 0 if the workers in the firm do not live in towns
- {
- Town* townPtr = town_array[workerPtr->town_recno];
- townPtr->jobless_race_pop_array[workerPtr->race_id-1]++; // decrease the town's population
- townPtr->jobless_population++;
- //------ put the spy in the town -------//
- if( workerPtr->spy_recno )
- spy_array[workerPtr->spy_recno]->set_place(SPY_TOWN, workerPtr->town_recno);
- }
- else
- {
- Worker thisWorker = worker_array[workerId-1];
- unitRecno = create_worker_unit(thisWorker); // if he is a spy, create_worker_unit wil call set_place(SPY_MOBILE)
- if(!unitRecno)
- return 0; // return 0 eg there is no space to create the unit
- }
- //------- delete the record from the worker_array ------//
- err_when( worker_count > MAX_WORKER );
- err_when( selected_worker_id > worker_count );
- m.del_array_rec(worker_array, worker_count, sizeof(Worker), workerId);
- if( selected_worker_id > workerId || selected_worker_id == worker_count )
- selected_worker_id--;
- worker_count--;
- err_when( worker_count < 0 );
- err_when( selected_worker_id > worker_count );
- return unitRecno;
- }
- //----------- End of function Firm::resign_worker -----------//
- //------- Begin of function Firm::think_worker_migrate ---------//
- //
- // Let the workers think if they want to worker_migrate or not.
- //
- void Firm::think_worker_migrate()
- {
- #define MIN_MIGRATE_ATTRACT_LEVEL 30
- if( worker_count==0 || !firm_res[firm_id]->live_in_town )
- return;
- int townPtrCount = town_array.size();
- int townRecno = m.random(townPtrCount)+1;
- int firmXLoc = center_x, firmYLoc = center_y;
- int i, j, raceId, workerId;
- Town *townPtr, *workerTownPtr;
- Worker *workerPtr;
- int curBaseAttractLevel, targetBaseAttractLevel, curAttractLevel, targetAttractLevel;
- for( i=townPtrCount ; i>0 ; i-- )
- {
- if( ++townRecno > townPtrCount )
- townRecno=1;
- if( town_array.is_deleted(townRecno) )
- continue;
- townPtr = town_array[townRecno];
- if(townPtr->population>=MAX_TOWN_POPULATION)
- continue;
- //------ check if this town is linked to the current firm -----//
- for( j=townPtr->linked_firm_count-1 ; j>=0 ; j-- )
- {
- if( townPtr->linked_firm_array[j] == firm_recno &&
- townPtr->linked_firm_enable_array[j] )
- {
- break;
- }
- }
- if( j<0 )
- continue;
- //------------------------------------------------//
- //
- // Calculate the attractive factor, it is based on:
- //
- // - the reputation of the target nation (+0 to 100)
- // - the racial harmony of the race in the target town (+0 to 100)
- // - the no. of people of the race in the target town
- // - distance between the current town and the target town (-0 to 100)
- //
- // Attractiveness level range: 0 to 200
- //
- //------------------------------------------------//
- targetBaseAttractLevel = 0;
- if( townPtr->nation_recno )
- targetBaseAttractLevel += (int) nation_array[townPtr->nation_recno]->reputation;
- //---- scan all workers, see if any of them want to worker_migrate ----//
- workerId=m.random(worker_count)+1;
- for(j=0 ; j<worker_count ; j++ )
- {
- if( ++workerId > worker_count )
- workerId = 1;
- workerPtr = worker_array+workerId-1;
- if( workerPtr->town_recno == townRecno )
- continue;
- //-- do not migrate if the target town's population of that race is less than half of the population of the current town --//
- raceId = workerPtr->race_id;
- workerTownPtr = town_array[workerPtr->town_recno];
- if( townPtr->race_pop_array[raceId-1] < workerTownPtr->race_pop_array[raceId-1]/2 )
- continue;
- //------ calc the current and target attractiveness level ------//
- workerTownPtr = town_array[workerPtr->town_recno];
- if( workerTownPtr->nation_recno )
- curBaseAttractLevel = (int) nation_array[workerTownPtr->nation_recno]->reputation;
- else
- curBaseAttractLevel = 0;
- targetAttractLevel = targetBaseAttractLevel +
- townPtr->race_harmony(raceId);
- if( targetAttractLevel < MIN_MIGRATE_ATTRACT_LEVEL )
- continue;
- curAttractLevel = curBaseAttractLevel +
- workerTownPtr->race_harmony(raceId) +
- ((int)workerPtr->loyalty() - 40); // loyalty > 40 is considered as positive force, < 40 is considered as negative force
- if( targetAttractLevel > curAttractLevel )
- {
- int newLoyalty = max( REBEL_LOYALTY+1, targetAttractLevel/2 );
- worker_migrate(workerId, townRecno, newLoyalty);
- return;
- }
- }
- }
- }
- //-------- End of function Firm::think_worker_migrate -----------//
- //------- Begin of function Firm::worker_migrate ---------//
- //
- // Worker worker_migrate from one town to another.
- //
- // <int> workerId - id. of the worker
- // <int> destTownRecno - recno of the destination town.
- // <int> newLoyalty - loyalty of the unit in the target town.
- //
- void Firm::worker_migrate(int workerId, int destTownRecno, int newLoyalty)
- {
- err_when( !worker_array ); // this function shouldn't be called if this firm does not need worker
- err_when( !firm_res[firm_id]->live_in_town );
- Worker* workerPtr = worker_array+workerId-1;
- int raceId = workerPtr->race_id;
- Town* srcTown = town_array[workerPtr->town_recno];
- Town* destTown = town_array[destTownRecno];
- err_when( !raceId );
- err_when( m.points_distance( center_x, center_y, destTown->center_x,
- destTown->center_y ) > EFFECTIVE_FIRM_TOWN_DISTANCE );
- //------------- add news --------------//
- if( srcTown->nation_recno==nation_array.player_recno ||
- destTown->nation_recno==nation_array.player_recno )
- {
- if( srcTown->nation_recno != destTown->nation_recno ) // don't add news for migrating between own towns
- news_array.migrate(srcTown->town_recno, destTownRecno, raceId, 1, firm_recno);
- }
- //--------- migrate now ----------//
- int keepJob = 1;
- workerPtr->town_recno = destTownRecno;
- //--------- decrease the population of the home town ------//
- srcTown->dec_pop(raceId, keepJob);
- //--------- increase the population of the target town ------//
- destTown->inc_pop(raceId, keepJob, newLoyalty);
- }
- //-------- End of function Firm::worker_migrate -----------//
- //-------- Begin of function Firm::set_worker_home_town --------//
- //
- // This function has two purposes.
- //
- // If the worker's home town is already the given one,
- // then resign the worker.
- //
- // Otherwise, set the worker's home town to the new onel.
- //
- // <int> townRecno - the new home town recno
- // [int] workerId - the id. of the worker to be set to a new home town
- // (default: the currently selected worker, selected_worker_id)
- //
- void Firm::set_worker_home_town(int townRecno, char remoteAction, int workerId)
- {
- if( !workerId )
- workerId = selected_worker_id;
- if( !workerId || workerId > worker_count )
- return;
- if(!remoteAction && remote.is_enable() )
- {
- // packet structure : <firm recno> <town recno> <workderId>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_SET_WORKER_HOME, 3*sizeof(short));
- shortPtr[0] = firm_recno;
- shortPtr[1] = townRecno;
- shortPtr[2] = workerId;
- return;
- }
- err_when( workerId<1 || workerId>worker_count );
- //-------------------------------------------------//
- Worker* workerPtr = worker_array+workerId-1;
- err_when( !workerPtr->race_id );
- if( workerPtr->town_recno == townRecno )
- {
- resign_worker(workerId);
- }
- //--- otherwise, set the worker's home town to the new one ---//
- else if( workerPtr->is_nation(firm_recno, nation_recno) ) // only allow when the worker lives in a town belonging to the same nation
- {
- int workerLoyalty = workerPtr->loyalty();
- town_array[workerPtr->town_recno]->dec_pop(workerPtr->race_id, 1);
- town_array[townRecno]->inc_pop(workerPtr->race_id, 1, workerLoyalty);
- workerPtr->town_recno = townRecno;
- }
- }
- //-------- End of function Firm::set_worker_home_town --------//
- //------- Begin of function Worker::loyalty ---------//
- //
- int Worker::loyalty()
- {
- if( town_recno ) // if the worker lives in a town
- return (int) town_array[town_recno]->race_loyalty_array[race_id-1];
- else
- return (int) worker_loyalty;
- }
- //-------- End of function Worker::loyalty -----------//
- //------- Begin of function Worker::target_loyalty ---------//
- //
- int Worker::target_loyalty(int firmRecno)
- {
- if( town_recno ) // if the worker lives in a town
- {
- return (int) town_array[town_recno]->race_loyalty_array[race_id-1];
- }
- else
- {
- Firm* firmPtr = firm_array[firmRecno];
- if( firmPtr->overseer_recno )
- {
- Unit* overseerUnit = unit_array[firmPtr->overseer_recno];
- int overseerSkill = overseerUnit->skill.get_skill(SKILL_LEADING);
- int targetLoyalty = 30 + overseerSkill/2;
- //---------------------------------------------------//
- //
- // Soldiers with higher combat and leadership skill
- // will get discontented if they are led by a general
- // with low leadership.
- //
- //---------------------------------------------------//
- targetLoyalty -= combat_level/2;
- if( skill_level > overseerSkill )
- targetLoyalty -= skill_level - overseerSkill;
- if( overseerUnit->rank_id == RANK_KING )
- targetLoyalty += 20;
- if( race_res.is_same_race(race_id, overseerUnit->race_id) )
- targetLoyalty += 20;
- if( targetLoyalty < 0 )
- targetLoyalty = 0;
- if( targetLoyalty > 100 )
- targetLoyalty = 100;
- return targetLoyalty;
- }
- else //-- if there is no overseer, just return the current loyalty --//
- {
- return worker_loyalty;
- }
- }
- }
- //-------- End of function Worker::target_loyalty -----------//
- //------- Begin of function Firm::setup_link ---------//
- //
- void Firm::setup_link()
- {
- //-----------------------------------------------------------------------------//
- // check the connected firms location and structure if ai_link_checked is true
- //-----------------------------------------------------------------------------//
- if(firm_ai)
- ai_link_checked = 0;
- //----- build firm-to-firm link relationship -------//
- int firmRecno, defaultLinkStatus;
- Firm* firmPtr;
- FirmInfo* firmInfo = firm_res[firm_id];
- linked_firm_count = 0;
- for( firmRecno=firm_array.size() ; firmRecno>0 ; firmRecno-- )
- {
- if( firm_array.is_deleted(firmRecno) || firmRecno==firm_recno )
- continue;
- firmPtr = firm_array[firmRecno];
- //---- do not allow links between firms of different nation ----//
- if( firmPtr->nation_recno != nation_recno )
- continue;
- //---------- check if the firm is close enough to this firm -------//
- if( m.points_distance( firmPtr->center_x, firmPtr->center_y,
- center_x, center_y ) > EFFECTIVE_FIRM_FIRM_DISTANCE )
- {
- continue;
- }
- //------ check if both are on the same terrain type ------//
- if( world.get_loc(firmPtr->center_x, firmPtr->center_y)->is_plateau()
- != world.get_loc(center_x, center_y)->is_plateau() )
- {
- continue;
- }
- //----- if the firms are linkable to each other -----//
- if( !firmInfo->is_linkable_to_firm(firmPtr->firm_id) )
- continue;
- //------- determine the default link status ------//
- 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
- defaultLinkStatus = firmInfo->default_link_status(firmPtr->firm_id);
- else
- defaultLinkStatus = LINK_DD; // if the two firms are of different nations, default link status is both side disabled
- //-------- add the link now -------//
- if( linked_firm_count < MAX_LINKED_FIRM_FIRM )
- {
- linked_firm_array[linked_firm_count] = firmRecno;
- linked_firm_enable_array[linked_firm_count] = defaultLinkStatus;
- linked_firm_count++;
- }
- 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
- {
- err_here();
- }
- if( firmPtr->linked_firm_count < MAX_LINKED_FIRM_FIRM )
- {
- if( defaultLinkStatus==LINK_ED ) // Reverse the link status for the opposite linker
- defaultLinkStatus=LINK_DE;
- else if( defaultLinkStatus==LINK_DE )
- defaultLinkStatus=LINK_ED;
- firmPtr->linked_firm_array[firmPtr->linked_firm_count] = firm_recno;
- firmPtr->linked_firm_enable_array[firmPtr->linked_firm_count] = defaultLinkStatus;
- firmPtr->linked_firm_count++;
- if(firmPtr->firm_ai)
- firmPtr->ai_link_checked = 0;
- if(firmPtr->firm_id==FIRM_HARBOR)
- {
- FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
- harborPtr->link_checked = 0;
- }
- }
- else
- {
- err_here();
- }
- }
- //----- build firm-to-town link relationship -------//
- linked_town_count = 0;
- if( !firmInfo->is_linkable_to_town )
- return;
- int townRecno;
- Town* townPtr;
- for( townRecno=town_array.size() ; townRecno>0 ; townRecno-- )
- {
- if( town_array.is_deleted(townRecno) )
- continue;
- townPtr = town_array[townRecno];
- //------ check if the town is close enough to this firm -------//
- if( m.points_distance( townPtr->center_x, townPtr->center_y,
- center_x, center_y ) > EFFECTIVE_FIRM_TOWN_DISTANCE )
- {
- continue;
- }
- //------ check if both are on the same terrain type ------//
- if( (world.get_loc(townPtr->center_x, townPtr->center_y)->is_plateau()==1)
- != (world.get_loc(center_x, center_y)->is_plateau()==1) )
- {
- continue;
- }
- //------- determine the default link status ------//
- 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
- defaultLinkStatus = LINK_EE;
- else
- defaultLinkStatus = LINK_DD; // if the two firms are of different nations, default link status is both side disabled
- //---------------------------------------------------//
- //
- // If this is a camp, it can be linked to the town when
- // either the town is an independent one or the town
- // is not linked to any camps of its own.
- //
- //---------------------------------------------------//
- if( firm_id==FIRM_CAMP )
- {
- if( townPtr->nation_recno==0 || !townPtr->has_linked_own_camp )
- defaultLinkStatus = LINK_EE;
- }
- //-------- add the link now -------//
- if( linked_town_count < MAX_LINKED_FIRM_TOWN )
- {
- linked_town_array[linked_town_count] = townRecno;
- linked_town_enable_array[linked_town_count] = defaultLinkStatus;
- linked_town_count++;
- }
- else
- {
- err_here();
- }
- if( townPtr->linked_firm_count < MAX_LINKED_FIRM_TOWN )
- {
- if( defaultLinkStatus==LINK_ED ) // Reverse the link status for the opposite linker
- defaultLinkStatus=LINK_DE;
- else if( defaultLinkStatus==LINK_DE )
- defaultLinkStatus=LINK_ED;
- townPtr->linked_firm_array[townPtr->linked_firm_count] = firm_recno;
- townPtr->linked_firm_enable_array[townPtr->linked_firm_count] = defaultLinkStatus;
- townPtr->linked_firm_count++;
- if(townPtr->ai_town)
- townPtr->ai_link_checked = 0;
- }
- else
- {
- err_here();
- }
- }
- }
- //-------- End of function Firm::setup_link -----------//
- //------- Begin of function Firm::release_link ---------//
- //
- void Firm::release_link()
- {
- int i;
- Firm *firmPtr;
- Town *townPtr;
- //------ release linked firms ------//
- for( i=0 ; i<linked_firm_count ; i++ )
- {
- firmPtr = firm_array[linked_firm_array[i]];
- firmPtr->release_firm_link(firm_recno);
- if(firmPtr->firm_ai)
- firmPtr->ai_link_checked = 0;
- }
- //------ release linked towns ------//
- for( i=0 ; i<linked_town_count ; i++ )
- {
- townPtr = town_array[linked_town_array[i]];
- townPtr->release_firm_link(firm_recno);
- if(townPtr->ai_town)
- townPtr->ai_link_checked = 0;
- }
- }
- //-------- End of function Firm::release_link -----------//
- //------- Begin of function Firm::release_firm_link ---------//
- //
- void Firm::release_firm_link(int releaseFirmRecno)
- {
- //-----------------------------------------------------------------------------//
- // check the connected firms location and structure if ai_link_checked is true
- //-----------------------------------------------------------------------------//
- if(firm_ai)
- ai_link_checked = 0;
- for( int i=0 ; i<linked_firm_count ; i++ )
- {
- if( linked_firm_array[i] == releaseFirmRecno )
- {
- err_when( linked_firm_count > MAX_LINKED_FIRM_FIRM );
- m.del_array_rec( linked_firm_array, linked_firm_count, sizeof(linked_firm_array[0]), i+1 );
- m.del_array_rec( linked_firm_enable_array, linked_firm_count, sizeof(linked_firm_enable_array[0]), i+1 );
- linked_firm_count--;
- return;
- }
- }
- err_here();
- }
- //------- End of function Firm::release_firm_link ---------//
- //------- Begin of function Firm::release_town_link ---------//
- //
- void Firm::release_town_link(int releaseTownRecno)
- {
- //-----------------------------------------------------------------------------//
- // check the connected firms location and structure if ai_link_checked is true
- //-----------------------------------------------------------------------------//
- if(firm_ai)
- ai_link_checked = 0;
- for( int i=0 ; i<linked_town_count ; i++ )
- {
- if( linked_town_array[i] == releaseTownRecno )
- {
- err_when( linked_town_count > MAX_LINKED_FIRM_TOWN );
- m.del_array_rec( linked_town_array, linked_town_count, sizeof(linked_town_array[0]), i+1 );
- m.del_array_rec( linked_town_enable_array, linked_town_count, sizeof(linked_town_enable_array[0]), i+1 );
- linked_town_count--;
- return;
- }
- }
- err_here();
- }
- //------- End of function Firm::release_town_link ---------//
- //--------- Begin of function Firm::capture_firm --------//
- //
- // The firm is being captured by another nation.
- //
- void Firm::capture_firm(int newNationRecno)
- {
- if( nation_recno == nation_array.player_recno )
- news_array.firm_captured(firm_recno, newNationRecno, 0); // 0 - the capturer is not a spy
- //-------- if this is an AI firm --------//
- if( firm_ai )
- ai_firm_captured(newNationRecno);
- //------------------------------------------//
- //
- // If there is an overseer in this firm, then the only
- // unit who can capture this firm will be the overseer only,
- // so calling its betray() function will capture the whole
- // firm already.
- //
- //------------------------------------------//
- if( overseer_recno && unit_array[overseer_recno]->spy_recno )
- unit_array[overseer_recno]->spy_change_nation(newNationRecno, COMMAND_AUTO);
- else
- change_nation(newNationRecno);
- }
- //--------- End of function Firm::capture_firm --------//
- //------- Begin of function Firm::change_nation ---------//
- //
- void Firm::change_nation(int newNationRecno)
- {
- if( nation_recno == newNationRecno )
- return;
- //---------- stop all attack actions to this firm ----------//
- unit_array.stop_attack_firm(firm_recno);
- rebel_array.stop_attack_firm(firm_recno);
- Nation *oldNationPtr = nation_array[nation_recno];
- Nation *newNationPtr = nation_array[newNationRecno];
- //------ if there is a builder in this firm, change its nation also ----//
- if( builder_recno )
- {
- Unit* unitPtr = unit_array[builder_recno];
- unitPtr->change_nation(newNationRecno);
- //--- if this is a spy, chance its cloak ----//
- if( unitPtr->spy_recno )
- spy_array[unitPtr->spy_recno]->cloaked_nation_recno = newNationRecno;
- }
- //---------- stop all actions attacking this firm --------//
- unit_array.stop_attack_firm(firm_recno);
- //------ clear defense mode for military camp -----//
- if(firm_id==FIRM_CAMP)
- ((FirmCamp*)this)->clear_defense_mode();
- //---- update nation_unit_count_array[] ----//
- FirmInfo* firmInfo = firm_res[firm_id];
- if( nation_recno )
- firmInfo->dec_nation_firm_count(nation_recno);
- if( newNationRecno )
- firmInfo->inc_nation_firm_count(newNationRecno);
- //---- reset should_close_flag -----//
- if( firm_ai )
- {
- if( should_close_flag )
- {
- oldNationPtr->firm_should_close_array[firm_id-1]--;
- should_close_flag = 0;
- err_when( oldNationPtr->firm_should_close_array[firm_id-1] < 0 );
- }
- }
- //------- update player_spy_count -------//
- spy_array.update_firm_spy_count(firm_recno);
- //--- update the cloaked_nation_recno of all spies in the firm ---//
- spy_array.change_cloaked_nation(SPY_FIRM, firm_recno, nation_recno, newNationRecno); // check the cloaked nation recno of all spies in the firm
- //-----------------------------------------//
- if(firm_ai)
- oldNationPtr->del_firm_info(firm_id, firm_recno);
- //------ update power nation recno ----------//
- if( should_set_power )
- world.restore_power(loc_x1, loc_y1, loc_x2, loc_y2, 0, firm_recno);
- should_set_power = get_should_set_power();
- if( should_set_power )
- world.set_power(loc_x1, loc_y1, loc_x2, loc_y2, newNationRecno); // set power of the new nation
- //------------ update link --------------//
- release_link(); // need to update link because firms are only linked to firms of the same nation
- nation_recno = newNationRecno;
- setup_link();
- //---------------------------------------//
- firm_ai = nation_array[nation_recno]->is_ai();
- if(firm_ai)
- newNationPtr->add_firm_info(firm_id, firm_recno);
- //--- if a nation set up a town in a location that the player has explored, contact between the nation and the player is established ---//
- establish_contact_with_player();
- //---- reset the action mode of all spies in this town ----//
- 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
- //-- refresh display if this firm is currently selected --//
- if( firm_array.selected_recno == firm_recno )
- info.disp();
- }
- //-------- End of function Firm::change_nation ---------//
- //------- Begin of function Firm::toggle_firm_link ---------//
- //
- // Toggle the firm link of the current firm.
- //
- // <int> linkId - id. of the link
- // <int> toggleFlag - 1-enable, 0-disable
- // [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)
- // if this is -1, the only one side will be set even though the nation recno of the firm and town are the same
- // (default: 0)
- //
- void Firm::toggle_firm_link(int linkId, int toggleFlag, char remoteAction, int setBoth)
- {
- if( !remoteAction && remote.is_enable() )
- {
- // packet structure : <firm recno> <link Id> <toggle Flag>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_TOGGLE_LINK_FIRM, 3*sizeof(short));
- shortPtr[0] = firm_recno;
- shortPtr[1] = linkId;
- shortPtr[2] = toggleFlag;
- return;
- }
- int linkedNationRecno = firm_array[linked_firm_array[linkId-1]]->nation_recno;
- int sameNation = linkedNationRecno == nation_recno || // if one of the linked end is an indepdendent firm/nation, consider this link as a single nation link
- linkedNationRecno == 0 ||
- nation_recno == 0;
- if( toggleFlag )
- {
- if( (sameNation && setBoth==0) || setBoth==1 )
- linked_firm_enable_array[linkId-1] = LINK_EE;
- else
- linked_firm_enable_array[linkId-1] |= LINK_ED;
- }
- else
- {
- if( (sameNation && setBoth==0) || setBoth==1 )
- linked_firm_enable_array[linkId-1] = LINK_DD;
- else
- linked_firm_enable_array[linkId-1] &= ~LINK_ED;
- }
- //---------- if this firm is harbor, set FirmHarbor's parameter link_checked to 0
- if(firm_id == FIRM_HARBOR)
- {
- FirmHarbor *harborPtr = (FirmHarbor*) this;
- harborPtr->link_checked = 0;
- }
- //------ set the linked flag of the opposite firm -----//
- Firm* firmPtr = firm_array[ linked_firm_array[linkId-1] ];
- //---------- if firm is harbor, set FirmHarbor's parameter link_checked to 0
- if(firmPtr->firm_id==FIRM_HARBOR)
- {
- FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
- harborPtr->link_checked = 0;
- }
- int i;
- for( i=0 ; i<firmPtr->linked_firm_count ; i++ )
- {
- if( firmPtr->linked_firm_array[i] == firm_recno )
- {
- if( toggleFlag )
- {
- if( (sameNation && setBoth==0) || setBoth==1 )
- firmPtr->linked_firm_enable_array[i] = LINK_EE;
- else
- firmPtr->linked_firm_enable_array[i] |= LINK_DE;
- }
- else
- {
- if( (sameNation && setBoth==0) || setBoth==1 )
- firmPtr->linked_firm_enable_array[i] = LINK_DD;
- else
- firmPtr->linked_firm_enable_array[i] &= ~LINK_DE;
- }
- break;
- }
- }
- }
- //-------- End of function Firm::toggle_firm_link ---------//
- //------- Begin of function Firm::toggle_town_link ---------//
- //
- // Toggle the town link of the current firm.
- //
- // <int> linkId - id. of the link
- // <int> toggleFlag - 1-enable, 0-disable
- // [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)
- // if this is -1, the only one side will be set even though the nation recno of the firm and town are the same
- // (default: 0)
- //
- void Firm::toggle_town_link(int linkId, int toggleFlag, char remoteAction, int setBoth)
- {
- if( !remoteAction && remote.is_enable() )
- {
- // packet structure : <firm recno> <link Id> <toggle Flag>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_TOGGLE_LINK_TOWN, 3*sizeof(short));
- shortPtr[0] = firm_recno;
- shortPtr[1] = linkId;
- shortPtr[2] = toggleFlag;
- return;
- }
- int linkedNationRecno = town_array[linked_town_array[linkId-1]]->nation_recno;
- int sameNation = linkedNationRecno == nation_recno || // if one of the linked end is an indepdendent firm/nation, consider this link as a single nation link
- 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.
- if( toggleFlag )
- {
- if( (sameNation && setBoth==0) || setBoth==1 )
- linked_town_enable_array[linkId-1] = LINK_EE;
- else
- linked_town_enable_array[linkId-1] |= LINK_ED;
- }
- else
- {
- if( (sameNation && setBoth==0) || setBoth==1 )
- linked_town_enable_array[linkId-1] = LINK_DD;
- else
- linked_town_enable_array[linkId-1] &= ~LINK_ED;
- }
- //------ set the linked flag of the opposite town -----//
- Town* townPtr = town_array[ linked_town_array[linkId-1] ];
- int i;
- for( i=0 ; i<townPtr->linked_firm_count ; i++ )
- {
- if( townPtr->linked_firm_array[i] == firm_recno )
- {
- if( toggleFlag )
- {
- if( (sameNation && setBoth==0) || setBoth==1 )
- townPtr->linked_firm_enable_array[i] = LINK_EE;
- else
- townPtr->linked_firm_enable_array[i] |= LINK_DE;
- }
- else
- {
- if( (sameNation && setBoth==0) || setBoth==1 )
- townPtr->linked_firm_enable_array[i] = LINK_DD;
- else
- townPtr->linked_firm_enable_array[i] &= ~LINK_DE;
- }
- break;
- }
- }
- //-------- update the town's influence --------//
- if( townPtr->nation_recno==0 )
- townPtr->update_target_resistance();
- //--- redistribute demand if a link to market place has been toggled ---//
- if( firm_id == FIRM_MARKET )
- town_array.distribute_demand();
- }
- //-------- End of function Firm::toggle_town_link ---------//
- //------- Begin of function Firm::auto_defense -----------//
- void Firm::auto_defense(short targetRecno)
- {
- //--------------------------------------------------------//
- // if the firm_id is FIRM_CAMP, send the units to defense
- // the firm
- //--------------------------------------------------------//
- if(firm_id == FIRM_CAMP)
- {
- FirmCamp *campPtr = cast_to_FirmCamp();
- campPtr->defend_target_recno = targetRecno;
- campPtr->defense(targetRecno);
- }
- Town *townPtr;
- for(int i=linked_town_count-1; i>=0; i--)
- {
- if(!linked_town_array[i] || town_array.is_deleted(linked_town_array[i]))
- continue;
- townPtr = town_array[linked_town_array[i]];
- //-------------------------------------------------------//
- // find whether military camp is linked to this town. If
- // so, defense for this firm
- //-------------------------------------------------------//
- if(townPtr->nation_recno == nation_recno)
- townPtr->auto_defense(targetRecno);
- //-------------------------------------------------------//
- // some linked town may be deleted after calling auto_defense().
- // Also, the data in the linked_town_array may also be changed.
- //-------------------------------------------------------//
- if(i>linked_town_count)
- i = linked_town_count;
- }
- }
- //--------- End of function Firm::auto_defense -----------//
- //------- Begin of function Worker::Worker -----------//
- //
- Worker::Worker()
- {
- memset( this, 0, sizeof(Worker) );
- }
- //--------- End of function Worker::Worker -----------//
- //------- Begin of function Worker::max_hit_points -----------//
- //
- short Worker::max_hit_points()
- {
- err_when( combat_level <= 0 );
- err_when( combat_level > 100 );
- return (int) unit_res[unit_id]->hit_points * combat_level / 100;
- }
- //--------- End of function Worker::max_hit_points -----------//
- //--------- Begin of function Worker::max_attack_range ---------//
- int Worker::max_attack_range()
- {
- int maxRange=0;
- AttackInfo *attackInfo = unit_res.get_attack_info(unit_res[unit_id]->first_attack);
- int attackCount = unit_res[unit_id]->attack_count;
- for(int i=0; i<attackCount; i++, attackInfo++)
- {
- if(combat_level >= attackInfo->combat_level &&
- attackInfo->attack_range>maxRange)
- maxRange = attackInfo->attack_range;
- }
-
- return maxRange;
- }
- //--------- End of function Worker::max_attack_range -----------//
- //--------- Begin of function Worker::is_nation ---------//
- //
- // Whether this worker belongs to the specific nation.
- //
- // <int> firmRecno - the recno of the firm the worker works in
- // <int> nationRecno - the recno of th nation to check against.
- //
- int Worker::is_nation(int firmRecno, int nationRecno)
- {
- if( spy_recno && spy_array[spy_recno]->true_nation_recno == nationRecno )
- return 1;
- if( town_recno )
- return town_array[town_recno]->nation_recno == nationRecno;
- else
- return firm_array[firmRecno]->nation_recno == nationRecno;
- }
- //----------- End of function Worker::is_nation ---------//
- //-------- Begin of function Firm::can_assign_capture ------//
- //
- // Return whether new units assigned to this firm can capture
- // this firm.
- //
- int Firm::can_assign_capture()
- {
- return (overseer_recno==0 && worker_count==0);
- }
- //----------- End of function Worker::can_assign_capture ---------//
- //-------- Begin of function Firm::should_show_info ------//
- //
- // Whether information of this firm should be shown.
- //
- int Firm::should_show_info()
- {
- if( config.show_ai_info || nation_recno==nation_array.player_recno ||
- player_spy_count > 0 )
- {
- return 1;
- }
- //------ if the builder is a spy of the player ------//
- if( builder_recno )
- {
- if( unit_array[builder_recno]->true_nation_recno() == nation_array.player_recno )
- return 1;
- }
- //----- if any of the workers belong to the player, show the info of this firm -----//
- Worker* workerPtr = worker_array;
- for( int i=0 ; i<worker_count ; i++, workerPtr++ )
- {
- if( workerPtr->is_nation(firm_recno, nation_array.player_recno) )
- return 1;
- }
- //---- if there is a phoenix of the player over this firm ----//
- if( nation_array.player_recno && (~nation_array)->revealed_by_phoenix(loc_x1, loc_y1) )
- return 1;
- return 0;
- }
- //---------- End of function Firm::should_show_info --------//
- //-------- Begin of function Firm::majority_race ------//
- //
- char Firm::majority_race()
- {
- //--- if there is a overseer, return the overseer's race ---//
- if( overseer_recno )
- return unit_array[overseer_recno]->race_id;
- if( worker_count==0 )
- return 0;
- //----- count the no. people in each race ------//
- char raceCountArray[MAX_RACE];
- memset( raceCountArray, 0, sizeof(raceCountArray) );
- int i;
- for( i=0 ; i<worker_count ; i++ )
- {
- if( worker_array[i].race_id )
- raceCountArray[ worker_array[i].race_id-1 ]++;
- }
- //---------------------------------------------//
- int mostRaceCount=0, mostRaceId=0;
- for( i=0 ; i<MAX_RACE ; i++ )
- {
- if( raceCountArray[i] > mostRaceCount )
- {
- mostRaceCount = raceCountArray[i];
- mostRaceId = i+1;
- }
- }
- return mostRaceId;
- }
- //---------- End of function Firm::majority_race --------//
- //---------- Begin of function Worker::small_icon_ptr --------//
- char* Worker::small_icon_ptr()
- {
- // ###### begin Gilbert 17/10 ########//
- return unit_res[unit_id]->get_small_icon_ptr(rank_id);
- // ###### end Gilbert 17/10 ########//
- }
- //---------- End of function Worker::small_icon_ptr --------//
- //---------- Begin of function Worker::change_loyalty --------//
- void Worker::change_loyalty(int loyaltyChange)
- {
- if( town_recno ) // for those live in town, their loyalty are based on town people loyalty.
- return;
- int newLoyalty = worker_loyalty + loyaltyChange;
- newLoyalty = min( 100, newLoyalty );
- worker_loyalty = max( 0, newLoyalty );
- }
- //---------- End of function Worker::change_loyalty --------//
- //---------- Begin of function Worker::change_hit_points --------//
- void Worker::change_hit_points(int changePoints)
- {
- err_when( town_recno ); // for those live in town, their loyalty are based on town people loyalty.
- int newHitPoints = hit_points + changePoints;
- int maxHitPoints = max_hit_points();
- newHitPoints = min( maxHitPoints, newHitPoints );
- hit_points = max( 0, newHitPoints );
- }
- //---------- End of function Worker::change_hit_points --------//
- //-------- Begin of function Firm::is_worker_full ------//
- //
- int Firm::is_worker_full()
- {
- return worker_count == MAX_WORKER;
- }
- //----------- End of function Firm::is_worker_full ---------//
- //--------- Begin of function Firm::reward ---------//
- //
- // Only military camp has the "reward" option and not the other firms also
- // because workers in other firms live in the towns and their loyalty
- // are based on the town they live. Military camp is not linked to a town.
- //
- // <int> workerId - 0 - commander, >0 - id. of the soldier
- // <int> remoteAction - either COMMAND_PLAYER or COMMAND_REMOTE
- //
- void Firm::reward(int workerId, int remoteAction)
- {
- if( remoteAction==COMMAND_PLAYER && remote.is_enable() )
- {
- if( !remoteAction && remote.is_enable() )
- {
- // packet structure : <firm recno> <worker id>
- short *shortPtr = (short *)remote.new_send_queue_msg(MSG_FIRM_REWARD, 2*sizeof(short) );
- *shortPtr = firm_recno;
- shortPtr[1] = workerId;
- }
- }
- else
- {
- if( workerId == 0 )
- {
- if( overseer_recno )
- unit_array[overseer_recno]->reward(nation_recno);
- }
- else
- {
- err_when( workerId < 1 || workerId > worker_count );
- worker_array[workerId-1].change_loyalty( REWARD_LOYALTY_INCREASE );
- nation_array[nation_recno]->add_expense( EXPENSE_REWARD_UNIT, (float)REWARD_COST);
- }
- }
- }
- //----------- End of function Firm::reward -----------//
|