| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509 |
- /*
- ** Command & Conquer Red Alert(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/>.
- */
- /* $Header: /CounterStrike/DISPLAY.CPP 3 3/09/97 8:04p Joe_bostic $ */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : DISPLAY.CPP *
- * *
- * Programmer : Joe L. Bostic *
- * *
- * Start Date : September 10, 1993 *
- * *
- * Last Update : October 20, 1996 [JLB] *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * DisplayClass::Compute_Start_Pos -- Computes player's start pos from unit coords. *
- * DisplayClass::AI -- Handles the maintenance tasks for the map display. *
- * DisplayClass::All_To_Look -- Direct all objects to look around for the player. *
- * DisplayClass::Calculated_Cell -- Fetch a map cell based on specified method. *
- * DisplayClass::Cell_Object -- Determines what has been clicked on. *
- * DisplayClass::Cell_Shadow -- Determine what shadow icon to use for the cell. *
- * DisplayClass::Center_Map -- Centers the map about the currently selected objects *
- * DisplayClass::Click_Cell_Calc -- Determines cell from screen X & Y. *
- * DisplayClass::Closest_Free_Spot -- Finds the closest cell sub spot that is free. *
- * DisplayClass::Coord_To_Pixel -- Determines X and Y pixel coordinates. *
- * DisplayClass::Cursor_Mark -- Set or resets the cursor display flag bits. *
- * DisplayClass::DisplayClass -- Default constructor for display class. *
- * DisplayClass::Draw_It -- Draws the tactical map. *
- * DisplayClass::Encroach_Shadow -- Causes the shadow to creep back by one cell. *
- * DisplayClass::Flag_Cell -- Flag the specified cell to be redrawn. *
- * DisplayClass::Flag_To_Redraw -- Flags the display so that it will be redrawn as soon as poss*
- * DisplayClass::Get_Occupy_Dimensions -- computes width & height of the given occupy list *
- * DisplayClass::Good_Reinforcement_Cell -- Checks cell for renforcement legality. *
- * DisplayClass::In_View -- Determines if cell is visible on screen. *
- * DisplayClass::Init_Clear -- Clears the display to a known state. *
- * DisplayClass::Init_IO -- Creates the map's button list *
- * DisplayClass::Init_Theater -- Theater-specific initialization *
- * DisplayClass::Is_Spot_Free -- Determines if cell sub spot is free of occupation. *
- * DisplayClass::Map_Cell -- Mark specified cell as having been mapped. *
- * DisplayClass::Mouse_Left_Held -- Handles the left button held down. *
- * DisplayClass::Mouse_Left_Press -- Handles the left mouse button press. *
- * DisplayClass::Mouse_Left_Release -- Handles the left mouse button release. *
- * DisplayClass::Mouse_Left_Up -- Handles the left mouse "cruising" over the map. *
- * DisplayClass::Mouse_Right_Press -- Handles the right mouse button press. *
- * DisplayClass::Next_Object -- Searches for next object on display. *
- * DisplayClass::One_Time -- Performs any special one time initializations. *
- * DisplayClass::Passes_Proximity_Check -- Determines if building placement is near friendly sq*
- * DisplayClass::Pixel_To_Coord -- converts screen coord to COORDINATE *
- * DisplayClass::Prev_Object -- Searches for the previous object on the map. *
- * DisplayClass::Read_INI -- Reads map control data from INI file. *
- * DisplayClass::Redraw_Icons -- Draws all terrain icons necessary. *
- * DisplayClass::Redraw_Shadow -- Draw the shadow overlay. *
- * DisplayClass::Refresh_Band -- Causes all cells under the rubber band to be redrawn. *
- * DisplayClass::Refresh_Cells -- Redraws all cells in list. *
- * DisplayClass::Remove -- Removes a game object from the rendering system. *
- * DisplayClass::Repair_Mode_Control -- Controls the repair mode. *
- * DisplayClass::Scroll_Map -- Scroll the tactical map in desired direction. *
- * DisplayClass::Select_These -- All selectable objects in region are selected. *
- * DisplayClass::Sell_Mode_Control -- Controls the sell mode. *
- * DisplayClass::Set_Cursor_Pos -- Controls the display and animation of the tac cursor. *
- * DisplayClass::Set_Cursor_Shape -- Changes the shape of the terrain square cursor. *
- * DisplayClass::Set_Tactical_Position -- Sets the tactical view position. *
- * DisplayClass::Set_View_Dimensions -- Sets the tactical display screen coordinates. *
- * DisplayClass::Shroud_Cell -- Returns the specified cell into the shrouded condition. *
- * DisplayClass::Submit -- Adds a game object to the map rendering system. *
- * DisplayClass::TacticalClass::Action -- Processes input for the tactical map. *
- * DisplayClass::Text_Overlap_List -- Creates cell overlap list for specified text string. *
- * DisplayClass::Write_INI -- Write the map data to the INI file specified. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include "vortex.h"
- /*
- ** These layer control elements are used to group the displayable objects
- ** so that proper overlap can be obtained.
- */
- LayerClass DisplayClass::Layer[LAYER_COUNT];
- /*
- ** Fading tables
- */
- unsigned char DisplayClass::FadingBrighten[256];
- unsigned char DisplayClass::FadingShade[256];
- unsigned char DisplayClass::FadingWayDark[256];
- unsigned char DisplayClass::FadingLight[256];
- unsigned char DisplayClass::FadingGreen[256];
- unsigned char DisplayClass::FadingYellow[256];
- unsigned char DisplayClass::FadingRed[256];
- unsigned char DisplayClass::TranslucentTable[(MAGIC_COL_COUNT+1)*256];
- unsigned char DisplayClass::WhiteTranslucentTable[(1+1)*256];
- unsigned char DisplayClass::MouseTranslucentTable[(4+1)*256];
- void const * DisplayClass::TransIconset;
- unsigned char DisplayClass::UnitShadow[(USHADOW_COL_COUNT+1)*256];
- unsigned char DisplayClass::UnitShadowAir[(USHADOW_COL_COUNT+1)*256];
- unsigned char DisplayClass::SpecialGhost[2*256];
- void const * DisplayClass::ShadowShapes;
- unsigned char DisplayClass::ShadowTrans[(SHADOW_COL_COUNT+1)*256];
- /*
- ** Bit array of cell redraw flags
- */
- BooleanVectorClass DisplayClass::CellRedraw;
- /*
- ** The main button that intercepts user input to the map
- */
- DisplayClass::TacticalClass DisplayClass::TacButton;
- static int const TEX_X = 0;
- static int const TEX_Y = 6;
- static int const TEX_W = 14;
- /***********************************************************************************************
- * DisplayClass::DisplayClass -- Default constructor for display class. *
- * *
- * This constructor for the display class just initializes some of the display settings. *
- * Most settings are initialized with the correct values at the time that the Init function *
- * is called. There are some cases where default values are wise and this routine fills *
- * those particular ones in. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 12/06/1994 JLB : Created. *
- *=============================================================================================*/
- DisplayClass::DisplayClass(void) :
- TacticalCoord(0),
- TacLeptonWidth(0),
- TacLeptonHeight(0),
- ZoneCell(0),
- ZoneOffset(0),
- CursorSize(0),
- ProximityCheck(false),
- PendingObjectPtr(0),
- PendingObject(0),
- PendingHouse(HOUSE_NONE),
- TacPixelX(0),
- TacPixelY(0),
- DesiredTacticalCoord(0),
- IsToRedraw(true),
- IsRepairMode(false),
- IsSellMode(false),
- IsTargettingMode(SPC_NONE),
- IsRubberBand(false),
- IsTentative(false),
- IsShadowPresent(false),
- BandX(0),
- BandY(0),
- NewX(0),
- NewY(0)
- {
- ShadowShapes = 0;
- TransIconset = 0;
- Set_View_Dimensions(0, 8, 320/CELL_PIXEL_W, 200/CELL_PIXEL_H);
- }
- /***********************************************************************************************
- * DisplayClass::One_Time -- Performs any special one time initializations. *
- * *
- * This routine is called from the game initialization process. It is to perform any one *
- * time initializations necessary for the map display system. It allocates the staging *
- * buffer needed for the radar map. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: This routine must be called ONCE and only once. *
- * *
- * HISTORY: *
- * 05/31/1994 JLB : Created. *
- * 05/31/1994 JLB : Handles layer system now. *
- * 06/02/1994 JLB : Takes care of misc display tables and data allocation. *
- *=============================================================================================*/
- void DisplayClass::One_Time(void)
- {
- MapClass::One_Time();
- /*
- ** Init the CellRedraw bit array. Do not do this in the constructor, since the
- ** BooleanVector may not have been constructed yet.
- */
- CellRedraw.Resize(MAP_CELL_TOTAL);
- for (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {
- Layer[layer].One_Time();
- }
- /*
- ** Load the generic transparent icon set.
- */
- TransIconset = MFCD::Retrieve("TRANS.ICN");
- #ifndef NDEBUG
- RawFileClass file("SHADOW.SHP");
- if (file.Is_Available()) {
- ShadowShapes = Load_Alloc_Data(file);
- } else {
- ShadowShapes = MFCD::Retrieve("SHADOW.SHP");
- }
- #else
- ShadowShapes = MFCD::Retrieve("SHADOW.SHP");
- #endif
- Set_View_Dimensions(0, 8 * RESFACTOR);
- }
- /***********************************************************************************************
- * DisplayClass::Init_Clear -- clears the display to a known state *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 03/17/1995 BRR : Created. *
- *=============================================================================================*/
- void DisplayClass::Init_Clear(void)
- {
- MapClass::Init_Clear();
- /*
- ** Clear any object being placed
- */
- PendingObjectPtr = 0;
- PendingObject = 0;
- PendingHouse = HOUSE_NONE;
- CursorSize = 0;
- IsTargettingMode = SPC_NONE;
- IsRepairMode = false;
- IsRubberBand = false;
- IsTentative = false;
- IsSellMode = false;
- /*
- ** Empty all the display's layers
- */
- for (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {
- Layer[layer].Init();
- }
- }
- /***********************************************************************************************
- * DisplayClass::Init_IO -- clears & re-builds the map's button list *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 03/17/1995 BRR : Created. *
- *=============================================================================================*/
- void DisplayClass::Init_IO(void)
- {
- MapClass::Init_IO();
- /*
- ** Re-attach our buttons to the main map button list, only in non-edit mode.
- */
- if (!Debug_Map) {
- TacButton.Zap();
- Add_A_Button(TacButton);
- }
- }
- /***********************************************************************************************
- * DisplayClass::Init_Theater -- Performs theater-specific initialization (mixfiles, etc) *
- * *
- * INPUT: *
- * theater new theater *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 03/17/1995 BRR : Created. *
- * 05/07/1996 JLB : Added translucent tables. *
- *=============================================================================================*/
- void DisplayClass::Init_Theater(TheaterType theater)
- {
- char fullname[16];
- static TLucentType const MouseCols[4] = {
- {BLACK, BLACK, 110, 0},
- {WHITE, WHITE, 110, 0},
- {LTGREY, LTGREY, 110, 0},
- {DKGREY, DKGREY, 110, 0}
- };
- static TLucentType const MagicCols[MAGIC_COL_COUNT] = {
- {32,32,110,0},
- {33,33,110,0},
- {34,34,110,0},
- {35,35,110,0},
- {36,36,110,0},
- {37,37,110,0},
- {38,38,110,0},
- {39,39,110,0},
- {BLACK, BLACK, 200, 0},
- {WHITE, BLACK, 40, 0},
- {LTGREY, BLACK, 80, 0},
- {DKGREY, BLACK, 140, 0},
- {LTGREEN, BLACK,130,0}
- };
- static TLucentType const WhiteCols[1] = {
- {1, WHITE, 80, 0}
- };
- static TLucentType const ShadowCols[SHADOW_COL_COUNT] = {
- {WHITE+1, BLACK,130,0},
- {WHITE, BLACK,170,0},
- {LTGRAY, BLACK,250,0},
- {DKGRAY, BLACK,250,0}
- };
- static TLucentType const UShadowCols[USHADOW_COL_COUNT] = {
- {LTGREEN, BLACK,130,0}
- };
- static TLucentType const UShadowColsAir[USHADOW_COL_COUNT] = {
- {LTGREEN, WHITE,0,0}
- };
- static TLucentType const UShadowColsSnow[USHADOW_COL_COUNT] = {
- {LTGREEN, BLACK,75,0}
- };
- /*
- ** Invoke parent's init routine.
- */
- MapClass::Init_Theater(theater);
- /*
- ** Save the new theater value
- */
- Scen.Theater = theater;
- /*
- ** Unload old mixfiles, and cache the new ones
- */
- sprintf(fullname, "%s.MIX", Theaters[theater].Root);
- #ifndef WIN32
- LastTheater = THEATER_NONE;
- #endif
- if (Scen.Theater != LastTheater) {
- if (TheaterData != NULL) {
- delete TheaterData;
- }
- TheaterData = new MFCD(fullname, &FastKey);
- assert(TheaterData != NULL);
- bool theaterload = TheaterData->Cache(TheaterBuffer);
- assert(theaterload);
- // LastTheater = Scen.Theater;
- }
- /*
- ** Load the custom palette associated with this theater.
- ** The fading palettes will have to be generated as well.
- */
- sprintf(fullname, "%s.PAL", Theaters[theater].Root);
- PaletteClass const * ptr = (PaletteClass *)MFCD::Retrieve(fullname);
- GamePalette = * ptr;
- OriginalPalette = GamePalette;
- Build_Fading_Table(GamePalette, FadingGreen, GREEN, 110);
- Build_Fading_Table(GamePalette, FadingYellow, YELLOW, 140);
- Build_Fading_Table(GamePalette, FadingRed, RED, 140);
- Build_Translucent_Table(GamePalette, &MouseCols[0], 4, MouseTranslucentTable);
- Build_Translucent_Table(GamePalette, &MagicCols[0], MAGIC_COL_COUNT, TranslucentTable);
- Build_Translucent_Table(GamePalette, &WhiteCols[0], 1, WhiteTranslucentTable);
- Build_Translucent_Table(GamePalette, &ShadowCols[0], SHADOW_COL_COUNT, ShadowTrans);
- Conquer_Build_Translucent_Table(GamePalette, &UShadowColsAir[0], USHADOW_COL_COUNT, UnitShadowAir);
- memcpy(&UnitShadowAir[256], ColorRemaps[PCOLOR_GOLD].RemapTable, sizeof(ColorRemaps[PCOLOR_GOLD].RemapTable));
- if (theater == THEATER_SNOW) {
- Conquer_Build_Translucent_Table(GamePalette, &UShadowColsSnow[0], USHADOW_COL_COUNT, UnitShadow);
- } else {
- Conquer_Build_Translucent_Table(GamePalette, &UShadowCols[0], USHADOW_COL_COUNT, UnitShadow);
- }
- if (theater == THEATER_SNOW) {
- Conquer_Build_Fading_Table(GamePalette, FadingShade, BLACK, 75);
- } else {
- Conquer_Build_Fading_Table(GamePalette, FadingShade, BLACK, 130);
- }
- Conquer_Build_Fading_Table(GamePalette, FadingLight, WHITE, 85);
- /*
- ** Create the shadow color used by aircraft.
- */
- Conquer_Build_Fading_Table(GamePalette, &SpecialGhost[256], BLACK, 100);
- for (int index = 0; index < 256; index++) {
- SpecialGhost[index] = 0;
- }
- Make_Fading_Table(GamePalette, FadingBrighten, WHITE, 25);
- Make_Fading_Table(GamePalette, FadingWayDark, DKGRAY, 192);
- /*
- ** Adjust the palette according to the visual control option settings.
- */
- Options.Fixup_Palette();
- }
- /***********************************************************************************************
- * DisplayClass::Text_Overlap_List -- Creates cell overlap list for specified text string. *
- * *
- * This routine is used to create an overlap list that specifies all the cells that are *
- * covered by the specified text string. This overlap list is used to handle map refresh *
- * logic. *
- * *
- * INPUT: text -- Pointer to the text that would appear on the map and must have an *
- * overlap list generated. *
- * *
- * x,y -- The coordinates that the text would appear (upper left corner). *
- * *
- * OUTPUT: Returns with a pointer to an overlap list that covers all cells "under" the text *
- * if were displayed at the coordinates specified. The list is actually a series of *
- * offsets from the display's upper left corner cell number. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 12/06/1994 JLB : Created. *
- * 12/07/1994 JLB : Sidebar fixup. *
- * 08/13/1995 JLB : Optimized for variable sized help text. *
- *=============================================================================================*/
- short const * DisplayClass::Text_Overlap_List(char const * text, int x, int y) const
- {
- static short _list[60];
- int count = ARRAY_SIZE(_list);
- if (text != NULL) {
- short * ptr = &_list[0];
- int len = String_Pixel_Width(text)+CELL_PIXEL_W;
- int right = TacPixelX + Lepton_To_Pixel(TacLeptonWidth);
- /*
- ** If the help text would spill into the sidebar, then flag this fact, but
- ** shorten the apparent length so that the icon list calculation will
- ** function correctly.
- */
- if (x+len >= TacPixelX+Lepton_To_Pixel(TacLeptonWidth)) {
- len = right-x;
- *ptr++ = REFRESH_SIDEBAR;
- count--;
- }
- /*
- ** Build the list of overlap cell offset values according to the text
- ** coordinate and the length.
- */
- if (x <= right) {
- CELL ul = Click_Cell_Calc(x, y-1);
- CELL lr = Click_Cell_Calc(x+len-1, Bound(y+24, TacPixelY, TacPixelY+Lepton_To_Pixel(TacLeptonHeight) - 1));
- if (ul == -1) ul = Click_Cell_Calc(x, y);
- if (ul != -1 && lr != -1) {
- for (int yy = Cell_Y(ul); yy <= Cell_Y(lr); yy++) {
- for (int xx = Cell_X(ul); xx <= Cell_X(lr); xx++) {
- *ptr++ = XY_Cell(xx, yy) - Coord_Cell(TacticalCoord);
- count--;
- if (count < 2) break;
- }
- if (count < 2) break;
- }
- }
- }
- *ptr = REFRESH_EOL;
- }
- return(_list);
- }
- /***********************************************************************************************
- * DisplayClass::Set_View_Dimensions -- Sets the tactical display screen coordinates. *
- * *
- * Use this routine to set the tactical map screen coordinates and dimensions. This routine *
- * is typically used when the screen size or position changes as a result of the sidebar *
- * changing position or appearance. *
- * *
- * INPUT: x,y -- The X and Y pixel position on the screen for the tactical map upper left *
- * corner. *
- * *
- * width -- The width of the tactical display (in icons). If this parameter is *
- * omitted, then the width will be as wide as the screen will allow. *
- * *
- * height-- The height of the tactical display (in icons). If this parameter is *
- * omitted, then the width will be as wide as the screen will allow. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 12/06/1994 JLB : Created. *
- * 06/27/1995 JLB : Adjusts tactical map position if necessary. *
- *=============================================================================================*/
- void DisplayClass::Set_View_Dimensions(int x, int y, int width, int height)
- {
- if (width == -1) {
- TacLeptonWidth = Pixel_To_Lepton(SeenBuff.Get_Width()-x);
- } else {
- TacLeptonWidth = width * CELL_LEPTON_W;
- }
- if (height == -1) {
- height = (SeenBuff.Get_Height()-y) / CELL_PIXEL_H;
- }
- TacLeptonHeight = height * CELL_LEPTON_H;
- /*
- ** Adjust the tactical cell if it is now in an invalid position
- ** because of the changed dimensions.
- */
- int xx = Coord_X(TacticalCoord) - (MapCellX * CELL_LEPTON_W);
- int yy = Coord_Y(TacticalCoord) - (MapCellY * CELL_LEPTON_H);
- Confine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, MapCellWidth * CELL_LEPTON_W, MapCellHeight * CELL_LEPTON_H);
- Set_Tactical_Position(XY_Coord(xx + (MapCellX * CELL_LEPTON_W), yy + (MapCellY * CELL_LEPTON_H)));
- TacPixelX = x;
- TacPixelY = y;
- WindowList[WINDOW_TACTICAL][WINDOWX] = x;
- WindowList[WINDOW_TACTICAL][WINDOWY] = y;
- WindowList[WINDOW_TACTICAL][WINDOWWIDTH] = Lepton_To_Pixel(TacLeptonWidth);
- WindowList[WINDOW_TACTICAL][WINDOWHEIGHT] = Lepton_To_Pixel(TacLeptonHeight);
- if (Window == WINDOW_TACTICAL) {
- Change_Window(0);
- Change_Window(Window);
- }
- IsToRedraw = true;
- Flag_To_Redraw(false);
- TacButton.X = TacPixelX;
- TacButton.Y = TacPixelY;
- TacButton.Width = Lepton_To_Pixel(TacLeptonWidth);
- TacButton.Height = Lepton_To_Pixel(TacLeptonHeight);
- }
- /***********************************************************************************************
- * DisplayClass::Set_Cursor_Shape -- Changes the shape of the terrain square cursor. *
- * *
- * This routine is used to set up the terrain cursor according to the size of the object *
- * that is to be placed down. The terrain cursor looks like an arbitrary collection of *
- * hatched square overlays. Typical use is when placing buildings. *
- * *
- * INPUT: list -- A pointer to the list that contains offsets to the cells that are to *
- * be marked. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/03/1994 JLB : Created. *
- * 06/26/1995 JLB : Puts placement cursor into static buffer. *
- *=============================================================================================*/
- void DisplayClass::Set_Cursor_Shape(short const * list)
- {
- if (CursorSize) {
- Cursor_Mark(ZoneCell+ZoneOffset, false);
- }
- ZoneOffset = 0;
- if (list) {
- int w,h;
- static short _list[50];
- memcpy(_list, list, sizeof(_list));
- CursorSize = _list;
- Get_Occupy_Dimensions (w, h, CursorSize);
- ZoneOffset = -(((h/2)*MAP_CELL_W)+(w/2));
- Cursor_Mark(ZoneCell+ZoneOffset, true);
- } else {
- CursorSize = 0;
- }
- }
- /***********************************************************************************************
- * DisplayClass::Passes_Proximity_Check -- Determines if building placement is near friendly sq*
- * *
- * This routine is used by the building placement cursor logic to determine whether the *
- * at the current cursor position if the building would be adjacent to another friendly *
- * building. In cases where this is not true, then the building cannot be placed at all. *
- * This determination is returned by the function. *
- * *
- * INPUT: object -- The building object that the current placement system is examining. *
- * *
- * house -- The house to base the proximity check upon. Typically this is the *
- * player's house, but in multiplay, the computer needs to check for *
- * proximity as well. *
- * *
- * list -- Pointer to the building's offset list. *
- * *
- * trycell -- The cell to base the offset list on. *
- * *
- * OUTPUT: bool; Can the pending building object be placed at the present cursor location *
- * checking only for proximity to friendly buildings? If this isn't for a *
- * building type object, then this routine always returns true. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/06/1994 JLB : Created. *
- * 06/07/1994 JLB : Handles concrete check. *
- * 10/11/1994 BWG : Added IsProximate check for ore refineries *
- *=============================================================================================*/
- bool DisplayClass::Passes_Proximity_Check(ObjectTypeClass const * object, HousesType house, short const * list, CELL trycell) const
- {
- short const * ptr;
- int retval = -1;
- bool noradar = false;
- bool nomapped = false;
- bool shipyard = false;
- if (house == PlayerPtr->Class->House) {
- PassedProximity = false;
- }
- /*
- ** In editor mode, the proximity check always passes.
- */
- if (Debug_Map) {
- return(true);
- }
- if (list == NULL || trycell == 0) {
- return(true);
- }
- if (object == NULL || object->What_Am_I() != RTTI_BUILDINGTYPE) {
- return(true);
- }
- BuildingTypeClass const * building = (BuildingTypeClass const *)object;
- /*
- ** Scan through all cells that the building foundation would cover. If any adjacent
- ** cells to these are of friendly persuasion, then consider the proximity check to
- ** have been a success.
- */
- ptr = list;
- // ptr = CursorSize;
- CELL cell = trycell;
- // CELL cell = ZoneCell;
- if (building->Adjacent == 1) {
- while (*ptr != REFRESH_EOL && (retval == -1) ) {
- cell = trycell + *ptr++;
- // cell = ZoneCell + ZoneOffset + *ptr++;
- if (!In_Radar(cell)) {
- retval = false;
- noradar = true;
- break;
- }
- for (FacingType facing = FACING_FIRST; facing < FACING_COUNT; facing++) {
- CELL newcell = Adjacent_Cell(cell, facing);
- if (!In_Radar(newcell)) continue;
- if (!(*this)[newcell].IsMapped) {
- nomapped = true;
- }
- TechnoClass * base = (*this)[newcell].Cell_Techno();
- /*
- ** The special cell ownership flag allows building adjacent
- ** to friendly walls and bibs even though there is no official
- ** building located there.
- */
- //BG: Modified so only walls can be placed next to walls - buildings can't.
- //JLB: Except for bibs, in which case buildings can be placed next to these.
- if (building->IsWall ||
- ((*this)[newcell].Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference((*this)[newcell].Smudge).IsBib)) {
- if ((*this)[newcell].Owner == house) {
- retval = true;
- break;
- }
- }
- // we've found a building...
- if (base != NULL && base->What_Am_I() == RTTI_BUILDING && base->House->Class->House == house && ((BuildingClass *)base)->Class->IsBase) {
- retval = true;
- break;
- }
- /* BG: modifications to allow buildings one cell away from other buildings.
- ** This is done by scanning each cell that fails the check (hence getting
- ** to this point) and looking at the n/s/e/w adjacent cells to see if they
- ** have buildings in them. If they do, and they match us, then succeed.
- */
- if (retval != -1) break;
- for (FacingType newface = FACING_N; newface < FACING_COUNT; newface++) {
- CELL newercell = Adjacent_Cell(newcell, newface);
- if (building->IsWall ||
- ((*this)[newercell].Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference((*this)[newercell].Smudge).IsBib)) {
- if ((*this)[newercell].Owner == house) {
- retval = true;
- break;
- }
- }
- TechnoClass * newbase = (*this)[newercell].Cell_Techno();
- // we've found a building...
- if (newbase != NULL && newbase->What_Am_I() == RTTI_BUILDING && newbase->House->Class->House == house && ((BuildingClass const *)newbase)->Class->IsBase) {
- retval = true;
- break;
- }
- }
- if (retval != -1) break;
- }
- }
- }
- if (retval == -1) retval = false;
- if (house == PlayerPtr->Class->House) {
- PassedProximity = (retval != false);
- }
- /*
- ** If this object has special dispensation to be placed further than one cell from
- ** other regular buildings, then check for this case now. Only bother to check if
- ** it hasn't already been given permission to be placed down.
- */
- if (!retval && !noradar && object->What_Am_I() == RTTI_BUILDINGTYPE) {
- // For land mines, let's make it check proximity within 10 squares
- if (building->Adjacent > 1) {
- for (int index = 0; index < Buildings.Count(); index++) {
- BuildingClass * obj = Buildings.Ptr(index);
- if (obj != NULL && !obj->IsInLimbo && obj->House->Class->House == house && obj->Class->IsBase) {
- int centdist = ::Distance(obj->Center_Coord(), Cell_Coord(cell));
- centdist /= CELL_LEPTON_W;
- centdist -= (obj->Class->Width() + obj->Class->Height()) / 2;
- if (centdist <= building->Adjacent) {
- retval = true;
- break;
- }
- }
- }
- }
- }
- return((bool)retval);
- }
- /***********************************************************************************************
- * DisplayClass::Set_Cursor_Pos -- Controls the display and animation of the tac cursor. *
- * *
- * This routine controls the location, display, and animation of the *
- * tactical map cursor. *
- * *
- * INPUT: pos -- Position to move the cursor do. If -1 is passed then *
- * the cursor will just be hidden. If the position *
- * passed is the same as the last position passed in, *
- * then animation could occur (based on timers). *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/22/1991 JLB : Created. *
- * 06/02/1994 JLB : Converted to member function. *
- * 06/08/1994 JLB : If position is -1, then follow mouse. *
- * 02/28/1995 JLB : Forces placement cursor to fit on map. *
- *=============================================================================================*/
- CELL DisplayClass::Set_Cursor_Pos(CELL pos)
- {
- CELL prevpos; // Last position of cursor (for jump-back reasons).
- /*
- ** Follow the mouse position if no cell number is provided.
- */
- if (pos == -1) {
- pos = Click_Cell_Calc(Get_Mouse_X(), Get_Mouse_Y());
- }
- if (CursorSize == NULL) {
- prevpos = ZoneCell;
- ZoneCell = pos;
- return(prevpos);
- }
- /*
- ** Adjusts the position so that the placement cursor is never part way off the
- ** tactical map.
- */
- int w,h;
- Get_Occupy_Dimensions(w, h, CursorSize);
- int x = Cell_X(pos + ZoneOffset);
- int y = Cell_Y(pos + ZoneOffset);
- if (x < Coord_XCell(TacticalCoord)) x = Coord_XCell(TacticalCoord);
- if (y < Coord_YCell(TacticalCoord)) y = Coord_YCell(TacticalCoord);
- if (x+w >= Coord_XCell(TacticalCoord) + Lepton_To_Cell(TacLeptonWidth)) x = Coord_XCell(TacticalCoord)+Lepton_To_Cell(TacLeptonWidth)-w;
- if (y+h >= Coord_YCell(TacticalCoord) + Lepton_To_Cell(TacLeptonHeight)) y = Coord_YCell(TacticalCoord)+Lepton_To_Cell(TacLeptonHeight)-h;
- pos = XY_Cell(x, y) - ZoneOffset;
- /*
- ** This checks to see if NO animation or drawing is to occur and, if so,
- ** exits.
- */
- if (pos == ZoneCell) return(pos);
- prevpos = ZoneCell;
- /*
- ** If the cursor is visible, then handle the graphic update.
- ** Otherwise, just update the global position of the cursor.
- */
- if (CursorSize != NULL) {
- /*
- ** Erase the old cursor (if it exists) AND the cursor is moving.
- */
- if (pos != ZoneCell && ZoneCell != -1) {
- Cursor_Mark(ZoneCell+ZoneOffset, false);
- }
- /*
- ** Render the cursor (could just be animation).
- */
- if (pos != -1) {
- Cursor_Mark(pos+ZoneOffset, true);
- }
- }
- ZoneCell = pos;
- ProximityCheck = Passes_Proximity_Check(PendingObject, PendingHouse, CursorSize, ZoneCell+ZoneOffset);
- return(prevpos);
- }
- /***********************************************************************************************
- * DisplayClass::Get_Occupy_Dimensions -- computes width & height of the given occupy list *
- * *
- * INPUT: *
- * w ptr to fill in with height *
- * h ptr to fill in with width *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 03/31/1995 BRR : Created. *
- *=============================================================================================*/
- void DisplayClass::Get_Occupy_Dimensions(int & w, int & h, short const * list) const
- {
- int min_x = MAP_CELL_W;
- int max_x = -MAP_CELL_W;
- int min_y = MAP_CELL_H;
- int max_y = -MAP_CELL_H;
- int x,y;
- w = 0;
- h = 0;
- if (!list) {
- /*
- ** Loop through all cell offsets, accumulating max & min x- & y-coords
- */
- while (*list != REFRESH_EOL) {
- /*
- ** Compute x & y coords of the current cell offset. We can't use Cell_X()
- ** & Cell_Y(), because they use shifts to compute the values, and if the
- ** offset is negative we'll get a bogus coordinate!
- */
- x = (*list) % MAP_CELL_W;
- y = (*list) / MAP_CELL_H;
- max_x = max(max_x, x);
- min_x = min(min_x, x);
- max_y = max(max_y, y);
- min_y = min(min_y, y);
- list++;
- }
- w = max(1, max_x - min_x + 1);
- h = min(1, max_y - min_y + 1);
- }
- }
- /***********************************************************************************************
- * DisplayClass::Cursor_Mark -- Set or resets the cursor display flag bits. *
- * *
- * This routine will clear or set the cursor display bits on the map. *
- * If the bit is set, then the cursor will be rendered on that map *
- * icon. *
- * *
- * INPUT: pos -- Position of the upper left corner of the cursor. *
- * *
- * on -- Should the bit be turned on? *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: Be sure that every call to set the bits is matched by a *
- * corresponding call to clear the bits. *
- * *
- * HISTORY: *
- * 09/04/1991 JLB : Created. *
- * 06/02/1994 JLB : Converted to member function. *
- *=============================================================================================*/
- void DisplayClass::Cursor_Mark(CELL pos, bool on)
- {
- CELL const * ptr;
- CellClass * cellptr;
- if (pos == -1) return;
- /*
- ** For every cell in the CursorSize list, invoke its Redraw_Objects and
- ** toggle its IsCursorHere flag
- */
- ptr = CursorSize;
- while (*ptr != REFRESH_EOL) {
- CELL cell = pos + *ptr++;
- if (In_Radar(cell)) {
- cellptr = &(*this)[cell];
- cellptr->Redraw_Objects();
- if (on) {
- cellptr->IsCursorHere = true;
- } else {
- cellptr->IsCursorHere = false;
- }
- }
- }
- /*
- ** For every cell in the PendingObjectPtr's Overlap_List, invoke its
- ** Redraw_Objects routine.
- */
- if (PendingObjectPtr) {
- ptr = PendingObjectPtr->Overlap_List();
- while (*ptr != REFRESH_EOL) {
- CELL cell = pos + *ptr++;
- if (In_Radar(cell)) {
- cellptr = &(*this)[cell];
- cellptr->Redraw_Objects();
- }
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::AI -- Handles the maintenance tasks for the map display. *
- * *
- * This routine is called once per game display frame (15 times per second). It handles *
- * the mouse shape tracking and map scrolling as necessary. *
- * *
- * INPUT: input -- The next key just fetched from the input queue. *
- * *
- * x,y -- Mouse coordinates. *
- * *
- * OUTPUT: Modifies the input code if necessary. When the input code is consumed, it gets *
- * set to 0. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/01/1994 JLB : Created. *
- * 06/02/1994 JLB : Filters mouse click input. *
- * 06/07/1994 JLB : Fixed so template click will behave right. *
- * 10/14/1994 JLB : Changing cursor shape over target. *
- * 12/31/1994 JLB : Takes mouse coordinates as parameters. *
- * 06/27/1995 JLB : Breaks out of rubber band mode if mouse leaves map. *
- *=============================================================================================*/
- void DisplayClass::AI(KeyNumType & input, int x, int y)
- {
- if (
- IsRubberBand &&
- (Get_Mouse_X() < TacPixelX ||
- Get_Mouse_Y() < TacPixelY ||
- Get_Mouse_X() >= (TacPixelX + Lepton_To_Pixel(TacLeptonWidth)) ||
- Get_Mouse_Y() >= (TacPixelY + Lepton_To_Pixel(TacLeptonHeight)))) {
- Mouse_Left_Release(-1, Get_Mouse_X(), Get_Mouse_Y(), NULL, ACTION_NONE);
- }
- MapClass::AI(input, x, y);
- }
- /***********************************************************************************************
- * DisplayClass::Submit -- Adds a game object to the map rendering system. *
- * *
- * This routine is used to add an arbitrary (but tangible) game object to the map. It will *
- * be rendered (made visible) once it is submitted to this function. This function builds *
- * the list of game objects that get rendered each frame as necessary. It is possible to *
- * submit the game object to different rendering layers. All objects in a layer get drawn *
- * at the same time. Using this layer method it becomes possible to have objects "below" *
- * other objects. *
- * *
- * INPUT: object -- Pointer to the object to add. *
- * *
- * layer -- The layer to add the object to. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/31/1994 JLB : Created. *
- * 05/31/1994 JLB : Improved layer system. *
- * 05/31/1994 JLB : Sorts object position if this is for the ground layer. *
- *=============================================================================================*/
- void DisplayClass::Submit(ObjectClass const * object, LayerType layer)
- {
- if (object) {
- Layer[layer].Submit(object, (layer == LAYER_GROUND));
- }
- }
- /***********************************************************************************************
- * DisplayClass::Remove -- Removes a game object from the rendering system. *
- * *
- * Every object that is to disappear from the map must be removed from the rendering *
- * system. *
- * *
- * INPUT: object -- The object to remove. *
- * *
- * layer -- The layer to remove it from. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/31/1994 JLB : Created. *
- * 05/31/1994 JLB : Improved layer system. *
- *=============================================================================================*/
- void DisplayClass::Remove(ObjectClass const * object, LayerType layer)
- {
- assert(object != 0);
- assert(object->IsActive);
- if (object) {
- Layer[layer].Delete((ObjectClass *)object);
- }
- }
- /***********************************************************************************************
- * DisplayClass::Click_Cell_Calc -- Determines cell from screen X & Y. *
- * *
- * This routine is used to determine the cell that is located at the *
- * screen pixel coordinates given. Typical use is when the player *
- * clicks with the mouse on the tactical map. *
- * *
- * INPUT: x,y -- Screen pixel coordinates. *
- * *
- * OUTPUT: Returns with cell that is under the coordinates specified. *
- * If the coordinate specified is outside of the tactical *
- * map, then -1 is returned. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/27/1994 JLB : Created. *
- *=============================================================================================*/
- CELL DisplayClass::Click_Cell_Calc(int x, int y) const
- {
- x -= TacPixelX;
- x = Pixel_To_Lepton(x);
- y -= TacPixelY;
- y = Pixel_To_Lepton(y);
- if ((unsigned)x < TacLeptonWidth && (unsigned)y < TacLeptonHeight) {
- COORDINATE tcoord = XY_Coord(Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(TacticalCoord))), Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(TacticalCoord))));
- return(Coord_Cell(Coord_Add(tcoord, XY_Coord(x, y))));
- }
- return(-1);
- }
- /***********************************************************************************************
- * DisplayClass::Scroll_Map -- Scroll the tactical map in desired direction. *
- * *
- * This routine is used to scroll the tactical map view in the desired *
- * direction. It can also be used to determine if scrolling would be *
- * legal without actually performing any scrolling action. *
- * *
- * INPUT: facing -- The direction to scroll the tactical map. *
- * *
- * distance -- The distance in leptons to scroll the map. *
- * *
- * really -- Should the map actually be scrolled? If false, *
- * then only the legality of a scroll is checked. *
- * *
- * OUTPUT: bool; Would scrolling in the desired direction be possible? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/07/1992 JLB : Created. *
- * 05/20/1994 JLB : Converted to member function. *
- * 08/09/1995 JLB : Added distance parameter. *
- * 08/10/1995 JLB : Any direction scrolling. *
- *=============================================================================================*/
- bool DisplayClass::Scroll_Map(DirType facing, int & distance, bool really)
- {
- /*
- ** If the distance is invalid then no further checking is required. Bail
- ** with a no-can-do flag.
- */
- if (distance == 0) return(false);
- FacingType crude = Dir_Facing(facing);
- if (Coord_X(TacticalCoord) == Cell_To_Lepton(MapCellX) && crude != FACING_W) {
- if (crude == FACING_SW) facing = DIR_S;
- if (crude == FACING_NW) facing = DIR_N;
- }
- if (Coord_Y(TacticalCoord) == Cell_To_Lepton(MapCellY) && crude != FACING_N) {
- if (crude == FACING_NW) facing = DIR_W;
- if (crude == FACING_NE) facing = DIR_E;
- }
- if (Coord_X(TacticalCoord) + TacLeptonWidth == Cell_To_Lepton(MapCellX+MapCellWidth) && crude != FACING_E) {
- if (crude == FACING_NE) facing = DIR_N;
- if (crude == FACING_SE) facing = DIR_S;
- }
- if (Coord_Y(TacticalCoord) + TacLeptonHeight == Cell_To_Lepton(MapCellY+MapCellHeight) && crude != FACING_S) {
- if (crude == FACING_SE) facing = DIR_E;
- if (crude == FACING_SW) facing = DIR_W;
- }
- /*
- ** Determine the coordinate that it wants to scroll to.
- */
- COORDINATE coord = Coord_Move(TacticalCoord, facing, distance);
- /*
- ** Clip the new coordinate to the edges of the game world.
- */
- int xx = (int)(short)Coord_X(coord) - (short)Cell_To_Lepton(MapCellX);
- int yy = (int)(short)Coord_Y(coord) - (short)Cell_To_Lepton(MapCellY);
- bool shifted = Confine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, Cell_To_Lepton(MapCellWidth), Cell_To_Lepton(MapCellHeight));
- if (xx < 0) {
- xx = 0;
- shifted = true;
- }
- if (yy < 0) {
- yy = 0;
- shifted = true;
- }
- coord = XY_Coord(xx + Cell_To_Lepton(MapCellX), yy + Cell_To_Lepton(MapCellY));
- /*
- ** If the desired scroll was bound by the edge of the map, then adjust the distance to more accurately
- ** reflect the actual distance moved.
- */
- if (shifted) {
- distance = Distance(TacticalCoord, coord);
- }
- /*
- ** If the new coordinate is the same as the old, then no scrolling would occur.
- */
- if (!distance || coord == TacticalCoord) return(false);
- /*
- ** Since the new coordinate is different than the old one, possibly adjust the real
- ** tactical map accordingly.
- */
- if (really) {
- Set_Tactical_Position(coord);
- IsToRedraw = true;
- Flag_To_Redraw(false);
- /*
- ** Scrolled map REQUIRES all top layer units to be redrawn.
- */
- for (int index = 0; index < Layer[LAYER_TOP].Count(); index++) {
- Layer[LAYER_TOP][index]->Mark(MARK_CHANGE);
- }
- for (index = 0; index < Layer[LAYER_AIR].Count(); index++) {
- Layer[LAYER_AIR][index]->Mark(MARK_CHANGE);
- }
- }
- return(true);
- }
- /***********************************************************************************************
- * DisplayClass::Refresh_Cells -- Redraws all cells in list. *
- * *
- * This routine is used to flag all cells in the specified list for *
- * redrawing. *
- * *
- * INPUT: cell -- The origin cell that the list is offset from. *
- * *
- * list -- Pointer to a list of offsets from the origin cell. *
- * Each cell so specified is flagged for redraw. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: This routine is rather slow (by definition). *
- * *
- * HISTORY: *
- * 05/14/1994 JLB : Created. *
- * 08/01/1994 JLB : Simplified. *
- *=============================================================================================*/
- void DisplayClass::Refresh_Cells(CELL cell, short const * list)
- {
- short tlist[36];
- if (*list == REFRESH_SIDEBAR) {
- list++;
- }
- List_Copy(list, ARRAY_SIZE(tlist), tlist);
- short * tt = tlist;
- while (*tt != REFRESH_EOL) {
- CELL newcell = cell + *tt++;
- if (In_Radar(newcell)) {
- (*this)[newcell].Redraw_Objects();
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::Cell_Shadow -- Determine what shadow icon to use for the cell. *
- * *
- * This routine will examine the specified cell and adjacent cells to *
- * determine what shadow icon to use. *
- * *
- * INPUT: cell -- The cell to examine. *
- * *
- * OUTPUT: Returns with the shadow icon to use. -2= all black. *
- * -1= map cell. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 03/01/1994 JLB : Created. *
- * 04/04/1994 JLB : Revamped for new shadow icon method. *
- * 04/30/1994 JLB : Converted to member function. *
- *=============================================================================================*/
- int DisplayClass::Cell_Shadow(CELL cell) const
- {
- static char const _shadow[256]={
- -1,33, 2, 2,34,37, 2, 2,
- 4,26, 6, 6, 4,26, 6, 6,
- 35,45,17,17,38,41,17,17,
- 4,26, 6, 6, 4,26, 6, 6,
- 8,21,10,10,27,31,10,10,
- 12,23,14,14,12,23,14,14,
- 8,21,10,10,27,31,10,10,
- 12,23,14,14,12,23,14,14,
- 32,36,25,25,44,40,25,25,
- 19,30,20,20,19,30,20,20,
- 39,43,29,29,42,46,29,29,
- 19,30,20,20,19,30,20,20,
- 8,21,10,10,27,31,10,10,
- 12,23,14,14,12,23,14,14,
- 8,21,10,10,27,31,10,10,
- 12,23,14,14,12,23,14,14,
- 1, 1, 3, 3,16,16, 3, 3,
- 5, 5, 7, 7, 5, 5, 7, 7,
- 24,24,18,18,28,28,18,18,
- 5, 5, 7, 7, 5, 5, 7, 7,
- 9, 9,11,11,22,22,11,11,
- 13,13,-2,-2,13,13,-2,-2,
- 9, 9,11,11,22,22,11,11,
- 13,13,-2,-2,13,13,-2,-2,
- 1, 1, 3, 3,16,16, 3, 3,
- 5, 5, 7, 7, 5, 5, 7, 7,
- 24,24,18,18,28,28,18,18,
- 5, 5, 7, 7, 5, 5, 7, 7,
- 9, 9,11,11,22,22,11,11,
- 13,13,-2,-2,13,13,-2,-2,
- 9, 9,11,11,22,22,11,11,
- 13,13,-2,-2,13,13,-2,-2
- };
- int index = 0, value = -1;
- /*
- ** Don't map cells that are at the top or bottom edge. This solves
- ** problem of accessing cells off the top or bottom of the map and into
- ** who-knows-what memory.
- */
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- if ((unsigned)(Cell_Y(cell)-1) >= MAP_CELL_H-2) return(-1);
- #else
- if ((unsigned)(Cell_Y(cell)-1) > MAP_CELL_H-2) return(-1);
- #endif
- //if ((unsigned)(Cell_Y(cell)-1) > MAP_CELL_H-2) return(-2);
- CellClass const * cellptr = &(*this)[cell];
- /*
- ** Presume solid black if that is what is here already.
- */
- if (!cellptr->IsVisible && !cellptr->IsMapped) value = -2;
- if (cellptr->IsMapped /*&& !cellptr->IsVisible*/) {
- /*
- ** Build an index into the lookup table using all 8 surrounding cells.
- ** We're mapping a revealed cell and we only care about the existence
- ** of black cells. Bit numbering starts at the upper-right corner and
- ** goes around the cell clockwise, so 0x80 = directly north.
- */
- cellptr-= MAP_CELL_W + 1;
- if (!cellptr->IsMapped) index |= 0x40;
- cellptr++;
- if (!cellptr->IsMapped) index |= 0x80;
- cellptr++;
- if (!cellptr->IsMapped) index |= 0x01;
- cellptr += MAP_CELL_W - 2;
- if (!cellptr->IsMapped) index |= 0x20;
- cellptr += 2;
- if (!cellptr->IsMapped) index |= 0x02;
- cellptr += MAP_CELL_W - 2;
- if (!cellptr->IsMapped) index |= 0x10;
- cellptr++;
- if (!cellptr->IsMapped) index |= 0x08;
- cellptr++;
- if (!cellptr->IsMapped) index |= 0x04;
- value = _shadow[index];
- }
- return(value);
- }
- /***********************************************************************************************
- * DisplayClass::Map_Cell -- Mark specified cell as having been mapped. *
- * *
- * This routine maps the specified cell. The cell must not already *
- * have been mapped and the mapping player must be the human. *
- * This routine will update any adjacent cell map icon as appropriate. *
- * *
- * INPUT: cell -- The cell to be mapped. *
- * *
- * house -- The player that is doing the mapping. *
- * *
- * OUTPUT: bool; Was action taken to map this cell? *
- * *
- * WARNINGS: none. *
- * *
- * HISTORY: *
- * 08/05/1992 JLB : Created. *
- * 04/30/1994 JLB : Converted to member function. *
- * 05/24/1994 JLB : Takes pointer to HouseClass. *
- * 02/20/1996 JLB : Allied units reveal the map for the player. *
- *=============================================================================================*/
- bool DisplayClass::Map_Cell(CELL cell, HouseClass * house)
- {
- /*
- ** First check for the condition where we're spying on a house's radar
- ** facility, to see if his mapping is applicable to us.
- */
- if (house && house != PlayerPtr) {
- if (house->RadarSpied & (1<<(PlayerPtr->Class->House))) house = PlayerPtr;
- if (Session.Type == GAME_NORMAL && house->Is_Ally(PlayerPtr)) house = PlayerPtr;
- }
- if (house != PlayerPtr || !In_Radar(cell)) return(false);
- CellClass * cellptr = &(*this)[cell];
- /*
- ** Don't bother remapping this cell if it is already mapped.
- */
- if (cellptr->IsMapped) {
- if (!cellptr->IsVisible) {
- cellptr->Redraw_Objects();
- }
- return(false);
- }
- /*
- ** Mark the cell as being mapped. This must be done first because
- ** if the IsVisible flag must be set, then it might affect the
- ** adjacent cell processing.
- */
- cellptr->IsMapped = true;
- cellptr->Redraw_Objects();
- if (Cell_Shadow(cell) == -1) {
- cellptr->IsVisible = true;
- }
- /*
- ** Check out all adjacent cells to see if they need
- ** to be mapped as well. This is necessary because of the
- ** "unique" method of showing shadowed cells. Many combinations
- ** are not allowed, and to fix this, just map the cells until
- ** all is ok.
- */
- for (FacingType dir = FACING_FIRST; dir < FACING_COUNT; dir++) {
- int shadow;
- CELL c;
- c = Adjacent_Cell(cell, dir);
- CellClass * cptr = &(*this)[c];
- cptr->Redraw_Objects();
- if (c != cell && !cptr->IsVisible) {
- shadow = Cell_Shadow(c);
- if (shadow == -1) {
- if (!cptr->IsMapped) {
- Map_Cell(c, house);
- } else {
- cptr->IsVisible = true;
- }
- } else {
- if (shadow != -2 && !cptr->IsMapped) {
- Map_Cell(c, house);
- }
- }
- }
- }
- TechnoClass * tech = (*this)[cell].Cell_Techno();
- if (tech) {
- tech->Revealed(house);
- }
- return(true);
- }
- /***********************************************************************************************
- * DisplayClass::Coord_To_Pixel -- Determines X and Y pixel coordinates. *
- * *
- * This is the routine that figures out the location on the screen for *
- * a specified coordinate. It is one of the fundamental routines *
- * necessary for rendering the game objects. It performs some quick *
- * tests to see if the coordinate is in a visible region and returns *
- * this check as a boolean value. *
- * *
- * INPUT: coord -- The coordinate to check. *
- * *
- * x,y -- Reference to the pixel coordinates that this *
- * coordinate would be when rendered. *
- * *
- * OUTPUT: bool; Is this coordinate in a visible portion of the map? *
- * *
- * WARNINGS: If the coordinate is not in a visible portion of the *
- * map, then this X and Y parameters are not set. *
- * *
- * HISTORY: *
- * 05/14/1994 JLB : Created. *
- * 12/15/1994 JLB : Converted to member function. *
- * 01/07/1995 JLB : Uses inline functions to extract coord components. *
- * 08/09/1995 JLB : Uses new coordinate system. *
- *=============================================================================================*/
- #define EDGE_ZONE (CELL_LEPTON_W*2)
- bool DisplayClass::Coord_To_Pixel(COORDINATE coord, int &x, int &y) const
- {
- if (coord) {
- int xtac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(TacticalCoord)));
- int xoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_X(coord)));
- xoff = (xoff+EDGE_ZONE) - xtac;
- if ((unsigned)xoff <= TacLeptonWidth + EDGE_ZONE*2) {
- int ytac = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(TacticalCoord)));
- int yoff = Pixel_To_Lepton(Lepton_To_Pixel(Coord_Y(coord)));
- yoff = (yoff+EDGE_ZONE) - ytac;
- if ((unsigned)yoff <= TacLeptonHeight + EDGE_ZONE*2) {
- x = Lepton_To_Pixel(xoff)-CELL_PIXEL_W*2;
- y = Lepton_To_Pixel(yoff)-CELL_PIXEL_H*2;
- return(true);
- }
- }
- }
- return(false);
- }
- /***********************************************************************************************
- * DisplayClass::Push_Onto_TacMap -- Moves x & y coords to being on tactical map *
- * *
- * This routine expects a line to be drawn between SOURCE & DEST, so it pushes the coords to *
- * be within the region bounded by TacMapX,Y - + TacMapW,H. *
- * *
- * INPUT: source, dest -- References to the coordinates to check. *
- * *
- * *
- * OUTPUT: bool; Are these coordinates in a visible portion of the map? *
- * Returns true if the pushed source & dest are visible, but if neither are *
- * within the map, then it returns false. *
- * *
- * *
- * HISTORY: *
- * 03/27/1995 BWG : Created. *
- *=============================================================================================*/
- bool DisplayClass::Push_Onto_TacMap(COORDINATE & source, COORDINATE & dest)
- {
- if (!source || !dest) return(false);
- int x1 = Coord_X(source);
- int y1 = Coord_Y(source);
- int x2 = Coord_X(dest);
- int y2 = Coord_Y(dest);
- int left = Coord_X(TacticalCoord);
- int right = Coord_X(TacticalCoord) + TacLeptonWidth;
- int top = Coord_Y(TacticalCoord);
- int bottom = Coord_Y(TacticalCoord) + TacLeptonHeight;
- if (x1 < left && x2 < left) return(false);
- if (x1 > right && x2 > right) return(false);
- if (y1 < top && y2 < top) return(false);
- if (y1 > bottom && y2 > bottom) return(false);
- x1 = Bound(x1, left, right);
- x2 = Bound(x2, left, right);
- y1 = Bound(y1, top, bottom);
- y2 = Bound(y2, top, bottom);
- source = XY_Coord(x1, y1);
- dest = XY_Coord(x2, y2);
- return(true);
- }
- /***********************************************************************************************
- * DisplayClass::Cell_Object -- Determines what has been clicked on. *
- * *
- * This routine is used to determine what the player has clicked on. *
- * It is passed the cell that the click was on and it then examines *
- * the cell and returns with a pointer to the object that is there. *
- * *
- * INPUT: cell -- The cell that has been clicked upon. *
- * *
- * x,y -- Optional offsets from the upper left corner of the cell to be used in *
- * determining exactly which object in the cell is desired. *
- * *
- * OUTPUT: Returns with a pointer to the object that is "clickable" in *
- * the specified cell. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 05/14/1994 JLB : Created. *
- *=============================================================================================*/
- ObjectClass * DisplayClass::Cell_Object(CELL cell, int x, int y) const
- {
- return(*this)[cell].Cell_Object(x, y);
- }
- /***********************************************************************************************
- * DisplayClass::Draw_It -- Draws the tactical map. *
- * *
- * This will draw the tactical map at the recorded position. This *
- * routine is used whenever the tactical map moves or needs to be *
- * completely redrawn. It will handle making the necessary adjustments *
- * to accomodate a moving cursor. *
- * *
- * INPUT: forced -- bool; force redraw of the entire display? *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 04/15/1991 JLB : Created. (benchmark = 292) *
- * 04/15/1991 JLB : Added _cell2meta[] reference array (206) *
- * 04/15/1991 JLB : Added actual map reference for terrain (207) *
- * 04/16/1991 JLB : _cell2meta converted to int (194) *
- * 04/16/1991 JLB : References actual CellIcon[] array (204) *
- * 04/16/1991 JLB : Cell size increased to 16 x 16 (167) *
- * 04/17/1991 JLB : Cell based tactical map rendering (165) *
- * 04/22/1991 JLB : Uses Draw_Stamp() for icon rendering (426) *
- * 04/22/1991 JLB : Draw_Stamp uses LogicPage now (276) *
- * 04/23/1991 JLB : Map active location cursor (334) *
- * 05/02/1991 JLB : Added smoothing and 3 icons sets (431) *
- * 05/22/1991 JLB : Broken into Draw_Map() and Refresh_Map(). *
- * 09/14/1991 JLB : Uses Refresh_Cell when new cells scroll onto display. *
- * 05/12/1992 JLB : Destination page support. *
- * 02/14/1994 JLB : Revamped. *
- * 05/01/1994 JLB : Converted to member function. *
- * 12/15/1994 JLB : Updated to work with display hierarchy. *
- * 12/24/1994 JLB : Examines redraw bit intelligently. *
- * 12/24/1994 JLB : Combined with old Refresh_Map() function. *
- * 01/10/1995 JLB : Rubber band drawing. *
- *=============================================================================================*/
- void DisplayClass::Draw_It(bool forced)
- {
- int x,y; // Working cell index values.
- MapClass::Draw_It(forced);
- if (IsToRedraw || forced) {
- BStart(BENCH_TACTICAL);
- IsToRedraw = false;
- /*
- ** In rubber band mode, mark all cells under the "rubber band" to be
- ** redrawn.
- */
- Refresh_Band();
- /*
- ** Mark all cells under the vortex to be redrawn
- */
- ChronalVortex.Set_Redraw();
- /*
- ** If the multiplayer message system is displaying one or more messages,
- ** flag all cells covered by the messages to redraw. This will prevent
- ** messages from smearing the map if it scrolls.
- */
- int num = Session.Messages.Num_Messages();
- if (num > 0) {
- for (CELL cell = Coord_Cell(TacticalCoord); cell < Coord_Cell(TacticalCoord) + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {
- (*this)[cell].Redraw_Objects();
- }
- for (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W;
- cell < Coord_Cell(TacticalCoord) + MAP_CELL_W + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {
- (*this)[cell].Redraw_Objects();
- }
- if (num > 1) {
- for (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*2;
- cell < Coord_Cell(TacticalCoord) + MAP_CELL_W*2 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {
- (*this)[cell].Redraw_Objects();
- }
- }
- if (num > 2) {
- for (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*3;
- cell < Coord_Cell(TacticalCoord) + MAP_CELL_W*3 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {
- (*this)[cell].Redraw_Objects();
- }
- }
- if (num > 3) {
- for (cell = Coord_Cell(TacticalCoord) + MAP_CELL_W*4;
- cell < Coord_Cell(TacticalCoord) + MAP_CELL_W*4 + Lepton_To_Cell(TacLeptonWidth)+1; cell++) {
- (*this)[cell].Redraw_Objects();
- }
- }
- }
- /*
- ** Check for a movement of the tactical map. If there has been some
- ** movement, then part (or all) of the icons must be redrawn.
- */
- if (Lepton_To_Pixel(Coord_X(DesiredTacticalCoord)) != Lepton_To_Pixel(Coord_X(TacticalCoord)) ||
- Lepton_To_Pixel(Coord_Y(DesiredTacticalCoord)) != Lepton_To_Pixel(Coord_Y(TacticalCoord))) {
- int xmod = Lepton_To_Pixel(Coord_X(DesiredTacticalCoord));
- int ymod = Lepton_To_Pixel(Coord_Y(DesiredTacticalCoord));
- int oldx = Lepton_To_Pixel(Coord_X(TacticalCoord))-xmod; // Old relative offset.
- int oldy = Lepton_To_Pixel(Coord_Y(TacticalCoord))-ymod;
- int oldw = Lepton_To_Pixel(TacLeptonWidth)-ABS(oldx); // Replicable width.
- int oldh = Lepton_To_Pixel(TacLeptonHeight)-ABS(oldy); // Replicable height.
- if (oldw < 1) forced = true;
- if (oldh < 1) forced = true;
- #ifdef WIN32 //For WIN32 only redraw the edges of the map that move into view
- /*
- ** Work out which map edges need to be redrawn
- */
- BOOL redraw_right = (oldx < 0) ? true : false; //Right hand edge
- BOOL redraw_left = (oldx > 0) ? true : false; //Left hand edge
- BOOL redraw_bottom= (oldy < 0) ? true : false; //Bottom edge
- BOOL redraw_top = (oldy > 0) ? true : false; //Top edge
- /*
- ** Blit any replicable block to avoid having to drawstamp.
- */
- if (!forced && (oldw != Lepton_To_Pixel(TacLeptonWidth) || oldh != Lepton_To_Pixel(TacLeptonHeight))) {
- Set_Cursor_Pos(-1);
- /*
- ** If hid page is in video memory then blit from the seen page to avoid blitting
- ** an overlapped region.
- */
- if (HidPage.Get_IsDirectDraw()) {
- Hide_Mouse();
- SeenBuff.Blit(HidPage,
- ((oldx < 0) ? -oldx : 0) +TacPixelX,
- ((oldy < 0) ? -oldy : 0) +TacPixelY,
- ((oldx < 0) ? 0 : oldx) +TacPixelX,
- ((oldy < 0) ? 0 : oldy) +TacPixelY,
- oldw,
- oldh);
- Show_Mouse();
- } else {
- HidPage.Blit(HidPage,
- ((oldx < 0) ? -oldx : 0) +TacPixelX,
- ((oldy < 0) ? -oldy : 0) +TacPixelY,
- ((oldx < 0) ? 0 : oldx) +TacPixelX,
- ((oldy < 0) ? 0 : oldy) +TacPixelY,
- oldw,
- oldh);
- }
- } else {
- forced = true;
- }
- if (oldx < 0) oldx = 0;
- if (oldy < 0) oldy = 0;
- /*
- ** Record new map position for future reference.
- */
- ScenarioInit++;
- Set_Tactical_Position(DesiredTacticalCoord);
- ScenarioInit--;
- if (!forced) {
- /*
- **
- ** Set the 'redraw stamp' bit for any cells that could not be copied.
- **
- */
- int startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));
- int starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));
- oldw -= 24;
- oldh -= 24;
- if (abs(oldx) < 0x25 && abs(oldy) < 0x25) {
- /*
- ** The width of the area we redraw depends on the scroll speed
- */
- int extra_x = (abs(oldx)>=16) ? 2 : 1;
- int extra_y = (abs(oldy)>=16) ? 2 : 1;
- /*
- ** Flag the cells across the top of the visible area if required
- */
- if (redraw_top) {
- for (y = starty; y <= starty+CELL_PIXEL_H*extra_y; y += CELL_PIXEL_H) {
- for (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {
- CELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,
- Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);
- if (c > 0) (*this)[c].Redraw_Objects(true);
- }
- }
- }
- /*
- ** Flag the cells across the bottom of the visible area if required
- */
- if (redraw_bottom) {
- for (y = Lepton_To_Pixel(TacLeptonHeight)-CELL_PIXEL_H*(1+extra_y); y <= Lepton_To_Pixel(TacLeptonHeight)+CELL_PIXEL_H*3; y += CELL_PIXEL_H) {
- for (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {
- CELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,
- Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);
- if (c > 0) (*this)[c].Redraw_Objects(true);
- }
- }
- }
- /*
- ** Flag the cells down the left of the visible area if required
- */
- if (redraw_left) {
- for (x = startx; x <= startx + CELL_PIXEL_W*extra_x; x += CELL_PIXEL_W) {
- for (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {
- CELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,
- Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);
- if (c > 0) (*this)[c].Redraw_Objects(true);
- }
- }
- }
- /*
- ** Flag the cells down the right of the visible area if required
- */
- if (redraw_right) {
- for (x = Lepton_To_Pixel(TacLeptonWidth)-CELL_PIXEL_W*(extra_x+1); x <= Lepton_To_Pixel(TacLeptonWidth)+CELL_PIXEL_W*3; x += CELL_PIXEL_W) {
- for (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {
- CELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,
- Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);
- if (c > 0) (*this)[c].Redraw_Objects(true);
- }
- }
- }
- } else {
- /*
- ** Set the 'redraw stamp' bit for any cells that could not be copied.
- */
- int startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));
- int starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));
- oldw -= 24;
- oldh -= 24;
- for (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {
- for (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {
- if (x <= oldx || x >= oldx+oldw || y <= oldy || y >= oldy+oldh) {
- CELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,
- Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);
- if (c > 0) {
- (*this)[c].Redraw_Objects(true);
- }
- }
- }
- }
- }
- }
- } else {
- /*
- ** Set the tactical coordinate just in case the desired tactical has changed but
- ** not enough to result in any visible map change. This is likely to occur with very
- ** slow scroll rates.
- */
- ScenarioInit++;
- if (DesiredTacticalCoord != TacticalCoord) {
- Set_Tactical_Position(DesiredTacticalCoord);
- }
- ScenarioInit--;
- }
- #else //WIN32
- /*
- ** Blit any replicable block to avoid having to drawstamp.
- */
- if (!forced && (oldw != Lepton_To_Pixel(TacLeptonWidth) || oldh != Lepton_To_Pixel(TacLeptonHeight))) {
- Set_Cursor_Pos(-1);
- HidPage.Blit(HidPage,
- ((oldx < 0) ? -oldx : 0) +TacPixelX,
- ((oldy < 0) ? -oldy : 0) +TacPixelY,
- ((oldx < 0) ? 0 : oldx) +TacPixelX,
- ((oldy < 0) ? 0 : oldy) +TacPixelY,
- oldw,
- oldh);
- } else {
- forced = true;
- }
- if (oldx < 0) oldx = 0;
- if (oldy < 0) oldy = 0;
- /*
- ** Record new map position for future reference.
- */
- ScenarioInit++;
- Set_Tactical_Position(DesiredTacticalCoord);
- ScenarioInit--;
- if (!forced) {
- /*
- ** Set the 'redraw stamp' bit for any cells that could not be copied.
- */
- int startx = -Lepton_To_Pixel(Coord_XLepton(TacticalCoord));
- int starty = -Lepton_To_Pixel(Coord_YLepton(TacticalCoord));
- oldw -= 24;
- oldh -= 24;
- for (y = starty; y <= Lepton_To_Pixel(TacLeptonHeight)+((CELL_PIXEL_H*2)); y += CELL_PIXEL_H) {
- for (x = startx; x <= Lepton_To_Pixel(TacLeptonWidth)+((CELL_PIXEL_W*2)); x += CELL_PIXEL_W) {
- if (x <= oldx || x >= oldx+oldw || y <= oldy || y >= oldy+oldh) {
- CELL c = Click_Cell_Calc(Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1) + TacPixelX,
- Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1) + TacPixelY);
- if (c > 0) {
- (*this)[c].Redraw_Objects(true);
- }
- }
- }
- }
- }
- } else {
- /*
- ** Set the tactical coordinate just in case the desired tactical has changed but
- ** not enough to result in any visible map change. This is likely to occur with very
- ** slow scroll rates.
- */
- ScenarioInit++;
- if (DesiredTacticalCoord != TacticalCoord) {
- Set_Tactical_Position(DesiredTacticalCoord);
- }
- ScenarioInit--;
- }
- #endif
- /*
- ** If the entire tactical map is forced to be redrawn, then set all the redraw flags
- ** and let the normal processing take care of the rest.
- */
- if (forced) {
- CellRedraw.Set();
- }
- /*
- ** The first order of business is to redraw all the underlying icons that are
- ** flagged to be redrawn.
- */
- if (HidPage.Lock()) {
- Redraw_Icons();
- /*
- ** Draw the infantry bodies in this special layer.
- */
- // for (int index = 0; index < Anims.Count(); index++) {
- // AnimClass * anim = Anims.Ptr(index);
- // if (*anim >= ANIM_CORPSE1 && *anim <= ANIM_CORPSE3) {
- // anim->Render(forced);
- // }
- // }
- #ifdef SORTDRAW
- Redraw_OIcons();
- #endif
- HidPage.Unlock();
- }
- #ifndef WIN32
- /*
- ** Once the icons are drawn, duplicate the bottom line of the screen into the phantom
- ** area one line below the screen. This causes the predator effect to work on any
- ** shape drawn at the bottom of the screen.
- */
- HidPage.Blit(HidPage, 0, HidPage.Get_Height()-1, 0, HidPage.Get_Height(), HidPage.Get_Width(), 1, false);
- #endif
- if (HidPage.Lock()) {
- /*
- ** Draw the vortex effect over the terrain
- */
- ChronalVortex.Render();
- /*
- ** Redraw the game objects layer by layer. The layer drawing occurs on the ground layer
- ** first and then followed by all the layers in increasing altitude.
- */
- BStart(BENCH_OBJECTS);
- for (LayerType layer = LAYER_FIRST; layer < LAYER_COUNT; layer++) {
- for (int index = 0; index < Layer[layer].Count(); index++) {
- ObjectClass * ptr = Layer[layer][index];
- #ifdef SORTDRAW
- /*
- ** Techno objects are drawn as part of the cell redraw process since techno
- ** objects in the ground layer are handled by the Occupier and Overlapper
- ** pointer lists.
- */
- if (!Debug_Map && ptr->Is_Techno() && layer == LAYER_GROUND && ((TechnoClass*)ptr)->Visual_Character() == VISUAL_NORMAL) continue;
- #endif
- // if (ptr->What_Am_I() == RTTI_ANIM && *((AnimClass*)ptr) >= ANIM_CORPSE1 && *((AnimClass*)ptr) <= ANIM_CORPSE3) {
- // continue;
- // }
- assert(ptr->IsActive);
- ptr->Render(forced);
- }
- }
- BEnd(BENCH_OBJECTS);
- //ChronalVortex.Render();
- /*
- ** Finally, redraw the shadow overlay as necessary.
- */
- BStart(BENCH_SHROUD);
- Redraw_Shadow();
- BEnd(BENCH_SHROUD);
- }
- HidPage.Unlock();
- #ifdef SORTDRAW
- for (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {
- Layer[LAYER_GROUND][index]->IsToDisplay = false;
- }
- #endif
- /*
- ** Draw the rubber band over the top of it all.
- */
- if (IsRubberBand) {
- LogicPage->Draw_Rect(BandX+TacPixelX, BandY+TacPixelY, NewX+TacPixelX, NewY+TacPixelY, WHITE);
- }
- /*
- ** Clear the redraw flags so that normal redraw flag setting can resume.
- */
- CellRedraw.Reset();
- #ifdef SCENARIO_EDITOR
- /*
- ** If we're placing an object (PendingObject is non-NULL), and that object
- ** is NOT an icon, smudge, or overlay, draw it here.
- ** Terrain, Buildings & Aircraft aren't drawn at the cell's center coord;
- ** they're drawn at the upper left coord, so I have to AND the coord value
- ** with 0xFF00FF00 to strip off the lepton coordinates, but leave the
- ** cell coordinates.
- */
- if (Debug_Map && PendingObjectPtr) {
- PendingObjectPtr->Coord = PendingObjectPtr->Class_Of().Coord_Fixup(Cell_Coord(ZoneCell + ZoneOffset));
- PendingObjectPtr->Render(true);
- }
- #endif
- BEnd(BENCH_TACTICAL);
- }
- }
- /***********************************************************************************************
- * DisplayClass::Redraw_Icons -- Draws all terrain icons necessary. *
- * *
- * This routine will redraw all of the terrain icons that are flagged *
- * to be redrawn. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none. *
- * *
- * HISTORY: *
- * 02/14/1994 JLB : Created. *
- * 05/01/1994 JLB : Converted to member function. *
- * 06/20/1994 JLB : Uses cell drawing support function. *
- * 12/06/1994 JLB : Scans tactical view in separate row/column loops *
- * 12/24/1994 JLB : Uses the cell bit flag array to determine what to redraw. *
- *=============================================================================================*/
- void DisplayClass::Redraw_Icons(void)
- {
- IsShadowPresent = false;
- for (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {
- for (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {
- COORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));
- CELL cell = Coord_Cell(coord);
- coord = Coord_Whole(Cell_Coord(cell));
- /*
- ** Only cells flagged to be redraw are examined.
- */
- if (In_View(cell) && Is_Cell_Flagged(cell)) {
- int xpixel;
- int ypixel;
- if (Coord_To_Pixel(coord, xpixel, ypixel)) {
- CellClass * cellptr = &(*this)[coord];
- /*
- ** If there is a portion of the underlying icon that could be visible,
- ** then draw it. Also draw the cell if the shroud is off.
- */
- if (cellptr->IsMapped || Debug_Unshroud) {
- cellptr->Draw_It(xpixel, ypixel);
- }
- /*
- ** If any cell is not fully mapped, then flag it so that the shadow drawing
- ** process will occur. Only draw the shadow if Debug_Unshroud is false.
- */
- if (!cellptr->IsVisible && !Debug_Unshroud) {
- IsShadowPresent = true;
- }
- }
- }
- }
- }
- }
- #ifdef SORTDRAW
- void DisplayClass::Redraw_OIcons(void)
- {
- for (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {
- for (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {
- COORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));
- CELL cell = Coord_Cell(coord);
- coord = Coord_Whole(Cell_Coord(cell));
- /*
- ** Only cells flagged to be redraw are examined.
- */
- if (In_View(cell) && Is_Cell_Flagged(cell)) {
- int xpixel;
- int ypixel;
- if (Coord_To_Pixel(coord, xpixel, ypixel)) {
- CellClass * cellptr = &(*this)[coord];
- /*
- ** If there is a portion of the underlying icon that could be visible,
- ** then draw it. Also draw the cell if the shroud is off.
- */
- if (cellptr->IsMapped || Debug_Unshroud) {
- cellptr->Draw_It(xpixel, ypixel, true);
- }
- }
- }
- }
- }
- }
- #endif
- /***********************************************************************************************
- * DisplayClass::Redraw_Shadow -- Draw the shadow overlay. *
- * *
- * This routine is called after all other tactical map rendering takes place. It draws *
- * the shadow map over the tactical map. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 01/01/1995 JLB : Created. *
- * 08/06/1995 JLB : Clips the fill rect if necessary. *
- *=============================================================================================*/
- void DisplayClass::Redraw_Shadow(void)
- {
- if (IsShadowPresent) {
- for (int y = -Coord_YLepton(TacticalCoord); y <= TacLeptonHeight; y += CELL_LEPTON_H) {
- for (int x = -Coord_XLepton(TacticalCoord); x <= TacLeptonWidth; x += CELL_LEPTON_W) {
- COORDINATE coord = Coord_Add(TacticalCoord, XY_Coord(x, y));
- CELL cell = Coord_Cell(coord);
- coord = Coord_Whole(Cell_Coord(cell));
- /*
- ** Only cells flagged to be redrawn are examined.
- */
- if (In_View(cell) && Is_Cell_Flagged(cell)) {
- int xpixel;
- int ypixel;
- if (Coord_To_Pixel(coord, xpixel, ypixel)) {
- CellClass * cellptr = &(*this)[coord];
- if (cellptr->IsVisible) continue;
- int shadow = -2;
- if (cellptr->IsMapped) {
- shadow = Cell_Shadow(cell);
- }
- if (shadow >= 0) {
- CC_Draw_Shape(ShadowShapes, shadow, xpixel, ypixel, WINDOW_TACTICAL, SHAPE_GHOST, NULL, ShadowTrans);
- } else {
- if (shadow != -1) {
- int ww = CELL_PIXEL_W;
- int hh = CELL_PIXEL_H;
- if (Clip_Rect(&xpixel, &ypixel, &ww, &hh, Lepton_To_Pixel(TacLeptonWidth), Lepton_To_Pixel(TacLeptonHeight)) >= 0) {
- LogicPage->Fill_Rect(TacPixelX+xpixel, TacPixelY+ypixel, TacPixelX+xpixel+ww-1, TacPixelY+ypixel+hh-1, BLACK);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::Next_Object -- Searches for next object on display. *
- * *
- * This utility routine is used to find the "next" object from the object specified. This *
- * is typically used when <TAB> is pressed and the current object shifts. *
- * *
- * INPUT: object -- The current object to base the "next" calculation off of. *
- * *
- * OUTPUT: Returns with a pointer to the next object. If there is no objects available, *
- * then NULL is returned. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 06/20/1994 JLB : Created. *
- *=============================================================================================*/
- ObjectClass * DisplayClass::Next_Object(ObjectClass * object) const
- {
- ObjectClass * firstobj = NULL;
- bool foundmatch = false;
- if (object == NULL) {
- foundmatch = true;
- }
- for (unsigned uindex = 0; uindex < Layer[LAYER_GROUND].Count(); uindex++) {
- ObjectClass * obj = Layer[LAYER_GROUND][uindex];
- /*
- ** Verify that the object can be selected by and is owned by the player.
- */
- if (obj != NULL && obj->Is_Players_Army()) {
- if (firstobj == NULL) firstobj = obj;
- if (foundmatch) return(obj);
- if (object == obj) foundmatch = true;
- }
- }
- return(firstobj);
- }
- /***********************************************************************************************
- * DisplayClass::Prev_Object -- Searches for the previous object on the map. *
- * *
- * This routine will search for the previous object. Previous is defined as the one listed *
- * before the specified object in the ground layer. If there is no specified object, then *
- * the last object in the ground layer is returned. *
- * *
- * INPUT: object -- Pointer to the object that "previous" is to be defined from. *
- * *
- * OUTPUT: Returns with a pointer to the object previous to the specified one. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 08/24/1995 JLB : Created. *
- *=============================================================================================*/
- ObjectClass * DisplayClass::Prev_Object(ObjectClass * object) const
- {
- ObjectClass * firstobj = NULL;
- bool foundmatch = false;
- if (object == NULL) {
- foundmatch = true;
- }
- for (int uindex = Layer[LAYER_GROUND].Count()-1; uindex >= 0; uindex--) {
- ObjectClass * obj = Layer[LAYER_GROUND][uindex];
- /*
- ** Verify that the object can be selected by and is owned by the player.
- */
- if (obj != NULL && obj->Is_Players_Army()) {
- if (firstobj == NULL) firstobj = obj;
- if (foundmatch) return(obj);
- if (object == obj) foundmatch = true;
- }
- }
- return(firstobj);
- }
- /***********************************************************************************************
- * DisplayClass::Pixel_To_Coord -- converts screen coord to COORDINATE *
- * *
- * INPUT: *
- * x,y pixel coordinates to convert *
- * *
- * OUTPUT: *
- * COORDINATE of pixel *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 11/09/1994 BR : Created. *
- * 12/06/1994 JLB : Uses map dimension variables in display class. *
- * 12/10/1994 JLB : Uses union to speed building coordinate value. *
- *=============================================================================================*/
- COORDINATE DisplayClass::Pixel_To_Coord(int x, int y) const
- {
- /*
- ** Normalize the pixel coordinates to be relative to the upper left corner
- ** of the tactical map. The coordinates are expressed in leptons.
- */
- x -= TacPixelX;
- x = Pixel_To_Lepton(x);
- y -= TacPixelY;
- y = Pixel_To_Lepton(y);
- /*
- ** If pixel coordinate is over the tactical map, then translate it into a coordinate
- ** value. If not, then just return with NULL.
- */
- if ((unsigned)x < TacLeptonWidth && (unsigned)y < TacLeptonHeight) {
- return(Coord_Add(TacticalCoord, XY_Coord(x, y)));
- }
- return(0);
- }
- /***********************************************************************************************
- * DisplayClass::Calculated_Cell -- Fetch a map cell based on specified method. *
- * *
- * Find a cell meeting the specified requirements. This function is *
- * used for scenario reinforcements. *
- * *
- * INPUT: dir -- Method of picking a map cell. *
- * *
- * waypoint -- Closest waypoint to use for finding appropriate map edge. *
- * *
- * cell -- Cell to find closest edge to if waypoint not specified. *
- * *
- * loco -- The locomotion of the reinforcements that are trying to enter. *
- * *
- * zonecheck -- Is zone checking required? *
- * *
- * mzone -- The movement zone type to check against (only if zone checking). *
- * *
- * OUTPUT: Returns with the calculated cell. If 0, then this indicates *
- * that no legal cell was found. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/07/1992 JLB : Created. *
- * 04/11/1994 JLB : Revamped. *
- * 05/18/1994 JLB : Converted to member function. *
- * 12/18/1995 JLB : Handles edge preference scan. *
- * 06/24/1996 JLB : Removed Dune II legacy code. *
- * 06/25/1996 JLB : Rewrote and greatly simplified. *
- * 10/05/1996 JLB : Checks for zone and crushable status. *
- *=============================================================================================*/
- CELL DisplayClass::Calculated_Cell(SourceType dir, WAYPOINT waypoint, CELL cell, SpeedType loco, bool zonecheck, MZoneType mzone) const
- {
- bool vert = false;
- bool horz = false;
- int x = 0;
- int y = 0;
- CELL punt = 0; // If all else fails, return this cell location.
- int zone = -1; // Tentative zone for legality checking.
- /*
- ** Waypoint edge detection for ground based reinforcements that have a waypoint origin are
- ** determined by finding the closest map edge to the waypoint. Reinforcement location
- ** scanning starts from that position.
- */
- CELL trycell = -1;
- if (waypoint != -1) {
- trycell = Scen.Waypoint[waypoint];
- }
- if (trycell == -1) {
- trycell = cell;
- }
- /*
- ** If zone checking is requested, then find the correct zone to use.
- */
- if (zonecheck && trycell != -1) {
- zone = (*this)[trycell].Zones[mzone];
- }
- /*
- ** If the cell or waypoint specified as been detected as legal, then set up the map edge
- ** scanning values accordingly.
- */
- if (trycell != -1) {
- x = Cell_X(trycell) - MapCellX;
- x = min(x, (-Cell_X(trycell) + (MapCellX+MapCellWidth)));
- y = Cell_Y(trycell) - MapCellY;
- y = min(y, (-Cell_Y(trycell) + (MapCellY+MapCellHeight)));
- if (x < y) {
- vert = true;
- horz = false;
- if ((Cell_X(trycell)-MapCellX) < MapCellWidth/2) {
- x = -1;
- } else {
- x = MapCellWidth;
- }
- y = Cell_Y(trycell) - MapCellY;
- } else {
- vert = false;
- horz = true;
- if ((Cell_Y(trycell)-MapCellY) < MapCellHeight/2) {
- y = -1;
- } else {
- y = MapCellHeight;
- }
- x = Cell_X(trycell) - MapCellX;
- }
- }
- /*
- ** If no map edge can be inferred from the waypoint, then go with the
- ** map edge specified by the edge parameter.
- */
- if (!vert && !horz) {
- switch (dir) {
- default:
- case SOURCE_NORTH:
- horz = true;
- y = -1;
- x = Random_Pick(0, MapCellWidth-1);
- break;
- case SOURCE_SOUTH:
- horz = true;
- y = MapCellHeight;
- x = Random_Pick(0, MapCellWidth-1);
- break;
- case SOURCE_EAST:
- vert = true;
- x = MapCellWidth;
- y = Random_Pick(0, MapCellHeight-1);
- break;
- case SOURCE_WEST:
- vert = true;
- x = -1;
- y = Random_Pick(0, MapCellHeight-1);
- break;
- }
- }
- /*
- ** Determine the default reinforcement cell if all else fails.
- */
- punt = XY_Cell(x + MapCellX, y + MapCellY);
- /*
- ** Scan through the vertical and horizontal edges of the map looking for
- ** a relatively clear cell for object placement. The cell scanned is
- ** from the edge position specified by the X and Y variables.
- */
- if (vert) {
- int modifier = (x > MapCellX) ? -1 : 1;
- for (int index = 0; index < MapCellHeight; index++) {
- CELL trycell = XY_Cell(x + MapCellX, ((y + index) % MapCellHeight) + MapCellY);
- if (Good_Reinforcement_Cell(trycell, trycell+modifier, loco, zone, mzone)) {
- return(trycell);
- }
- }
- }
- if (horz) {
- int modifier = (y > MapCellY) ? -MAP_CELL_W : MAP_CELL_W;
- for (int index = 0; index < MapCellWidth; index++) {
- CELL trycell = XY_Cell(((x + index) % MapCellWidth) + MapCellX, y + MapCellY);
- if (Good_Reinforcement_Cell(trycell, trycell+modifier, loco, zone, mzone)) {
- return(trycell);
- }
- }
- }
- /*
- ** If there was no success in finding a suitable reinforcement edge cell, then return
- ** with the default 'punt' cell location.
- */
- return(punt);
- }
- /***********************************************************************************************
- * DisplayClass::Good_Reinforcement_Cell -- Checks cell for renforcement legality. *
- * *
- * This routine will check the secified cell (given the specified conditions) and determine *
- * if that is a good cell for reinforcement purposes. It checks for passability of the cell *
- * as well as zone and whether blocking walls can be crushed. *
- * *
- * INPUT: outcell -- The cell that is just outside the edge of the map. *
- * *
- * incell -- The cell that is just inside the edge of the map. *
- * *
- * loco -- The locomotion type of the reinforcement. *
- * *
- * zone -- The zone that the eventual movement destination lies. A reinforcement *
- * edge must fall within the same zone. *
- * *
- * mzone -- The zone check type to check against (if zone checking required) *
- * *
- * OUTPUT: bool; Is the specified cell good for reinforcement purposes? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/05/1996 JLB : Created. *
- *=============================================================================================*/
- bool DisplayClass::Good_Reinforcement_Cell(CELL outcell, CELL incell, SpeedType loco, int zone, MZoneType mzone) const
- {
- /*
- ** If the map edge location is not clear for object placement, then this is not
- ** a good cell for reinforcement purposes.
- */
- if (!(*this)[outcell].Is_Clear_To_Move(loco, false, false)) {
- return(false);
- }
- /*
- ** If it looks like the on-map cell cannot be driven on to, then return with
- ** the failure code.
- */
- if (!(*this)[incell].Is_Clear_To_Move(loco, false, false, zone, mzone)) {
- return(false);
- }
- /*
- ** If the reinforcement cell is already occupied, then return a failure code.
- */
- if ((*this)[outcell].Cell_Techno() != NULL) {
- return(false);
- }
- if ((*this)[incell].Cell_Techno() != NULL) return(false);
- /*
- ** All tests have passed, return with success code.
- */
- //Mono_Printf("<%04X>\n", incell);Keyboard->Get();
- return(true);
- }
- /***********************************************************************************************
- * DisplayClass::Select_These -- All selectable objects in region are selected. *
- * *
- * Use this routine to simultaneously select all objects within the coordinate region *
- * specified. This routine is used by the multi-select rubber band handler. *
- * *
- * INPUT: coord1 -- Coordinate of one corner of the selection region. *
- * *
- * coord2 -- The opposite corner of the selection region. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 01/19/1995 JLB : Created. *
- * 04/25/1995 JLB : Limited to non-building type. *
- * 03/06/1996 JLB : Allows selection of aircraft with bounding box. *
- *=============================================================================================*/
- void DisplayClass::Select_These(COORDINATE coord1, COORDINATE coord2)
- {
- COORDINATE tcoord = TacticalCoord; //Cell_Coord(TacticalCell) & 0xFF00FF00L;
- coord1 = Coord_Add(tcoord, coord1);
- coord2 = Coord_Add(tcoord, coord2);
- int x1 = Coord_X(coord1);
- int x2 = Coord_X(coord2);
- int y1 = Coord_Y(coord1);
- int y2 = Coord_Y(coord2);
- /*
- ** Ensure that coordinate number one represents the upper left corner
- ** and coordinate number two represents the lower right corner.
- */
- if (x1 > x2) {
- int temp = x1;
- x1 = x2;
- x2 = temp;
- }
- if (y1 > y2) {
- int temp = y1;
- y1 = y2;
- y2 = temp;
- }
- /*
- ** Sweep through all ground layer objects and select the ones within the
- ** bounding box.
- */
- Unselect_All();
- AllowVoice = true;
- for (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {
- ObjectClass * obj = Layer[LAYER_GROUND][index];
- COORDINATE ocoord = obj->Center_Coord();
- int x = Coord_X(ocoord);
- int y = Coord_Y(ocoord);
- /*
- ** Only try to select objects that are owned by the player, are allowed to be
- ** selected, and are within the bounding box.
- */
- HouseClass * hptr = HouseClass::As_Pointer(obj->Owner());
- if ( (hptr != NULL && hptr->IsPlayerControl) &&
- obj->Class_Of().IsSelectable &&
- obj->What_Am_I() != RTTI_BUILDING &&
- x >= x1 && x <= x2 && y >= y1 && y <= y2) {
- if (obj->Select()) {
- AllowVoice = false;
- }
- }
- }
- /*
- ** Select any aircraft with the bounding box.
- */
- for (int air_index = 0; air_index < Aircraft.Count(); air_index++) {
- AircraftClass * aircraft = Aircraft.Ptr(air_index);
- COORDINATE ocoord = aircraft->Center_Coord();
- int x = Coord_X(ocoord);
- int y = Coord_Y(ocoord);
- /*
- ** Only try to select objects that are owned by the player, are allowed to be
- ** selected, and are within the bounding box.
- */
- if ( aircraft->House->IsPlayerControl &&
- aircraft->Class->IsSelectable &&
- !aircraft->IsSelected &&
- x >= x1 && x <= x2 && y >= y1 && y <= y2) {
- if (aircraft->Select()) {
- AllowVoice = false;
- }
- }
- }
- AllowVoice = true;
- }
- /***********************************************************************************************
- * DisplayClass::Refresh_Band -- Causes all cells under the rubber band to be redrawn. *
- * *
- * Use this routine to flag all cells that are covered in some fashion by the multi-unit *
- * select "rubber band" to be redrawn. This is necessary whenever the rubber band changes *
- * size or is being removed. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 01/19/1995 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Refresh_Band(void)
- {
- if (IsRubberBand) {
- /*
- ** In rubber band mode, mark all cells under the "rubber band" to be
- ** redrawn.
- */
- int x1 = BandX+TacPixelX;
- int y1 = BandY+TacPixelY;
- int x2 = NewX+TacPixelX;
- int y2 = NewY+TacPixelY;
- if (x1 > x2) {
- int temp = x1;
- x1 = x2;
- x2 = temp;
- }
- if (y1 > y2) {
- int temp = y1;
- y1 = y2;
- y2 = temp;
- }
- CELL cell;
- for (int y = y1; y <= y2+CELL_PIXEL_H; y += CELL_PIXEL_H) {
- cell = Click_Cell_Calc(x1, Bound(y, 0, TacPixelY+Lepton_To_Pixel(TacLeptonHeight)));
- if (cell != -1) (*this)[cell].Redraw_Objects();
- cell = Click_Cell_Calc(x2, Bound(y, 0, TacPixelY+Lepton_To_Pixel(TacLeptonHeight)));
- if (cell != -1) (*this)[cell].Redraw_Objects();
- }
- for (int x = x1; x <= x2+CELL_PIXEL_W; x += CELL_PIXEL_W) {
- cell = Click_Cell_Calc(Bound(x, 0, TacPixelX+Lepton_To_Pixel(TacLeptonWidth)), y1);
- if (cell != -1) (*this)[cell].Redraw_Objects();
- cell = Click_Cell_Calc(Bound(x, 0, TacPixelX+Lepton_To_Pixel(TacLeptonWidth)), y2);
- if (cell != -1) (*this)[cell].Redraw_Objects();
- }
- /*
- ** Stretching the rubber band requires all objects to be redrawn.
- */
- for (int index = 0; index < Layer[LAYER_TOP].Count(); index++) {
- Layer[LAYER_TOP][index]->Mark(MARK_CHANGE);
- }
- for (index = 0; index < Layer[LAYER_AIR].Count(); index++) {
- Layer[LAYER_AIR][index]->Mark(MARK_CHANGE);
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::TacticalClass::Action -- Processes input for the tactical map. *
- * *
- * This routine handles the input directed at the tactical map. Since input, in this *
- * regard, includes even the presence of the mouse over the tactical map, this routine *
- * is called nearly every game frame. It handles adjusting the mouse shape as well as *
- * giving orders to units. *
- * *
- * INPUT: flags -- The gadget event flags that triggered the call to this function. *
- * *
- * key -- A reference to the keyboard event (if any). *
- * *
- * OUTPUT: bool; Should processing be aborted on any succeeding buttons in the chain? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/17/1995 JLB : Created. *
- *=============================================================================================*/
- int DisplayClass::TacticalClass::Action(unsigned flags, KeyNumType & key)
- {
- int x,y; // Sub cell pixel coordinates.
- bool shadow;
- ObjectClass * object = 0;
- ActionType action = ACTION_NONE; // Action possible with currently selected object.
- /*
- ** Set some working variables that depend on the mouse position. For the press
- ** or release event, special mouse queuing storage variables are used. Other
- ** events must use the current mouse position globals.
- */
- if (flags & (LEFTPRESS|LEFTRELEASE|RIGHTPRESS|RIGHTRELEASE)) {
- x = Keyboard->MouseQX;
- y = Keyboard->MouseQY;
- } else {
- x = Get_Mouse_X();
- y = Get_Mouse_Y();
- }
- bool edge = (y == 0 || x == 0 || x == SeenBuff.Get_Width()-1 || y == SeenBuff.Get_Height()-1);
- COORDINATE coord = Map.Pixel_To_Coord(x, y);
- CELL cell = Coord_Cell(coord);
- if (coord) {
- shadow = (!Map[cell].IsMapped && !Debug_Unshroud);
- x -= Map.TacPixelX;
- y -= Map.TacPixelY;
- /*
- ** Cause any displayed cursor to move along with the mouse cursor.
- */
- if (cell != Map.ZoneCell) {
- Map.Set_Cursor_Pos(cell);
- }
- /*
- ** Determine the object that the mouse is currently over.
- */
- if (!shadow) {
- object = Map.Close_Object(coord);
- /*
- ** Special case check to ignore cloaked object if not owned by the player.
- */
- if (object != NULL && object->Is_Techno() && !((TechnoClass *)object)->IsOwnedByPlayer && (((TechnoClass *)object)->Cloak == CLOAKED || ((TechnoClass *)object)->Techno_Type_Class()->IsInvisible)) {
- object = NULL;
- }
- }
- /*
- ** If there is a currently selected object, then the action to perform if
- ** the left mouse button were clicked must be determined.
- */
- if (CurrentObject.Count()) {
- if (object != NULL) {
- action = CurrentObject[0]->What_Action(object);
- } else {
- action = CurrentObject[0]->What_Action(cell);
- }
- } else {
- if (object && object->Class_Of().IsSelectable) {
- action = ACTION_SELECT;
- }
- if (Map.IsRepairMode) {
- if (object && object->Owner() == PlayerPtr->Class->House && object->Can_Repair()) {
- action = ACTION_REPAIR;
- } else {
- action = ACTION_NO_REPAIR;
- }
- }
- if (Map.IsSellMode) {
- if (object && object->Owner() == PlayerPtr->Class->House && object->Can_Demolish()) {
- if (object->What_Am_I() == RTTI_BUILDING) {
- action = ACTION_SELL;
- } else {
- action = ACTION_SELL_UNIT;
- }
- } else {
- /*
- ** Check to see if the cursor is over an owned wall.
- */
- if (Map[cell].Overlay != OVERLAY_NONE &&
- OverlayTypeClass::As_Reference(Map[cell].Overlay).IsWall &&
- Map[cell].Owner == PlayerPtr->Class->House) {
- action = ACTION_SELL;
- } else {
- action = ACTION_NO_SELL;
- }
- }
- }
- if (Map.IsTargettingMode == SPC_NUCLEAR_BOMB) {
- action = ACTION_NUKE_BOMB;
- }
- if (Map.IsTargettingMode == SPC_PARA_BOMB) {
- action = ACTION_PARA_BOMB;
- }
- if (Map.IsTargettingMode == SPC_PARA_INFANTRY) {
- action = ACTION_PARA_INFANTRY;
- }
- if (Map.IsTargettingMode == SPC_SPY_MISSION) {
- action = ACTION_SPY_MISSION;
- }
- if (Map.IsTargettingMode == SPC_IRON_CURTAIN) {
- action = ACTION_IRON_CURTAIN;
- }
- if (Map.IsTargettingMode == SPC_CHRONOSPHERE) {
- action = ACTION_CHRONOSPHERE;
- }
- if (Map.IsTargettingMode == SPC_CHRONO2) {
- action = ACTION_CHRONO2;
- if (shadow) action = ACTION_NOMOVE;
- ObjectClass const * tobject = As_Object(PlayerPtr->UnitToTeleport);
- /*
- ** Determine if the object can be teleported to the destination cell.
- */
- if (tobject != NULL && tobject->Is_Techno()) {
- TechnoClass const * uobject = (TechnoClass const *)tobject;
- if (!uobject->Can_Teleport_Here(cell)) {
- // if (((UnitClass *)As_Object(PlayerPtr->UnitToTeleport))->Can_Enter_Cell(cell, FACING_NONE) != MOVE_OK) {
- action = ACTION_NOMOVE;
- }
- }
- #ifdef FIXIT_CSII // checked - ajw 9/28/98
- else { // If the object is no longer valid, cancel targetting mode.
- action = ACTION_NOMOVE;
- Map.IsTargettingMode = SPC_NONE;
- }
- #endif
- }
- if (Map.PendingObject) {
- action = ACTION_NONE;
- }
- }
- /*
- ** Move any cursor displayed.
- */
- if (cell != Map.ZoneCell) {
- Map.Set_Cursor_Pos(cell);
- }
- /*
- ** A right mouse button press cancels the current action or selection.
- */
- if (flags & RIGHTPRESS) {
- Map.Mouse_Right_Press();
- }
- /*
- ** Make sure that if the mouse button has been released and the map doesn't know about it,
- ** then it must be informed. Do this by faking a mouse release event.
- */
- if ((flags & LEFTUP) && Map.IsRubberBand) {
- flags |= LEFTRELEASE;
- }
- /*
- ** When the mouse buttons aren't pressed, only the mouse cursor shape is processed.
- ** The shape changes depending on what object the mouse is currently over and what
- ** object is currently selected.
- */
- if (!edge) {
- if (flags & LEFTUP) {
- Map.Mouse_Left_Up(cell, shadow, object, action);
- }
- }
- /*
- ** Normal actions occur when the mouse button is released. The press event is
- ** intercepted and possible rubber-band mode is flagged.
- */
- if (flags & LEFTRELEASE) {
- Map.Mouse_Left_Release(cell, x, y, object, action);
- }
- /*
- ** When the mouse is first pressed on the map, then record the mouse
- ** position so that a proper check before going into rubber band
- ** mode can be made. Rubber band mode starts when the mouse is
- ** held down and moved a certain minimum distance.
- */
- if (!edge && (flags & LEFTPRESS)) {
- Map.Mouse_Left_Up(cell, shadow, object, action);
- Map.Mouse_Left_Press(x, y);
- }
- /*
- ** While the mouse is being held down, determine if rubber band mode should
- ** start. If rubber band mode is already active, then update the size
- ** and flag the map to redraw it.
- */
- if (flags & LEFTHELD) {
- Map.Mouse_Left_Held(x, y);
- }
- }
- return(GadgetClass::Action(0, key));
- }
- /***********************************************************************************************
- * DisplayClass::Mouse_Right_Press -- Handles the right mouse button press. *
- * *
- * This routine is called when the right mouse button is pressed. This action is supposed *
- * to cancel whatever mode or process is active. If there is nothing to cancel, then it *
- * will default to unselecting any units that might be currently selected. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/24/1995 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Mouse_Right_Press(void)
- {
- if (PendingObjectPtr && PendingObjectPtr->Is_Techno()) {
- //PendingObjectPtr->Transmit_Message(RADIO_OVER_OUT);
- PendingObjectPtr = 0;
- PendingObject = 0;
- PendingHouse = HOUSE_NONE;
- Set_Cursor_Shape(0);
- } else {
- if (IsRepairMode) {
- IsRepairMode = false;
- } else {
- if (IsSellMode) {
- IsSellMode = false;
- } else {
- if (IsTargettingMode != SPC_NONE) {
- IsTargettingMode = SPC_NONE;
- } else {
- Unselect_All();
- }
- }
- }
- }
- // If it breaks... call 228.
- Set_Default_Mouse(MOUSE_NORMAL, Map.IsSmall);
- }
- /***********************************************************************************************
- * DisplayClass::Mouse_Left_Up -- Handles the left mouse "cruising" over the map. *
- * *
- * This routine is called continuously while the mouse is over the tactical map but there *
- * are no mouse buttons pressed. Typically, this adjusts the mouse shape and the pop-up *
- * help text. *
- * *
- * INPUT: shadow -- Is the mouse hovering over shadowed terrain? *
- * *
- * object -- Pointer to the object that the mouse is currently over (may be NULL). *
- * *
- * action -- This is the action that the currently selected object (if any) will *
- * perform if the left mouse button were clicked at this location. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/24/1995 JLB : Created. *
- * 07/05/1995 JLB : Removed pop up help text for shadow and terrain after #3. *
- *=============================================================================================*/
- void DisplayClass::Mouse_Left_Up(CELL cell, bool shadow, ObjectClass * object, ActionType action, bool wsmall)
- {
- IsTentative = false;
- TARGET target = TARGET_NONE;
- if (object != NULL) {
- target = object->As_Target();
- } else {
- if (cell != -1) {
- target = As_Target(cell);
- }
- }
- /*
- ** Don't allow selection of an object that is located in shadowed terrain.
- ** In fact, just show the normal move cursor in order to keep the shadowed
- ** terrain a mystery.
- */
- if (shadow) {
- switch (action) {
- case ACTION_NO_DEPLOY:
- Set_Default_Mouse(MOUSE_NO_DEPLOY, wsmall);
- break;
- case ACTION_NO_ENTER:
- Set_Default_Mouse(MOUSE_NO_ENTER, wsmall);
- break;
- case ACTION_NO_GREPAIR:
- Set_Default_Mouse(MOUSE_NO_GREPAIR, wsmall);
- break;
- case ACTION_DAMAGE:
- Set_Default_Mouse(MOUSE_NORMAL, wsmall);
- break;
- case ACTION_GREPAIR:
- Set_Default_Mouse(MOUSE_NORMAL, wsmall);
- break;
- case ACTION_GUARD_AREA:
- Set_Default_Mouse(MOUSE_AREA_GUARD, wsmall);
- break;
- case ACTION_NONE:
- Set_Default_Mouse(MOUSE_NORMAL, wsmall);
- break;
- case ACTION_NO_SELL:
- case ACTION_SELL:
- case ACTION_SELL_UNIT:
- Set_Default_Mouse(MOUSE_NO_SELL_BACK, wsmall);
- break;
- case ACTION_NO_REPAIR:
- case ACTION_REPAIR:
- Set_Default_Mouse(MOUSE_NO_REPAIR, wsmall);
- break;
- case ACTION_NUKE_BOMB:
- Set_Default_Mouse(MOUSE_NUCLEAR_BOMB, wsmall);
- break;
- case ACTION_AIR_STRIKE:
- case ACTION_PARA_BOMB:
- case ACTION_PARA_INFANTRY:
- case ACTION_SPY_MISSION:
- case ACTION_IRON_CURTAIN:
- Set_Default_Mouse(MOUSE_AIR_STRIKE, wsmall);
- break;
- case ACTION_CHRONOSPHERE:
- Set_Default_Mouse(MOUSE_CHRONO_SELECT, wsmall);
- break;
- case ACTION_CHRONO2:
- Set_Default_Mouse(MOUSE_CHRONO_DEST, wsmall);
- break;
- case ACTION_HEAL:
- Set_Default_Mouse(MOUSE_HEAL, wsmall);
- break;
- case ACTION_NOMOVE:
- if (CurrentObject.Count() && CurrentObject[0]->What_Am_I() == RTTI_AIRCRAFT) {
- Set_Default_Mouse(MOUSE_NO_MOVE, wsmall);
- break;
- }
- // Fall into next case for non aircraft object types.
- default:
- Set_Default_Mouse(MOUSE_CAN_MOVE, wsmall);
- break;
- }
- } else {
- /*
- ** Change the mouse shape according to the default action that will occur
- ** if the mouse button were clicked at this location.
- */
- switch (action) {
- case ACTION_NO_DEPLOY:
- Set_Default_Mouse(MOUSE_NO_DEPLOY, wsmall);
- break;
- case ACTION_NO_ENTER:
- Set_Default_Mouse(MOUSE_NO_ENTER, wsmall);
- break;
- case ACTION_NO_GREPAIR:
- Set_Default_Mouse(MOUSE_NO_GREPAIR, wsmall);
- break;
- case ACTION_DAMAGE:
- Set_Default_Mouse(MOUSE_DAMAGE, wsmall);
- break;
- case ACTION_GREPAIR:
- Set_Default_Mouse(MOUSE_GREPAIR, wsmall);
- break;
- case ACTION_TOGGLE_SELECT:
- case ACTION_SELECT:
- Set_Default_Mouse(MOUSE_CAN_SELECT, wsmall);
- break;
- case ACTION_MOVE:
- Set_Default_Mouse(MOUSE_CAN_MOVE, wsmall);
- break;
- case ACTION_GUARD_AREA:
- Set_Default_Mouse(MOUSE_AREA_GUARD, wsmall);
- break;
- case ACTION_ATTACK:
- if (Target_Legal(target) && CurrentObject.Count() == 1 && CurrentObject[0]->Is_Techno() && ((TechnoClass *)CurrentObject[0])->In_Range(target, 0)) {
- Set_Default_Mouse(MOUSE_STAY_ATTACK, wsmall);
- break;
- }
- // fall into next case.
- case ACTION_HARVEST:
- Set_Default_Mouse(MOUSE_CAN_ATTACK, wsmall);
- break;
- case ACTION_SABOTAGE:
- Set_Default_Mouse(MOUSE_DEMOLITIONS, wsmall);
- break;
- case ACTION_ENTER:
- case ACTION_CAPTURE:
- Set_Default_Mouse(MOUSE_ENTER, wsmall);
- break;
- case ACTION_NOMOVE:
- Set_Default_Mouse(MOUSE_NO_MOVE, wsmall);
- break;
- case ACTION_NO_SELL:
- Set_Default_Mouse(MOUSE_NO_SELL_BACK, wsmall);
- break;
- case ACTION_NO_REPAIR:
- Set_Default_Mouse(MOUSE_NO_REPAIR, wsmall);
- break;
- case ACTION_SELF:
- Set_Default_Mouse(MOUSE_DEPLOY, wsmall);
- break;
- case ACTION_REPAIR:
- Set_Default_Mouse(MOUSE_REPAIR, wsmall);
- break;
- case ACTION_SELL_UNIT:
- Set_Default_Mouse(MOUSE_SELL_UNIT, wsmall);
- break;
- case ACTION_SELL:
- Set_Default_Mouse(MOUSE_SELL_BACK, wsmall);
- break;
- case ACTION_NUKE_BOMB:
- Set_Default_Mouse(MOUSE_NUCLEAR_BOMB, wsmall);
- break;
- case ACTION_AIR_STRIKE:
- case ACTION_PARA_BOMB:
- case ACTION_PARA_INFANTRY:
- case ACTION_SPY_MISSION:
- case ACTION_IRON_CURTAIN:
- Set_Default_Mouse(MOUSE_AIR_STRIKE, wsmall);
- break;
- case ACTION_CHRONOSPHERE:
- Set_Default_Mouse(MOUSE_CHRONO_SELECT, wsmall);
- break;
- case ACTION_CHRONO2:
- Set_Default_Mouse(MOUSE_CHRONO_DEST, wsmall);
- break;
- case ACTION_HEAL:
- Set_Default_Mouse(MOUSE_HEAL, wsmall);
- break;
- default:
- Set_Default_Mouse(MOUSE_NORMAL, wsmall);
- break;
- }
- }
- /*
- ** Never display help text if the mouse is held over the radar map.
- */
- if (wsmall) {
- return;
- }
- /*
- ** Give a generic help message when over shadow terrain.
- */
- if (shadow) {
- // if (Scen.Scenario < 4) {
- Help_Text(TXT_SHADOW);
- // } else {
- // Help_Text(TXT_NONE);
- // }
- } else {
- /*
- ** If the mouse is held over objects on the map, then help text may
- ** pop up that tells what the object is. This call informs the help
- ** system of the text name for the object under the mouse.
- */
- if (object != NULL) {
- int text;
- int color = LTGREY;
- /*
- ** Fetch the appropriate background color for help text.
- */
- if (PlayerPtr->Is_Ally(object)) {
- color = GREEN;
- } else {
- if (object->Owner() == HOUSE_NONE || object->Owner() == HOUSE_NEUTRAL) {
- color = LTGREY;
- } else {
- color = PINK;
- }
- }
- /*
- ** Fetch the name of the object. If it is an enemy object, then
- ** the exact identity is glossed over with a generic text.
- */
- text = object->Full_Name();
- if (object->Is_Techno() && !((TechnoTypeClass const &)object->Class_Of()).IsNominal) {
- if (!((TechnoClass *)object)->House->Is_Ally(PlayerPtr)) {
- // if (!PlayerPtr->Is_Ally(object)) {
- switch (object->What_Am_I()) {
- case RTTI_INFANTRY:
- text = TXT_ENEMY_SOLDIER;
- break;
- case RTTI_UNIT:
- text = TXT_ENEMY_VEHICLE;
- break;
- case RTTI_BUILDING:
- text = TXT_ENEMY_STRUCTURE;
- break;
- }
- }
- }
- if (/*Scen.Scenario > 3 ||*/ object->What_Am_I() != RTTI_TERRAIN) {
- Help_Text(text, -1, -1, color);
- } else {
- Help_Text(TXT_NONE);
- }
- } else {
- if ((*this)[cell].Land_Type() == LAND_TIBERIUM) {
- Help_Text(TXT_MINERALS);
- } else {
- Help_Text(TXT_NONE);
- }
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::Mouse_Left_Release -- Handles the left mouse button release. *
- * *
- * This routine is called when the left mouse button is released over the tactical map. *
- * The release event is the workhorse of the game. Most actions occur at the moment of *
- * mouse release. *
- * *
- * INPUT: cell -- The cell that the mouse is over. *
- * *
- * x,y -- The mouse pixel coordinate. *
- * *
- * object -- Pointer to the object that the mouse is over. *
- * *
- * action -- The action that the currently selected object (if any) will *
- * perform. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/24/1995 JLB : Created. *
- * 03/27/1995 JLB : Handles sell and repair actions. *
- *=============================================================================================*/
- void DisplayClass::Mouse_Left_Release(CELL cell, int x, int y, ObjectClass * object, ActionType action, bool wsmall)
- {
- if (PendingObjectPtr) {
- /*
- ** Try to place the pending object onto the map.
- */
- if (ProximityCheck) {
- OutList.Add(EventClass(EventClass::PLACE, PendingObjectPtr->What_Am_I(), cell + ZoneOffset));
- } else {
- Speak(VOX_DEPLOY);
- }
- } else {
- if (IsRubberBand) {
- Refresh_Band();
- Select_These(XYP_Coord(BandX, BandY), XYP_Coord(x, y));
- Set_Default_Mouse(MOUSE_NORMAL, wsmall);
- IsRubberBand = false;
- IsTentative = false;
- Map.DisplayClass::IsToRedraw = true;
- Map.Flag_To_Redraw(false);
- } else {
- /*
- ** Toggle the select state of the object.
- */
- if (action == ACTION_TOGGLE_SELECT) {
- if (!object || !CurrentObject.Count() || CurrentObject[0]->Owner() != PlayerPtr->Class->House) {
- action = ACTION_SELECT;
- } else {
- if (object->IsSelected) {
- object->Unselect();
- } else {
- object->Select();
- }
- }
- }
- /*
- ** Selection of other object action.
- */
- if (action == ACTION_SELECT || (action == ACTION_NONE && object && object->Class_Of().IsSelectable && !object->IsSelected)) {
- Unselect_All();
- object->Select();
- Set_Default_Mouse(MOUSE_NORMAL, wsmall);
- }
- /*
- ** If an action was detected as possible, then pass this action event
- ** to all selected objects.
- */
- if (action != ACTION_NONE && action != ACTION_SELECT) {
- /*
- ** Pass the action to all the selected objects. But first, redetermine
- ** what action that object should perform. This, seemingly redundant
- ** process, is necessary since multiple objects could be selected and each
- ** might perform a different action when the click occurs.
- */
- bool doflash = true;
- AllowVoice = true;
- FormMove = false;
- FormSpeed = SPEED_WHEEL;
- FormMaxSpeed = MPH_LIGHT_SPEED;
- if ( (action == ACTION_MOVE || action == ACTION_NOMOVE) && CurrentObject.Count()) {
- /*
- ** Scan all units. If any are selected that shouldn't be, or aren't
- ** selected but should be, then this is not a formation move.
- */
- int group = 254; // init to invalid group #
- if (CurrentObject[0]->Is_Foot()) {
- group = ((FootClass *)CurrentObject[0])->Group;
- }
- /*
- ** Presume this is a formation move unless something is detected
- ** that will prevent it.
- */
- FormMove = true;
- /*
- ** First scan through all the selected units to make sure that they
- ** are all of the same team and have been assigned a particular formation
- */
- for (int index = 0; index < CurrentObject.Count(); index++) {
- ObjectClass const * tobject = CurrentObject[index];
- /*
- ** Only moveable (i.e., FootClass) objects can ever be in a formation
- ** so if a selected object isn't of a FootClass type then it can't be
- ** a formation move.
- */
- if (tobject->Is_Foot() == false) {
- FormMove = false;
- break;
- }
- /*
- ** If the object is not part of the same team as the rest of the
- ** selected group, or it just plain has never been assigned a
- ** formation offset, then it can't be a formation move.
- */
- FootClass const * foot = (FootClass *)tobject;
- if (foot->Group != group || foot->XFormOffset == 0x80000000) {
- FormMove = false;
- break;
- }
- /*
- ** Determine the formation speed on the presumption that this
- ** will turn out to be a formation move.
- */
- FormMaxSpeed = foot->Techno_Type_Class()->MaxSpeed;
- FormSpeed = foot->Techno_Type_Class()->Speed;
- }
- /*
- ** Loop through all objects (that can theoretically be part of a team) and
- ** if there are any that are part of the currently selected team, but
- ** are not currently selected themselves, then this will force this move
- ** to NOT be a formation move.
- */
- if (FormMove) {
- for (index = 0; index < ::Logic.Count(); index++) {
- ObjectClass const * obj = ::Logic[index];
- /*
- ** If the object is selected, then it has already been scanned
- ** by the previous loop.
- */
- if (obj->IsSelected) continue;
- /*
- ** Only consider footclass objects.
- */
- if (!obj->Is_Foot()) continue;
- FootClass const * foot = (FootClass *)obj;
- /*
- ** Only consider objects that are owned by the player.
- */
- if (!foot->IsOwnedByPlayer) continue;
- /*
- ** If another member of this team has been discovered and
- ** it isn't selected, then the formation move cannot take
- ** place.
- */
- if (foot->Group == group) {
- FormMove = false;
- break;
- }
- }
- }
- }
- for (int index = 0; index < CurrentObject.Count(); index++) {
- ObjectClass * tobject = CurrentObject[index];
- if (object != NULL) {
- tobject->Active_Click_With(tobject->What_Action(object), object);
- } else {
- /*
- ** Trap for formation moves: if this unit is part of a
- ** formation (being part of a team qualifies) and they're
- ** told to move, adjust the target destination so they stay
- ** in formation when they arrive.
- */
- CELL newmove = cell;
- int whatami = tobject->What_Am_I();
- if (action == ACTION_MOVE && tobject->Is_Foot()) {
- int oldisform;
- FootClass * foot = (FootClass *)tobject;
- oldisform = foot->IsFormationMove;
- foot->IsFormationMove = FormMove;
- if (FormMove && foot->Group != 255 ) {
- newmove = foot->Adjust_Dest(cell);
- }
- foot->IsFormationMove = oldisform;
- }
- tobject->Active_Click_With(tobject->What_Action(cell), newmove);
- }
- AllowVoice = false;
- }
- AllowVoice = true;
- FormMove = false;
- if (action == ACTION_REPAIR && object->What_Am_I() == RTTI_BUILDING) {
- OutList.Add(EventClass(EventClass::REPAIR, TargetClass(object)));
- }
- if (action == ACTION_SELL_UNIT && object) {
- switch (object->What_Am_I()) {
- case RTTI_AIRCRAFT:
- case RTTI_UNIT:
- OutList.Add(EventClass(EventClass::SELL, TargetClass(object)));
- break;
- default:
- break;
- }
- }
- if (action == ACTION_SELL) {
- if (object) {
- OutList.Add(EventClass(EventClass::SELL, TargetClass(object)));
- } else {
- OutList.Add(EventClass(EventClass::SELLCELL, cell));
- // OutList.Add(EventClass(EventClass::SELL, ::As_Target(cell)));
- }
- }
- if (action == ACTION_NUKE_BOMB) {
- OutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_NUCLEAR_BOMB, cell));
- }
- if (action == ACTION_PARA_BOMB) {
- OutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_PARA_BOMB, cell));
- }
- if (action == ACTION_PARA_INFANTRY) {
- OutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_PARA_INFANTRY, cell));
- }
- if (action == ACTION_SPY_MISSION) {
- OutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_SPY_MISSION, cell));
- }
- if (action == ACTION_IRON_CURTAIN) {
- OutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_IRON_CURTAIN, cell));
- }
- if (action == ACTION_CHRONOSPHERE) {
- OutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_CHRONOSPHERE, cell));
- }
- if (action == ACTION_CHRONO2) {
- OutList.Add(EventClass(EventClass::SPECIAL_PLACE, SPC_CHRONO2, cell));
- }
- }
- IsTentative = false;
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::Mouse_Left_Press -- Handles the left mouse button press. *
- * *
- * Handle the left mouse button press while over the tactical map. If it isn't is *
- * repair or sell mode, then a tentative transition to rubber band mode is flagged. If the *
- * mouse moves a sufficient distance from this recorded position, then rubber band mode *
- * is officially started. *
- * *
- * INPUT: x,y -- The mouse coordinates at the time of the press. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/24/1995 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Mouse_Left_Press(int x, int y)
- {
- if (!IsRepairMode && !IsSellMode && IsTargettingMode == SPC_NONE && !PendingObject) {
- IsTentative = true;
- BandX = x;
- BandY = y;
- NewX = x;
- NewY = y;
- }
- }
- /***********************************************************************************************
- * DisplayClass::Mouse_Left_Held -- Handles the left button held down. *
- * *
- * This routine is called continuously while the left mouse button is held down over *
- * the tactical map. This handles the rubber band mode detection and dragging. *
- * *
- * INPUT: x,y -- The mouse coordinate. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/24/1995 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Mouse_Left_Held(int x, int y)
- {
- if (IsRubberBand) {
- if (x != NewX || y != NewY) {
- x = Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1);
- y = Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1);
- Refresh_Band();
- NewX = x;
- NewY = y;
- IsToRedraw = true;
- Flag_To_Redraw(false);
- }
- } else {
- /*
- ** If the mouse is still held down while a tentative extended select is possible, then
- ** check to see if the mouse has moved a sufficient distance in order to activate
- ** extended select mode.
- */
- if (IsTentative) {
- /*
- ** The mouse must have moved a minimum distance before rubber band mode can be
- ** initiated.
- */
- if (ABS(x - BandX) > 4 || ABS(y - BandY) > 4) {
- IsRubberBand = true;
- x = Bound(x, 0, Lepton_To_Pixel(TacLeptonWidth)-1);
- y = Bound(y, 0, Lepton_To_Pixel(TacLeptonHeight)-1);
- NewX = x;
- NewY = y;
- IsToRedraw = true;
- Flag_To_Redraw(false);
- /*
- ** Stretching the rubber band requires all objects to be redrawn.
- */
- for (int index = 0; index < Layer[LAYER_TOP].Count(); index++) {
- Layer[LAYER_TOP][index]->Mark(MARK_CHANGE);
- }
- for (index = 0; index < Layer[LAYER_AIR].Count(); index++) {
- Layer[LAYER_AIR][index]->Mark(MARK_CHANGE);
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::Set_Tactical_Position -- Sets the tactical view position. *
- * *
- * This routine is used to set the tactical view position. The requested position is *
- * clipped to the map dimensions as necessary. *
- * *
- * INPUT: coord -- The coordinate desired for the upper left corner. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 08/13/1995 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Set_Tactical_Position(COORDINATE coord)
- {
- /*
- ** Bound the desired location to fit the legal map edges.
- */
- int xx = (int)Coord_X(coord) - (int)Cell_To_Lepton(MapCellX);
- int yy = (int)Coord_Y(coord) - (int)Cell_To_Lepton(MapCellY);
- Confine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, Cell_To_Lepton(MapCellWidth), Cell_To_Lepton(MapCellHeight));
- coord = XY_Coord(xx + Cell_To_Lepton(MapCellX), yy + Cell_To_Lepton(MapCellY));
- if (ScenarioInit) {
- TacticalCoord = coord;
- }
- DesiredTacticalCoord = coord;
- IsToRedraw = true;
- Flag_To_Redraw(false);
- }
- /***********************************************************************************************
- * DisplayClass::Compute_Start_Pos -- Computes player's start pos from unit coords. *
- * *
- * Use this function in multiplayer games, to compute the scenario starting Tactical Pos. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 02/28/1995 JLB : Commented. *
- * 06/26/1995 JLB : Fixed building loop. *
- * 10/20/1996 JLB : Doesn't wrap. *
- *=============================================================================================*/
- void DisplayClass::Compute_Start_Pos(void)
- {
- /*
- ** Find the summation cell-x & cell-y for all the player's units, infantry,
- ** and buildings. Buildings are weighted so that they count 16 times more
- ** than units or infantry.
- */
- long x = 0;
- long y = 0;
- long num = 0;
- for (int i = 0; i < Infantry.Count(); i++) {
- InfantryClass * infp = Infantry.Ptr(i);
- if (!infp->IsInLimbo && infp->IsOwnedByPlayer) {
- x += (long)Coord_XCell(infp->Coord);
- y += (long)Coord_YCell(infp->Coord);
- num++;
- }
- }
- for (i = 0; i < Units.Count(); i++) {
- UnitClass * unitp = Units.Ptr(i);
- if (!unitp->IsInLimbo && unitp->IsOwnedByPlayer) {
- x += (long)Coord_XCell(unitp->Coord);
- y += (long)Coord_YCell(unitp->Coord);
- num++;
- }
- }
- for (i = 0; i < Buildings.Count(); i++) {
- BuildingClass * bldgp = Buildings.Ptr(i);
- if (!bldgp->IsInLimbo && bldgp->IsOwnedByPlayer) {
- x += (((long)Coord_XCell(bldgp->Coord)) * 16);
- y += (((long)Coord_YCell(bldgp->Coord)) * 16);
- num += 16;
- }
- }
- for (i = 0; i < Vessels.Count(); i++) {
- VesselClass * bldgp = Vessels.Ptr(i);
- if (!bldgp->IsInLimbo && bldgp->IsOwnedByPlayer) {
- x += (((long)Coord_XCell(bldgp->Coord)));
- y += (((long)Coord_YCell(bldgp->Coord)));
- num++;
- }
- }
- /*
- ** Divide each coord by 'num' to compute the average value
- */
- if (num > 0) {
- x /= num;
- } else {
- x = 0;
- }
- if (num > 0) {
- y /= num;
- } else {
- y = 0;
- }
- /*
- ** Tactical position is based on the cell of the upper left corner. Make adjustments
- ** and bound the calculated location to the map dimensions.
- */
- // x -= 5 * RESFACTOR;
- // y -= 4 * RESFACTOR;
- if (x < MapCellX + 5*RESFACTOR) x = MapCellX + 5*RESFACTOR;
- if (y < MapCellY + 4*RESFACTOR) y = MapCellY + 4*RESFACTOR;
- if (x > MapCellX+MapCellWidth - 5*RESFACTOR) x = MapCellX+MapCellWidth - 5*RESFACTOR;
- if (y > MapCellY+MapCellHeight - 4*RESFACTOR) y = MapCellY+MapCellHeight - 4*RESFACTOR;
- Scen.Waypoint[WAYPT_HOME] = Scen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = XY_Cell(x, y);
- Map.Set_Tactical_Position(Coord_Whole(Cell_Coord((Scen.Views[0] - (MAP_CELL_W * 4 * RESFACTOR)) - (5*RESFACTOR))));
- // Set_Tactical_Position(Cell_Coord(XY_Cell(x, y)));
- }
- /***********************************************************************************************
- * DisplayClass::Sell_Mode_Control -- Controls the sell mode. *
- * *
- * This routine will control the sell mode for the player. *
- * *
- * INPUT: control -- The mode to set the sell state to. *
- * 0 = Turn sell mode off. *
- * 1 = Turn sell mode on. *
- * -1 = Toggle sell mode. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 07/08/1995 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Sell_Mode_Control(int control)
- {
- bool mode = IsSellMode;
- switch (control) {
- case 0:
- mode = false;
- break;
- case -1:
- mode = (IsSellMode == false);
- break;
- case 1:
- mode = true;
- break;
- }
- if (mode != IsSellMode && !PendingObject) {
- IsRepairMode = false;
- if (mode && PlayerPtr->BScan) {
- IsSellMode = true;
- Unselect_All();
- } else {
- IsSellMode = false;
- Revert_Mouse_Shape();
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::Repair_Mode_Control -- Controls the repair mode. *
- * *
- * This routine is used to control the repair mode for the player. *
- * *
- * INPUT: control -- The mode to set the repair to. *
- * 0 = Turn repair off. *
- * 1 = Turn repair on. *
- * -1= Toggle repair state. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 07/08/1995 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Repair_Mode_Control(int control)
- {
- bool mode = IsRepairMode;
- switch (control) {
- case 0:
- mode = false;
- break;
- case -1:
- mode = (IsRepairMode == false);
- break;
- case 1:
- mode = true;
- break;
- }
- if (mode != IsRepairMode && !PendingObject) {
- IsSellMode = false;
- if (mode && PlayerPtr->BScan) {
- IsRepairMode = true;
- Unselect_All();
- } else {
- IsRepairMode = false;
- Revert_Mouse_Shape();
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::In_View -- Determines if cell is visible on screen. *
- * *
- * Use this routine to determine if the specified cell is visible on *
- * the display. This is a useful fact, since many display operations *
- * can be skipped if the cell is not visible. *
- * *
- * INPUT: cell -- The cell number to check. *
- * *
- * OUTPUT: bool; Is this cell visible on the display? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 04/30/1994 JLB : Created. *
- * 04/30/1994 JLB : Converted to member function. *
- *=============================================================================================*/
- bool DisplayClass::In_View(register CELL cell) const
- {
- if (cell & 0xC000) return(false);
- COORDINATE coord = Coord_Whole(Cell_Coord(cell));
- COORDINATE tcoord = Coord_Whole(TacticalCoord);
- if ((unsigned)(Coord_X(coord) - Coord_X(tcoord)) > TacLeptonWidth+CELL_LEPTON_W-1) return(false);
- if ((unsigned)(Coord_Y(coord) - Coord_Y(tcoord)) > TacLeptonHeight+CELL_LEPTON_H-1) return(false);
- return(true);
- }
- /***********************************************************************************************
- * DisplayClass::Closest_Free_Spot -- Finds the closest cell sub spot that is free. *
- * *
- * Use this routine to find the sub cell spot closest to the coordinate specified that is *
- * free from occupation. Typical use of this is for infantry destination calculation. *
- * *
- * INPUT: coord -- The coordinate to use as the starting point when finding the closest *
- * free spot. *
- * *
- * any -- Ignore occupation and just return the closest sub cell spot? *
- * *
- * OUTPUT: Returns with the coordinate of the closest free (possibly) sub cell location. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 09/22/1995 JLB : Created. *
- *=============================================================================================*/
- COORDINATE DisplayClass::Closest_Free_Spot(COORDINATE coord, bool any) const
- {
- if (coord & HIGH_COORD_MASK) {
- return(0x00800080);
- }
- return Map[coord].Closest_Free_Spot(coord, any);
- }
- /***********************************************************************************************
- * DisplayClass::Is_Spot_Free -- Determines if cell sub spot is free of occupation. *
- * *
- * Use this routine to determine if the coordinate (rounded to the nearest sub cell *
- * position) is free for placement. Typical use of this would be for infantry placement. *
- * *
- * INPUT: coord -- The coordinate to examine for "freeness". The coordinate is rounded to *
- * the nearest free sub cell spot. *
- * *
- * OUTPUT: Is the sub spot indicated by the coordinate free from previous occupation? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 09/22/1995 JLB : Created. *
- *=============================================================================================*/
- bool DisplayClass::Is_Spot_Free(COORDINATE coord) const
- {
- if (coord & HIGH_COORD_MASK) {
- return(0x00800080);
- }
- return Map[coord].Is_Spot_Free(CellClass::Spot_Index(coord));
- }
- /***********************************************************************************************
- * DisplayClass::Center_Map -- Centers the map about the currently selected objects *
- * *
- * This routine will average the position of all the selected objects and then center *
- * the map about those objects. *
- * *
- * INPUT: center -- The is an optional center about override coordinate. If specified, *
- * then the map will be centered about that coordinate. Otherwise it *
- * will center about the average location of all selected objects. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: The map position changes by this routine. *
- * *
- * HISTORY: *
- * 08/22/1995 JLB : Created. *
- * 09/16/1996 JLB : Takes coordinate to center about (as override). *
- *=============================================================================================*/
- void DisplayClass::Center_Map(COORDINATE center)
- {
- int x = 0;
- // unsigned x = 0;
- int y = 0;
- // unsigned y = 0;
- bool centerit = false;
- if (CurrentObject.Count()) {
- for (int index = 0; index < CurrentObject.Count(); index++) {
- COORDINATE coord = CurrentObject[index]->Center_Coord();
- x += Coord_X(coord);
- y += Coord_Y(coord);
- }
- x /= CurrentObject.Count();
- y /= CurrentObject.Count();
- centerit = true;
- }
- if (center != 0L) {
- x = Coord_X(center);
- y = Coord_Y(center);
- centerit = true;
- }
- if (centerit) {
- x = x - (int)TacLeptonWidth/2;
- if (x < Cell_To_Lepton(MapCellX)) x = Cell_To_Lepton(MapCellX);
- y = y - (int)TacLeptonHeight/2;
- if (y < Cell_To_Lepton(MapCellY)) y = Cell_To_Lepton(MapCellY);
- Set_Tactical_Position(XY_Coord(x, y));
- }
- }
- /***********************************************************************************************
- * DisplayClass::Encroach_Shadow -- Causes the shadow to creep back by one cell. *
- * *
- * This routine will cause the shadow to creep back by one cell. Multiple calls to this *
- * routine will result in the shadow becoming more and more invasive until only the sight *
- * range of player controlled units will keep the shadow pushed back. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/16/1995 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Encroach_Shadow(void)
- {
- for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
- if (!In_Radar(cell)) continue;
- CellClass * cellptr = &(*this)[cell];
- if (cellptr->IsVisible || !cellptr->IsMapped) continue;
- cellptr->IsToShroud = true;
- }
- /*
- ** Mark all shadow edge cells to be fully shrouded. All adjacent mapped
- ** cell should become partially shrouded.
- */
- for (cell = 0; cell < MAP_CELL_TOTAL; cell++) {
- if (!In_Radar(cell)) continue;
- if ((*this)[cell].IsToShroud) {
- (*this)[cell].IsToShroud = false;
- Shroud_Cell(cell);
- }
- }
- All_To_Look();
- Flag_To_Redraw(true);
- }
- /***********************************************************************************************
- * DisplayClass::Shroud_Cell -- Returns the specified cell into the shrouded condition. *
- * *
- * This routine is called to add the shroud back to the cell specified. Typical of this *
- * would be when the shroud is to regenerate. *
- * *
- * INPUT: cell -- The cell that the shroud is to be regenerated upon. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: Adjacent cells might be affected by this routine. The affect is determined *
- * according to the legality of the partial shadow artwork. In the illegal cases *
- * the adjacent cell might become shrouded as well. *
- * *
- * HISTORY: *
- * 10/17/1995 JLB : Created. *
- * 06/17/1996 JLB : Modified to handle the new shadow pieces. *
- *=============================================================================================*/
- void DisplayClass::Shroud_Cell(CELL cell/*KO, bool shadeit*/)
- {
- if (PlayerPtr->IsGPSActive) {
- if ( (*this)[cell].Jammed & (1 << PlayerPtr->Class->House) ) {
- return;
- }
- }
- if (!In_Radar(cell)) return;
- CellClass * cellptr = &(*this)[cell];
- if (cellptr->IsMapped) {
- cellptr->IsMapped = false;
- cellptr->IsVisible = false;
- cellptr->Redraw_Objects();
- /*
- ** Check adjacent cells. There might be some weird combination of
- ** shrouded cells such that more cells must be shrouded in order for
- ** this to work.
- */
- for (FacingType dir = FACING_FIRST; dir < FACING_COUNT; dir++) {
- CELL c = Adjacent_Cell(cell, dir);
- CellClass * cptr = &(*this)[c];
- /*
- ** If this adjacent cell must be completely shrouded as a result
- ** of the map change, yet it isn't already shrouded, then recursively
- ** shroud that cell.
- */
- if (c != cell) {
- cptr->IsVisible = false;
- }
- /*
- ** Always redraw the cell because, more than likely, the shroud
- ** edge will change shape because of the map change.
- */
- cptr->Redraw_Objects();
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::Read_INI -- Reads map control data from INI file. *
- * *
- * This routine is used to read the map control data from the INI *
- * file. *
- * *
- * INPUT: buffer -- Pointer to the loaded INI file data. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: The TriggerClass INI data must have been read before calling this function. *
- * *
- * HISTORY: *
- * 05/27/1994 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Read_INI(CCINIClass & ini)
- {
- /*
- ** Read the map dimensions.
- */
- char const * const name = "Map";
- int x = ini.Get_Int(name, "X", 1);
- int y = ini.Get_Int(name, "Y", 1);
- int w = ini.Get_Int(name, "Width", MAP_CELL_W-2);
- int h = ini.Get_Int(name, "Height", MAP_CELL_H-2);
- #ifndef FIXIT_VERSION_3 // Map size no longer restricted.
- #ifdef FIXIT_CSII // checked - ajw
- if(Session.Type >= GAME_MODEM && Session.Type <= GAME_INTERNET && PlayingAgainstVersion < VERSION_AFTERMATH_CS) {
- /*
- ** HACK ALERT:
- ** Force the map to be limited to the size that 96x96 would be. If the
- ** size is greater (due to hacking?) then shrink it down to legal size.
- ** BG Note: only do this for multiplayer games against non-AfterMath.
- */
- if (w * h > 96 * 96) {
- h -= (((w*h) - (96*96)) / w) + 1;
- }
- }
- #else
- /*
- ** HACK ALERT:
- ** Force the map to be limited to the size that 96x96 would be. If the
- ** size is greater (due to hacking?) then shrink it down to legal size.
- */
- if (w * h > 96 * 96) {
- h -= (((w*h) - (96*96)) / w) + 1;
- }
- #endif
- #endif // !FIXIT_VERSION_3
- Set_Map_Dimensions( x, y, w, h );
- /*
- ** The theater is determined at this point. There is specific data that
- ** is custom to this data. Load the custom data (as it related to terrain)
- ** at this point.
- */
- Scen.Theater = ini.Get_TheaterType(name, "Theater", THEATER_TEMPERATE);
- /*
- ** Remove any old theater specific uncompressed shapes
- */
- #ifdef WIN32
- if (Scen.Theater != LastTheater) {
- Reset_Theater_Shapes();
- }
- #endif //WIN32
- /*
- ** Now that the theater is known, init the entire map hierarchy
- */
- Init(Scen.Theater);
- /*
- ** Special initializations occur when the theater is known.
- */
- TerrainTypeClass::Init(Scen.Theater);
- TemplateTypeClass::Init(Scen.Theater);
- OverlayTypeClass::Init(Scen.Theater);
- UnitTypeClass::Init(Scen.Theater);
- InfantryTypeClass::Init(Scen.Theater);
- BuildingTypeClass::Init(Scen.Theater);
- BulletTypeClass::Init(Scen.Theater);
- AnimTypeClass::Init(Scen.Theater);
- AircraftTypeClass::Init(Scen.Theater);
- VesselTypeClass::Init(Scen.Theater);
- SmudgeTypeClass::Init(Scen.Theater);
- /*
- ** Read the Waypoint entries.
- */
- for (int i = 0; i < WAYPT_COUNT; i++) {
- char buf[20];
- sprintf(buf, "%d", i);
- Scen.Waypoint[i] = ini.Get_Int("Waypoints", buf, -1);
- if (Scen.Waypoint[i] != -1) {
- (*this)[Scen.Waypoint[i]].IsWaypoint = 1;
- }
- }
- /*
- ** Set the starting position (do this after Init(), which clears the cells'
- ** IsWaypoint flags).
- */
- if (Scen.Waypoint[WAYPT_HOME] == -1) {
- Scen.Waypoint[WAYPT_HOME] = XY_Cell(MapCellX + 5*RESFACTOR, MapCellY + 4*RESFACTOR);
- }
- Scen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = Scen.Waypoint[WAYPT_HOME];
- Set_Tactical_Position(Cell_Coord((Scen.Waypoint[WAYPT_HOME] - (MAP_CELL_W * 4 * RESFACTOR)) - (5*RESFACTOR)));
- /*
- ** Loop through all CellTrigger entries.
- */
- int len = ini.Entry_Count("CellTriggers");
- for (int index = 0; index < len; index++) {
- /*
- ** Get a cell trigger and cell assignment.
- */
- char const * cellentry = ini.Get_Entry("CellTriggers", index);
- TriggerTypeClass * tp = ini.Get_TriggerType("CellTriggers", cellentry);
- CELL cell = atoi(cellentry);
- if (tp != NULL && !(*this)[cell].Trigger.Is_Valid()) {
- TriggerClass * tt = Find_Or_Make(tp);
- if (tt) {
- tt->AttachCount++;
- tt->Cell = cell;
- (*this)[cell].Trigger = tt;
- }
- }
- }
- /*
- ** Read the map template data.
- */
- static char const * const MAPPACK = "MapPack";
- len = ini.Get_UUBlock(MAPPACK, _staging_buffer, sizeof(_staging_buffer));
- BufferStraw bstraw(_staging_buffer, len);
- Map.Read_Binary(bstraw);
- LastTheater = Scen.Theater;
- }
- /***********************************************************************************************
- * DisplayClass::Write_INI -- Write the map data to the INI file specified. *
- * *
- * This routine will output all the data of this map to the INI database specified. *
- * *
- * INPUT: ini -- Reference to the INI handler to store the map data to. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: Any existing map data in the INI database will be replaced by this function. *
- * *
- * HISTORY: *
- * 07/03/1996 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Write_INI(CCINIClass & ini)
- {
- char entry[20];
- /*
- ** Save the map parameters.
- */
- static char const * const NAME = "Map";
- ini.Clear(NAME);
- ini.Put_TheaterType(NAME, "Theater", Scen.Theater);
- ini.Put_Int(NAME, "X", MapCellX);
- ini.Put_Int(NAME, "Y", MapCellY);
- ini.Put_Int(NAME, "Width", MapCellWidth);
- ini.Put_Int(NAME, "Height", MapCellHeight);
- /*
- ** Save the Waypoint entries.
- */
- static char const * const WAYNAME = "Waypoints";
- ini.Clear(WAYNAME);
- for (int i = 0; i < WAYPT_COUNT; i++) {
- if (Scen.Waypoint[i] != -1) {
- sprintf(entry, "%d", i);
- ini.Put_Int(WAYNAME, entry, Scen.Waypoint[i]);
- }
- }
- /*
- ** Save the cell's triggers.
- */
- static char const * const CELLTRIG = "CellTriggers";
- ini.Clear(CELLTRIG);
- for (CELL cell = 0; cell < MAP_CELL_TOTAL; cell++) {
- if ((*this)[cell].Trigger.Is_Valid()) {
- TriggerClass * tp = (*this)[cell].Trigger;
- if (tp != NULL) {
- /*
- ** Generate entry name.
- */
- sprintf(entry, "%d", cell);
- /*
- ** Save entry.
- */
- ini.Put_TriggerType(CELLTRIG, entry, tp->Class);
- }
- }
- }
- /*
- ** Write the map template data out to the ini file.
- */
- static char const * const MAPPACK = "MapPack";
- BufferPipe bpipe(_staging_buffer, sizeof(_staging_buffer));
- int len = Map.Write_Binary(bpipe);
- ini.Clear(MAPPACK);
- if (len) {
- ini.Put_UUBlock(MAPPACK, _staging_buffer, len);
- }
- }
- /***********************************************************************************************
- * DisplayClass::All_To_Look -- Direct all objects to look around for the player. *
- * *
- * This routine will scan through all objects and tell them to look if they are supposed *
- * to be able to reveal the map for the player. This routine may be necessary in cases *
- * of gap generator reshroud logic. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 09/23/1996 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::All_To_Look(bool units_only)
- {
- for (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {
- ObjectClass * object = Layer[LAYER_GROUND][index];
- if (object != NULL && object->Is_Techno()) {
- TechnoClass * tech = ((TechnoClass *)object);
- if (tech->What_Am_I() == RTTI_BUILDING && units_only) continue;
- if (tech->House->IsPlayerControl) {
- if (tech->IsDiscoveredByPlayer) {
- object->Look();
- }
- } else {
- if (tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr)) {
- tech->Look();
- }
- }
- }
- }
- }
- void DisplayClass::Constrained_Look(COORDINATE center, LEPTON distance)
- {
- for (int index = 0; index < Layer[LAYER_GROUND].Count(); index++) {
- ObjectClass * object = Layer[LAYER_GROUND][index];
- if (object != NULL && object->Is_Techno()) {
- TechnoClass * tech = ((TechnoClass *)object);
- // if (tech->What_Am_I() == RTTI_BUILDING && units_only) continue;
- if (tech->House->IsPlayerControl) {
- if (tech->IsDiscoveredByPlayer && Distance(tech->Center_Coord(), center) <= (tech->Techno_Type_Class()->SightRange * CELL_LEPTON_W) + distance) {
- object->Look();
- }
- } else {
- if (tech->What_Am_I() == RTTI_BUILDING && Rule.IsAllyReveal && tech->House->Is_Ally(PlayerPtr) &&
- Distance(tech->Center_Coord(), center) <= (tech->Techno_Type_Class()->SightRange * CELL_LEPTON_W) + distance) {
- tech->Look();
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * DisplayClass::Flag_Cell -- Flag the specified cell to be redrawn. *
- * *
- * This will flag the cell to be redrawn. *
- * *
- * INPUT: cell -- The cell to be flagged. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 10/20/1996 JLB : Created. *
- *=============================================================================================*/
- void DisplayClass::Flag_Cell(CELL cell)
- {
- Flag_To_Redraw(false);
- IsToRedraw = true;
- CellRedraw[cell] = true;
- }
|