| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** 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 3 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/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // InGameUI.cpp ///////////////////////////////////////////////////////////////////////////////////
- // Implementation of in-game user interface singleton inteface
- // Author: Michael S. Booth, March 2001
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #define DEFINE_SHADOW_NAMES
- #include "Common/ActionManager.h"
- #include "Common/GameAudio.h"
- #include "Common/GameEngine.h"
- #include "Common/GameType.h"
- #include "Common/MessageStream.h"
- #include "Common/PerfTimer.h"
- #include "Common/Player.h"
- #include "Common/PlayerList.h"
- #include "Common/Radar.h"
- #include "Common/Team.h"
- #include "Common/ThingFactory.h"
- #include "Common/ThingTemplate.h"
- #include "Common/BuildAssistant.h"
- #include "Common/Recorder.h"
- #include "Common/BuildAssistant.h"
- #include "Common/SpecialPower.h"
- #include "GameClient/Anim2D.h"
- #include "GameClient/ControlBar.h"
- #include "GameClient/DisplayStringManager.h"
- #include "GameClient/Diplomacy.h"
- #include "GameClient/Eva.h"
- #include "GameClient/GameText.h"
- #include "GameClient/GameWindowManager.h"
- #include "GameClient/Drawable.h"
- #include "GameClient/GadgetPushButton.h"
- #include "GameClient/GameClient.h"
- #include "GameClient/GameWindowGlobal.h"
- #include "GameClient/GameWindowID.h"
- #include "GameClient/GUICallbacks.h"
- #include "GameClient/InGameUI.h"
- #include "GameClient/VideoPlayer.h"
- #include "GameClient/Mouse.h"
- #include "GameClient/GadgetStaticText.h"
- #include "GameClient/View.h"
- #include "GameClient/TerrainVisual.h"
- #include "GameClient/ControlBar.h"
- #include "GameClient/Display.h"
- #include "GameClient/WindowLayout.h"
- #include "GameClient/LookAtXlat.h"
- #include "GameClient/SelectionXlat.h"
- #include "GameClient/Shadow.h"
- #include "GameClient/GlobalLanguage.h"
- #include "GameLogic/AIGuard.h"
- #include "GameLogic/Weapon.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/PartitionManager.h"
- #include "GameLogic/ScriptEngine.h"
- #include "GameLogic/Module/ContainModule.h"
- #include "GameLogic/Module/ProductionUpdate.h"
- #include "GameLogic/Module/SpecialPowerModule.h"
- #include "GameLogic/Module/StealthUpdate.h"
- #include "GameLogic/Module/SupplyWarehouseDockUpdate.h"
- #include "GameLogic/Module/MobMemberSlavedUpdate.h"//ML
- #include "Common/UnitTimings.h" //Contains the DO_UNIT_TIMINGS define jba.
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- // ------------------------------------------------------------------------------------------------
- static const Real placementOpacity = 0.45f;
- static const RGBColor illegalBuildColor = { 1.0, 0.0, 0.0 };
- //-------------------------------------------------------------------------------------------------
- /// The InGameUI singleton instance.
- InGameUI *TheInGameUI = NULL;
- GameWindow *m_replayWindow = NULL;
- // ------------------------------------------------------------------------------------------------
- struct KindOfSelectionData
- {
- KindOfMaskType m_mustbeSet;
- KindOfMaskType m_mustbeClear;
- DrawableList newlySelectedDrawables;
- };
- // ------------------------------------------------------------------------------------------------
- static Bool kindOfUnitSelection( Drawable *test, void *userData )
- {
- KindOfSelectionData *data = (KindOfSelectionData *) userData;
- if( test )
- {
- const Object *object = test->getObject();
- // Only things with objects can be selected, and the code below isn't
- // safe unless you've verified that there is a valid object.
- if (!object)
- return FALSE;
- Bool isKindOfMatch = object->isKindOfMulti(data->m_mustbeSet, data->m_mustbeClear);
- // only select objects if not already selected
- if( object && isKindOfMatch
- && object->isLocallyControlled()
- && !object->isContained()
- && !object->getDrawable()->isSelected()
- && !object->isEffectivelyDead()
- && object->isMassSelectable()
- && !object->isOffMap()
- )
- {
- // enforce optional unit cap
- if (TheInGameUI->getMaxSelectCount() > 0 && TheInGameUI->getSelectCount() >= TheInGameUI->getMaxSelectCount())
- {
- if ( !TheInGameUI->getDisplayedMaxWarning() )
- {
- TheInGameUI->setDisplayedMaxWarning( TRUE );
- UnicodeString msg;
- msg.format(TheGameText->fetch("GUI:MaxSelectionSize").str(), TheInGameUI->getMaxSelectCount());
- TheInGameUI->message(msg);
- }
- }
- else
- {
- TheInGameUI->selectDrawable( test );
- TheInGameUI->setDisplayedMaxWarning( FALSE );
- data->newlySelectedDrawables.push_back(test);
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- // ------------------------------------------------------------------------------------------------
- struct MatchingUnitSelectionData
- {
- const ThingTemplate *templateToSelect;
- DrawableList newlySelectedDrawables;
- Bool isCarBomb;
- };
- // ------------------------------------------------------------------------------------------------
- static Bool similarUnitSelection( Drawable *test, void *userData )
- {
- MatchingUnitSelectionData *data = (MatchingUnitSelectionData *) userData;
- const ThingTemplate *selectedType = data->templateToSelect;
- if( test )
- {
- const Object *object = test->getObject();
- // Only things with objects can be selected, and the code below isn't
- // safe unless you've verified that there is a valid object.
- if (!object)
- return FALSE;
- Bool isEquivalent = object->getTemplate()->isEquivalentTo( selectedType );
- if( data->isCarBomb && !isEquivalent && object->testStatus( OBJECT_STATUS_IS_CARBOMB ) )
- {
- isEquivalent = TRUE;
- }
- // only select objects if not already selected
- if( object && isEquivalent
- && object->isLocallyControlled()
- && !object->isContained()
- && !( object->getDrawable()->isSelected() )
- && object->isMassSelectable() // And only if they can be multiply selected. (otherwise the drawable will be, but the object will not be)
- && !object->isOffMap()
- )
- {
- // enforce optional unit cap
- if (TheInGameUI->getMaxSelectCount() > 0 && TheInGameUI->getSelectCount() >= TheInGameUI->getMaxSelectCount())
- {
- if ( !TheInGameUI->getDisplayedMaxWarning() )
- {
- TheInGameUI->setDisplayedMaxWarning( TRUE );
- UnicodeString msg;
- msg.format(TheGameText->fetch("GUI:MaxSelectionSize").str(), TheInGameUI->getMaxSelectCount());
- TheInGameUI->message(msg);
- }
- }
- else
- {
- TheInGameUI->selectDrawable( test );
- TheInGameUI->setDisplayedMaxWarning( FALSE );
- data->newlySelectedDrawables.push_back(test);
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void showReplayControls( void )
- {
- if (m_replayWindow)
- {
- Bool show = TheGameLogic->isInReplayGame();
- m_replayWindow->winHide(!show);
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void hideReplayControls( void )
- {
- if (m_replayWindow)
- {
- m_replayWindow->winHide(TRUE);
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void toggleReplayControls( void )
- {
- if (m_replayWindow)
- {
- Bool show = TheGameLogic->isInReplayGame() && m_replayWindow->winIsHidden();
- m_replayWindow->winHide(!show);
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- SuperweaponInfo::SuperweaponInfo(
- ObjectID id,
- UnsignedInt timestamp,
- Bool hiddenByScript,
- Bool hiddenByScience,
- Bool ready,
- Bool evaReadyPlayed,
- const AsciiString& superweaponNormalFont,
- Int superweaponNormalPointSize,
- Bool superweaponNormalBold,
- Color c,
- const SpecialPowerTemplate* spt
- ) :
- m_id(id),
- m_timestamp(timestamp),
- m_hiddenByScript(hiddenByScript),
- m_hiddenByScience(hiddenByScience),
- m_ready(ready),
- m_evaReadyPlayed( evaReadyPlayed ),
- m_forceUpdateText(false),
- m_nameDisplayString(NULL),
- m_timeDisplayString(NULL),
- m_color(c),
- m_powerTemplate(spt)
- {
- m_nameDisplayString = TheDisplayStringManager->newDisplayString();
- m_nameDisplayString->reset();
- m_nameDisplayString->setText( UnicodeString::TheEmptyString );
- m_timeDisplayString = TheDisplayStringManager->newDisplayString();
- m_timeDisplayString->reset();
- m_timeDisplayString->setText( UnicodeString::TheEmptyString );
- setFont( superweaponNormalFont, superweaponNormalPointSize, superweaponNormalBold );
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- SuperweaponInfo::~SuperweaponInfo()
- {
- if (m_nameDisplayString)
- TheDisplayStringManager->freeDisplayString( m_nameDisplayString );
- m_nameDisplayString = NULL;
- if (m_timeDisplayString)
- TheDisplayStringManager->freeDisplayString( m_timeDisplayString );
- m_timeDisplayString = NULL;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void SuperweaponInfo::setFont(const AsciiString& superweaponNormalFont, Int superweaponNormalPointSize, Bool superweaponNormalBold)
- {
- m_nameDisplayString->setFont( TheFontLibrary->getFont( superweaponNormalFont,
- TheGlobalLanguageData->adjustFontSize(superweaponNormalPointSize), superweaponNormalBold ) );
- m_timeDisplayString->setFont( TheFontLibrary->getFont( superweaponNormalFont,
- TheGlobalLanguageData->adjustFontSize(superweaponNormalPointSize), superweaponNormalBold ) );
- }
- // ------------------------------------------------------------------------------------------------
- void SuperweaponInfo::setText(const UnicodeString& name, const UnicodeString& time)
- {
- m_nameDisplayString->setText(name);
- m_timeDisplayString->setText(time);
- }
- // ------------------------------------------------------------------------------------------------
- void SuperweaponInfo::drawName(Int x, Int y, Color color, Color dropColor)
- {
- if (color == 0)
- color = m_color;
- m_nameDisplayString->draw(x - m_nameDisplayString->getWidth(), y, color, dropColor);
- }
- // ------------------------------------------------------------------------------------------------
- void SuperweaponInfo::drawTime(Int x, Int y, Color color, Color dropColor)
- {
- if (color == 0)
- color = m_color;
- m_timeDisplayString->draw(x, y, color, dropColor);
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Real SuperweaponInfo::getHeight() const
- {
- return m_nameDisplayString->getFont()->height;
- }
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void InGameUI::crc( Xfer *xfer )
- {
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version
- * 2: Save NamedTimers, but not specifically their Info structs. We'll recreate them.
- * 3: Added m_evaReadyPlayed boolean to transfer
- */
- // ------------------------------------------------------------------------------------------------
- void InGameUI::xfer( Xfer *xfer )
- {
- // version
- const XferVersion currentVersion = 3;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- if( version >= 2 )
- {
- // Saving the named timer infos and their friends so we get script timers back after we load
- xfer->xferInt(&m_namedTimerLastFlashFrame);
- xfer->xferBool(&m_namedTimerUsedFlashColor);
- xfer->xferBool(&m_showNamedTimers);
- // For the timers themselves, all I need to save is the things that are used in the call to addNamedTimer.
- // It is okay to do this, because SuperweaponInfos pushes things on to a map; addNamedTimer is just a more
- // organized way to push things on the namedTimer Map.
- // addNamedTimer needs (const AsciiString& timerName, const UnicodeString& text, Bool isCountdown)
- if (xfer->getXferMode() == XFER_SAVE)
- {
- Int timerCount = m_namedTimers.size();
- xfer->xferInt( &timerCount );
- for( NamedTimerMapIt timerIter = m_namedTimers.begin(); timerIter != m_namedTimers.end(); ++timerIter )
- {
- xfer->xferAsciiString( &(timerIter->second->m_timerName) );
- xfer->xferUnicodeString( &(timerIter->second->timerText) );
- xfer->xferBool( &(timerIter->second->isCountdown) );
- }
- }
- else // iz a Load
- {
- Int timerCount;
- xfer->xferInt( &timerCount );
- for( Int timerIndex = 0; timerIndex < timerCount; ++timerIndex )
- {
- AsciiString timerName;
- UnicodeString timerText;
- Bool isCountdown;
- xfer->xferAsciiString( &timerName );
- xfer->xferUnicodeString( &timerText );
- xfer->xferBool( &isCountdown );
- addNamedTimer( timerName, timerText, isCountdown );
- }
- }
- }
- xfer->xferBool(&m_superweaponHiddenByScript);
- //xfer->xferBool(&m_inputEnabled); // no, don't save this yet. somewhat problematic.
- if (xfer->getXferMode() == XFER_SAVE)
- {
- for (Int playerIndex = 0; playerIndex < MAX_PLAYER_COUNT; ++playerIndex)
- {
- for (SuperweaponMap::iterator mapIt = m_superweapons[playerIndex].begin(); mapIt != m_superweapons[playerIndex].end(); ++mapIt)
- {
- AsciiString powerName = mapIt->first;
- SuperweaponList& swList = mapIt->second;
- for (SuperweaponList::iterator listIt = swList.begin(); listIt != swList.end(); ++listIt)
- {
- SuperweaponInfo* swInfo = *listIt;
- // since this list tends to be somewhat sparse, we write stuff out pretty explicitly.
- xfer->xferInt(&playerIndex);
-
- AsciiString templateName = swInfo->getSpecialPowerTemplate()->getName();
- xfer->xferAsciiString(&templateName);
- xfer->xferAsciiString(&powerName);
- xfer->xferObjectID(&swInfo->m_id);
- xfer->xferUnsignedInt(&swInfo->m_timestamp);
- xfer->xferBool(&swInfo->m_hiddenByScript);
- xfer->xferBool(&swInfo->m_hiddenByScience);
- xfer->xferBool(&swInfo->m_ready);
- if ( currentVersion >= 3 )
- {
- xfer->xferBool( &swInfo->m_evaReadyPlayed );
- }
- }
- }
- }
- Int noMorePlayers = -1; // our "done" sentinel
- xfer->xferInt(&noMorePlayers);
- }
- else if (xfer->getXferMode() == XFER_LOAD)
- {
- for (;;)
- {
- Int playerIndex;
- xfer->xferInt(&playerIndex);
- if (playerIndex == -1)
- {
- break; // our "done" sentinel
- }
- else if (playerIndex < 0 || playerIndex >= MAX_PLAYER_COUNT)
- {
- DEBUG_CRASH(("SWInfo bad plyrindex\n"));
- throw INI_INVALID_DATA;
- }
- AsciiString templateName;
- xfer->xferAsciiString(&templateName);
- const SpecialPowerTemplate* powerTemplate = TheSpecialPowerStore->findSpecialPowerTemplate(templateName);
- if (powerTemplate == NULL)
- {
- DEBUG_CRASH(("power %s not found\n",templateName.str()));
- throw INI_INVALID_DATA;
- }
- AsciiString powerName;
- ObjectID id;
- UnsignedInt timestamp;
- Bool hiddenByScript, hiddenByScience, ready, evaReadyPlayed;
- xfer->xferAsciiString(&powerName);
- xfer->xferObjectID(&id);
- xfer->xferUnsignedInt(×tamp);
- xfer->xferBool(&hiddenByScript);
- xfer->xferBool(&hiddenByScience);
- xfer->xferBool(&ready);
- if ( currentVersion >= 3 )
- {
- xfer->xferBool( &evaReadyPlayed );
- }
- else
- {
- evaReadyPlayed = ready;
- }
- // srj sez: due to order-of-operation stuff, sometimes these will already exist,
- // sometimes not. not sure why. so handle both cases.
- SuperweaponInfo* swInfo = findSWInfo(playerIndex, powerName, id, powerTemplate);
- if (swInfo == NULL)
- {
- const Player* player = ThePlayerList->getNthPlayer(playerIndex);
- swInfo = newInstance(SuperweaponInfo)(
- id,
- timestamp,
- hiddenByScript,
- hiddenByScience,
- ready,
- evaReadyPlayed,
- m_superweaponNormalFont,
- m_superweaponNormalPointSize,
- m_superweaponNormalBold,
- player->getPlayerColor(),
- powerTemplate);
- m_superweapons[playerIndex][powerName].push_back(swInfo);
- }
- else
- {
- // swInfo->m_id = id; // redundant, already matches
- swInfo->m_timestamp = timestamp;
- swInfo->m_hiddenByScript = hiddenByScript;
- swInfo->m_hiddenByScience = hiddenByScience;
- swInfo->m_ready = ready;
- swInfo->m_evaReadyPlayed = evaReadyPlayed;
- }
- swInfo->m_forceUpdateText = true;
-
- }
- }
- }
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void InGameUI::loadPostProcess( void )
- {
- } // end loadPostProcess
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::setMouseCursor(Mouse::MouseCursor c)
- {
- if (!TheMouse)
- return;
- TheMouse->setCursor(c);
- if (m_mouseMode == MOUSEMODE_GUI_COMMAND && c != Mouse::ARROW && c != Mouse::SCROLL)
- m_mouseModeCursor = c;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- SuperweaponInfo* InGameUI::findSWInfo(Int playerIndex, const AsciiString& powerName, ObjectID id, const SpecialPowerTemplate *powerTemplate)
- {
- SuperweaponMap::iterator mapIt = m_superweapons[playerIndex].find(powerName);
- if (mapIt != m_superweapons[playerIndex].end())
- {
- for (SuperweaponList::iterator listIt = mapIt->second.begin(); listIt != mapIt->second.end(); ++listIt)
- {
- if ((*listIt)->m_id == id)
- {
- return *listIt;
- }
- }
- }
- return NULL;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::addSuperweapon(Int playerIndex, const AsciiString& powerName, ObjectID id, const SpecialPowerTemplate *powerTemplate)
- {
- if (powerTemplate == NULL)
- return;
- // srj sez: don't allow adding the same superweapon more than once. it can happen. not sure how. (srj)
- SuperweaponInfo* swInfo = findSWInfo(playerIndex, powerName, id, powerTemplate);
- if (swInfo != NULL)
- return;
- const Player* player = ThePlayerList->getNthPlayer(playerIndex);
- Bool hiddenByScience = (powerTemplate->getRequiredScience() != SCIENCE_INVALID) && (player->hasScience(powerTemplate->getRequiredScience()) == false);
- #ifndef DO_UNIT_TIMINGS
- DEBUG_LOG(("Adding superweapon UI timer\n"));
- #endif
- SuperweaponInfo *info = newInstance(SuperweaponInfo)(
- id,
- -1, // timestamp
- FALSE, // hiddenByScript
- hiddenByScience,//Aaayeeee! This is meaningless and just clogs up the works, sez srj, nuke or repair or SHIP WITH(tm), ASAP
- // THe trouble is: There is no mechanism to clear this bit when the science is granted, thus,
- // the timer never, ever, ever get drawn.... unless the owning object is post-science constructed.
- FALSE, // ready
- FALSE, // evaReadyPlayed
- m_superweaponNormalFont,
- m_superweaponNormalPointSize,
- m_superweaponNormalBold,
- player->getPlayerColor(),
- powerTemplate);
- m_superweapons[playerIndex][powerName].push_back(info);
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Bool InGameUI::removeSuperweapon(Int playerIndex, const AsciiString& powerName, ObjectID id, const SpecialPowerTemplate *powerTemplate)
- {
- DEBUG_LOG(("Removing superweapon UI timer\n"));
- SuperweaponMap::iterator mapIt = m_superweapons[playerIndex].find(powerName);
- if (mapIt != m_superweapons[playerIndex].end())
- {
- SuperweaponList& swList = mapIt->second;
- for (SuperweaponList::iterator listIt = swList.begin(); listIt != swList.end(); ++listIt)
- {
- if ((*listIt)->m_id == id)
- {
- SuperweaponInfo *info = *listIt;
- swList.erase(listIt);
- info->deleteInstance();
- if (swList.size() == 0)
- {
- m_superweapons[playerIndex].erase(mapIt);
- }
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::objectChangedTeam(const Object *obj, Int oldPlayerIndex, Int newPlayerIndex)
- {
- // if we already had it listed, remove and re-add it
- if (obj && oldPlayerIndex >= 0 && newPlayerIndex >= 0)
- {
- ObjectID id = obj->getID();
- AsciiString powerName;
- for (BehaviorModule** m = obj->getBehaviorModules(); *m; ++m)
- {
- SpecialPowerModuleInterface* sp = (*m)->getSpecialPower();
- if (!sp)
- continue;
- const SpecialPowerTemplate *powerTemplate = sp->getSpecialPowerTemplate();
- powerName = powerTemplate->getName();
- SuperweaponMap::iterator mapIt = m_superweapons[oldPlayerIndex].find(powerName);
- Bool found = false;
- if (mapIt != m_superweapons[oldPlayerIndex].end())
- {
- for (SuperweaponList::iterator listIt = mapIt->second.begin(); listIt != mapIt->second.end(); ++listIt)
- {
- if ((*listIt)->m_id == id)
- {
- removeSuperweapon(oldPlayerIndex, powerName, id, powerTemplate);
- addSuperweapon(newPlayerIndex, powerName, id, powerTemplate);
- found = true;
- break;
- }
- }
- }
- if (!found)
- {
- if( TheGameLogic->getFrame() == 0 && !obj->getStatusBits().test( OBJECT_STATUS_UNDER_CONSTRUCTION ) &&
- obj->isKindOf( KINDOF_COMMANDCENTER ) == FALSE )
- addSuperweapon(newPlayerIndex, powerName, id, powerTemplate);
- }
- }
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::hideObjectSuperweaponDisplayByScript(const Object *obj)
- {
- ObjectID objID = obj->getID();
- for (Int playerIndex = 0; playerIndex < MAX_PLAYER_COUNT; ++playerIndex)
- {
- for (SuperweaponMap::iterator mapIt = m_superweapons[playerIndex].begin(); mapIt != m_superweapons[playerIndex].end(); ++mapIt)
- {
- for (SuperweaponList::iterator listIt = mapIt->second.begin(); listIt != mapIt->second.end(); ++listIt)
- {
- if ((*listIt)->m_id == objID)
- {
- (*listIt)->m_hiddenByScript = TRUE;
- }
- }
- }
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::showObjectSuperweaponDisplayByScript(const Object *obj)
- {
- ObjectID objID = obj->getID();
- for (Int playerIndex = 0; playerIndex < MAX_PLAYER_COUNT; ++playerIndex)
- {
- for (SuperweaponMap::iterator mapIt = m_superweapons[playerIndex].begin(); mapIt != m_superweapons[playerIndex].end(); ++mapIt)
- {
- for (SuperweaponList::iterator listIt = mapIt->second.begin(); listIt != mapIt->second.end(); ++listIt)
- {
- if ((*listIt)->m_id == objID)
- {
- (*listIt)->m_hiddenByScript = FALSE;
- }
- }
- }
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::setSuperweaponDisplayEnabledByScript(Bool enable)
- {
- m_superweaponHiddenByScript = !enable;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Bool InGameUI::getSuperweaponDisplayEnabledByScript(void) const
- {
- return m_superweaponHiddenByScript;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::addNamedTimer( const AsciiString& timerName, const UnicodeString& text, Bool isCountdown )
- {
- NamedTimerInfo *info = newInstance( NamedTimerInfo );
- info->m_timerName = timerName;
- info->color = m_namedTimerNormalColor;
- info->timerText = text;
- info->displayString = TheDisplayStringManager->newDisplayString();
- info->displayString->reset();
- info->displayString->setFont( TheFontLibrary->getFont( m_namedTimerNormalFont,
- TheGlobalLanguageData->adjustFontSize(m_namedTimerNormalPointSize), m_namedTimerNormalBold ) );
- info->displayString->setText( UnicodeString::TheEmptyString );
- info->timestamp = -1;
- info->isCountdown = isCountdown;
- // GameFont *font = info->displayString->getFont();
- removeNamedTimer(timerName);
- m_namedTimers[timerName] = info;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::removeNamedTimer( const AsciiString& timerName )
- {
- NamedTimerMapIt mapIt = m_namedTimers.find(timerName);
- if (mapIt != m_namedTimers.end())
- {
- TheDisplayStringManager->freeDisplayString( mapIt->second->displayString );
- mapIt->second->deleteInstance();
- m_namedTimers.erase(mapIt);
- return;
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::showNamedTimerDisplay( Bool show )
- {
- m_showNamedTimers = show;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- const FieldParse InGameUI::s_fieldParseTable[] =
- {
- { "MaxSelectionSize", INI::parseInt, NULL, offsetof( InGameUI, m_maxSelectCount ) },
- { "MessageColor1", INI::parseColorInt, NULL, offsetof( InGameUI, m_messageColor1 ) },
- { "MessageColor2", INI::parseColorInt, NULL, offsetof( InGameUI, m_messageColor2 ) },
- { "MessagePosition", INI::parseICoord2D, NULL, offsetof( InGameUI, m_messagePosition ) },
- { "MessageFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_messageFont ) },
- { "MessagePointSize", INI::parseInt, NULL, offsetof( InGameUI, m_messagePointSize ) },
- { "MessageBold", INI::parseBool, NULL, offsetof( InGameUI, m_messageBold ) },
- { "MessageDelayMS", INI::parseInt, NULL, offsetof( InGameUI, m_messageDelayMS ) },
- { "MilitaryCaptionColor", INI::parseRGBAColorInt, NULL, offsetof( InGameUI, m_militaryCaptionColor ) },
- { "MilitaryCaptionPosition", INI::parseICoord2D, NULL, offsetof( InGameUI, m_militaryCaptionPosition ) },
- { "MilitaryCaptionTitleFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_militaryCaptionTitleFont ) },
- { "MilitaryCaptionTitlePointSize", INI::parseInt, NULL, offsetof( InGameUI, m_militaryCaptionTitlePointSize ) },
- { "MilitaryCaptionTitleBold", INI::parseBool, NULL, offsetof( InGameUI, m_militaryCaptionTitleBold ) },
- { "MilitaryCaptionFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_militaryCaptionFont ) },
- { "MilitaryCaptionPointSize", INI::parseInt, NULL, offsetof( InGameUI, m_militaryCaptionPointSize ) },
- { "MilitaryCaptionBold", INI::parseBool, NULL, offsetof( InGameUI, m_militaryCaptionBold ) },
- { "MilitaryCaptionRandomizeTyping", INI::parseBool, NULL, offsetof( InGameUI, m_militaryCaptionRandomizeTyping ) },
- { "MilitaryCaptionSpeed", INI::parseInt, NULL, offsetof( InGameUI, m_militaryCaptionSpeed ) },
- { "MilitaryCaptionPosition", INI::parseICoord2D, NULL, offsetof( InGameUI, m_militaryCaptionPosition ) },
- { "SuperweaponCountdownPosition", INI::parseCoord2D, NULL, offsetof( InGameUI, m_superweaponPosition ) },
- { "SuperweaponCountdownFlashDuration", INI::parseDurationReal, NULL, offsetof( InGameUI, m_superweaponFlashDuration ) },
- { "SuperweaponCountdownFlashColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_superweaponFlashColor ) },
- { "SuperweaponCountdownNormalFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_superweaponNormalFont ) },
- { "SuperweaponCountdownNormalPointSize", INI::parseInt, NULL, offsetof( InGameUI, m_superweaponNormalPointSize ) },
- { "SuperweaponCountdownNormalBold", INI::parseBool, NULL, offsetof( InGameUI, m_superweaponNormalBold ) },
- { "SuperweaponCountdownReadyFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_superweaponReadyFont ) },
- { "SuperweaponCountdownReadyPointSize", INI::parseInt, NULL, offsetof( InGameUI, m_superweaponReadyPointSize ) },
- { "SuperweaponCountdownReadyBold", INI::parseBool, NULL, offsetof( InGameUI, m_superweaponReadyBold ) },
- { "NamedTimerCountdownPosition", INI::parseCoord2D, NULL, offsetof( InGameUI, m_namedTimerPosition ) },
- { "NamedTimerCountdownFlashDuration", INI::parseDurationReal, NULL, offsetof( InGameUI, m_namedTimerFlashDuration ) },
- { "NamedTimerCountdownFlashColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_namedTimerFlashColor ) },
- { "NamedTimerCountdownNormalFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_namedTimerNormalFont ) },
- { "NamedTimerCountdownNormalPointSize", INI::parseInt, NULL, offsetof( InGameUI, m_namedTimerNormalPointSize ) },
- { "NamedTimerCountdownNormalBold", INI::parseBool, NULL, offsetof( InGameUI, m_namedTimerNormalBold ) },
- { "NamedTimerCountdownNormalColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_namedTimerNormalColor ) },
- { "NamedTimerCountdownReadyFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_namedTimerReadyFont ) },
- { "NamedTimerCountdownReadyPointSize", INI::parseInt, NULL, offsetof( InGameUI, m_namedTimerReadyPointSize ) },
- { "NamedTimerCountdownReadyBold", INI::parseBool, NULL, offsetof( InGameUI, m_namedTimerReadyBold ) },
- { "NamedTimerCountdownReadyColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_namedTimerReadyColor ) },
- { "FloatingTextTimeOut", INI::parseDurationUnsignedInt, NULL, offsetof( InGameUI, m_floatingTextTimeOut ) },
- { "FloatingTextMoveUpSpeed", INI::parseVelocityReal, NULL, offsetof( InGameUI, m_floatingTextMoveUpSpeed ) },
- { "FloatingTextVanishRate", INI::parseVelocityReal, NULL, offsetof( InGameUI, m_floatingTextMoveVanishRate ) },
- { "PopupMessageColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_popupMessageColor ) },
-
- { "DrawableCaptionFont", INI::parseAsciiString, NULL, offsetof( InGameUI, m_drawableCaptionFont ) },
- { "DrawableCaptionPointSize", INI::parseInt, NULL, offsetof( InGameUI, m_drawableCaptionPointSize ) },
- { "DrawableCaptionBold", INI::parseBool, NULL, offsetof( InGameUI, m_drawableCaptionBold ) },
- { "DrawableCaptionColor", INI::parseColorInt, NULL, offsetof( InGameUI, m_drawableCaptionColor ) },
- { "DrawRMBScrollAnchor", INI::parseBool, NULL, offsetof( InGameUI, m_drawRMBScrollAnchor ) },
- { "MoveRMBScrollAnchor", INI::parseBool, NULL, offsetof( InGameUI, m_moveRMBScrollAnchor ) },
- { "AttackDamageAreaRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[RADIUSCURSOR_ATTACK_DAMAGE_AREA] ) },
- { "AttackScatterAreaRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[RADIUSCURSOR_ATTACK_SCATTER_AREA] ) },
- { "AttackContinueAreaRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[RADIUSCURSOR_ATTACK_CONTINUE_AREA] ) },
- { "FriendlySpecialPowerRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[RADIUSCURSOR_FRIENDLY_SPECIALPOWER] ) },
- { "OffensiveSpecialPowerRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[RADIUSCURSOR_OFFENSIVE_SPECIALPOWER] ) },
- { "SuperweaponScatterAreaRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[RADIUSCURSOR_SUPERWEAPON_SCATTER_AREA] ) },
- { "GuardAreaRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[RADIUSCURSOR_GUARD_AREA] ) },
- { "EmergencyRepairRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[RADIUSCURSOR_EMERGENCY_REPAIR] ) },
- { "ParticleCannonRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_PARTICLECANNON] ) },
- { "A10StrikeRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_A10STRIKE] ) },
- { "CarpetBombRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_CARPETBOMB] ) },
- { "DaisyCutterRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_DAISYCUTTER] ) },
- { "ParadropRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_PARADROP] ) },
- { "SpySatelliteRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_SPYSATELLITE] ) },
- { "SpectreGunshipRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_SPECTREGUNSHIP] ) },
- { "HelixNapalmBombRadiusCursor",RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_HELIX_NAPALM_BOMB] ) },
-
- { "NuclearMissileRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_NUCLEARMISSILE] ) },
- { "EMPPulseRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_EMPPULSE] ) },
- { "ArtilleryRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_ARTILLERYBARRAGE] ) },
- { "FrenzyRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_FRENZY] ) },
- { "NapalmStrikeRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_NAPALMSTRIKE] ) },
- { "ClusterMinesRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_CLUSTERMINES] ) },
-
- { "ScudStormRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_SCUDSTORM] ) },
- { "AnthraxBombRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_ANTHRAXBOMB] ) },
- { "AmbushRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_AMBUSH] ) },
- { "RadarRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_RADAR] ) },
- { "SpyDroneRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_SPYDRONE] ) },
- { "ClearMinesRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_CLEARMINES] ) },
- { "AmbulanceRadiusCursor", RadiusDecalTemplate::parseRadiusDecalTemplate, NULL, offsetof( InGameUI, m_radiusCursors[ RADIUSCURSOR_AMBULANCE] ) },
- { NULL, NULL, NULL, 0 } // keep this last
- };
- //-------------------------------------------------------------------------------------------------
- /** Parse MouseCursor entry */
- //-------------------------------------------------------------------------------------------------
- void INI::parseInGameUIDefinition( INI* ini )
- {
- if( TheInGameUI )
- {
- // parse the ini weapon definition
- ini->initFromINI( TheInGameUI, TheInGameUI->getFieldParse() );
- }
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- InGameUI::InGameUI()
- {
- Int i;
-
- m_inputEnabled = true;
- m_isDragSelecting = false;
- m_nextMoveHint = 0;
- m_selectCount = 0;
- m_frameSelectionChanged = 0;
- m_duringDoubleClickAttackMoveGuardHintTimer = 0;
- m_duringDoubleClickAttackMoveGuardHintStashedPosition.zero();
- m_maxSelectCount = -1;
- m_isScrolling = FALSE;
- m_isSelecting = FALSE;
- m_mouseMode = MOUSEMODE_DEFAULT;
- m_mouseModeCursor = Mouse::ARROW;
- m_mousedOverDrawableID = INVALID_DRAWABLE_ID;
-
- //Added By Sadullah Nader
- //Initializations missing and needed
- m_currentlyPlayingMovie.clear();
- m_militarySubtitle = NULL;
- m_popupMessageData = NULL;
- m_waypointMode = FALSE;
- m_clientQuiet = FALSE;
-
- m_messageColor1 = GameMakeColor( 255, 255, 255, 255 );
- m_messageColor2 = GameMakeColor( 180, 180, 180, 255 );
- m_messagePosition.x = 10;
- m_messagePosition.y = 10;
- m_messageFont = "Arial";
- m_messagePointSize = 10;
- m_messageBold = FALSE;
- m_messageDelayMS = 5000;
- m_militaryCaptionColor.red = 200;
- m_militaryCaptionColor.green = 200;
- m_militaryCaptionColor.blue = 30;
- m_militaryCaptionColor.alpha = 255;
- m_militaryCaptionPosition.x = 10;
- m_militaryCaptionPosition.y = 380;
- m_militaryCaptionTitleFont = "Courier";
- m_militaryCaptionTitlePointSize = 12;
- m_militaryCaptionTitleBold = TRUE;
- m_militaryCaptionFont = "Courier";
- m_militaryCaptionPointSize = 12;
- m_militaryCaptionBold = FALSE;
- m_militaryCaptionRandomizeTyping = FALSE;
- m_militaryCaptionSpeed = 1;
- m_popupMessageColor = GameMakeColor(255,255,255,255);
- m_tooltipsDisabledUntil = 0;
- // init hint lists
- for( i = 0; i < MAX_MOVE_HINTS; i++ )
- {
- m_moveHint[ i ].pos.zero();
- m_moveHint[ i ].sourceID = 0;
- m_moveHint[ i ].frame = 0;
- } // end for i
- for( i = 0; i < MAX_BUILD_PROGRESS; i++ )
- {
- m_buildProgress[ i ].m_thingTemplate = NULL;
- m_buildProgress[ i ].m_percentComplete = 0.0f;
- m_buildProgress[ i ].m_control = NULL;
- } // end for i
- m_pendingGUICommand = NULL;
- // allocate an array for the placement icons
- m_placeIcon = NEW Drawable* [ TheGlobalData->m_maxLineBuildObjects ];
- for( i = 0; i < TheGlobalData->m_maxLineBuildObjects; i++ )
- m_placeIcon[ i ] = NULL;
- m_pendingPlaceType = NULL;
- m_pendingPlaceSourceObjectID = INVALID_ID;
- m_preventLeftClickDeselectionInAlternateMouseModeForOneClick = FALSE;
- m_placeAnchorStart.x = m_placeAnchorStart.y = 0;
- m_placeAnchorEnd.x = m_placeAnchorEnd.y = 0;
- m_placeAnchorInProgress = FALSE;
- m_videoStream = NULL;
- m_videoBuffer = NULL;
- m_cameoVideoStream = NULL;
- m_cameoVideoBuffer = NULL;
- // message info
- for( i = 0; i < MAX_UI_MESSAGES; i++ )
- {
- m_uiMessages[ i ].fullText.clear();
- m_uiMessages[ i ].displayString = NULL;
- m_uiMessages[ i ].timestamp = 0;
- m_uiMessages[ i ].color = 0;
- } // end for i
- m_replayWindow = NULL;
- m_messagesOn = TRUE;
- m_superweaponPosition.x = 0.7f;
- m_superweaponPosition.y = 0.7f;
- m_superweaponFlashDuration = 1.0f;
- m_superweaponNormalFont = "Arial";
- m_superweaponNormalPointSize = 10;
- m_superweaponNormalBold = FALSE;
- m_superweaponReadyFont = "Arial";
- m_superweaponReadyPointSize = 10;
- m_superweaponReadyBold = FALSE;
- m_superweaponFlashColor = GameMakeColor(255, 255, 255, 255);
- m_superweaponLastFlashFrame = 0;
- m_superweaponUsedFlashColor = TRUE; // so next one is false
- m_superweaponHiddenByScript = FALSE;
- m_namedTimerPosition.x = 0.05f;
- m_namedTimerPosition.y = 0.7f;
- m_namedTimerFlashDuration = 1.0f;
- m_namedTimerNormalFont = "Arial";
- m_namedTimerNormalPointSize = 10;
- m_namedTimerNormalBold = FALSE;
- m_namedTimerReadyFont = "Arial";
- m_namedTimerReadyPointSize = 10;
- m_namedTimerReadyBold = FALSE;
- m_namedTimerNormalColor = GameMakeColor(255, 255, 0, 255);
- m_namedTimerReadyColor = GameMakeColor(255, 0, 255, 255);
- m_namedTimerFlashColor = GameMakeColor( 0, 255, 255, 255);
- m_namedTimerLastFlashFrame = 0;
- m_namedTimerUsedFlashColor = TRUE; // so next one is false
- m_showNamedTimers = TRUE;
- m_floatingTextTimeOut = DEFAULT_FLOATING_TEXT_TIMEOUT;
- m_floatingTextMoveUpSpeed = 1.0f;
- m_floatingTextMoveVanishRate = 0.1f;
- m_drawableCaptionFont = "Arial";
- m_drawableCaptionPointSize = 10;
- m_drawableCaptionBold = FALSE;
- m_drawableCaptionColor = GameMakeColor(255, 255, 255, 255);
- m_drawRMBScrollAnchor = FALSE;
- m_moveRMBScrollAnchor = FALSE;
- m_displayedMaxWarning = FALSE;
- m_idleWorkerWin = NULL;
- m_currentIdleWorkerDisplay = -1;
- m_waypointMode = false;
- m_forceAttackMode = false;
- m_forceMoveToMode = false;
- m_attackMoveToMode = false;
- m_preferSelection = false;
- m_curRcType = RADIUSCURSOR_NONE;
-
- m_soloNexusSelectedDrawableID = INVALID_DRAWABLE_ID;
- } // end InGameUI
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- InGameUI::~InGameUI()
- {
- delete TheControlBar;
- TheControlBar = NULL;
- // free all the display strings if we're
- removeMilitarySubtitle();
- stopMovie();
- stopCameoMovie();
- // remove any build available status
- placeBuildAvailable( NULL, NULL );
- setRadiusCursorNone();
- // delete the message resources
- freeMessageResources();
- // delete the array for the drawbles
- delete [] m_placeIcon;
- m_placeIcon = NULL;
- // clear floating text
- clearFloatingText();
- // clear world animations
- clearWorldAnimations();
- resetIdleWorker();
- }
- //-------------------------------------------------------------------------------------------------
- /** Initialize the in game user interface */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::init( void )
- {
- INI ini;
- ini.load( AsciiString( "Data\\INI\\InGameUI.ini" ), INI_LOAD_OVERWRITE, NULL );
- //override INI values with language localized values:
- if (TheGlobalLanguageData)
- {
- if (TheGlobalLanguageData->m_drawableCaptionFont.name.isNotEmpty())
- { m_drawableCaptionFont = TheGlobalLanguageData->m_drawableCaptionFont.name;
- m_drawableCaptionPointSize = TheGlobalLanguageData->m_drawableCaptionFont.size;
- m_drawableCaptionBold = TheGlobalLanguageData->m_drawableCaptionFont.bold;
- }
- if (TheGlobalLanguageData->m_messageFont.name.isNotEmpty())
- { m_messageFont = TheGlobalLanguageData->m_messageFont.name;
- m_messagePointSize = TheGlobalLanguageData->m_messageFont.size;
- m_messageBold = TheGlobalLanguageData->m_messageFont.bold;
- }
- if (TheGlobalLanguageData->m_militaryCaptionTitleFont.name.isNotEmpty())
- { m_militaryCaptionTitleFont = TheGlobalLanguageData->m_militaryCaptionTitleFont.name;
- m_militaryCaptionTitlePointSize = TheGlobalLanguageData->m_militaryCaptionTitleFont.size;
- m_militaryCaptionTitleBold = TheGlobalLanguageData->m_militaryCaptionTitleFont.bold;
- }
- if (TheGlobalLanguageData->m_militaryCaptionFont.name.isNotEmpty())
- { m_militaryCaptionFont = TheGlobalLanguageData->m_militaryCaptionFont.name;
- m_militaryCaptionPointSize = TheGlobalLanguageData->m_militaryCaptionFont.size;
- m_militaryCaptionBold = TheGlobalLanguageData->m_militaryCaptionFont.bold;
- }
- if (TheGlobalLanguageData->m_superweaponCountdownNormalFont.name.isNotEmpty())
- { m_superweaponNormalFont = TheGlobalLanguageData->m_superweaponCountdownNormalFont.name;
- m_superweaponNormalPointSize = TheGlobalLanguageData->m_superweaponCountdownNormalFont.size;
- m_superweaponNormalBold = TheGlobalLanguageData->m_superweaponCountdownNormalFont.bold;
- }
- if (TheGlobalLanguageData->m_superweaponCountdownReadyFont.name.isNotEmpty())
- { m_superweaponReadyFont = TheGlobalLanguageData->m_superweaponCountdownReadyFont.name;
- m_superweaponReadyPointSize = TheGlobalLanguageData->m_superweaponCountdownReadyFont.size;
- m_superweaponReadyBold = TheGlobalLanguageData->m_superweaponCountdownReadyFont.bold;
- }
- if (TheGlobalLanguageData->m_namedTimerCountdownNormalFont.name.isNotEmpty())
- { m_namedTimerNormalFont = TheGlobalLanguageData->m_namedTimerCountdownNormalFont.name;
- m_namedTimerNormalPointSize = TheGlobalLanguageData->m_namedTimerCountdownNormalFont.size;
- m_namedTimerNormalBold = TheGlobalLanguageData->m_namedTimerCountdownNormalFont.bold;
- }
- if (TheGlobalLanguageData->m_namedTimerCountdownReadyFont.name.isNotEmpty())
- { m_namedTimerReadyFont = TheGlobalLanguageData->m_namedTimerCountdownReadyFont.name;
- m_namedTimerReadyPointSize = TheGlobalLanguageData->m_namedTimerCountdownReadyFont.size;
- m_namedTimerReadyBold = TheGlobalLanguageData->m_namedTimerCountdownReadyFont.bold;
- }
- }
- /**@ todo we used to put in the hint spy translator, but it's difficult
- to order the translators when the code is not centralized so it has
- been moved to where all the other translators are attached in game client */
- // create the tactical view
- if (TheDisplay)
- {
- TheTacticalView = createView();
- TheTacticalView->init();
- TheDisplay->attachView( TheTacticalView );
- // make the tactical display the full screen width for now
- TheTacticalView->setWidth( TheDisplay->getWidth());
- // make the tactical display 0.76 of full screen so no drawing under GUI.
- TheTacticalView->setHeight( TheDisplay->getHeight() * 0.77f);
- }
- TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f);
- /** @todo this may be the wrong place to create the sidebar, but for now
- this is where it lives */
- createControlBar();
- /** @todo This may be the wrong place to create the replay menu, but for now
- this is where it lives */
- createReplayControl();
- // create the command bar
- TheControlBar = NEW ControlBar;
- TheControlBar->init();
- m_windowLayouts.clear();
- m_soloNexusSelectedDrawableID = INVALID_DRAWABLE_ID;
- } // end init
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void InGameUI::setRadiusCursor(RadiusCursorType cursorType, const SpecialPowerTemplate* specPowTempl, WeaponSlotType weaponSlot)
- {
- if (cursorType == m_curRcType)
- return;
- m_curRadiusCursor.clear();
- m_curRcType = RADIUSCURSOR_NONE;
- if (cursorType == RADIUSCURSOR_NONE)
- return;
- Object* obj = NULL;
- if( m_pendingGUICommand && m_pendingGUICommand->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT )
- {
- if( ThePlayerList && ThePlayerList->getLocalPlayer() && specPowTempl != NULL )
- {
- obj = ThePlayerList->getLocalPlayer()->findMostReadyShortcutSpecialPowerOfType( specPowTempl->getSpecialPowerType() );
- }
- }
- else
- {
- if (getSelectCount() == 0)
- return;
- Drawable *draw = getFirstSelectedDrawable();
- if (draw == NULL)
- return;
- obj = draw->getObject();
- }
- if (obj == NULL)
- return;
-
- Player* controller = obj->getControllingPlayer();
- if (controller == NULL)
- return;
- Real radius = 0.0f;
- const Weapon* w = NULL;
- switch (cursorType)
- {
- // already handled
- //case RADIUSCURSOR_NONE:
- // return;
- case RADIUSCURSOR_ATTACK_DAMAGE_AREA:
- w = obj->getWeaponInWeaponSlot(weaponSlot);
- radius = w ? w->getPrimaryDamageRadius(obj) : 0.0f;
- break;
- case RADIUSCURSOR_ATTACK_SCATTER_AREA:
- w = obj->getWeaponInWeaponSlot(weaponSlot);
- radius = w ? (w->getScatterRadius() + w->getScatterTargetScalar()) : 0.0f;
- break;
- case RADIUSCURSOR_ATTACK_CONTINUE_AREA:
- case RADIUSCURSOR_CLEARMINES:
- w = obj->getWeaponInWeaponSlot(weaponSlot);
- radius = w ? w->getContinueAttackRange() : 0.0f;
- break;
- case RADIUSCURSOR_GUARD_AREA:
- radius = AIGuardMachine::getStdGuardRange(obj);
- break;
- case RADIUSCURSOR_FRIENDLY_SPECIALPOWER:
- case RADIUSCURSOR_OFFENSIVE_SPECIALPOWER:
- case RADIUSCURSOR_SUPERWEAPON_SCATTER_AREA:
- case RADIUSCURSOR_EMERGENCY_REPAIR:
- case RADIUSCURSOR_PARTICLECANNON:
- case RADIUSCURSOR_A10STRIKE:
- case RADIUSCURSOR_SPECTREGUNSHIP:
- case RADIUSCURSOR_HELIX_NAPALM_BOMB:
- case RADIUSCURSOR_DAISYCUTTER:
- case RADIUSCURSOR_CARPETBOMB:
- case RADIUSCURSOR_PARADROP:
- case RADIUSCURSOR_SPYSATELLITE:
- case RADIUSCURSOR_NUCLEARMISSILE:
- case RADIUSCURSOR_EMPPULSE:
- case RADIUSCURSOR_ARTILLERYBARRAGE:
- case RADIUSCURSOR_FRENZY:
- case RADIUSCURSOR_NAPALMSTRIKE:
- case RADIUSCURSOR_CLUSTERMINES:
- case RADIUSCURSOR_SCUDSTORM:
- case RADIUSCURSOR_ANTHRAXBOMB:
- case RADIUSCURSOR_AMBUSH:
- case RADIUSCURSOR_RADAR:
- case RADIUSCURSOR_SPYDRONE:
- case RADIUSCURSOR_AMBULANCE:
- radius = specPowTempl ? specPowTempl->getRadiusCursorRadius() : 0.0f;
- break;
- }
- if (radius <= 0.0f)
- return;
- Coord3D pos = { 0, 0, 0 }; // will be updated right away
- m_radiusCursors[cursorType].createRadiusDecal(pos, radius, controller, m_curRadiusCursor);
- m_curRcType = cursorType;
- handleRadiusCursor();
- }
- //-------------------------------------------------------------------------------------------------
- /** handle updating of "radius cursors" that follow the mouse pos */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::handleRadiusCursor()
- {
- if (!m_curRadiusCursor.isEmpty())
- {
- const MouseIO* mouseIO = TheMouse->getMouseStatus();
- Coord3D pos;
- //
- // if the mouse is in the radar window, the position in the world is that which is
- // represented by the radar, otherwise we use the mouse position itself transformed
- // from screen to world
- // But only if the radar is on.
- //
- Bool radarOn = TheRadar->isRadarForced()
- || ( !TheRadar->isRadarHidden()
- && ThePlayerList->getLocalPlayer()
- && ThePlayerList->getLocalPlayer()->hasRadar()
- );
- if( !radarOn || (TheRadar->screenPixelToWorld( &mouseIO->pos, &pos ) == FALSE) )// if radar off, or point not on radar
- TheTacticalView->screenToTerrain( &mouseIO->pos, &pos );
- if ( TheGlobalData->m_doubleClickAttackMove && m_duringDoubleClickAttackMoveGuardHintTimer > 0 )
- {
- m_curRadiusCursor.setOpacity( m_duringDoubleClickAttackMoveGuardHintTimer * 0.1f );
- m_curRadiusCursor.setPosition( m_duringDoubleClickAttackMoveGuardHintStashedPosition ); //world space position of center of decal
- }
- else
- {
- m_curRadiusCursor.setPosition(pos); //world space position of center of decal
- m_curRadiusCursor.update();
- }
- }
- }
- void InGameUI::triggerDoubleClickAttackMoveGuardHint( void )
- {
- m_duringDoubleClickAttackMoveGuardHintTimer = 11;
- const MouseIO* mouseIO = TheMouse->getMouseStatus();
- TheTacticalView->screenToTerrain( &mouseIO->pos, &m_duringDoubleClickAttackMoveGuardHintStashedPosition );
- }
- //-------------------------------------------------------------------------------------------------
- /** Handle the placement "icons" that appear at the cursor when we're putting down a
- * structure to build. Note that this has additional logic to also show a line
- * of objects because when we build "walls" we want to draw a line of repeating
- * wall pieces on the map where we want to put all of them */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::evaluateSoloNexus( Drawable *newlyAddedDrawable )
- {
- m_soloNexusSelectedDrawableID = INVALID_DRAWABLE_ID;//failsafe...
- // short test: If the thing just added is a nonmobster, bail with NULL
- if ( newlyAddedDrawable )
- {
- const Object *newObj = newlyAddedDrawable->getObject();
- if ( newObj && ! ( newObj->isKindOf(KINDOF_MOB_NEXUS) || newObj->isKindOf(KINDOF_IGNORED_IN_GUI) ) )
- return;
- }
- //LoopAllSelectedDrawables
- UnsignedShort nexaeFound = 0;
- for( DrawableListCIt it = m_selectedDrawables.begin(); it != m_selectedDrawables.end(); ++it )
- {
- Drawable *draw = (*it);
- const Object *obj = draw->getObject();
- if ( ! obj )
- continue;
-
- if ( obj->isKindOf( KINDOF_MOB_NEXUS ) )
- {
- ++nexaeFound;
- if ( nexaeFound == 1 )
- {
- m_soloNexusSelectedDrawableID = draw->getID();
- }
- else // darn! more than one!
- {
- m_soloNexusSelectedDrawableID = INVALID_DRAWABLE_ID;
- return;
- }
- }
- else if ( ! obj->isKindOf( KINDOF_IGNORED_IN_GUI ) )// darn! a non-angrymobster!
- {
- m_soloNexusSelectedDrawableID = INVALID_DRAWABLE_ID;
- return;
- }
- } // end for
- }
- void InGameUI::handleBuildPlacements( void )
- {
- //
- // if we're in the process of placing something we need up update one or more drawables
- // based on the position of the mouse
- //
- if( m_pendingPlaceType )
- {
- ICoord2D loc;
- Coord3D world;
- Real angle = m_placeIcon[ 0 ]->getOrientation();
- // update the angle of the icon to match any placement angle and pick the
- // location the icon will be at (anchored is the start, otherwise it's the mouse)
- if( isPlacementAnchored() )
- {
- ICoord2D start, end;
-
- // get the placement arrow points
- getPlacementPoints( &start, &end );
- // set icon to anchor point
- loc = start;
- // only adjust angle if we've actually moved the mouse
- if( start.x != end.x || start.y != end.y )
- {
- Coord3D worldStart, worldEnd;
- // project the start and the end points of the line anchor into the 3D world
- TheTacticalView->screenToTerrain( &start, &worldStart );
- TheTacticalView->screenToTerrain( &end, &worldEnd );
-
- Coord2D v;
- v.x = worldEnd.x - worldStart.x;
- v.y = worldEnd.y - worldStart.y;
- angle = v.toAngle();
- } // end if
- } // end if
- else
- {
- const MouseIO *mouseIO = TheMouse->getMouseStatus();
- // location is the mouse position
- loc = mouseIO->pos;
- } // end else
- // set the location and angle of the place icon
- /**@todo this whole orientation vector thing is LAME! Must replace, all I want to
- to do is set a simple angle and have it automatically change, ug! */
- TheTacticalView->screenToTerrain( &loc, &world );
- m_placeIcon[ 0 ]->setPosition( &world );
- m_placeIcon[ 0 ]->setOrientation( angle );
- //
- // check to see if this is a legal location to build something at and tint or "un-tint"
- // the cursor icons as appropriate. This involves a pathfind which could be
- // expensive so we don't want to do it on every frame (althought that would be ideal)
- // If we discover there are cases that this is just too slow we should increase the
- // delay time between checks or we need to come up with a way of recording what is
- // valid and what isn't or "fudge" the results to feel "ok"
- //
- if( TheGameClient->getFrame() & 0x1 )
- {
- TheTerrainVisual->removeAllBibs();
- Object *builderObject = TheGameLogic->findObjectByID( getPendingPlaceSourceObjectID() );
- LegalBuildCode lbc;
- lbc = TheBuildAssistant->isLocationLegalToBuild( &world,
- m_pendingPlaceType,
- angle,
- BuildAssistant::USE_QUICK_PATHFIND |
- BuildAssistant::TERRAIN_RESTRICTIONS |
- BuildAssistant::CLEAR_PATH |
- BuildAssistant::NO_OBJECT_OVERLAP |
- BuildAssistant::SHROUD_REVEALED |
- BuildAssistant::IGNORE_STEALTHED,
- builderObject,
- NULL );
- if( lbc != LBC_OK )
- m_placeIcon[ 0 ]->colorTint( &illegalBuildColor );
- else
- m_placeIcon[ 0 ]->colorTint( NULL );
-
- // Add the bibs around the structure.
- if (lbc != LBC_OK)
- {
- TheTerrainVisual->addFactionBibDrawable(m_placeIcon[0], lbc != LBC_OK);
- } else {
- TheTerrainVisual->removeFactionBibDrawable(m_placeIcon[0]);
- }
- } // end if
- //
- // we have additional place icons when we're placing down a line of walls or other
- // similarly placed object ... for those we will have them be oriented the same way
- // as the first one, but we'll set their positions so that they "tile" end to end
- //
- if( isPlacementAnchored() && TheBuildAssistant->isLineBuildTemplate( m_pendingPlaceType ) )
- {
- Int i;
- // get our line placement points
- ICoord2D screenStart, screenEnd;
- getPlacementPoints( &screenStart, &screenEnd );
- // project the start and the end points of the line anchor into the 3D world
- Coord3D worldStart, worldEnd;
- TheTacticalView->screenToTerrain( &screenStart, &worldStart );
- TheTacticalView->screenToTerrain( &screenEnd, &worldEnd );
- // how big are each of our objects
- Real objectSize = m_pendingPlaceType->getTemplateGeometryInfo().getMajorRadius() * 2.0f;
-
- // what is our max tiling length we can make
- Int maxObjects = TheGlobalData->m_maxLineBuildObjects;
- // get the builder object that will be constructing things
- Object *builderObject = TheGameLogic->findObjectByID( TheInGameUI->getPendingPlaceSourceObjectID() );
- //
- // given the start/end points in the world and the the angle of the wall, fill
- // out an array of positions that "tile" this wall across the landscape
- //
- BuildAssistant::TileBuildInfo *tileBuildInfo;
- tileBuildInfo = TheBuildAssistant->buildTiledLocations( m_pendingPlaceType, angle,
- &worldStart, &worldEnd,
- objectSize, maxObjects,
- builderObject );
- // create any necessary drawables we need to "fill out" the line
- for( i = 0; i < tileBuildInfo->tilesUsed; i++ )
- {
-
- if( m_placeIcon[ i ] == NULL )
- m_placeIcon[ i ] = TheThingFactory->newDrawable( m_pendingPlaceType,
- DRAWABLE_STATUS_NO_STATE_PARTICLES );
- } // end for i
- //
- // destroy any drawables that we're not using anymore because a previous
- // line length was longer
- //
- for( i = tileBuildInfo->tilesUsed; i < maxObjects; i++ )
- {
- if( m_placeIcon[ i ] != NULL )
- TheGameClient->destroyDrawable( m_placeIcon[ i ] );
- m_placeIcon[ i ] = NULL;
- } // end for i
- //
- // march down each drawable and set the position based on its position in the
- // line and set their angles all the same
- //
- for( i = 0; i < tileBuildInfo->tilesUsed; i++ )
- {
- // set the drawble position
- m_placeIcon[ i ]->setPosition( &tileBuildInfo->positions[ i ] );
- // set opacity for the drawble
- m_placeIcon[ i ]->setDrawableOpacity( placementOpacity );
- // set the drawable angle
- m_placeIcon[ i ]->setOrientation( angle );
- } // end for i
- } // end if
- } // end if
- } // end handleBuildPlacements
- //-------------------------------------------------------------------------------------------------
- /** Pre-draw phase of the in game ui */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::preDraw( void )
- {
- // handle any "icons" for the act of building things and placing them in the world
- handleBuildPlacements();
- // handle radius-cursors, if any
- handleRadiusCursor();
- // draw the floating text first;
- drawFloatingText();
- // draw world animations
- updateAndDrawWorldAnimations();
- } // end preDraw
- //-------------------------------------------------------------------------------------------------
- /** Update the in game user interface */
- //-------------------------------------------------------------------------------------------------
- //DECLARE_PERF_TIMER(InGameUI_update)
- void InGameUI::update( void )
- {
- //USE_PERF_TIMER(InGameUI_update)
- Int i;
- /// @todo make sure this code gets called even when the UI is not being drawn
- if ( m_videoStream && m_videoBuffer )
- {
- if ( m_videoStream->isFrameReady())
- {
- m_videoStream->frameDecompress();
- m_videoStream->frameRender( m_videoBuffer );
- m_videoStream->frameNext();
- if ( m_videoStream->frameIndex() == 0 )
- {
- stopMovie();
- }
- }
- }
- if ( m_cameoVideoStream && m_cameoVideoBuffer )
- {
- if ( m_cameoVideoStream->isFrameReady())
- {
- m_cameoVideoStream->frameDecompress();
- m_cameoVideoStream->frameRender( m_cameoVideoBuffer );
- m_cameoVideoStream->frameNext();
- // if ( m_cameoVideoStream->frameIndex() == 0 )
- // {
- // stopMovie();
- // }
- }
- }
- //
- // remove any message strings that have expired, note that the oldest strings are
- // always at the end of the array (higher index numbers) so we can just remove things
- // from the rear and never have to worry about shifting entries cause we check every
- // frame
- //
- UnsignedInt currLogicFrame = TheGameLogic->getFrame();
- const int messageTimeout = m_messageDelayMS / LOGICFRAMES_PER_SECOND / 1000;
- UnsignedByte r, g, b, a;
- Int amount;
- for( i = MAX_UI_MESSAGES - 1; i >= 0; i-- )
- {
- if( currLogicFrame - m_uiMessages[ i ].timestamp > messageTimeout )
- {
- // get the current color of this text
- GameGetColorComponents( m_uiMessages[ i ].color, &r, &g, &b, &a );
- // start fading the alpha on this color down
- amount = REAL_TO_INT( ((currLogicFrame - m_uiMessages[ i ].timestamp) * 0.01f) );
- if( a - amount < 0 )
- a = 0;
- else
- a -= amount;
-
- // set the new color
- m_uiMessages[ i ].color = GameMakeColor( r, g, b, a );
- // when alpha is completely zero we remove this string
- if( a == 0 )
- removeMessageAtIndex( i );
- } // end if
- } // end for i
- //
- // Update the Military Subtitle display
- //
- if( m_militarySubtitle ) // if we have a subtitle, work on it
- {
- // if the timeis frozen by a script, then we still want the text to display
- if(TheScriptEngine->isTimeFrozenScript())
- {
- m_militarySubtitle->lifetime--;
- m_militarySubtitle->blockBeginFrame--;
- m_militarySubtitle->incrementOnFrame--;
- }
- // if it's time to remove the subtitle, Then remove it
- if((Int)m_militarySubtitle->lifetime < (Int)currLogicFrame)
- {
- //steal colins fade from above :)
- GameGetColorComponents( m_militarySubtitle->color, &r, &g, &b, &a );
- // start fading the alpha on this color down
- amount = REAL_TO_INT( ((currLogicFrame - m_militarySubtitle->lifetime ) * 0.1f) );
- if( a - amount < 0 )
- {
- removeMilitarySubtitle();
- }
- else
- {
- a -= amount;
- m_militarySubtitle->color = GameMakeColor(r, g, b, a);
- }
- }
- else
- {
- // trigger whether or not we should draw the block
- if( m_militarySubtitle->blockBeginFrame + 9 < currLogicFrame )
- {
- m_militarySubtitle->blockBeginFrame = currLogicFrame;
- m_militarySubtitle->blockDrawn = !m_militarySubtitle->blockDrawn;
- }
- // If it's time to add another letter to the display string, lets do that.
- if( m_militarySubtitle->incrementOnFrame < currLogicFrame )
- {
- // first grab the letter we want to add
- WideChar tempWChar = m_militarySubtitle->subtitle.getCharAt(m_militarySubtitle->index);
- // if that letter is a return, add a new line
- if(tempWChar == L'\n')
- {
- // increment the Block position's Y value to draw it on the next line
- Int height;
- m_militarySubtitle->displayStrings[m_militarySubtitle->currentDisplayString]->getSize(NULL, &height);
- m_militarySubtitle->blockPos.y = m_militarySubtitle->blockPos.y + height;
- // Now add a new display string
- m_militarySubtitle->currentDisplayString++;
- if(!(m_militarySubtitle->currentDisplayString >= MAX_SUBTITLE_LINES) )
- {
- m_militarySubtitle->blockPos.x = m_militarySubtitle->position.x;
- m_militarySubtitle->displayStrings[m_militarySubtitle->currentDisplayString] = TheDisplayStringManager->newDisplayString();
- m_militarySubtitle->displayStrings[m_militarySubtitle->currentDisplayString]->reset();
- m_militarySubtitle->displayStrings[m_militarySubtitle->currentDisplayString]->setFont( TheFontLibrary->getFont( m_militaryCaptionFont, TheGlobalLanguageData->adjustFontSize(m_militaryCaptionPointSize), m_militaryCaptionBold ) ) ;
- m_militarySubtitle->blockDrawn = TRUE;
- m_militarySubtitle->incrementOnFrame = currLogicFrame + (Int)(((Real)LOGICFRAMES_PER_SECOND * TheGlobalLanguageData->m_militaryCaptionDelayMS)/1000.0f);
- }
- else
- {
- // if we've exceeded the allocated number of display strings, this will force us to essentially truncate the remaining text
- m_militarySubtitle->index = m_militarySubtitle->subtitle.getLength();
- DEBUG_CRASH(("You're Only Allowed to use %d lines of subtitle text\n",MAX_SUBTITLE_LINES));
- }
- }
- else
- {
- // okay, we're not a \n, lets append this character to the display string
- m_militarySubtitle->displayStrings[m_militarySubtitle->currentDisplayString]->appendChar(tempWChar);
- // increment the draw position of the block
- Int width;
- m_militarySubtitle->displayStrings[m_militarySubtitle->currentDisplayString]->getSize(&width,NULL);
- m_militarySubtitle->blockPos.x = m_militarySubtitle->position.x + width;
- // lets make a sound
- static AudioEventRTS click("MilitarySubtitlesTyping");
- TheAudio->addAudioEvent(&click);
- if(TheGlobalLanguageData)
- m_militarySubtitle->incrementOnFrame = currLogicFrame + TheGlobalLanguageData->m_militaryCaptionSpeed;
- else
- m_militarySubtitle->incrementOnFrame = currLogicFrame + m_militaryCaptionSpeed;
- }
- // increment the index
- m_militarySubtitle->index++;
- if(m_militarySubtitle->index >= m_militarySubtitle->subtitle.getLength())
- {
- // We're at the end of the subtitle, set everything to persist till the subtitle has expired
- m_militarySubtitle->incrementOnFrame = m_militarySubtitle->lifetime + 1;
- }
- /*
- else
- {
- // randomize the space between printing of characters
- if(GameClientRandomValueReal(0,1) < 0.95f)
- {
- m_militarySubtitle->incrementOnFrame = GameClientRandomValue(2, 5) + currLogicFrame;
- }
- else
- {
- m_militarySubtitle->incrementOnFrame = GameClientRandomValue(10, 13) + currLogicFrame;
- }
- }*/
-
- }
- }
- }
- // update the player money window if the money amount has changed
- // this seems like as good a place as any to do the power hide/show
- static Int lastMoney = -1;
- static NameKeyType moneyWindowKey = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:MoneyDisplay" );
- static NameKeyType powerWindowKey = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:PowerWindow" );
- GameWindow *moneyWin = TheWindowManager->winGetWindowFromId( NULL, moneyWindowKey );
- GameWindow *powerWin = TheWindowManager->winGetWindowFromId( NULL, powerWindowKey );
- // if( moneyWin == NULL )
- // {
- // NameKeyType moneyWindowKey = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:MoneyDisplay" );
- //
- // moneyWin = TheWindowManager->winGetWindowFromId( NULL, moneyWindowKey );
- //
- // } // end if
- Player *moneyPlayer = NULL;
- if( TheControlBar->isObserverControlBarOn())
- moneyPlayer = TheControlBar->getObserverLookAtPlayer();
- else
- moneyPlayer = ThePlayerList->getLocalPlayer();
- if( moneyPlayer)
- {
- Int currentMoney = moneyPlayer->getMoney()->countMoney();
- if( lastMoney != currentMoney )
- {
- UnicodeString buffer;
- buffer.format( TheGameText->fetch( "GUI:ControlBarMoneyDisplay" ), currentMoney );
- GadgetStaticTextSetText( moneyWin, buffer );
- lastMoney = currentMoney;
-
- } // end if
- moneyWin->winHide(FALSE);
- powerWin->winHide(FALSE);
- }
- else
- {
- moneyWin->winHide(TRUE);
- powerWin->winHide(TRUE);
- }
-
- // Update the floating Text;
- updateFloatingText();
- // update the control bar
- TheControlBar->update();
- updateIdleWorker();
- // update any random window layout that so requests
- for (std::list<WindowLayout *>::iterator it = m_windowLayouts.begin(); it != m_windowLayouts.end(); ++it)
- {
- WindowLayout *layout = *it;
- layout->runUpdate();
- }
- //Handle keyboard camera rotations
- if( m_cameraRotatingLeft && !m_cameraRotatingRight )
- {
- //Keyboard rotate left
- TheTacticalView->setAngle( TheTacticalView->getAngle() - TheGlobalData->m_keyboardCameraRotateSpeed );
- }
- if( m_cameraRotatingRight && !m_cameraRotatingLeft )
- {
- //Keyboard rotate right
- TheTacticalView->setAngle( TheTacticalView->getAngle() + TheGlobalData->m_keyboardCameraRotateSpeed );
- }
- if( m_cameraZoomingIn && !m_cameraZoomingOut )
- {
- //Keyboard zoom in
- TheTacticalView->zoomIn();
- }
- if( m_cameraZoomingOut && !m_cameraZoomingIn )
- {
- //Keyboard zoom out
- TheTacticalView->zoomOut();
- }
- } // end update
- //-------------------------------------------------------------------------------------------------
- void InGameUI::registerWindowLayout( WindowLayout *layout )
- {
- unregisterWindowLayout(layout); // sanity
- m_windowLayouts.push_back(layout);
- }
- //-------------------------------------------------------------------------------------------------
- void InGameUI::unregisterWindowLayout( WindowLayout *layout )
- {
- for (std::list<WindowLayout *>::iterator it = m_windowLayouts.begin(); it != m_windowLayouts.end(); ++it)
- {
- if (*it == layout)
- {
- m_windowLayouts.erase(it);
- return;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Reset the in game user interface */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::reset( void )
- {
- m_isQuitMenuVisible = FALSE;
- m_inputEnabled = true;
- // reset the command bar
- TheControlBar->reset();
- TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f);
- ResetInGameChat();
- // stop any movie currently playing
- stopMovie();
- // remove any pending GUI command
- setGUICommand( NULL );
- // remove any build available status
- placeBuildAvailable( NULL, NULL );
- // free any message resources allocated
- freeMessageResources();
- Int i;
- for (i=0; i<MAX_PLAYER_COUNT; ++i)
- {
- for (SuperweaponMap::iterator mapIt = m_superweapons[i].begin(); mapIt != m_superweapons[i].end(); ++mapIt)
- {
- for (SuperweaponList::iterator listIt = mapIt->second.begin(); listIt != mapIt->second.end(); ++listIt)
- {
- SuperweaponInfo *info = *listIt;
- info->deleteInstance();
- }
- mapIt->second.clear();
- }
- m_superweapons[i].clear();
- }
- for (NamedTimerMapIt timerIt = m_namedTimers.begin(); timerIt != m_namedTimers.end(); ++timerIt)
- {
- NamedTimerInfo *info = timerIt->second;
- TheDisplayStringManager->freeDisplayString(info->displayString);
- info->deleteInstance();
- }
- m_namedTimers.clear();
- m_namedTimerLastFlashFrame = 0;
- m_namedTimerUsedFlashColor = TRUE; // so next one is false
- m_showNamedTimers = TRUE;
- removeMilitarySubtitle();
- clearPopupMessageData();
- m_superweaponLastFlashFrame = 0;
- m_superweaponUsedFlashColor = TRUE; // so next one is false
- m_superweaponHiddenByScript = FALSE;
- clearFloatingText();
- clearWorldAnimations();
- resetIdleWorker();
- // clear hint lists
- for( i = 0; i < MAX_MOVE_HINTS; i++ )
- {
- m_moveHint[ i ].pos.zero();
- m_moveHint[ i ].sourceID = 0;
- m_moveHint[ i ].frame = 0;
- } // end for i
- m_waypointMode = false;
- m_forceAttackMode = false;
- m_forceMoveToMode = false;
- m_attackMoveToMode = false;
- m_preferSelection = false;
- m_clientQuiet = false;
-
- m_windowLayouts.clear();
- m_tooltipsDisabledUntil = 0;
- UpdateDiplomacyBriefingText(AsciiString::TheEmptyString, TRUE);
- } // end reset
- //-------------------------------------------------------------------------------------------------
- /** Free any resources we used for our messages */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::freeMessageResources( void )
- {
- Int i;
- // release display strings and set text to empty
- for( i = 0; i < MAX_UI_MESSAGES; i++ )
- {
- // emtpy text
- m_uiMessages[ i ].fullText.clear();
- // free display string
- if( m_uiMessages[ i ].displayString )
- TheDisplayStringManager->freeDisplayString( m_uiMessages[ i ].displayString );
- m_uiMessages[ i ].displayString = NULL;
- // set timestamp to zero
- m_uiMessages[ i ].timestamp = 0;
- } // end for i
- } // end freeMessageResources
- //-------------------------------------------------------------------------------------------------
- /** Same as the unicode message method, but this takes an ascii string which is assumed
- * to me a string manager label */
- //-------------------------------------------------------------------------------------------------
- // srj sez: passing as const-ref screws up varargs for some reason. dunno why. just pass by value.
- void InGameUI::message( AsciiString stringManagerLabel, ... )
- {
- UnicodeString stringManagerString;
- UnicodeString formattedMessage;
- // fetch the string from the string manger
- stringManagerString = TheGameText->fetch( stringManagerLabel.str() );
- // construct the final text after formatting
- va_list args;
- va_start( args, stringManagerLabel );
- WideChar buf[ UnicodeString::MAX_FORMAT_BUF_LEN ];
- if( _vsnwprintf(buf, sizeof( buf )/sizeof( WideChar ) - 1, stringManagerString.str(), args ) < 0 )
- throw ERROR_OUT_OF_MEMORY;
- formattedMessage.set( buf );
- va_end(args);
- // add the text to the ui
- addMessageText( formattedMessage );
- } // end
- //-------------------------------------------------------------------------------------------------
- /** Interface for display text messages to the user */
- //-------------------------------------------------------------------------------------------------
- // srj sez: passing as const-ref screws up varargs for some reason. dunno why. just pass by value.
- void InGameUI::message( UnicodeString format, ... )
- {
- UnicodeString formattedMessage;
- // construct the final text after formatting
- va_list args;
- va_start( args, format );
- WideChar buf[ UnicodeString::MAX_FORMAT_BUF_LEN ];
- if( _vsnwprintf(buf, sizeof( buf )/sizeof( WideChar ) - 1, format.str(), args ) < 0 )
- throw ERROR_OUT_OF_MEMORY;
- formattedMessage.set( buf );
- va_end(args);
- // add the text to the ui
- addMessageText( formattedMessage );
- } // end message
- //-------------------------------------------------------------------------------------------------
- /** Interface for display text messages to the user */
- //-------------------------------------------------------------------------------------------------
- // srj sez: passing as const-ref screws up varargs for some reason. dunno why. just pass by value.
- void InGameUI::messageColor( const RGBColor *rgbColor, UnicodeString format, ... )
- {
- UnicodeString formattedMessage;
- // construct the final text after formatting
- va_list args;
- va_start( args, format );
- WideChar buf[ UnicodeString::MAX_FORMAT_BUF_LEN ];
- if( _vsnwprintf(buf, sizeof( buf )/sizeof( WideChar ) - 1, format.str(), args ) < 0 )
- throw ERROR_OUT_OF_MEMORY;
- formattedMessage.set( buf );
- va_end(args);
- // add the text to the ui
- addMessageText( formattedMessage, rgbColor );
- } // end message
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void InGameUI::addMessageText( const UnicodeString& formattedMessage, const RGBColor *rgbColor )
- {
- Int i;
- Color color1 = m_messageColor1;
- Color color2 = m_messageColor2;
- if (rgbColor)
- {
- color1 = rgbColor->getAsInt() | GameMakeColor( 0, 0, 0, 255 );
- color2 = rgbColor->getAsInt() | GameMakeColor( 0, 0, 0, 255 );
- }
- // delete the message stuff at the last index
- m_uiMessages[ MAX_UI_MESSAGES - 1 ].fullText.clear();
- if( m_uiMessages[ MAX_UI_MESSAGES - 1 ].displayString )
- TheDisplayStringManager->freeDisplayString( m_uiMessages[ MAX_UI_MESSAGES - 1 ].displayString );
- m_uiMessages[ MAX_UI_MESSAGES - 1 ].displayString = NULL;
- m_uiMessages[ MAX_UI_MESSAGES - 1 ].timestamp = 0;
- // shift all the messages down one index and remove the last one
- for( i = MAX_UI_MESSAGES - 1; i >= 1; i-- )
- m_uiMessages[ i ] = m_uiMessages[ i - 1 ];
- //
- // set the new message in index 0, note that we need to allocate a display string, but
- // we do not need to free the one that is already there because it has been moved
- // "up" an index
- //
- m_uiMessages[ 0 ].fullText = formattedMessage;
- m_uiMessages[ 0 ].timestamp = TheGameLogic->getFrame();
- m_uiMessages[ 0 ].displayString = TheDisplayStringManager->newDisplayString();
- m_uiMessages[ 0 ].displayString->setFont( TheFontLibrary->getFont( m_messageFont,
- TheGlobalLanguageData->adjustFontSize(m_messagePointSize), m_messageBold ) );
- m_uiMessages[ 0 ].displayString->setText( m_uiMessages[ 0 ].fullText );
-
- //
- // assign a color for this string instance that will stay with it no matter what
- // line it is rendered on
- //
- if( m_uiMessages[ 1 ].displayString == NULL || m_uiMessages[ 1 ].color == color2 )
- m_uiMessages[ 0 ].color = color1;
- else
- m_uiMessages[ 0 ].color = color2;
- } // end addFormattedMessage
- //-------------------------------------------------------------------------------------------------
- /** Remove the message on screen at index i */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::removeMessageAtIndex( Int i )
- {
- m_uiMessages[ i ].fullText.clear();
- if( m_uiMessages[ i ].displayString )
- TheDisplayStringManager->freeDisplayString( m_uiMessages[ i ].displayString );
- m_uiMessages[ i ].displayString = NULL;
- m_uiMessages[ i ].timestamp = 0;
- } // end removeMessageAtIndex
- //-------------------------------------------------------------------------------------------------
- /** An area selection is occurring, start graphical "hint". */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::beginAreaSelectHint( const GameMessage *msg )
- {
- m_isDragSelecting = true;
- m_dragSelectRegion = msg->getArgument( 0 )->pixelRegion;
- }
- //-------------------------------------------------------------------------------------------------
- /** An area selection has occurred, finish graphical "hint". */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::endAreaSelectHint( const GameMessage *msg )
- {
- m_isDragSelecting = false;
- }
- //-------------------------------------------------------------------------------------------------
- /** A move command has occurred, start graphical "hint". */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::createMoveHint( const GameMessage *msg )
- {
- Int i;
- // first, remove any existing move hint for this source if present
- for( i = 0; i < MAX_MOVE_HINTS; i++ )
- if( m_moveHint[ i ].sourceID == msg->getArgument( 0 )->objectID &&
- m_moveHint[ i ].frame != 0 )
- expireHint( MOVE_HINT, i );
-
- if( getSelectCount() == 1 )
- {
- Drawable *draw = getFirstSelectedDrawable();
- Object *obj = draw ? draw->getObject() : NULL;
- if( obj && obj->isKindOf( KINDOF_IMMOBILE ) )
- {
- //Don't allow move hints to be created if our selected object can't move!
- return;
- }
- }
- m_moveHint[ m_nextMoveHint ].frame = TheGameClient->getFrame();
- m_moveHint[ m_nextMoveHint ].pos = msg->getArgument( 0 )->location;
-
- m_nextMoveHint++;
- // wrap around
- if (m_nextMoveHint == InGameUI::MAX_MOVE_HINTS)
- m_nextMoveHint = 0;
- }
- //-------------------------------------------------------------------------------------------------
- /** An attack command has occurred, start graphical "hint". */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::createAttackHint( const GameMessage *msg )
- {
- }
- //-------------------------------------------------------------------------------------------------
- /** A force attack command has occurred, start graphical "hint". */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::createForceAttackHint( const GameMessage *msg )
- {
- }
- //-------------------------------------------------------------------------------------------------
- /** An garrison command has occurred, start graphical "hint". */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::createGarrisonHint( const GameMessage *msg )
- {
- Drawable *draw = TheGameClient->findDrawableByID( msg->getArgument(0)->drawableID );
- if( draw )
- {
- draw->onSelected();
- }
- }
- #if defined(_DEBUG) || defined(_INTERNAL)
- #define AI_DEBUG_TOOLTIPS 1
- #ifdef AI_DEBUG_TOOLTIPS
- #include "Common/StateMachine.h"
- #include "GameLogic/Module/AIUpdate.h"
- #include "GameLogic/AIPathfind.h"
- #endif // AI_DEBUG_TOOLTIPS
- #endif // defined(_DEBUG) || defined(_INTERNAL)
- //-------------------------------------------------------------------------------------------------
- /** Details of what is mouse hovered over right now are in this message. Terrain might result
- * in just a tooltip. An object might get a tooltip and show its hit points.
- */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::createMouseoverHint( const GameMessage *msg )
- {
- if (m_isScrolling || m_isSelecting)
- return; // no mouseover for you
- GameWindow *window = NULL;
- const MouseIO *io = TheMouse->getMouseStatus();
- Bool underWindow = false;
- if (io && TheWindowManager)
- window = TheWindowManager->getWindowUnderCursor(io->pos.x, io->pos.y);
- while (window)
- {
- if (window->winGetInputFunc() == LeftHUDInput) {
- underWindow = false;
- break;
- }
-
- // check to see if it or any of its parents are opaque. If so, we can't select anything.
- if (!BitTest( window->winGetStatus(), WIN_STATUS_SEE_THRU ))
- {
- underWindow = true;
- break;
- }
- window = window->winGetParent();
- }
- if (underWindow)
- {
- setMouseCursor(Mouse::ARROW); // regardless of m_mouseMode
- return;
- }
-
- DrawableID oldID = m_mousedOverDrawableID;
- if (msg->getType() == GameMessage::MSG_MOUSEOVER_DRAWABLE_HINT)
- {
- TheMouse->setCursorTooltip(UnicodeString::TheEmptyString );
- m_mousedOverDrawableID = INVALID_DRAWABLE_ID;
- const Drawable *draw = TheGameClient->findDrawableByID(msg->getArgument(0)->drawableID);
- const Object *obj = draw ? draw->getObject() : NULL;
- if( obj )
- {
-
- //Ahh, here is a wierd exception: if the moused-over drawable is a mob-member
- //(e.g. AngryMob), Lets fool the UI into creating the hint for the NEXUS instead...
- if (obj->isKindOf( KINDOF_IGNORED_IN_GUI ))
- {
- static NameKeyType key_MobMemberSlavedUpdate = NAMEKEY( "MobMemberSlavedUpdate" );
- MobMemberSlavedUpdate *MMSUpdate = (MobMemberSlavedUpdate*)obj->findUpdateModule( key_MobMemberSlavedUpdate );
- if( MMSUpdate )
- {
- Object *slaver = TheGameLogic->findObjectByID(MMSUpdate->getSlaverID());
- if ( slaver )
- {
- Drawable *slaverDraw = slaver->getDrawable();
- if ( slaverDraw )
- m_mousedOverDrawableID = slaverDraw->getID();
- // if this fails, not to worry... it has already defaulted to INVALID_DRAWABLE_ID, above
- }
- }
- }
- else
- m_mousedOverDrawableID = draw->getID();
- #if defined(_DEBUG) || defined(_INTERNAL) //Extra hacky, sorry, but I need to use this in constantdebug report
- if ( TheGlobalData->m_constantDebugUpdate == TRUE )
- m_mousedOverDrawableID = draw->getID();
- #endif
- const Player* player = NULL;
- const ThingTemplate *thingTemplate = obj->getTemplate();
- ContainModuleInterface* contain = obj->getContain();
- if( contain )
- player = contain->getApparentControllingPlayer(ThePlayerList->getLocalPlayer());
- if (player == NULL)
- player = obj->getControllingPlayer();
- Bool disguised = false;
- if( obj->isKindOf( KINDOF_DISGUISER ) )
- {
- //Because we have support for disguised units pretending to be units from another
- //team, we need to intercept it here and make sure it's rendered appropriately
- //based on which client is rendering it.
- StealthUpdate *update = obj->getStealth();
- if( update )
- {
- if( update->isDisguised() )
- {
- Player *clientPlayer = ThePlayerList->getLocalPlayer();
- Player *disguisedPlayer = ThePlayerList->getNthPlayer( update->getDisguisedPlayerIndex() );
- if( player->getRelationship( clientPlayer->getDefaultTeam() ) != ALLIES && clientPlayer->isPlayerActive() )
- {
- //Neutrals and enemies will see this disguised unit as the team it's disguised as.
- player = disguisedPlayer;
- const ThingTemplate *disguisedTemplate = update->getDisguisedTemplate();
- if( disguisedTemplate )
- {
- thingTemplate = disguisedTemplate;
- disguised = true;
- }
- }
- //Otherwise, the color will show up as the team it really belongs to (already set above).
- }
- }
- }
- UnicodeString str = thingTemplate->getDisplayName();
- UnicodeString displayName = thingTemplate->getDisplayName();
- if( str.isEmpty() )
- {
- AsciiString txtTemp;
- txtTemp.format("ThingTemplate:%s", obj->getTemplate()->getName().str());
- str = TheGameText->fetch(txtTemp);
- //str.format(L"ThingTemplate:'%hs'", obj->getTemplate()->getName().str());
- }
- #ifdef AI_DEBUG_TOOLTIPS
- if (TheGlobalData->m_debugAI) {
- const Team *team = obj->getTeam();
- AsciiString objName = obj->getName();
- AsciiString teamName;
- AsciiString stateName;
-
- AIUpdateInterface *ai = (AIUpdateInterface*)obj->getAI();
- if (ai) {
- if (ai->getPath()) {
- TheAI->pathfinder()->setDebugPath(ai->getPath());
- }
- #ifdef STATE_MACHINE_DEBUG
- stateName = ai->getCurrentStateName();
- if (ai->getAttackInfo()) {
- stateName.concat(" AttackPriority=");
- stateName.concat(ai->getAttackInfo()->getName());
- }
- #endif
- }
- if( team )
- {
- teamName = team->getName();
- }
- if (!objName.isEmpty())
- {
- if (!teamName.isEmpty())
- {
- str.format(L"%hs(%hs): %s", teamName.str(), objName.str(), str.str());
- }
- else
- {
- str.format(L"%hs: %s", objName.str(), str.str());
- }
- }
- else
- {
- if (!teamName.isEmpty())
- {
- str.format(L"%hs: %s", teamName.str(), str.str());
- }
- }
- str.format(L"%s - %hs", str.str(), stateName.str());
- }
- #endif
- UnicodeString warehouseFeedback;
- // Add on dollar amount of warehouse contents so people don't freak out until the art is hooked up
- static const NameKeyType warehouseModuleKey = TheNameKeyGenerator->nameToKey( "SupplyWarehouseDockUpdate" );
- SupplyWarehouseDockUpdate *warehouseModule = (SupplyWarehouseDockUpdate *)obj->findUpdateModule( warehouseModuleKey );
- if( warehouseModule != NULL )
- {
- Int boxes = warehouseModule->getBoxesStored();
- Int value = boxes * TheGlobalData->m_baseValuePerSupplyBox;
- warehouseFeedback.format(TheGameText->fetch("TOOLTIP:SupplyWarehouse"), value);
- str.concat(warehouseFeedback);
- }
- if (player)
- {
- UnicodeString tooltip;
- //if (TheRecorder->isMultiplayer() && player->getPlayerType() == PLAYER_HUMAN)
- if (TheRecorder->isMultiplayer() && player->isPlayableSide())
- tooltip.format(L"%s\n%s", str.str(), ((Player *)player)->getPlayerDisplayName().str());
- else
- tooltip = str;
- Int localPlayerIndex = ThePlayerList ? ThePlayerList->getLocalPlayer()->getPlayerIndex() : 0;
- Int x, y;
- ThePartitionManager->worldToCell(obj->getPosition()->x, obj->getPosition()->y, &x, &y);
- if( ThePartitionManager->getShroudStatusForPlayer(localPlayerIndex, x, y) == CELLSHROUD_CLEAR )
- {
- RGBColor rgb;
- if( disguised )
- {
- rgb.setFromInt( player->getPlayerColor() );
- }
- else
- {
- rgb.setFromInt(draw->getObject()->getIndicatorColor());
- // Unless this is a stealth garrisoned building,
- // Let's not use the contained's housecolor
- const Object *obj = draw->getObject();
- if ( obj )
- {
- ContainModuleInterface *contain = obj->getContain();
- if ( contain && contain->isGarrisonable() )
- {
- const Player *play = contain->getApparentControllingPlayer( ThePlayerList->getLocalPlayer() );
- if ( play )
- rgb.setFromInt( play->getPlayerColor() );
- }
- }
- }
- //Object:Prop is a blank string... but we don't want to show
- //any popup box at all if that is the case!
- if( displayName.compare( TheGameText->fetch( "OBJECT:Prop" ) ) )
- {
- TheMouse->setCursorTooltip(tooltip, -1, &rgb );
- }
- }
- }
- }
- }
- else
- {
- m_mousedOverDrawableID = INVALID_DRAWABLE_ID;
- }
- if (oldID != m_mousedOverDrawableID)
- {
- //DEBUG_LOG(("Resetting tooltip delay\n"));
- TheMouse->resetTooltipDelay();
- }
- if (m_mouseMode == MOUSEMODE_DEFAULT && !m_isScrolling && !m_isSelecting && !TheInGameUI->getSelectCount() && (TheRecorder->getMode() != RECORDERMODETYPE_PLAYBACK || TheLookAtTranslator->hasMouseMovedRecently()))
- {
- if( m_mousedOverDrawableID != INVALID_DRAWABLE_ID )
- {
- Drawable *draw = TheGameClient->findDrawableByID(m_mousedOverDrawableID);
-
- //Add basic logic to determine if we can select a unit (or hint)
- const Object *obj = draw ? draw->getObject() : NULL;
- Bool drawSelectable = CanSelectDrawable(draw, FALSE);
- if( !obj )
- {
- drawSelectable = false;
- }
- if( drawSelectable && obj->isLocallyControlled() )
- {
- setMouseCursor(Mouse::SELECTING);
- }
- else
- {
- setMouseCursor(Mouse::ARROW);
- }
- }
- else
- {
- setMouseCursor(Mouse::ARROW);
- }
- }
- else if (m_mouseMode != MOUSEMODE_DEFAULT && m_mouseMode != MOUSEMODE_BUILD_PLACE )
- {
- setMouseCursor((Mouse::MouseCursor)m_mouseModeCursor);
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** A command would be given if a click were to happen, so give a preview hint of what it would be.
- * Changing the mouse cursor is an example
- */
- void InGameUI::createCommandHint( const GameMessage *msg )
- {
- if (m_isScrolling || m_isSelecting || TheRecorder->getMode() == RECORDERMODETYPE_PLAYBACK)
- return;
- const Drawable *draw = TheGameClient->findDrawableByID(m_mousedOverDrawableID);
- GameMessage::Type t = msg->getType();
- //#ifdef DO_SHROUD_PROJECTION
- if( draw && (t == GameMessage::MSG_DO_ATTACK_OBJECT_HINT || t == GameMessage::MSG_DO_ATTACK_OBJECT_AFTER_MOVING_HINT) )
- {
- const Object* obj = draw->getObject();
- Int localPlayerIndex = ThePlayerList ? ThePlayerList->getLocalPlayer()->getPlayerIndex() : 0;
- #if defined(_DEBUG) || defined(_INTERNAL)
- ObjectShroudStatus ss = (!obj || !TheGlobalData->m_shroudOn) ? OBJECTSHROUD_CLEAR : obj->getShroudedStatus(localPlayerIndex);
- #else
- ObjectShroudStatus ss = (!obj) ? OBJECTSHROUD_CLEAR : obj->getShroudedStatus(localPlayerIndex);
- #endif
- if (ss == OBJECTSHROUD_SHROUDED)
- {
- t = GameMessage::MSG_DO_MOVETO_HINT; // if the object is hidden, switch to something innocuous
- }
- }
- //#endif
- setRadiusCursorNone();
- if ( TheGlobalData->m_doubleClickAttackMove )
- {
- if ( --m_duringDoubleClickAttackMoveGuardHintTimer > 0 )
- {
- setMouseCursor(Mouse::FORCE_ATTACK_GROUND);
- setRadiusCursor(RADIUSCURSOR_GUARD_AREA,
- NULL,
- PRIMARY_WEAPON);
- return;
- }
- }
- // set cursor to normal if there is a window under the cursor
- GameWindow *window = NULL;
- const MouseIO *io = TheMouse->getMouseStatus();
- Bool underWindow = false;
- if (io && TheWindowManager)
- window = TheWindowManager->getWindowUnderCursor(io->pos.x, io->pos.y);
- while (window)
- {
- if (window->winGetInputFunc() == LeftHUDInput) {
- underWindow = false;
- break;
- }
-
- // check to see if it or any of its parents are opaque. If so, we can't select anything.
- if (!BitTest( window->winGetStatus(), WIN_STATUS_SEE_THRU ))
- {
- underWindow = true;
- break;
- }
- window = window->winGetParent();
- }
- //Add basic logic to determine if we can select a unit (or hint)
- const Object *obj = draw ? draw->getObject() : NULL;
- Bool drawSelectable = CanSelectDrawable(draw, FALSE);
- if( !obj )
- {
- drawSelectable = false;
- }
- // Note: These are only non-NULL if there is exactly one thing selected.
- const Drawable *srcDraw = NULL;
- const Object *srcObj = NULL;
- if (getSelectCount() == 1) {
- srcDraw = getAllSelectedDrawables()->front();
- srcObj = (srcDraw ? srcDraw->getObject() : NULL);
- }
- switch (m_mouseMode)
- {
- case MOUSEMODE_DEFAULT:
- {
- // This section of code only gets called when there is no specific cursor mode happening.
- if (underWindow || (srcObj && !srcObj->isLocallyControlled()))
- {
- setMouseCursor(Mouse::ARROW);
- return;
- }
- switch (t)
- {
- case GameMessage::MSG_DO_MOVETO_HINT:
- {
- if( !drawSelectable && srcObj && srcObj->isLocallyControlled() && srcObj->isKindOf(KINDOF_STRUCTURE))
- setMouseCursor( Mouse::GENERIC_INVALID );
- else if( drawSelectable && obj->isLocallyControlled() && !obj->isKindOf(KINDOF_MINE))
- setMouseCursor( Mouse::SELECTING );
- else if( TheRadar->isRadarWindow( window ) &&
- TheRadar->isRadarForced() == FALSE &&
- (TheRadar->isRadarHidden() ||
- ThePlayerList->getLocalPlayer()->hasRadar() == FALSE) )
- setMouseCursor( Mouse::ARROW );
- else
- setMouseCursor( Mouse::MOVETO );
- break;
- }
- case GameMessage::MSG_DO_ATTACKMOVETO_HINT:
- if( drawSelectable && obj->isLocallyControlled() )
- setMouseCursor( Mouse::SELECTING );
- else
- setMouseCursor( Mouse::ATTACKMOVETO );
- break;
- case GameMessage::MSG_ADD_WAYPOINT_HINT:
- setMouseCursor( Mouse::WAYPOINT );
- break;
- case GameMessage::MSG_DO_ATTACK_OBJECT_HINT:
- setMouseCursor( Mouse::ATTACK_OBJECT );
- break;
- case GameMessage::MSG_DO_ATTACK_OBJECT_AFTER_MOVING_HINT:
- setMouseCursor( Mouse::OUTRANGE );
- break;
- case GameMessage::MSG_DO_FORCE_ATTACK_OBJECT_HINT:
- setMouseCursor( Mouse::FORCE_ATTACK_OBJECT );
- break;
- case GameMessage::MSG_DO_FORCE_ATTACK_GROUND_HINT:
- setMouseCursor( Mouse::FORCE_ATTACK_GROUND );
- break;
- case GameMessage::MSG_GET_REPAIRED_HINT:
- setMouseCursor( Mouse::GET_REPAIRED );
- break;
- case GameMessage::MSG_DOCK_HINT:
- setMouseCursor( Mouse::DOCK );
- break;
- case GameMessage::MSG_GET_HEALED_HINT:
- setMouseCursor( Mouse::GET_HEALED );
- break;
- case GameMessage::MSG_DO_REPAIR_HINT:
- setMouseCursor( Mouse::DO_REPAIR );
- break;
- case GameMessage::MSG_RESUME_CONSTRUCTION_HINT:
- setMouseCursor( Mouse::RESUME_CONSTRUCTION );
- break;
- case GameMessage::MSG_ENTER_HINT:
- setMouseCursor( Mouse::ENTER_FRIENDLY );
- break;
- case GameMessage::MSG_CONVERT_TO_CARBOMB_HINT:
- case GameMessage::MSG_HIJACK_HINT:
- case GameMessage::MSG_SABOTAGE_HINT:
- setMouseCursor( Mouse::ENTER_AGGRESSIVELY );
- break;
- case GameMessage::MSG_DEFECTOR_HINT:
- setMouseCursor( Mouse::DEFECTOR );
- break;
- #ifdef ALLOW_SURRENDER
- case GameMessage::MSG_PICK_UP_PRISONER_HINT:
- setMouseCursor( Mouse::PICK_UP_PRISONER );
- break;
- #endif
- case GameMessage::MSG_CAPTUREBUILDING_HINT:
- setMouseCursor( Mouse::CAPTUREBUILDING );
- break;
- case GameMessage::MSG_HACK_HINT:
- setMouseCursor( Mouse::HACK );
- break;
- case GameMessage::MSG_IMPOSSIBLE_ATTACK_HINT:
- setMouseCursor( Mouse::GENERIC_INVALID );
- break;
- case GameMessage::MSG_SET_RALLY_POINT_HINT:
- if ( !drawSelectable )
- setMouseCursor( Mouse::SET_RALLY_POINT );
- else
- setMouseCursor( Mouse::SELECTING );
- break;
- case GameMessage::MSG_DO_SPECIAL_POWER_OVERRIDE_DESTINATION_HINT:
- setMouseCursor( Mouse::PARTICLE_UPLINK_CANNON );
- break;
- case GameMessage::MSG_DO_SALVAGE_HINT:
- setMouseCursor( Mouse::MOVETO );
- break;
- case GameMessage::MSG_DO_INVALID_HINT:
- setMouseCursor( Mouse::GENERIC_INVALID );
- break;
- }
- }
- break;
- case MOUSEMODE_BUILD_PLACE:
- {
- if (underWindow)
- {
- setMouseCursor(Mouse::ARROW);
- return;
- }
- switch (t)
- {
- case GameMessage::MSG_DO_MOVETO_HINT:
- case GameMessage::MSG_DO_ATTACKMOVETO_HINT:
- case GameMessage::MSG_ADD_WAYPOINT:
- setMouseCursor(Mouse::BUILD_PLACEMENT);
- break;
- case GameMessage::MSG_DO_ATTACK_OBJECT_HINT:
- case GameMessage::MSG_DO_ATTACK_OBJECT_AFTER_MOVING_HINT:
- setMouseCursor(Mouse::INVALID_BUILD_PLACEMENT);
- break;
- }
- }
- break;
- case MOUSEMODE_GUI_COMMAND:
- {
- if (underWindow)
- {
- setMouseCursor(Mouse::ARROW);
- return;
- }
- // set the mouse cursor for commands that need a targeting or to normal with no command
- if( m_pendingGUICommand )
- {
- if( m_pendingGUICommand->isContextCommand() ||
- m_pendingGUICommand->getCommandType() == GUI_COMMAND_SPECIAL_POWER ||
- m_pendingGUICommand->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT )
- {
- //Here is the hook for when we are in a context sensitive command mode. We can
- //either do the specified command mode command or nothing! Whether or not the
- //command is valid or not was determined in evaluateContextCommand which is
- //called first, and posts the appropriate message.
- AsciiString cursorName; // empty by default
- switch( t )
- {
- case GameMessage::MSG_VALID_GUICOMMAND_HINT:
- cursorName = m_pendingGUICommand->getCursorName();
- break;
- case GameMessage::MSG_INVALID_GUICOMMAND_HINT:
- default:
- cursorName = m_pendingGUICommand->getInvalidCursorName();
- break;
- }
- Int index = TheMouse->getCursorIndex(cursorName);
- if( index != Mouse::INVALID_MOUSE_CURSOR )
- {
- setMouseCursor( (Mouse::MouseCursor)index );
- }
- else
- {
- setMouseCursor( Mouse::CROSS );
- }
- setRadiusCursor(m_pendingGUICommand->getRadiusCursorType(), //*****************************************************************
- m_pendingGUICommand->getSpecialPowerTemplate(),
- m_pendingGUICommand->getWeaponSlot());
- }
- else if( BitTest( m_pendingGUICommand->getOptions(), COMMAND_OPTION_NEED_TARGET ) )
- {
- Int index = TheMouse->getCursorIndex(m_pendingGUICommand->getCursorName());
- if (index != Mouse::INVALID_MOUSE_CURSOR)
- setMouseCursor( (Mouse::MouseCursor)index );
- else
- setMouseCursor( Mouse::CROSS );
- setRadiusCursor(m_pendingGUICommand->getRadiusCursorType(), //*****************************************************************
- m_pendingGUICommand->getSpecialPowerTemplate(),
- m_pendingGUICommand->getWeaponSlot());
- }
- else
- {
- setRadiusCursorNone();
- }
- }
- }
- break;
- }
- }
- //-------------------------------------------------------------------------------------------------
- /// Get drawable ID under cursor
- //-------------------------------------------------------------------------------------------------
- DrawableID InGameUI::getMousedOverDrawableID( void ) const
- {
- return m_mousedOverDrawableID;
- }
- //-------------------------------------------------------------------------------------------------
- /// set right-click scroll mode
- //-------------------------------------------------------------------------------------------------
- void InGameUI::setScrolling( Bool isScrolling )
- {
- if (m_isScrolling == isScrolling)
- {
- return;
- }
- if (isScrolling)
- {
- TheMouse->capture();
- setMouseCursor( Mouse::SCROLL );
- // break any camera locks
- TheTacticalView->setCameraLock( INVALID_ID );
- TheTacticalView->setCameraLockDrawable( NULL );
- }
- else
- {
- setMouseCursor( Mouse::ARROW );
- TheMouse->releaseCapture();
- }
- m_isScrolling = isScrolling;
- }
- //-------------------------------------------------------------------------------------------------
- /// are we scrolling?
- //-------------------------------------------------------------------------------------------------
- Bool InGameUI::isScrolling( void )
- {
- return m_isScrolling;
- }
- //-------------------------------------------------------------------------------------------------
- /// set drag select mode
- //-------------------------------------------------------------------------------------------------
- void InGameUI::setSelecting( Bool isSelecting )
- {
- if (m_isSelecting == isSelecting)
- {
- return;
- }
- //setMouseCursor( Mouse::SELECTING );
- m_isSelecting = isSelecting;
- }
- //-------------------------------------------------------------------------------------------------
- /// are we selecting?
- //-------------------------------------------------------------------------------------------------
- Bool InGameUI::isSelecting( void )
- {
- return m_isSelecting;
- }
- //-------------------------------------------------------------------------------------------------
- /// get scroll amount
- //-------------------------------------------------------------------------------------------------
- void InGameUI::setScrollAmount( Coord2D amt )
- {
- m_scrollAmt = amt;
- }
- //-------------------------------------------------------------------------------------------------
- /// get scroll amount
- //-------------------------------------------------------------------------------------------------
- Coord2D InGameUI::getScrollAmount( void )
- {
- return m_scrollAmt;
- }
- //-------------------------------------------------------------------------------------------------
- /** Like the building "placement" mode, clicking on some buttons in the UI require us to
- * provide additional data by clicking on a target object/location in the world. This
- * is where we enable that "mode" so that we can get the additional data needed for a
- * command from the user */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::setGUICommand( const CommandButton *command )
- {
- if (TheRecorder->getMode() == RECORDERMODETYPE_PLAYBACK)
- return;
- // sanity
- if( command )
- {
- if( BitTest( command->getOptions(), COMMAND_OPTION_NEED_TARGET ) == FALSE )
- {
- DEBUG_ASSERTCRASH( 0, ("setGUICommand: Command '%s' does not need additional user interaction\n",
- command->getName().str()) );
- m_pendingGUICommand = NULL;
- m_mouseMode = MOUSEMODE_DEFAULT;
- return;
- } // end if
- m_mouseMode = MOUSEMODE_GUI_COMMAND;
- } // end if
- else
- {
- m_mouseMode = MOUSEMODE_DEFAULT;
- }
- // set the command
- m_pendingGUICommand = command;
- // set the mouse cursor for commands that need a targeting or to normal with no command
- if( command && BitTest( command->getOptions(), COMMAND_OPTION_NEED_TARGET ) && !command->isContextCommand() )
- {
- setMouseCursor( Mouse::ARROW );// This occurs on the mouse-up of a panel button, so make an arrow
- // the mouseoverhint code will take care of the cursor context, once the mouse leaves the panel
- // but we will set the radius cursor here, so you can see it bleeding out from beneath the panel
- setRadiusCursor(command->getRadiusCursorType(), //*****************************************************************
- command->getSpecialPowerTemplate(),
- command->getWeaponSlot());
- }
- else
- {
- if (TheMouse)
- {
- setMouseCursor( Mouse::ARROW );
- }
- setRadiusCursorNone();
- }
- m_mouseModeCursor = TheMouse->getMouseCursor();
- } // end setGUICommand
- //-------------------------------------------------------------------------------------------------
- /** Get the pending gui command */
- //-------------------------------------------------------------------------------------------------
- const CommandButton *InGameUI::getGUICommand( void ) const
- {
- return m_pendingGUICommand;
- }
- //-------------------------------------------------------------------------------------------------
- /** Destroy any drawables we have in our placement icon array and set to NULL */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::destroyPlacementIcons( void )
- {
- Int i;
- for( i = 0; i < TheGlobalData->m_maxLineBuildObjects; ++i )
- {
- if( m_placeIcon[ i ] )
- {
- TheTerrainVisual->removeFactionBibDrawable(m_placeIcon[ i ]);
- TheGameClient->destroyDrawable( m_placeIcon[ i ] );
- }
- m_placeIcon[ i ] = NULL;
- } // end for i
- TheTerrainVisual->removeAllBibs();
- } // end destroyPlacementIcons
- //-------------------------------------------------------------------------------------------------
- /** User has clicked on a built item that requires placement in the world. We will
- * record what that thing is so that the we can catch the next click in the world
- * and try to place the object there */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::placeBuildAvailable( const ThingTemplate *build, Drawable *buildDrawable )
- {
- if (build != NULL)
- {
- // if building something, no radius cursor, thankew
- setRadiusCursorNone();
- }
- //
- // if we're setting another place available, but we're somehow already in the placement
- // mode, get out of it before we start a new one
- //
- if( m_pendingPlaceType != NULL && build != NULL )
- placeBuildAvailable( NULL, NULL );
- //
- // keep a record of what we are trying to place, if we are already trying to
- // place something, it is overwritten
- //
- m_pendingPlaceType = build;
- //Keep the prev pending place for left click deselection prevention in alternate mouse mode.
- //We want to keep our dozer selected after initiating construction.
- setPreventLeftClickDeselectionInAlternateMouseModeForOneClick( m_pendingPlaceSourceObjectID != INVALID_ID );
- m_pendingPlaceSourceObjectID = INVALID_ID;
- Object *sourceObject = NULL;
- if( buildDrawable )
- sourceObject = buildDrawable->getObject();
- if( sourceObject )
- m_pendingPlaceSourceObjectID = sourceObject->getID();
- //
- // hack, change our cursor to at least something different ... also note that it's
- // possible to not have the mouse yet, as some UI systems as part of initialization
- // make sure that there isn't anything valid for to "place build"
- //
- if( TheMouse )
- {
- if( build )
- {
- m_mouseMode = MOUSEMODE_BUILD_PLACE;
- m_mouseModeCursor = Mouse::CROSS;
- Drawable *draw;
- // capture the mouse for our window, windows is lame and changes it if we don't
- TheMouse->capture();
- // hack for changing cursor
- setMouseCursor( Mouse::CROSS );
- // deselect all drawables, otherwise they move to the place we click
- ///@ todo when message stream order more formalized eliminate this
- // TheInGameUI->deselectAllDrawables();
- // create a drawble of what we are building to be "attached" at the cursor
- draw = TheThingFactory->newDrawable( build, DRAWABLE_STATUS_NO_STATE_PARTICLES );
- if (sourceObject)
- {
- if (TheGlobalData->m_timeOfDay == TIME_OF_DAY_NIGHT)
- draw->setIndicatorColor(sourceObject->getControllingPlayer()->getPlayerNightColor());
- else
- draw->setIndicatorColor(sourceObject->getControllingPlayer()->getPlayerColor());
- }
- DEBUG_ASSERTCRASH( draw, ("Unable to create icon at cursor for placement '%s'\n",
- build->getName().str()) );
- //
- // set the initial angle of the free floating building to the property from INI
- // we have this so we can have the "cool" face the user until they click and
- // pick an actual direction for placement
- //
- Real angle = build->getPlacementViewAngle();
- // don't forget to take into account the current view angle
- // angle += TheTacticalView->getAngle(); Don't do this - makes odd angled building placements. jba.
- // set the angle in the icon we just created
- draw->setOrientation( angle );
- // set the build icon attached to the cursor to be "see-thru"
- draw->setDrawableOpacity( placementOpacity );
- // set the "icon" in the icon array at the first index
- DEBUG_ASSERTCRASH( m_placeIcon[ 0 ] == NULL, ("placeBuildAvailable, build icon array is not empty!") );
- m_placeIcon[ 0 ] = draw;
- } // end if
- else
- {
- if (m_mouseMode == MOUSEMODE_BUILD_PLACE)
- {
- m_mouseMode = MOUSEMODE_DEFAULT;
- m_mouseModeCursor = Mouse::ARROW;
- }
- TheMouse->releaseCapture();
- setMouseCursor( Mouse::ARROW );
- setPlacementStart( NULL );
- // if we have a place icons destroy them
- destroyPlacementIcons();
- if( sourceObject )
- {
- ProductionUpdateInterface *puInterface = sourceObject->getProductionUpdateInterface();
- if( puInterface )
- {
- //Clear the special power mode for construction if we set it. Actually call it everytime
- //rather than checking if it's set before clearing (cheaper).
- puInterface->setSpecialPowerConstructionCommandButton( NULL );
- }
- }
- } // end else
- } // end if
- } // end placeBuildAvailable
- //-------------------------------------------------------------------------------------------------
- /** Return the thing we're attempting to place */
- //-------------------------------------------------------------------------------------------------
- const ThingTemplate *InGameUI::getPendingPlaceType( void )
- {
- return m_pendingPlaceType;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- const ObjectID InGameUI::getPendingPlaceSourceObjectID( void )
- {
- return m_pendingPlaceSourceObjectID;
- } // end getPendingPlaceSourceObjectID
- //-------------------------------------------------------------------------------------------------
- /** Start the angle selection interface for selecting building angles when placing them */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::setPlacementStart( const ICoord2D *start )
- {
- // if we have a start point we turn "on" the interface, otherwise we turn it "off"
- if( start )
- {
- m_placeAnchorStart = *start;
- m_placeAnchorEnd = *start;
- m_placeAnchorInProgress = TRUE;
- } // end if
- else
- m_placeAnchorInProgress = FALSE;
- } // end setPlacementStart
- //-------------------------------------------------------------------------------------------------
- /** Set the end anchor for the angle build interface */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::setPlacementEnd( const ICoord2D *end )
- {
- if( end )
- m_placeAnchorEnd = *end;
- } // end setPlacementEnd
- //-------------------------------------------------------------------------------------------------
- /** Is the angle selection interface for placing building at angles up? */
- //-------------------------------------------------------------------------------------------------
- Bool InGameUI::isPlacementAnchored( void )
- {
- return m_placeAnchorInProgress;
- } // end isPlacementAnchored
- //-------------------------------------------------------------------------------------------------
- /** Get the start and end anchor points for the building angle selection interface */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::getPlacementPoints( ICoord2D *start, ICoord2D *end )
- {
- if( start )
- *start = m_placeAnchorStart;
- if( end )
- *end = m_placeAnchorEnd;
- } // end getPlacementPoints
- //-------------------------------------------------------------------------------------------------
- /** Return the angle of the drawable at the cursor if any */
- //-------------------------------------------------------------------------------------------------
- Real InGameUI::getPlacementAngle( void )
- {
- if( m_placeIcon[ 0 ] )
- return m_placeIcon[ 0 ]->getOrientation();
- return 0.0f;
- } // end getPlacementAngle
- //-------------------------------------------------------------------------------------------------
- /** Mark given Drawable as "selected". */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::selectDrawable( Drawable *draw )
- {
- if( draw->isSelected() == FALSE )
- {
- m_frameSelectionChanged = TheGameLogic->getFrame();
- // set the selection in the drawable
- draw->friend_setSelected();
- // add to our selected list
- m_selectedDrawables.push_front( draw );
- // we now have one more selected drawable
- incrementSelectCount();
- // evaluate whether our selection consists of exactly one angry mob
- evaluateSoloNexus( draw );
- // the control needs to update its context sensitive display now
- TheControlBar->onDrawableSelected( draw );
- } // end if
- } // end selectDrawable
- //-------------------------------------------------------------------------------------------------
- /** Clear "selected" status of Drawable. */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::deselectDrawable( Drawable *draw )
- {
- if( draw->isSelected() )
- {
- m_frameSelectionChanged = TheGameLogic->getFrame();
- // clear the selected bit out of the drawable
- draw->friend_clearSelected();
- // find the drawable entry in our list
- DrawableListIt findIt = std::find( m_selectedDrawables.begin(),
- m_selectedDrawables.end(),
- draw );
- // sanity
- DEBUG_ASSERTCRASH( findIt != m_selectedDrawables.end(),
- ("deselectDrawable: Drawable not found in the selected drawable list '%s'\n",
- draw->getTemplate()->getName().str()) );
- // remove it from the selected drawable list
- m_selectedDrawables.erase( findIt );
- // keep out own internal count happy
- decrementSelectCount();
- // evaluate whether our selection consists of exactly one angry mob
- evaluateSoloNexus();
- // the control needs to update its context sensitive display now
- TheControlBar->onDrawableDeselected( draw );
- } // end if
- } // end deselectDrawable
- //-------------------------------------------------------------------------------------------------
- /** Clear all drawables' "select" status */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::deselectAllDrawables( Bool postMsg )
- {
- const DrawableList *selected = TheInGameUI->getAllSelectedDrawables();
- // loop through all the selected drawables
- for ( DrawableListCIt it = selected->begin(); it != selected->end(); )
- {
- // get drawable and increment iterator, we will invalidate it as we deselect
- Drawable* draw = *it++;
- // do the deselection
- TheInGameUI->deselectDrawable( draw );
- } // end while
- // keep our list all tidy
- m_selectedDrawables.clear();
- // our selection can no longer consist of exactly one angry mob
- m_soloNexusSelectedDrawableID = INVALID_DRAWABLE_ID;
- ///@todo don't we want to not emit this message if there wasn't a group at all? (CBD)
- /** @todo also, we probably are sending this message too much, we should come up with
- some kind of "selections are dirty" status that we can check once per frame and send
- the correct group info over the network ... could be tricky tho (or impossible) given
- the order of operations of things happening in the code (CBD) */
- if( postMsg )
- {
- GameMessage *groupMsg = TheMessageStream->appendMessage( GameMessage::MSG_DESTROY_SELECTED_GROUP );
- //True deletes entire group.
- groupMsg->appendBooleanArgument( true );
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Return the list of all the currently selected Drawable pointers. */
- //-------------------------------------------------------------------------------------------------
- const DrawableList *InGameUI::getAllSelectedDrawables( void ) const
- {
- return &m_selectedDrawables;
- }
- //-------------------------------------------------------------------------------------------------
- /** Return the list of all the currently selected Drawable pointers. */
- //-------------------------------------------------------------------------------------------------
- const DrawableList *InGameUI::getAllSelectedLocalDrawables( void )
- {
- m_selectedLocalDrawables.clear();
- for (DrawableList::const_iterator it = m_selectedDrawables.begin(); it != m_selectedDrawables.end(); ++it)
- {
- Drawable *draw = (*it);
- if (draw && draw->getObject() && draw->getObject()->isLocallyControlled())
- m_selectedLocalDrawables.push_back( draw );
- }
- return &m_selectedLocalDrawables;
- }
- //-------------------------------------------------------------------------------------------------
- /** Return poiner to the first selected drawable, if any */
- //-------------------------------------------------------------------------------------------------
- Drawable *InGameUI::getFirstSelectedDrawable( void )
- {
- // sanity
- if( m_selectedDrawables.empty() )
- return NULL; // this is valid, nothing is selected
- return m_selectedDrawables.front();
- } // end getFirstSelectedDrawable
- //-------------------------------------------------------------------------------------------------
- /** Return true if the selected ID is in the drawable list */
- //-------------------------------------------------------------------------------------------------
- Bool InGameUI::isDrawableSelected( DrawableID idToCheck ) const
- {
- for( DrawableListCIt it = m_selectedDrawables.begin(); it != m_selectedDrawables.end(); ++it )
- {
- if( (*it)->getID() == idToCheck )
- return TRUE;
- } // end for
- return FALSE;
- } // end isDrawableSelected
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Bool InGameUI::isAnySelectedKindOf( KindOfType kindOf ) const
- {
- Drawable *draw;
- for( DrawableListCIt it = m_selectedDrawables.begin();
- it != m_selectedDrawables.end();
- ++it )
- {
- /** @todo, it seems like we might want to keep a list of drawable pointers so we
- don't have to do this lookup ... it seems "tightly coupled" to me (CBD) */
- // get the drawable from the ID
- draw = *it;
- if( draw && draw->isKindOf( kindOf ) )
- return TRUE;
- } // end for, it
- return FALSE; // no selected objects are of the kind of type
- } // end isAnySelectedKindOf
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Bool InGameUI::isAllSelectedKindOf( KindOfType kindOf ) const
- {
- Drawable *draw;
- for( DrawableListCIt it = m_selectedDrawables.begin();
- it != m_selectedDrawables.end();
- ++it )
- {
- /** @todo, it seems like we might want to keep a list of drawable pointers so we
- don't have to do this lookup ... it seems "tightly coupled" to me (CBD) */
- // get the drawable from the ID
- draw = *it;
- if( draw && draw->isKindOf( kindOf ) == FALSE )
- return FALSE; // not all objects are of the kind of type
- } // end for, it
- return TRUE; // all objects have this kindof bit set in them
- } // end isAllSelectedKindOf
- //-------------------------------------------------------------------------------------------------
- /** Set the input enabled/disabled */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::setInputEnabled( Bool enable )
- {
- if(!enable)
- setSelecting( FALSE );
-
- Bool wasEnabled = m_inputEnabled;
- m_inputEnabled = enable;
-
- if (wasEnabled && !enable)
- {
- /*
- when input is disabled, clear out all the special "modes" we can be in, since we can miss
- the "exit mode" message during the cinematic. e.g., hold down the ctrl key when a cinematic
- begins, then release it during the cinematic... since input is disabled, we never see the keyup
- and thus think we're still in forceattack when its done, until you jiggle that key again.
- (admittedly, this code will actually do the wrong thing if you were to hold down the ctrl
- key thru the whole cinematic, but that's even more unlikely...)
- */
- setForceAttackMode( false ); // CTRL
- setForceMoveMode( false ); // apparently unmapped in current CommandMap.ini
- setWaypointMode( false ); // ALT
- setPreferSelectionMode( false ); // SHIFT
- setCameraRotateLeft( false ); // KP4
- setCameraRotateRight( false ); // KP6
- setCameraZoomIn( false ); // KP8
- setCameraZoomOut( false ); // KP2
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Drawable is being destroyed, clean up any UI elements associated with it. */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::disregardDrawable( Drawable *draw )
- {
- // make sure drawable is no longer selected
- deselectDrawable( draw );
- }
- //-------------------------------------------------------------------------------------------------
- /** This is called after the UI has been drawn. */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::postDraw( void )
- {
- // render our display strings for the messages if on
- if( m_messagesOn )
- {
- Int i, x, y;
- Color dropColor;
- UnsignedByte r, g, b, a;
- x = m_messagePosition.x;
- y = m_messagePosition.y;
- for( i = MAX_UI_MESSAGES - 1; i >= 0; i-- )
- {
- if( m_uiMessages[ i ].displayString )
- {
- // make drop color black, but use the alpha setting of the fill color specified (for fading)
- GameGetColorComponents( m_uiMessages[ i ].color, &r, &g, &b, &a );
- dropColor = GameMakeColor( 0, 0, 0, a );
- // draw the text
- m_uiMessages[ i ].displayString->draw( x, y, m_uiMessages[ i ].color, dropColor );
- // increment text spot to next location
- GameFont *font = m_uiMessages[ i ].displayString->getFont();
- y += font->height;
- } //end if
- } // end for i
- } // end if
- if( m_militarySubtitle )
- {
- ICoord2D pos;
- pos.x = m_militarySubtitle->position.x;
- pos.y = m_militarySubtitle->position.y;
- Color dropColor;
- UnsignedByte r, g, b, a;
- GameGetColorComponents( m_militarySubtitle->color, &r, &g, &b, &a );
- dropColor = GameMakeColor( 0, 0, 0, a );
- for(Int i = 0; i <= m_militarySubtitle->currentDisplayString; i++)
- {
- m_militarySubtitle->displayStrings[i]->draw(pos.x,pos.y, m_militarySubtitle->color,dropColor );
- Int height;
- m_militarySubtitle->displayStrings[i]->getSize(NULL, &height);
- pos.y += height;
- }
- if( m_militarySubtitle->blockDrawn )
- {
- ICoord2D size;
- size.y = m_militarySubtitle->displayStrings[m_militarySubtitle->currentDisplayString]->getFont()->height;
- size.x = size.y * 0.8f;
- TheDisplay->drawFillRect(m_militarySubtitle->blockPos.x, m_militarySubtitle->blockPos.y, size.x, size.y, m_militarySubtitle->color);
- }
- }
- // draw superweapon timers
- // Also responsible for Eva saying "Superweapon is ready for launch"
- // IMPORTANT: Don't bail out of this block early just because you don't
- // want to display the timers -- Eva still needs to be checked
- if (TheGameLogic->getFrame() > 0 )
- {
- // Int superweaponCount = 0;
- Int startX = (Int)(m_superweaponPosition.x * TheDisplay->getWidth());
- Int startY = (Int)(m_superweaponPosition.y * TheDisplay->getHeight());
-
- Int bottomMargin = (Int)( (Real)TheTacticalView->getHeight() * 0.82f );
-
- Bool marginExceeded = FALSE;
- for (Int i=0; i<MAX_PLAYER_COUNT; ++i)
- {
- Color bgColor = GameMakeColor( 0, 0, 0, 255 );
- for (SuperweaponMap::iterator mapIt = m_superweapons[i].begin(); mapIt != m_superweapons[i].end(); ++mapIt)
- {
- AsciiString templateName = mapIt->first;
- for (SuperweaponList::iterator listIt = mapIt->second.begin(); listIt != mapIt->second.end(); ++listIt)
- {
- SuperweaponInfo *info = *listIt;
- DEBUG_ASSERTCRASH(info, ("No superweapon info!"));
- if (info && !info->m_hiddenByScript && !info->m_hiddenByScience)
- {
- //enforce bottom margin of tactical view
- if ( startY >= bottomMargin)
- {
- UnicodeString ellipsis;
- ellipsis.format(L"...");
- info->setText( ellipsis, ellipsis );
- info->setFont( m_superweaponReadyFont, m_superweaponNormalPointSize, m_superweaponNormalBold );
- info->drawTime( startX, startY, m_superweaponFlashColor, bgColor );
-
- marginExceeded = TRUE;
- }
- Object * owningObject = TheGameLogic->findObjectByID(info->m_id);
- if (owningObject)
- {
-
- // We don't draw our timers until we are finished with construction.
- // It is important that let the SpecialPowerUpdate is add its timer in its contructor,,
- // since the science for it could be added before construction is finished,
- // And thus the timer set to READY before the timer is first drawn, here
- if ( owningObject->testStatus( OBJECT_STATUS_UNDER_CONSTRUCTION ))
- continue;
- SpecialPowerModuleInterface *module = owningObject->getSpecialPowerModule(info->getSpecialPowerTemplate());
- if (module)
- {
- // found one - draw it
- Bool isReady = module->isReady();
- Int readySecs;
-
- // IsReady includes disabledness, so if you have a 0 timer disabled super, you don't want
- // the UnsignedInt to wrap around to hundreds of millions of seconds.
- if( module->getReadyFrame() < TheGameLogic->getFrame() )
- readySecs = 0;
- else
- readySecs = (module->getReadyFrame() - TheGameLogic->getFrame()) / LOGICFRAMES_PER_SECOND;
- // Yes, integer math. We can't have float imprecision display 4:01 on a disabled superweapon.
-
- // Only if we actually changed the ready status do we want to play an Eva event.
- if ( isReady && !info->m_evaReadyPlayed )
- {
- if ( TheGameLogic->getFrame() > 0 )
- {
- SpecialPowerType type = module->getSpecialPowerTemplate()->getSpecialPowerType();
-
- Player *localPlayer = ThePlayerList->getLocalPlayer();
-
- if( type == SPECIAL_PARTICLE_UPLINK_CANNON || type == SUPW_SPECIAL_PARTICLE_UPLINK_CANNON || type == LAZR_SPECIAL_PARTICLE_UPLINK_CANNON )
- {
- if ( localPlayer == owningObject->getControllingPlayer() )
- {
- TheEva->setShouldPlay(EVA_SuperweaponReady_Own_ParticleCannon);
- }
- else if ( localPlayer->getRelationship(owningObject->getTeam()) != ENEMIES )
- {
- // Note: counting relationship NEUTRAL as ally. Not sure if this makes a difference???
- TheEva->setShouldPlay(EVA_SuperweaponReady_Ally_ParticleCannon);
- }
- else
- {
- TheEva->setShouldPlay(EVA_SuperweaponReady_Enemy_ParticleCannon);
- }
- }
- else if( type == SPECIAL_NEUTRON_MISSILE || type == NUKE_SPECIAL_NEUTRON_MISSILE || type == SUPW_SPECIAL_NEUTRON_MISSILE )
- {
- if ( localPlayer == owningObject->getControllingPlayer() )
- {
- TheEva->setShouldPlay(EVA_SuperweaponReady_Own_Nuke);
- }
- else if ( localPlayer->getRelationship(owningObject->getTeam()) != ENEMIES )
- {
- // Note: counting relationship NEUTRAL as ally. Not sure if this makes a difference???
- TheEva->setShouldPlay(EVA_SuperweaponReady_Ally_Nuke);
- }
- else
- {
- TheEva->setShouldPlay(EVA_SuperweaponReady_Enemy_Nuke);
- }
- }
- else if (type == SPECIAL_SCUD_STORM)
- {
- if ( localPlayer == owningObject->getControllingPlayer() )
- {
- TheEva->setShouldPlay(EVA_SuperweaponReady_Own_ScudStorm);
- }
- else if ( localPlayer->getRelationship(owningObject->getTeam()) != ENEMIES )
- {
- // Note: counting relationship NEUTRAL as ally. Not sure if this makes a difference???
- TheEva->setShouldPlay(EVA_SuperweaponReady_Ally_ScudStorm);
- }
- else
- {
- TheEva->setShouldPlay(EVA_SuperweaponReady_Enemy_ScudStorm);
- }
- }
- }
- info->m_evaReadyPlayed = true;
- }
- else
- {
- if ( !isReady )
- info->m_evaReadyPlayed = false; // Reset Eva for next time
- }
-
- // draw the text
- if ( !m_superweaponHiddenByScript && !marginExceeded )
- {
- // Similarly, only checking timers is not truly indicitive of readyness.
- Bool changeBolding = (readySecs != info->m_timestamp) || (isReady != info->m_ready) || info->m_forceUpdateText;
- if (changeBolding)
- {
- if (isReady)
- {
- // go bold - we're good to go
- info->setFont( m_superweaponReadyFont, m_superweaponReadyPointSize, m_superweaponReadyBold );
- }
- else
- {
- // if we were at 0, we've just fired - kill the bold
- if (info->m_timestamp == 0)
- {
- info->setFont( m_superweaponNormalFont, m_superweaponNormalPointSize, m_superweaponNormalBold );
- }
- }
-
-
- info->m_forceUpdateText = false;
- info->m_ready = isReady;
- info->m_timestamp = readySecs;
- Int min = readySecs/60;
- Int sec = readySecs - min*60;
- AsciiString strIndex;
- strIndex.format("GUI:%s", templateName.str());
- UnicodeString name, time;
- name.format(L"%ls: ", TheGameText->fetch(strIndex.str()).str());
- time.format(L"%d:%2.2d", min, sec);
- info->setText(name, time);
- }
- if (isReady)
- {
- if ( m_superweaponFlashDuration != 0.0f )
- {
- if ( TheGameLogic->getFrame() >= m_superweaponLastFlashFrame + (Int)(m_superweaponFlashDuration) )
- {
- m_superweaponUsedFlashColor = !m_superweaponUsedFlashColor;
- m_superweaponLastFlashFrame = TheGameLogic->getFrame();
- }
- info->drawName( startX,
- startY, (m_superweaponUsedFlashColor)?0:m_superweaponFlashColor, bgColor );
- info->drawTime( startX,
- startY, (m_superweaponUsedFlashColor)?0:m_superweaponFlashColor, bgColor );
- }
- else
- {
- info->drawName( startX, startY, 0, bgColor );
- info->drawTime( startX, startY, 0, bgColor );
- }
- }
- else
- {
- info->drawName( startX, startY, 0, bgColor );
- info->drawTime( startX, startY, 0, bgColor );
- }
- // increment text spot to next location
- startY += info->getHeight();
- }
- if (info->getSpecialPowerTemplate()->isSharedNSync())
- break; // Wow, it is almost too easy!
- // This prevents redundant timers for shared powers/superweapons
- // No matter how many specialpowermodules register their timers with me,
- // I will only draw the timer of the first valid one in my list,
- // since they all have the same template, ans they all
- // use the Player::getReadyFrame() functions to stay in sync.
- }
- }
- }
- }
- }
- }
- }
- // draw named timers
- if (TheGameLogic->getFrame() > 0 && m_showNamedTimers)
- {
- // Int namedTimerCount = 0;
- Bool reverseXDir = (m_namedTimerPosition.x >= 0.5f);
- Int startX = (Int)(m_namedTimerPosition.x * TheDisplay->getWidth());
- Int startY = (Int)(m_namedTimerPosition.y * TheDisplay->getHeight());
- Color bgColor = GameMakeColor( 0, 0, 0, 255 );
- for (NamedTimerMapIt mapIt = m_namedTimers.begin(); mapIt != m_namedTimers.end(); ++mapIt)
- {
- AsciiString timerName = mapIt->first;
- NamedTimerInfo *info = mapIt->second;
- DEBUG_ASSERTCRASH(info, ("No namedTimer info!"));
- if (info)
- {
- // found one - draw it
- UnicodeString line;
- Int framesLeft = TheScriptEngine->getCounter(timerName)->value;
- UnsignedInt readyFrame = TheGameLogic->getFrame();
- if (framesLeft > 0)
- readyFrame += framesLeft;
- Int readySecs = (Int)(SECONDS_PER_LOGICFRAME_REAL * (readyFrame - TheGameLogic->getFrame()));
- if ( (info->isCountdown && readySecs != info->timestamp) || (!info->isCountdown && framesLeft != info->timestamp) )
- {
- if (!readySecs && info->isCountdown)
- {
- // go bold - we're good to go
- info->displayString->setFont( TheFontLibrary->getFont( m_namedTimerReadyFont,
- TheGlobalLanguageData->adjustFontSize(m_namedTimerReadyPointSize), m_namedTimerReadyBold ) );
- }
- else
- {
- // if we were at 0, we've just fired - kill the bold
- if (info->timestamp == 0 || info->isCountdown)
- {
- info->displayString->setFont( TheFontLibrary->getFont( m_namedTimerNormalFont,
- TheGlobalLanguageData->adjustFontSize(m_namedTimerNormalPointSize), m_namedTimerNormalBold ) );
- }
- }
- info->timestamp = readySecs;
- Int min = readySecs/60;
- Int sec = readySecs - min*60;
-
- if (!info->isCountdown)
- line.format(L"%s %d", info->timerText.str(), framesLeft);
- else
- {
- if (sec >= 10)
- line.format(L"%s %d:%d", info->timerText.str(), min, sec);
- else
- line.format(L"%s %d:0%d", info->timerText.str(), min, sec);
- }
- info->displayString->setText(line);
- }
- // draw the text
- Int drawX = startX;
- if (reverseXDir)
- drawX -= info->displayString->getWidth();
- if (!readySecs && info->isCountdown)
- {
- if ( m_namedTimerFlashDuration != 0.0f )
- {
- if ( TheGameLogic->getFrame() >= m_namedTimerLastFlashFrame + (Int)(m_namedTimerFlashDuration) )
- {
- m_namedTimerUsedFlashColor = !m_namedTimerUsedFlashColor;
- m_namedTimerLastFlashFrame = TheGameLogic->getFrame();
- }
- info->displayString->draw( drawX, startY, (m_namedTimerUsedFlashColor)?info->color:m_namedTimerFlashColor, bgColor );
- }
- else
- {
- info->displayString->draw( drawX, startY, info->color, bgColor );
- }
- }
- else
- {
- info->displayString->draw( drawX, startY, info->color, bgColor );
- }
- // increment text spot to next location
- startY -= info->displayString->getFont()->height;
- }
- }
- }
-
- // draw RMB scroll anchor
- if (TheLookAtTranslator && m_drawRMBScrollAnchor)
- {
- const ICoord2D* anchor = TheLookAtTranslator->getRMBScrollAnchor();
- if (anchor)
- {
- static const Int w = 2;
- static const Int h = 2;
- static const Int r = 4; // ratio
- static const Color mainColor = GameMakeColor(0, 255, 0, 255);
- static const Color dropColor = GameMakeColor(0, 0, 0, 255);
- TheDisplay->drawFillRect( anchor->x-w*r-1, anchor->y-h-1, w*2*r+3, h*2+3, dropColor );
- TheDisplay->drawFillRect( anchor->x-w-1, anchor->y-h*r-1, w*2+3, h*2*r+3, dropColor );
- TheDisplay->drawFillRect( anchor->x-w*r, anchor->y-h, w*2*r+1, h*2+1, mainColor );
- TheDisplay->drawFillRect( anchor->x-w, anchor->y-h*r, w*2+1, h*2*r+1, mainColor );
- }
- }
- //draw superweapon ready multipliers
- TheControlBar->drawSpecialPowerShortcutMultiplierText();
- } // end postDraw
- //-------------------------------------------------------------------------------------------------
- /** Expire a hint of the specified type with the corresponding hint index */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::expireHint( HintType type, UnsignedInt hintIndex )
- {
- if( type == MOVE_HINT )
- {
- // sanity
- if( hintIndex < 0 || hintIndex >= MAX_MOVE_HINTS )
- return;
- m_moveHint[ hintIndex ].sourceID = 0;
- m_moveHint[ hintIndex ].frame = 0;
- } // end if
- else
- {
- // undefined hint type
- DEBUG_CRASH(("undefined hint type"));
- return;
- } // end else
- } // end expireHint
- //-------------------------------------------------------------------------------------------------
- /** Create the control user interface GUI */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::createControlBar( void )
- {
- TheWindowManager->winCreateFromScript( AsciiString("ControlBar.wnd") );
- HideControlBar();
- /*
- // hide all windows created from this layout
- GameWindow *window = TheWindowManager->winGetWindowList();
- for( ; window; window = window->winGetPrev() )
- window->winHide( TRUE );
- */
- } // end createControlBar
- //-------------------------------------------------------------------------------------------------
- /** Create the replay control GUI */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::createReplayControl( void )
- {
- m_replayWindow = TheWindowManager->winCreateFromScript( AsciiString("ReplayControl.wnd") );
- /*
- // hide all windows created from this layout
- GameWindow *window = TheWindowManager->winGetWindowList();
- for( ; window; window = window->winGetPrev() )
- window->winHide( TRUE );
- */
- } // end createReplayControl
- // ------------------------------------------------------------------------------------------------
- // InGameUI::playMovie
- // ------------------------------------------------------------------------------------------------
- void InGameUI::playMovie( const AsciiString& movieName )
- {
- stopMovie();
- m_videoStream = TheVideoPlayer->open( movieName );
- if ( m_videoStream == NULL )
- {
- return;
- }
- m_currentlyPlayingMovie = movieName;
- m_videoBuffer = TheDisplay->createVideoBuffer();
- if ( m_videoBuffer == NULL ||
- !m_videoBuffer->allocate( m_videoStream->width(),
- m_videoStream->height())
- )
- {
- stopMovie();
- return;
- }
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::stopMovie( void )
- {
- delete m_videoBuffer;
- m_videoBuffer = NULL;
- if ( m_videoStream )
- {
- m_videoStream->close();
- m_videoStream = NULL;
- }
- if (!m_currentlyPlayingMovie.isEmpty()) {
- //TheScriptEngine->notifyOfCompletedVideo(m_currentlyPlayingMovie); // removing sync error source -MDC
- m_currentlyPlayingMovie = AsciiString::TheEmptyString;
- }
- }
- // ------------------------------------------------------------------------------------------------
- // InGameUI::videoBuffer
- // ------------------------------------------------------------------------------------------------
- VideoBuffer* InGameUI::videoBuffer( void )
- {
- return m_videoBuffer;
- }
- // ------------------------------------------------------------------------------------------------
- // InGameUI::playMovie
- // ------------------------------------------------------------------------------------------------
- void InGameUI::playCameoMovie( const AsciiString& movieName )
- {
- stopCameoMovie();
- m_cameoVideoStream = TheVideoPlayer->open( movieName );
- if ( m_cameoVideoStream == NULL )
- {
- return;
- }
- m_cameoVideoBuffer = TheDisplay->createVideoBuffer();
- if ( m_cameoVideoBuffer == NULL ||
- !m_cameoVideoBuffer->allocate( m_cameoVideoStream->width(),
- m_cameoVideoStream->height())
- )
- {
- stopCameoMovie();
- return;
- }
- GameWindow *window = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey( AsciiString("ControlBar.wnd:RightHUD") ));
- WinInstanceData *winData = window->winGetInstanceData();
- winData->setVideoBuffer(m_cameoVideoBuffer);
- // window->winHide(FALSE);
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void InGameUI::stopCameoMovie( void )
- {
- //RightHUD
- //GameWindow *window = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey( AsciiString("ControlBar.wnd:CameoMovieWindow") ));
- GameWindow *window = TheWindowManager->winGetWindowFromId(NULL,TheNameKeyGenerator->nameToKey( AsciiString("ControlBar.wnd:RightHUD") ));
- // window->winHide(FALSE);
- WinInstanceData *winData = window->winGetInstanceData();
- winData->setVideoBuffer(NULL);
-
- delete m_cameoVideoBuffer;
- m_cameoVideoBuffer = NULL;
- if ( m_cameoVideoStream )
- {
- m_cameoVideoStream->close();
- m_cameoVideoStream = NULL;
- }
-
- }
- // ------------------------------------------------------------------------------------------------
- // InGameUI::videoBuffer
- // ------------------------------------------------------------------------------------------------
- VideoBuffer* InGameUI::cameoVideoBuffer( void )
- {
- return m_cameoVideoBuffer;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void InGameUI::displayCantBuildMessage( LegalBuildCode lbc )
- {
- switch( lbc )
- {
- //---------------------------------------------------------------------------------------------
- case LBC_RESTRICTED_TERRAIN:
- TheInGameUI->message( "GUI:CantBuildRestrictedTerrain" );
- break;
- //---------------------------------------------------------------------------------------------
- case LBC_NOT_FLAT_ENOUGH:
- TheInGameUI->message( "GUI:CantBuildNotFlatEnough" );
- break;
- //---------------------------------------------------------------------------------------------
- case LBC_OBJECTS_IN_THE_WAY:
- TheInGameUI->message( "GUI:CantBuildObjectsInTheWay" );
- break;
- //---------------------------------------------------------------------------------------------
- case LBC_TOO_CLOSE_TO_SUPPLIES:
- TheInGameUI->message( "GUI:CantBuildTooCloseToSupplies" );
- break;
- //---------------------------------------------------------------------------------------------
- case LBC_NO_CLEAR_PATH:
- TheInGameUI->message( "GUI:CantBuildNoClearPath" );
- break;
- //---------------------------------------------------------------------------------------------
- case LBC_SHROUD:
- TheInGameUI->message( "GUI:CantBuildShroud" );
- break;
- //---------------------------------------------------------------------------------------------
- case LBC_GENERIC_FAILURE:
- default:
- TheInGameUI->message( "GUI:CantBuildThere" );
- break;
- } // end switch
- } // end displayCantBuildMessage
- // ------------------------------------------------------------------------------------------------
- // InGameUI::militarySubtitle
- // ------------------------------------------------------------------------------------------------
- void InGameUI::militarySubtitle( const AsciiString& label, Int duration )
- {
- // make sure we don't already have a subtitle up there
- removeMilitarySubtitle();
- // update our history
- UpdateDiplomacyBriefingText(label, FALSE);
- UnicodeString title = TheGameText->fetch(label);
- // make sure we actually will be displaying something
- if( title.isEmpty() || duration <= 0)
- {
- DEBUG_CRASH(("Trying to create a military subtitle but either title is empty (%ls) or duration is <= 0 (%d)",title.str(), duration));
- return;
- }
- // we need some frame info to set our timings
- UnsignedInt currLogicFrame = TheGameLogic->getFrame();
- const int messageTimeout = currLogicFrame + (Int)(((Real)LOGICFRAMES_PER_SECOND * duration)/1000.0f);
- // disable tooltips until this frame, cause we don't want to collide with the military subtitles.
- TheInGameUI->disableTooltipsUntil(messageTimeout);
-
- // calculate where this screen position should be since the position being passed in is based off 8x6
- Coord2D multiplier;
- multiplier.x = (float)TheDisplay->getWidth() / 800.0f;
- multiplier.y = (float)TheDisplay->getHeight() / 600.0f;
-
- // lets bring out the data structure!
- m_militarySubtitle = NEW MilitarySubtitleData;
- m_militarySubtitle->subtitle.set(title);
- m_militarySubtitle->blockDrawn = TRUE;
- m_militarySubtitle->blockBeginFrame = currLogicFrame;
- m_militarySubtitle->lifetime = messageTimeout;
- m_militarySubtitle->blockPos.x = m_militarySubtitle->position.x = m_militaryCaptionPosition.x * multiplier.x;
- m_militarySubtitle->blockPos.y = m_militarySubtitle->position.y = m_militaryCaptionPosition.y * multiplier.y;
- m_militarySubtitle->incrementOnFrame = currLogicFrame + (Int)(((Real)LOGICFRAMES_PER_SECOND * TheGlobalLanguageData->m_militaryCaptionDelayMS)/1000.0f);
- m_militarySubtitle->index = 0;
- for (int i = 1; i < MAX_SUBTITLE_LINES; i ++)
- m_militarySubtitle->displayStrings[i] = NULL;
- m_militarySubtitle->currentDisplayString = 0;
- m_militarySubtitle->displayStrings[0] = TheDisplayStringManager->newDisplayString();
- m_militarySubtitle->displayStrings[0]->reset();
- m_militarySubtitle->displayStrings[0]->setFont( TheFontLibrary->getFont( m_militaryCaptionTitleFont,
- TheGlobalLanguageData->adjustFontSize(m_militaryCaptionTitlePointSize), m_militaryCaptionTitleBold ) );
- m_militarySubtitle->color = GameMakeColor(m_militaryCaptionColor.red, m_militaryCaptionColor.green, m_militaryCaptionColor.blue, m_militaryCaptionColor.alpha);
- }
- // ------------------------------------------------------------------------------------------------
- // InGameUI::removeMilitarySubtitle
- // ------------------------------------------------------------------------------------------------
- void InGameUI::removeMilitarySubtitle( void )
- {
- // sanity (is there really such a thing in this world?)
- if(!m_militarySubtitle)
- return;
- TheInGameUI->clearTooltipsDisabled();
- // loop through and free up the display strings
- for(Int i = 0; i <= m_militarySubtitle->currentDisplayString; i ++)
- {
- TheDisplayStringManager->freeDisplayString(m_militarySubtitle->displayStrings[i]);
- m_militarySubtitle->displayStrings[i] = NULL;
- }
- //delete it man!
- delete m_militarySubtitle;
- m_militarySubtitle= NULL;
- }
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- Bool InGameUI::areSelectedObjectsControllable() const
- {
- const DrawableList *selected = TheInGameUI->getAllSelectedDrawables();
- // loop through all the selected drawables
- const Drawable *draw;
- for( DrawableListCIt it = selected->begin(); it != selected->end(); ++it )
- {
- // get this drawable
- draw = *it;
- // All selected objects will have the same local controller, so
- // simply return the first one.
- return draw->getObject()->isLocallyControlled();
- }
- // Nothing selected...
- return FALSE;
- }
- //------------------------------------------------------------------------------
- //Resets the camera to default zoom and orientation.
- //------------------------------------------------------------------------------
- void InGameUI::resetCamera()
- {
- ViewLocation currentView;
- TheTacticalView->getLocation( ¤tView );
- TheTacticalView->resetCamera( ¤tView.getPosition(), 1, 0.0f, 0.0f );
- }
- //------------------------------------------------------------------------------
- //Checks to see if an object can interact with an object in a non-hostile manner. This is currently used by the selection
- //translator to determine whether to do something to an object or select it instead based on the context of what is currently
- //selected.
- //------------------------------------------------------------------------------
- Bool InGameUI::canSelectedObjectsNonAttackInteractWithObject( const Object *objectToInteractWith, SelectionRules rule ) const
- {
- for( int i = 1; i < NUM_ACTIONTYPES; i++ )
- {
- if( i != ACTIONTYPE_ATTACK_OBJECT )
- {
- if( canSelectedObjectsDoAction( (ActionType)i, objectToInteractWith, rule ) )
- {
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- CanAttackResult InGameUI::getCanSelectedObjectsAttack( ActionType action, const Object *objectToInteractWith, SelectionRules rule, Bool additionalChecking ) const
- {
- //Kris: Aug 16, 2003
- //John McDonald added this code back in Oct 09, 2002.
- //Replaced it with palatable code.
- //if( (objectToInteractWith == NULL) != (action == ACTIONTYPE_SET_RALLY_POINT)) <---BAD CODE
- if( !objectToInteractWith && action != ACTIONTYPE_SET_RALLY_POINT || //No object to interact with (and not rally point mode)
- objectToInteractWith && action == ACTIONTYPE_SET_RALLY_POINT ) //Object to interact with (and rally point mode)
- {
- //Sanity check OR can't set a rally point over an object.
- return ATTACKRESULT_NOT_POSSIBLE;
- }
- // get selected list of drawables
- const DrawableList *selected = TheInGameUI->getAllSelectedDrawables();
- // set up counters for rule checking
- Int count = 0;
- CanAttackResult bestResult = ATTACKRESULT_NOT_POSSIBLE;
- CanAttackResult worstResult = ATTACKRESULT_POSSIBLE;
- // loop through all the selected drawables
- Drawable *other;
- for( DrawableListCIt it = selected->begin(); it != selected->end(); ++it )
- {
-
- // get this drawable
- other = *it;
- count++;
- switch( action )
- {
- case ACTIONTYPE_ATTACK_OBJECT:
- {
- //additionalChecking is TRUE only if force attack mode is on.
- CanAttackResult result = TheActionManager->getCanAttackObject( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER,
- additionalChecking ? ATTACK_NEW_TARGET_FORCED : ATTACK_NEW_TARGET );
- if( result > bestResult )
- {
- //Best result is used for the rule: SELECTION_ANY
- bestResult = result;
- }
- if( result < worstResult )
- {
- //Worst result is used for the rule: SELECTION_ALL
- worstResult = result;
- }
- break;
- }
- case ACTIONTYPE_NONE:
- case ACTIONTYPE_GET_REPAIRED_AT:
- case ACTIONTYPE_DOCK_AT:
- case ACTIONTYPE_GET_HEALED_AT:
- case ACTIONTYPE_REPAIR_OBJECT:
- case ACTIONTYPE_RESUME_CONSTRUCTION:
- case ACTIONTYPE_COMBATDROP_INTO:
- case ACTIONTYPE_ENTER_OBJECT:
- case ACTIONTYPE_HIJACK_VEHICLE:
- case ACTIONTYPE_SABOTAGE_BUILDING:
- case ACTIONTYPE_CONVERT_OBJECT_TO_CARBOMB:
- case ACTIONTYPE_CAPTURE_BUILDING:
- case ACTIONTYPE_DISABLE_VEHICLE_VIA_HACKING:
- #ifdef ALLOW_SURRENDER
- case ACTIONTYPE_PICK_UP_PRISONER:
- #endif
- case ACTIONTYPE_STEAL_CASH_VIA_HACKING:
- case ACTIONTYPE_DISABLE_BUILDING_VIA_HACKING:
- case ACTIONTYPE_MAKE_DEFECTOR:
- case ACTIONTYPE_SET_RALLY_POINT:
- default:
- DEBUG_CRASH( ("Called InGameUI::getCanSelectedObjectsAttack() with actiontype %d. Only accepts attack types! Should you be calling InGameUI::canSelectedObjectsDoAction() instead?") );
- return ATTACKRESULT_INVALID_SHOT;
- }
- } // end for
- if( count > 0 )
- {
- if( rule == SELECTION_ANY )
- {
- return bestResult;
- }
- return worstResult;
- }
- // no can do!
- return ATTACKRESULT_NOT_POSSIBLE;
- }
- //------------------------------------------------------------------------------
- //Wrapper function that checks a specific action.
- //------------------------------------------------------------------------------
- Bool InGameUI::canSelectedObjectsDoAction( ActionType action, const Object *objectToInteractWith, SelectionRules rule, Bool additionalChecking ) const
- {
- //Kris: Aug 16, 2003
- //John McDonald added this code back in Oct 09, 2002. This code is SO wrong that it should
- //be a firing offense. Strangely enough, this code has gone unnoticed for nearly a year
- //and nearly two projects. I'm fixing this now by moving it to the rally point code...
- //because it would be nice if a saboteur could actually sabotage a building via a
- //commandbutton.
- //if( (objectToInteractWith == NULL) != (action == ACTIONTYPE_SET_RALLY_POINT))
- if( !objectToInteractWith && action != ACTIONTYPE_SET_RALLY_POINT || //No object to interact with (and not rally point mode)
- objectToInteractWith && action == ACTIONTYPE_SET_RALLY_POINT ) //Object to interact with (and rally point mode)
- {
- //Sanity check OR can't set a rally point over an object.
- return FALSE;
- }
- // get selected list of drawables
- const DrawableList *selected = TheInGameUI->getAllSelectedDrawables();
- // set up counters for rule checking
- Int count = 0;
- Int qualify = 0;
- // loop through all the selected drawables
- Drawable *other;
- for( DrawableListCIt it = selected->begin(); it != selected->end(); ++it )
- {
-
- // get this drawable
- other = *it;
- count++;
- Bool success = FALSE;
- switch( action )
- {
- case ACTIONTYPE_NONE:
- //However strange this might be, it is always possible to do "nothing"
- //although I can't think of why this would be needed...
- return TRUE;
- case ACTIONTYPE_GET_REPAIRED_AT:
- success = TheActionManager->canGetRepairedAt( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_DOCK_AT:
- success = TheActionManager->canDockAt( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_GET_HEALED_AT:
- success = TheActionManager->canGetHealedAt( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- if( success )
- {
- ContainModuleInterface *contain = objectToInteractWith->getContain();
- if( contain && contain->isHealContain() )
- {
- //This container is only used for the purposes of healing and we cannot
- //enter it normally -- this is NOT a transport!
- success = false;
- }
- }
- break;
- case ACTIONTYPE_REPAIR_OBJECT:
- {
- ObjectID currentRepairer = objectToInteractWith->getSoleHealingBenefactor();
- success = ( TheActionManager->canRepairObject( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER )
- && ( currentRepairer == INVALID_ID || currentRepairer == other->getObject()->getID() ) );
- // unless someone else is already healing it...
- // please note that this add'l test is left out of canRepairObject() since canRepairObject
- // gets called from within the Dozer/WorkerAIUpdates' stateMachines as they continue the repair process.
- // This remains true.
- break;
- }
- case ACTIONTYPE_RESUME_CONSTRUCTION:
- success = TheActionManager->canResumeConstructionOf( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_COMBATDROP_INTO:
- success = TheActionManager->canEnterObject( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER, COMBATDROP_INTO );
- break;
- case ACTIONTYPE_ENTER_OBJECT:
- //additionalChecking is TRUE only if we want to check if transport is full first.
- success = TheActionManager->canEnterObject( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER, additionalChecking ? CHECK_CAPACITY : DONT_CHECK_CAPACITY );
- break;
- case ACTIONTYPE_ATTACK_OBJECT:
- DEBUG_CRASH( ("Called InGameUI::canSelectedObjectsDoAction() with ACTIONTYPE_ATTACK_OBJECT. You must use InGameUI::getCanSelectedObjectsAttack() instead.") );
- return FALSE;
- case ACTIONTYPE_HIJACK_VEHICLE:
- success = TheActionManager->canHijackVehicle( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_SABOTAGE_BUILDING:
- success = TheActionManager->canSabotageBuilding( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_CONVERT_OBJECT_TO_CARBOMB:
- success = TheActionManager->canConvertObjectToCarBomb( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_CAPTURE_BUILDING:
- success = TheActionManager->canCaptureBuilding( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_DISABLE_VEHICLE_VIA_HACKING:
- success = TheActionManager->canDisableVehicleViaHacking( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- #ifdef ALLOW_SURRENDER
- case ACTIONTYPE_PICK_UP_PRISONER:
- success = TheActionManager->canPickUpPrisoner( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- #endif
- case ACTIONTYPE_STEAL_CASH_VIA_HACKING:
- success = TheActionManager->canStealCashViaHacking( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_DISABLE_BUILDING_VIA_HACKING:
- success = TheActionManager->canDisableBuildingViaHacking( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_MAKE_DEFECTOR:
- success = TheActionManager->canMakeObjectDefector( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER );
- break;
- case ACTIONTYPE_SET_RALLY_POINT:
- {
- Object *obj = other->getObject();
- if (!obj) {
- success = false;
- break;
- }
- success = (obj->isKindOf(KINDOF_AUTO_RALLYPOINT) && obj->isLocallyControlled());
- break;
- }
- }
- if( success )
- {
- if( rule == SELECTION_ANY )
- {
- return TRUE;
- }
- ++qualify;
- }
- } // end for
- //If the rule is all must qualify, do the check now and return success
- //only if all the selected units qualified.
- if( rule == SELECTION_ALL && count > 0 && qualify == count )
- {
- return TRUE;
- }
- // no can do!
- return FALSE;
- }
- //------------------------------------------------------------------------------
- Bool InGameUI::canSelectedObjectsDoSpecialPower( const CommandButton *command, const Object *objectToInteractWith, const Coord3D *position, SelectionRules rule, UnsignedInt commandOptions, Object* ignoreSelObj ) const
- {
- //Get the special power template.
- const SpecialPowerTemplate *spTemplate = command->getSpecialPowerTemplate();
- //Order of precendence:
- //1) NO TARGET OR POS
- //2) COMMAND_OPTION_NEED_OBJECT_TARGET
- //3) NEED_TARGET_POS
- Bool doAtPosition = BitTest( command->getOptions(), NEED_TARGET_POS );
- Bool doAtObject = BitTest( command->getOptions(), COMMAND_OPTION_NEED_OBJECT_TARGET );
- //Sanity checks
- if( doAtObject && !objectToInteractWith )
- {
- return false;
- }
- if( doAtPosition && !position )
- {
- return false;
- }
- // get selected list of drawables
- Drawable* ignoreSelDraw = ignoreSelObj ? ignoreSelObj->getDrawable() : NULL;
- DrawableList tmpList;
- if (ignoreSelDraw)
- tmpList.push_back(ignoreSelDraw);
- const DrawableList* selected = (tmpList.size() > 0) ? &tmpList : TheInGameUI->getAllSelectedDrawables();
- // set up counters for rule checking
- Int count = 0;
- Int qualify = 0;
- // loop through all the selected drawables
- for( DrawableListCIt it = selected->begin(); it != selected->end(); ++it )
- {
-
- // get this drawable
- Drawable* other = *it;
- count++;
- if( !doAtObject && !doAtPosition )
- {
- if( TheActionManager->canDoSpecialPower( other->getObject(), spTemplate, CMD_FROM_PLAYER, commandOptions ) )
- {
- //This is the no target version
- if( rule == SELECTION_ANY )
- {
- return true;
- }
- qualify++;
- }
- }
- else if( doAtObject )
- {
- if( TheActionManager->canDoSpecialPowerAtObject( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER, spTemplate, commandOptions ) )
- {
- //This requires a object target
- if( rule == SELECTION_ANY )
- {
- return true;
- }
- qualify++;
- }
- }
- else if( doAtPosition )
- {
- if( TheActionManager->canDoSpecialPowerAtLocation( other->getObject(), position, CMD_FROM_PLAYER, spTemplate, objectToInteractWith, commandOptions ) )
- {
- //This requires a valid location.
- if( rule == SELECTION_ANY )
- {
- return true;
- }
- qualify++;
- }
- }
- }
- if( rule == SELECTION_ALL && count > 0 && qualify == count )
- {
- return true;
- }
- return false;
- }
- //------------------------------------------------------------------------------
- Bool InGameUI::canSelectedObjectsOverrideSpecialPowerDestination( const Coord3D *loc, SelectionRules rule, SpecialPowerType spType ) const
- {
- // set up counters for rule checking
- Int count = 0;
- Int qualify = 0;
- // get selected list of drawables
- const DrawableList *selected = TheInGameUI->getAllSelectedDrawables();
- // loop through all the selected drawables
- Drawable *other;
- for( DrawableListCIt it = selected->begin(); it != selected->end(); ++it )
- {
-
- // get this drawable
- other = *it;
- count++;
- if( TheActionManager->canOverrideSpecialPowerDestination( other->getObject(), loc, spType, CMD_FROM_PLAYER ) )
- {
- if( rule == SELECTION_ANY )
- {
- return true;
- }
- qualify++;
- }
- }
- if( rule == SELECTION_ALL && count > 0 && qualify == count )
- {
- return true;
- }
- return false;
- }
- //------------------------------------------------------------------------------
- Bool InGameUI::canSelectedObjectsEffectivelyUseWeapon( const CommandButton *command, const Object *objectToInteractWith, const Coord3D *position, SelectionRules rule ) const
- {
- //Get the special power template.
- WeaponSlotType slot = command->getWeaponSlot();
- //Order of precendence:
- //1) NO TARGET OR POS
- //2) COMMAND_OPTION_NEED_OBJECT_TARGET
- //3) NEED_TARGET_POS
- Bool doAtPosition = BitTest( command->getOptions(), NEED_TARGET_POS );
- Bool doAtObject = BitTest( command->getOptions(), COMMAND_OPTION_NEED_OBJECT_TARGET );
- //Sanity checks
- if( doAtObject && !objectToInteractWith )
- {
- return false;
- }
- if( doAtPosition && !position )
- {
- return false;
- }
- // get selected list of drawables
- const DrawableList *selected = TheInGameUI->getAllSelectedDrawables();
- // set up counters for rule checking
- Int count = 0;
- Int qualify = 0;
- // loop through all the selected drawables
- Drawable *other;
- for( DrawableListCIt it = selected->begin(); it != selected->end(); ++it )
- {
-
- // get this drawable
- other = *it;
- count++;
- if( !doAtObject && !doAtPosition )
- {
- if( TheActionManager->canFireWeapon( other->getObject(), slot, CMD_FROM_PLAYER ) )
- {
- //This is the no target version
- if( rule == SELECTION_ANY )
- {
- return true;
- }
- qualify++;
- }
- }
- else if( doAtObject )
- {
- if( TheActionManager->canFireWeaponAtObject( other->getObject(), objectToInteractWith, CMD_FROM_PLAYER, slot ) )
- {
- //This requires a object target
- if( rule == SELECTION_ANY )
- {
- return true;
- }
- qualify++;
- }
- }
- else if( doAtPosition )
- {
- if( TheActionManager->canFireWeaponAtLocation( other->getObject(), position, CMD_FROM_PLAYER, slot, objectToInteractWith ) )
- {
- //This requires a valid location.
- if( rule == SELECTION_ANY )
- {
- return true;
- }
- qualify++;
- }
- }
- }
- if( rule == SELECTION_ALL && count > 0 && qualify == count )
- {
- return true;
- }
- return false;
- }
- // ------------------------------------------------------------------------------------------------
- Int InGameUI::selectAllUnitsByTypeAcrossRegion( IRegion2D *region, KindOfMaskType mustBeSet, KindOfMaskType mustBeClear )
- {
- KindOfSelectionData data;
- Int newSelectionCount = 0;
- Int oldSelectionCount = getAllSelectedDrawables()->size();
- data.m_mustbeSet = mustBeSet;
- data.m_mustbeClear = mustBeClear;
- if (region)
- {
- TheTacticalView->iterateDrawablesInRegion(region, kindOfUnitSelection, (void *)&data);
- newSelectionCount += data.newlySelectedDrawables.size();
- }
- else
- {
- // loop over the map
- Drawable *temp = TheGameClient->firstDrawable();
- while( temp )
- {
- if( kindOfUnitSelection( temp, (void *)&data) )
- {
- newSelectionCount ++;
- }
- temp = temp->getNextDrawable();
- }
- }
- setDisplayedMaxWarning( FALSE );
- if (newSelectionCount > 0)
- {
- // create selected message
- GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP );
- teamMsg->appendBooleanArgument( (oldSelectionCount == 0) ? TRUE : FALSE );
- const Drawable *draw;
- //Loop through each drawable add append it's objectID to the event.
- for( DrawableListCIt it = data.newlySelectedDrawables.begin(); it != data.newlySelectedDrawables.end(); ++it )
- {
- draw = *it;
- if( draw && draw->getObject() )
- {
- teamMsg->appendObjectIDArgument( draw->getObject()->getID() );
- }
- }
- }
- return newSelectionCount;
- }
- // ------------------------------------------------------------------------------------------------
- /** Selects maching units on the screen */
- // ------------------------------------------------------------------------------------------------
- Int InGameUI::selectMatchingAcrossRegion( IRegion2D *region )
- {
- const DrawableList *selected = getAllSelectedDrawables();
- /* loop through all the selected drawables and create a set of all the objects,
- so that you only iterate once through each type of object
- */
- const Drawable *draw;
- //std::set<AsciiString> drawableList;
- std::set<const ThingTemplate*> drawableList;
- Bool carBomb = FALSE;
-
- for( DrawableListCIt it = selected->begin(); it != selected->end(); ++it )
- {
- // get this drawable
- draw = *it;
- if( draw && draw->getObject() && draw->getObject()->isLocallyControlled() )
- {
- // Use the Object's thing template, doing so will prevent wierdness for disguised vehicles.
- drawableList.insert( draw->getObject()->getTemplate() );
- if( draw->getObject()->testStatus( OBJECT_STATUS_IS_CARBOMB ) )
- {
- carBomb = TRUE;
- }
- }
- }
- if (drawableList.size() == 0)
- return -1; // nothing useful selected to begin with - don't bother iterating
- std::set<const ThingTemplate*>::iterator iter;
- const ThingTemplate *templateName;
- // now use the list to select across screen
- MatchingUnitSelectionData data;
- Int newSelectionCount = 0;
- for( iter = drawableList.begin(); iter != drawableList.end(); ++iter )
- {
- // get this drawable
- templateName = *iter;
- data.templateToSelect = templateName;
- data.isCarBomb = carBomb;
- if (region)
- newSelectionCount +=TheTacticalView->iterateDrawablesInRegion(region, similarUnitSelection, (void *)&data);
- else
- {
- // loop over the map
- Drawable *temp = TheGameClient->firstDrawable();
- while( temp )
- {
- newSelectionCount += similarUnitSelection( temp, (void *)&data);
- temp = temp->getNextDrawable();
- }
- }
- setDisplayedMaxWarning( FALSE );
- }
- if (newSelectionCount > 0)
- {
- // create selected message
- GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP_NO_SOUND );
- // not creating a new team so pass in false
- teamMsg->appendBooleanArgument( FALSE );
- //Loop through each drawable add append it's objectID to the event.
- for( DrawableListCIt it = data.newlySelectedDrawables.begin(); it != data.newlySelectedDrawables.end(); ++it )
- {
- draw = *it;
- if( draw && draw->getObject() )
- {
- teamMsg->appendObjectIDArgument( draw->getObject()->getID() );
- }
- }
- }
- return newSelectionCount;
- }
- // ------------------------------------------------------------------------------------------------
- Int InGameUI::selectAllUnitsByTypeAcrossScreen(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear)
- {
- /// When implementing this, obey TheInGameUI->getMaxSelectCount() if it is > 0
-
- IRegion2D region;
- ICoord2D origin;
- ICoord2D size;
-
- TheTacticalView->getOrigin( &origin.x, &origin.y );
- size.x = TheTacticalView->getWidth();
- size.y = TheTacticalView->getHeight();
-
- buildRegion( &origin, &size, ®ion );
- Int numSelected = selectAllUnitsByTypeAcrossRegion(®ion, mustBeSet, mustBeClear);
- if (numSelected == -1)
- {
- UnicodeString message = TheGameText->fetch( "GUI:NothingSelected" );
- TheInGameUI->message( message );
- }
- else if (numSelected == 0)
- {
- }
- else
- {
- UnicodeString message = TheGameText->fetch( "GUI:SelectedAcrossScreen" );
- TheInGameUI->message( message );
- }
- return numSelected;
- }
- // ------------------------------------------------------------------------------------------------
- /** Selects maching units on the screen */
- // ------------------------------------------------------------------------------------------------
- Int InGameUI::selectMatchingAcrossScreen( void )
- {
- /// When implementing this, obey TheInGameUI->getMaxSelectCount() if it is > 0
-
- IRegion2D region;
- ICoord2D origin;
- ICoord2D size;
-
- TheTacticalView->getOrigin( &origin.x, &origin.y );
- size.x = TheTacticalView->getWidth();
- size.y = TheTacticalView->getHeight();
-
- buildRegion( &origin, &size, ®ion );
- Int numSelected = selectMatchingAcrossRegion(®ion);
- if (numSelected == -1)
- {
- UnicodeString message = TheGameText->fetch( "GUI:NothingSelected" );
- TheInGameUI->message( message );
- }
- else if (numSelected == 0)
- {
- }
- else
- {
- UnicodeString message = TheGameText->fetch( "GUI:SelectedAcrossScreen" );
- TheInGameUI->message( message );
- }
- return numSelected;
- }
- //-------------------------------------------------------------------------------------------------
- Int InGameUI::selectAllUnitsByTypeAcrossMap(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear)
- {
- /// When implementing this, obey TheInGameUI->getMaxSelectCount() if it is > 0
- Int numSelected = selectAllUnitsByTypeAcrossRegion(NULL, mustBeSet, mustBeClear);
- if (numSelected == -1)
- {
- UnicodeString message = TheGameText->fetch( "GUI:NothingSelected" );
- TheInGameUI->message( message );
- }
- else if (numSelected == 0)
- {
- Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
- if( !draw || !draw->getObject() || !draw->getObject()->isKindOf( KINDOF_STRUCTURE ) )
- {
- UnicodeString message = TheGameText->fetch( "GUI:SelectedAcrossMap" );
- TheInGameUI->message( message );
- }
- }
- else
- {
- UnicodeString message = TheGameText->fetch( "GUI:SelectedAcrossMap" );
- TheInGameUI->message( message );
- }
- return numSelected;
- }
- //-------------------------------------------------------------------------------------------------
- /** Selects matching units across map */
- //-------------------------------------------------------------------------------------------------
- Int InGameUI::selectMatchingAcrossMap()
- {
- /// When implementing this, obey TheInGameUI->getMaxSelectCount() if it is > 0
- Int numSelected = selectMatchingAcrossRegion(NULL);
- if (numSelected == -1)
- {
- UnicodeString message = TheGameText->fetch( "GUI:NothingSelected" );
- TheInGameUI->message( message );
- }
- else if (numSelected == 0)
- {
- Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
- if( !draw || !draw->getObject() || !draw->getObject()->isKindOf( KINDOF_STRUCTURE ) )
- {
- UnicodeString message = TheGameText->fetch( "GUI:SelectedAcrossMap" );
- TheInGameUI->message( message );
- }
- }
- else
- {
- UnicodeString message = TheGameText->fetch( "GUI:SelectedAcrossMap" );
- TheInGameUI->message( message );
- }
- return numSelected;
- }
- //-------------------------------------------------------------------------------------------------
- Int InGameUI::selectAllUnitsByType(KindOfMaskType mustBeSet, KindOfMaskType mustBeClear)
- {
- /// When implementing this, obey TheInGameUI->getMaxSelectCount() if it is > 0
- Int numSelected = selectAllUnitsByTypeAcrossScreen(mustBeSet, mustBeClear);
- if (numSelected == -1)
- {
- return numSelected;
- }
- if (numSelected == 0)
- {
- Int numSelectedAcrossMap = selectAllUnitsByTypeAcrossMap(mustBeSet, mustBeClear);
- return numSelectedAcrossMap;
- }
- return numSelected;
- }
- //-------------------------------------------------------------------------------------------------
- /** Selects matching units, either on screen or across map. When called by pressing 'T',
- their is not a way to tell if the game is supposed to select across the screen, or
- across the map. For mouse clicks, i.e. Alt + click or double click, we can directly call
- selectMatchingAcrossScreen or selectMatchingAcrossMap */
- //-------------------------------------------------------------------------------------------------
- Int InGameUI::selectUnitsMatchingCurrentSelection()
- {
- /// When implementing this, obey TheInGameUI->getMaxSelectCount() if it is > 0
- Int numSelected = selectMatchingAcrossScreen();
- if (numSelected == -1)
- return numSelected;
- if (numSelected == 0)
- {
- Int numSelectedAcrossMap = selectMatchingAcrossMap();
- //if (numSelectedAcrossMap < 1)
- //{
- //UnicodeString message = TheGameText->fetch( "GUI:NothingSelected" );
- //TheInGameUI->message( message );
- //}
- return numSelectedAcrossMap;
- }
- return numSelected;
- }
- //-----------------------------------------------------------------------------
- /**
- * Given an "anchor" point and the current mouse position (dest),
- * construct a valid 2D bounding region.
- */
- //-----------------------------------------------------------------------------------
- void InGameUI::buildRegion( const ICoord2D *anchor, const ICoord2D *dest, IRegion2D *region )
- {
- // build rectangular region defined by the drag selection
- if (anchor->x < dest->x)
- {
- region->lo.x = anchor->x;
- region->hi.x = dest->x;
- }
- else
- {
- region->lo.x = dest->x;
- region->hi.x = anchor->x;
- }
- if (anchor->y < dest->y)
- {
- region->lo.y = anchor->y;
- region->hi.y = dest->y;
- }
- else
- {
- region->lo.y = dest->y;
- region->hi.y = anchor->y;
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Add a new floating text to our list */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::addFloatingText(const UnicodeString& text,const Coord3D *pos, Color color)
- {
- if( TheGameLogic->getDrawIconUI() )
- {
- FloatingTextData *newFTD = newInstance( FloatingTextData );
- newFTD->m_frameCount = 0;
- newFTD->m_color = color;
- newFTD->m_pos3D.x = pos->x;
- newFTD->m_pos3D.z = pos->z;
- newFTD->m_pos3D.y = pos->y;
- newFTD->m_text = text;
- newFTD->m_dString->setText(text);
-
-
- if(m_floatingTextTimeOut <= 0)
- newFTD->m_frameTimeOut = TheGameLogic->getFrame() + DEFAULT_FLOATING_TEXT_TIMEOUT;
- else
- newFTD->m_frameTimeOut = TheGameLogic->getFrame() + m_floatingTextTimeOut;
-
- m_floatingTextList.push_front( newFTD ); // add to the list
- }
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- #if defined(_DEBUG) || defined(_INTERNAL)
- inline Bool isClose(Real a, Real b) { return fabs(a-b) <= 1.0f; }
- inline Bool isClose(const Coord3D& a, const Coord3D& b)
- {
- return isClose(a.x, b.x) &&
- isClose(a.y, b.y) &&
- isClose(a.z, b.z);
- }
- void InGameUI::DEBUG_addFloatingText(const AsciiString& text, const Coord3D * pos, Color color)
- {
- const Int POINTSIZE = 8;
- const Int LEADING = 0;
- Coord3D posToUse = *pos;
- try_again:
- for (FloatingTextListIt it = m_floatingTextList.begin(); it != m_floatingTextList.end(); ++it)
- {
- if (isClose((*it)->m_pos3D, posToUse))
- {
- posToUse.z -= (POINTSIZE + LEADING);
- goto try_again;
- }
- }
- FloatingTextData *newFTD = newInstance( FloatingTextData );
- newFTD->m_color = color;
- newFTD->m_pos3D.x = posToUse.x;
- newFTD->m_pos3D.y = posToUse.y;
- newFTD->m_pos3D.z = posToUse.z;
- UnicodeString translate;
- translate.translate(text);
- newFTD->m_text = translate;
- newFTD->m_dString->setText(translate);
- newFTD->m_dString->setFont(TheWindowManager->winFindFont( AsciiString("Arial"), POINTSIZE, FALSE ));
-
- if(m_floatingTextTimeOut <= 0)
- newFTD->m_frameTimeOut = TheGameLogic->getFrame() + DEFAULT_FLOATING_TEXT_TIMEOUT;
- else
- newFTD->m_frameTimeOut = TheGameLogic->getFrame() + m_floatingTextTimeOut;
-
- m_floatingTextList.push_front( newFTD ); // add to the list
- //DEBUG_LOG(("%s\n",text.str()));
- }
- #endif
- //-------------------------------------------------------------------------------------------------
- /** modify the position of our floating text */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::updateFloatingText( void )
- {
- FloatingTextData *ftd; // pointer to our floating point data
- UnsignedInt currLogicFrame = TheGameLogic->getFrame(); // the current logic frame
- UnsignedByte r, g, b, a; // we'll need to break apart our color so we can modify the alpha
- Int amount; // The amout we'll change the alpha
- static UnsignedInt lastLogicFrameUpdate = currLogicFrame; // We need to make sure our current frame is different then our last frame we updated.
- // only update the position if we're incrementing frames
- if(lastLogicFrameUpdate == currLogicFrame)
- return;
-
- lastLogicFrameUpdate = currLogicFrame;
- // Loop through our floating text list
- for(FloatingTextListIt it = m_floatingTextList.begin(); it != m_floatingTextList.end();)
- {
- ftd = *it;
-
- // move it up
- ++ftd->m_frameCount;
-
- // fade the text
- if( currLogicFrame > ftd->m_frameTimeOut)
- {
- // modify the color
- GameGetColorComponents(ftd->m_color, &r, &g, &b, &a);
- amount = REAL_TO_INT( (currLogicFrame - ftd->m_frameTimeOut) * m_floatingTextMoveVanishRate);
- if(a - amount < 0)
- a = 0;
- else
- a -= amount;
- ftd->m_color = GameMakeColor(r, g, b, a);
- // if we have 0 alpha delete it
- if( a <= 0)
- {
- it = m_floatingTextList.erase(it);
- ftd->deleteInstance();
- continue; // don't do the ++it below
- }
- }
- // increase our itterator
- ++it;
-
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Itterates through and draws each floating text */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::drawFloatingText( void )
- {
- FloatingTextData *ftd;
- // loop through and draw all the texts
- for(FloatingTextListIt it = m_floatingTextList.begin(); it != m_floatingTextList.end(); ++it)
- {
- ftd = *it;
- ICoord2D pos;
- // get the local player's index
- Int playerNdx = ThePlayerList->getLocalPlayer()->getPlayerIndex();
- // which PartitionManager cells are we looking at?
- Int pCX, pCY;
- ThePartitionManager->worldToCell(ftd->m_pos3D.x, ftd->m_pos3D.y, &pCX, &pCY);
- // translate it's 3d pos into a 2d screen pos
- if( TheTacticalView->worldToScreen(&ftd->m_pos3D, &pos)
- && ftd->m_dString
- && ThePartitionManager->getShroudStatusForPlayer(playerNdx, pCX, pCY) == CELLSHROUD_CLEAR )
- {
- pos.y -= ftd->m_frameCount * m_floatingTextMoveUpSpeed;
- Color dropColor;
- UnsignedByte r, g, b, a;
- Int width;
- // make drop color black, but use the alpha setting of the fill color specified (for fading)
- GameGetColorComponents( ftd->m_color, &r, &g, &b, &a );
- dropColor = GameMakeColor( 0, 0, 0, a );
- ftd->m_dString->getSize(&width, NULL);
- // draw it!
- ftd->m_dString->draw(pos.x - (width / 2), pos.y, ftd->m_color,dropColor);
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** ittereate through and clear out the list of floating text */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::clearFloatingText( void )
- {
- FloatingTextData *ftd;
- // loop through and draw all the texts
- for(FloatingTextListIt it = m_floatingTextList.begin(); it != m_floatingTextList.end();)
- {
- ftd = *it;
- it = m_floatingTextList.erase(it);
- ftd->deleteInstance();
- }
-
- }
- //-------------------------------------------------------------------------------------------------
- /** If we want to use the default text color, then we call this function */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::popupMessage( const AsciiString& message, Int x, Int y, Int width, Bool pause, Bool pauseMusic)
- {
- popupMessage( message, x, y, width, m_popupMessageColor, pause, pauseMusic);
- }
- //-------------------------------------------------------------------------------------------------
- /** initialize, and popup a message box to the user */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::popupMessage( const AsciiString& identifier, Int x, Int y, Int width, Color textColor, Bool pause, Bool pauseMusic)
- {
- if(m_popupMessageData)
- clearPopupMessageData();
- UpdateDiplomacyBriefingText(identifier, FALSE);
- UnicodeString message = TheGameText->fetch(identifier);
- m_popupMessageData = newInstance( PopupMessageData );
- m_popupMessageData->message = message;
- // x and why are passed in as a percentage of the screen, convert to screen coords
- if( x > 100 )
- x = 100;
- if( x < 0 )
- x = 0;
-
- if( y > 100 )
- y = 100;
- if( y < 0 )
- y = 0;
- m_popupMessageData->x = TheDisplay->getWidth() * (INT_TO_REAL(x) / 100);
- m_popupMessageData->y = TheDisplay->getHeight() * (INT_TO_REAL(y) / 100);
- // cap the lower limit of the width
- if(width < 50)
- width = 50;
- m_popupMessageData->width = width;
- m_popupMessageData->textColor = textColor;
- m_popupMessageData->pause = pause;
- m_popupMessageData->pauseMusic = pauseMusic;
- if( pause )
- TheGameLogic->setGamePaused(TRUE, pauseMusic);
- m_popupMessageData->layout = TheWindowManager->winCreateLayout(AsciiString("InGamePopupMessage.wnd"));
- m_popupMessageData->layout->runInit();
- }
- //-------------------------------------------------------------------------------------------------
- /** take care of the logic of clearing the popupMessageData */
- //-------------------------------------------------------------------------------------------------
- void InGameUI::clearPopupMessageData( void )
- {
- if(!m_popupMessageData)
- return;
- if(m_popupMessageData->layout)
- {
- m_popupMessageData->layout->destroyWindows();
- m_popupMessageData->layout->deleteInstance();
- m_popupMessageData->layout = NULL;
- }
- if( m_popupMessageData->pause )
- TheGameLogic->setGamePaused(FALSE, m_popupMessageData->pauseMusic);
- m_popupMessageData->deleteInstance();
- m_popupMessageData = NULL;
-
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- /** Floating Text Constructor */
- //-------------------------------------------------------------------------------------------------
- FloatingTextData::FloatingTextData(void)
- {
- // Added By Sadullah Nader
- // Initializations missing and needed
- m_color = 0;
- m_frameCount = 0;
- m_frameTimeOut = 0;
- m_pos3D.zero();
- m_text.clear();
- //
- m_dString = TheDisplayStringManager->newDisplayString();
- }
- //-------------------------------------------------------------------------------------------------
- /** Floating Text Destructor */
- //-------------------------------------------------------------------------------------------------
- FloatingTextData::~FloatingTextData(void)
- {
- if(m_dString)
- TheDisplayStringManager->freeDisplayString( m_dString );
- m_dString = NULL;
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // WORLD ANIMATION DATA ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- WorldAnimationData::WorldAnimationData( void )
- {
- m_anim = NULL;
- m_worldPos.zero();
- m_expireFrame = 0;
- m_options = WORLD_ANIM_NO_OPTIONS;
- m_zRisePerSecond = 0.0f;
- } // end WorldAnimationData
- // ------------------------------------------------------------------------------------------------
- /** Add a 2D animation at a spot in the world */
- // ------------------------------------------------------------------------------------------------
- void InGameUI::addWorldAnimation( Anim2DTemplate *animTemplate,
- const Coord3D *pos,
- WorldAnimationOptions options,
- Real durationInSeconds,
- Real zRisePerSecond )
- {
- // sanity
- if( animTemplate == NULL || pos == NULL || durationInSeconds <= 0.0f )
- return;
- // allocate a new world animation data struct
- // (huh huh, he said "wad")
- WorldAnimationData *wad = NEW WorldAnimationData;
- if( wad == NULL )
- return;
- // allocate a new animation instance
- Anim2D *anim = newInstance(Anim2D)( animTemplate, TheAnim2DCollection );
- // assign all data
- wad->m_anim = anim;
- wad->m_expireFrame = TheGameLogic->getFrame() + (durationInSeconds * LOGICFRAMES_PER_SECOND);
- wad->m_options = options;
- wad->m_worldPos = *pos;
- wad->m_zRisePerSecond = zRisePerSecond;
- // add to list
- m_worldAnimationList.push_front( wad );
- } // end addWorldAnimation
- // ------------------------------------------------------------------------------------------------
- /** Delete all world animations */
- // ------------------------------------------------------------------------------------------------
- void InGameUI::clearWorldAnimations( void )
- {
- WorldAnimationData *wad;
- // iterate through all entries and delete the animation data
- for( WorldAnimationListIterator it = m_worldAnimationList.begin();
- it != m_worldAnimationList.end(); /*empty*/ )
- {
- wad = *it;
- if( wad )
- {
- // delete the animation instance
- wad->m_anim->deleteInstance();
- // delete the world animation data
- delete wad;
- } // end if
- it = m_worldAnimationList.erase( it );
- } // end for
-
- } // end clearWorldAnimations
- static const UnsignedInt FRAMES_BEFORE_EXPIRE_TO_FADE = LOGICFRAMES_PER_SECOND * 1;
- // ------------------------------------------------------------------------------------------------
- /** Update all world animations and draw the visible ones */
- // ------------------------------------------------------------------------------------------------
- void InGameUI::updateAndDrawWorldAnimations( void )
- {
- WorldAnimationData *wad;
- // go through all animations
- for( WorldAnimationListIterator it = m_worldAnimationList.begin();
- it != m_worldAnimationList.end(); /*empty*/ )
- {
- // get data
- wad = *it;
- // update portion ... only when the game is in motion
- if( wad && TheGameLogic->isGamePaused() == FALSE )
- {
- //
- // see if it's time to expire this animation based on animation type and options or
- // the expire frame
- //
- if( TheGameLogic->getFrame() >= wad->m_expireFrame ||
- (BitTest( wad->m_options, WORLD_ANIM_PLAY_ONCE_AND_DESTROY ) &&
- BitTest( wad->m_anim->getStatus(), ANIM_2D_STATUS_COMPLETE )) )
- {
- // delete this element and continue
- wad->m_anim->deleteInstance();
- delete wad;
- it = m_worldAnimationList.erase( it );
- continue;
- } // end if
- // update the Z value
- if( wad->m_zRisePerSecond )
- wad->m_worldPos.z += wad->m_zRisePerSecond / LOGICFRAMES_PER_SECOND;
- } // end if
- //
- // don't bother going forward with the draw process if this location is shrouded for
- // the local player
- //
- Int playerIndex = ThePlayerList->getLocalPlayer()->getPlayerIndex();
- if( ThePartitionManager->getShroudStatusForPlayer( playerIndex, &wad->m_worldPos ) != CELLSHROUD_CLEAR )
- {
- ++it;
- continue;
- } // end if
- // update translucency value
- if( BitTest( wad->m_options, WORLD_ANIM_FADE_ON_EXPIRE ) )
- {
- // see if we should be setting the translucency value
- UnsignedInt framesTillExpire = wad->m_expireFrame - TheGameLogic->getFrame();
- if( framesTillExpire < FRAMES_BEFORE_EXPIRE_TO_FADE )
- {
-
- // compute alpha level so that we're totally gone by the expire frame
- Real alpha = INT_TO_REAL( framesTillExpire ) / INT_TO_REAL( FRAMES_BEFORE_EXPIRE_TO_FADE );
- wad->m_anim->setAlpha( alpha );
-
- } // end if
- } // end if
- // project the point to screen space
- ICoord2D screen;
- if( TheTacticalView->worldToScreen( &wad->m_worldPos, &screen ) == TRUE )
- {
- UnsignedInt width = wad->m_anim->getCurrentFrameWidth();
- UnsignedInt height = wad->m_anim->getCurrentFrameHeight();
- // scale the width and height given the camera zoom level
- Real zoomScale = TheTacticalView->getMaxZoom() / TheTacticalView->getZoom();
- width *= zoomScale;
- height *= zoomScale;
- // adjust the screen position to draw so the image is centered at the location
- screen.x -= width / 2;
- screen.y -= height / 2;
- // draw the animation
- wad->m_anim->draw( screen.x, screen.y, width, height );
- } // end if
- // go to the next element in the list
- ++it;
- } // end for
- } // end updateAndDrawWorldAnimations
- Object *InGameUI::findIdleWorker( Object *obj)
- {
- if(!obj)
- return NULL;
-
- Int index = obj->getControllingPlayer()->getPlayerIndex();
- if(m_idleWorkers[index].empty())
- return NULL;
- ObjectListIt it = m_idleWorkers[index].begin();
- while(it != m_idleWorkers[index].end())
- {
- Object *itObj = *it;
- if(itObj == obj)
- {
- return itObj;
- break;
- }
- ++it;
- }
- return NULL;
- }
- void InGameUI::addIdleWorker( Object *obj )
- {
- if(!obj)
- return;
- if(findIdleWorker(obj))
- return;
- Int index = obj->getControllingPlayer()->getPlayerIndex();
- m_idleWorkers[index].push_back(obj);
- }
- void InGameUI::removeIdleWorker( Object *obj, Int playerNumber )
- {
- if(!obj)
- return;
- if(playerNumber < 0 || playerNumber >= MAX_PLAYER_COUNT) // we're leaving the game, so this is all screwed
- return;
-
- if(m_idleWorkers[playerNumber].empty())
- return;
-
- ObjectListIt it = m_idleWorkers[playerNumber].begin();
- while(it != m_idleWorkers[playerNumber].end())
- {
- Object *itObj = *it;
- if(itObj == obj)
- {
- m_idleWorkers[playerNumber].erase(it);
- return;
- }
- ++it;
- }
- return;
- }
- void InGameUI::selectNextIdleWorker( void )
- {
- Int index = ThePlayerList->getLocalPlayer()->getPlayerIndex();
- if(m_idleWorkers[index].empty())
- {
- DEBUG_ASSERTCRASH(FALSE, ("InGameUI::selectNextIdleWorker We're trying to select a worker when our list is empty for player %ls", ThePlayerList->getLocalPlayer()->getPlayerDisplayName().str()));
- return;
- }
- Object *selectThisObject = NULL;
-
- if(getSelectCount() == 0 || getSelectCount() > 1)
- {
- selectThisObject = *m_idleWorkers[index].begin();
- }
- else
- {
- Drawable *selectedDrawable = TheInGameUI->getFirstSelectedDrawable();
-
- ObjectListIt it = m_idleWorkers[index].begin();
- while(it != m_idleWorkers[index].end())
- {
- Object *itObj = *it;
- if(itObj == selectedDrawable->getObject())
- {
- ++it;
- if(it != m_idleWorkers[index].end())
- selectThisObject = *it;
- else
- selectThisObject = *m_idleWorkers[index].begin();
- break;
- }
- ++it;
- }
- // if we had something selected that wasn't a worker, we'll get here
- if(!selectThisObject)
- selectThisObject = *m_idleWorkers[index].begin();
- }
- DEBUG_ASSERTCRASH(selectThisObject, ("InGameUI::selectNextIdleWorker Could not select the next IDLE worker"));
- if(selectThisObject)
- {
-
- //If our idle worker is contained by anything, we need to select the container instead.
- Object *containedBy = selectThisObject->getContainedBy();
- if( containedBy )
- {
- selectThisObject = containedBy;
- }
- deselectAllDrawables();
- GameMessage *teamMsg = TheMessageStream->appendMessage( GameMessage::MSG_CREATE_SELECTED_GROUP );
- //New group or add to group? Passed in value is true if we are creating a new group.
- teamMsg->appendBooleanArgument( TRUE );
- teamMsg->appendObjectIDArgument( selectThisObject->getID() );
-
- selectDrawable( selectThisObject->getDrawable() );
- /*// removed becuase we're already playing a select sound... left in, just in case i"m wrong.
- // play the units sound
- const AudioEventRTS *soundEvent = selectThisObject->getTemplate()->getVoiceSelect();
- if (soundEvent)
- {
- TheAudio->addAudioEvent( soundEvent );
- }*/
-
- // center on the unit
- TheTacticalView->lookAt(selectThisObject->getPosition());
- }
- }
- Int InGameUI::getIdleWorkerCount( void )
- {
- Int index = ThePlayerList->getLocalPlayer()->getPlayerIndex();
- return m_idleWorkers[index].size();
- }
- void InGameUI::showIdleWorkerLayout( void )
- {
- if (!m_idleWorkerWin)
- {
- m_idleWorkerWin = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonIdleWorker"));
- DEBUG_ASSERTCRASH(m_idleWorkerWin, ("InGameUI::showIdleWorkerLayout could not find IdleWorker.wnd to load "));
- return;
- }
- m_idleWorkerWin->winEnable(TRUE);
- m_currentIdleWorkerDisplay = getIdleWorkerCount();
-
- // if(m_currentIdleWorkerDisplay < 1)
- // GadgetButtonSetText(m_idleWorkerWin, UnicodeString::TheEmptyString);
- // else
- // {
- // UnicodeString number;
- // number.format(L"%d",m_currentIdleWorkerDisplay);
- // GadgetButtonSetText(m_idleWorkerWin, number);
- // }
- }
- void InGameUI::hideIdleWorkerLayout( void )
- {
- if(!m_idleWorkerWin)
- return;
- GadgetButtonSetText(m_idleWorkerWin, UnicodeString::TheEmptyString);
- m_idleWorkerWin->winEnable(FALSE);
- m_currentIdleWorkerDisplay = -1;
- }
- void InGameUI::updateIdleWorker( void )
- {
- Int idleCount = getIdleWorkerCount();
- if(idleCount > 0 && m_currentIdleWorkerDisplay != idleCount && getInputEnabled())
- showIdleWorkerLayout();
- if((idleCount <= 0 && m_idleWorkerWin) || !getInputEnabled())
- hideIdleWorkerLayout();
- }
- void InGameUI::resetIdleWorker( void )
- {
- if(m_idleWorkerWin)
- {
- GadgetButtonSetText(m_idleWorkerWin, UnicodeString::TheEmptyString);
- }
- m_currentIdleWorkerDisplay = -1;
- for(Int i = 0; i < MAX_PLAYER_COUNT; ++i)
- {
- m_idleWorkers[i].clear();
- }
- }
- void InGameUI::recreateControlBar( void )
- {
- GameWindow *win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey(AsciiString("ControlBar.wnd")));
- if(win)
- win->deleteInstance();
-
- m_idleWorkerWin = NULL;
-
- createControlBar();
-
- if(TheControlBar)
- {
- delete TheControlBar;
- TheControlBar = NEW ControlBar;
- TheControlBar->init();
- }
- }
- void InGameUI::disableTooltipsUntil(UnsignedInt frameNum)
- {
- if (frameNum > m_tooltipsDisabledUntil)
- m_tooltipsDisabledUntil = frameNum;
- }
- void InGameUI::clearTooltipsDisabled()
- {
- m_tooltipsDisabledUntil = 0;
- }
- Bool InGameUI::areTooltipsDisabled() const
- {
- return (TheGameLogic->getFrame() < m_tooltipsDisabledUntil);
- }
- WindowMsgHandledType IdleWorkerSystem( GameWindow *window, UnsignedInt msg,
- WindowMsgData mData1, WindowMsgData mData2 )
- {
- switch( msg )
- {
- //---------------------------------------------------------------------------------------------
- case GWM_INPUT_FOCUS:
- {
- // if we're givin the opportunity to take the keyboard focus we must say we don't want it
- if( mData1 == TRUE )
- *(Bool *)mData2 = FALSE;
- }
- //---------------------------------------------------------------------------------------------
- case GBM_SELECTED:
- {
- GameWindow *control = (GameWindow *)mData1;
- static NameKeyType buttonSelectID = NAMEKEY( "IdleWorker.wnd:ButtonSelectNextIdleWorker" );
- if (control && control->winGetWindowId() == buttonSelectID)
- {
- TheInGameUI->selectNextIdleWorker( );
- }
- break;
- } // end button selected
- //---------------------------------------------------------------------------------------------
- default:
- return MSG_IGNORED;
- } // end switch( msg )
- return MSG_HANDLED;
- }
|