| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- #ifdef WOLAPI_INTEGRATION // Now implies also WINSOCK_IPX, WIN32, and FIXIT_CSII must be true
- #include "wol_gsup.h"
- #include "function.h"
- #include "IconList.h"
- #include <time.h>
- #include "WolStrng.h"
- #include "wsproto.h"
- #include "BigCheck.h"
- #include "ToolTip.h"
- extern char const* EngMisStr[];
- bool Is_Mission_126x126 (char *file_name);
- bool Is_Mission_Aftermath (char *file_name);
- bool Is_Mission_Counterstrike (char *file_name);
- bool Force_Scenario_Available( const char* szName );
- int ScenarioIndex_From_Filename( const char* szScenarioFilename );
- bool bSpecialAftermathScenario( const char* szScenarioDescription );
- #include "WolDebug.h"
- #define PARAMREFRESHWAIT 2000
- #define PING_AND_DISPLAY_WAIT 5000
- void WOL_PrintMessage( IconListClass& ILTarget, const char* szText, PlayerColorType iColorRemap = PCOLOR_NONE );
- void WOL_PrintMessage( IconListClass& ILTarget, const char* szText, RemapControlType* pColorRemap );
- void CC_Draw_DIB( const char* pDIB, int xDest, int yDest, int iWidth, WindowNumberType window );
- bool operator==( const GAMEPARAMS& gp1, const GAMEPARAMS& gp2 );
- bool operator==( const GlobalPacketType& gp1, const GlobalPacketType& gp2 );
- PlayerColorType PlayerColorTypeOf( RemapControlType* pColorRemap );
- extern unsigned long PlanetWestwoodStartTime; //Time that game was started
- extern bool cancel_current_msgbox;
- extern bool disable_current_msgbox;
- void Debug_GlobalPacketType( const GlobalPacketType& gp1 );
- //***********************************************************************************************
- /* Game startup logic:
- When a guest joins the channel, the host sends all current setup info.
- When a guest changes house, he tells the host, who informs everyone. A house change can't be denied.
- When a guest changes color, he asks the host for the new color, and assumes the request will go through. If it doesn't, the
- host sends the guest a messages setting him back to the old color, otherwise, everyone gets the new color for the guest.
- When the host changes a game param, the change will be noticed within PARAMREFRESHWAIT milliseconds and then transmitted to
- all guests.
- All player specific information is stored within the players list (IconListClass), and nowhere else. Though this storage
- method got a bit inelegant, it gets the job done.
- All "informs" (messages sent from host to guest) except color changes (WOL_GAMEOPT_INFCOLOR) and player "accept" status
- changes (WOL_GAMEOPT_INFACCEPT) are assigned a ID, which
- increments on each send. Color informs are: a) not a condition for removing a guest's "accept" status, and b) sent out to
- individual guests in certain cases, and would thus complicate the ID tracking scheme.
- When a guest "accepts" the game setup (with a WOL_GAMEOPT_REQACCEPT), the latest received ID is included in the message.
- If the host receives a WOL_GAMEOPT_REQACCEPT with an out-of-date ID, the accept is ignored. Though the guest sets himself to
- "accepted" when he sends the WOL_GAMEOPT_REQACCEPT, if it gets ignored by the host it is because a new inform is already on its
- way, which will reset the guest's own status to "not accepted" when it arrives.
- Host clears all accepteds when params are changed, player joins or leaves, or house change message arrives. Though a
- WOL_GAMEOPT_INFACCEPT is sent out when a guest accepts, there is no corresponding "unaccept all" message sent out at this point,
- as all guests will naturally clear their recorded accept status for everyone when the change arrives there.
- Guest clears own accepted when an inform from the server other than color change arrives, player joins or leaves, or own
- house is directly changed.
- When all players are "accepted", and the host says "start", a WOL_GAMEOPT_INFSTART is sent to all guests and the host goes into
- "waiting to start" mode. If a house change or other arrives in this phase, host clears waiting mode and (naturally) marks guests
- unaccepted and sends out the house change to the guests. (The same applies to player joins/leaves.)
- While in this mode, the host user is locked out of making any changes to game params.
- If a change does come in during this phase, a WOL_GAMEOPT_INFCANCELSTART is sent to the guests, and the waiting mode cancelled.
- When a guest receives WOL_GAMEOPT_INFSTART: If he does not see himself as accepted, it is because a change has just been sent
- to the host, or some other event occurred that the host will learn about, so the guest can simply ignore the WOL_GAMEOPT_INFSTART.
- If the guest does see himself as accepted when WOL_GAMEOPT_INFSTART arrives, he responds with WOL_GAMEOPT_REQSTART and goes into
- "waiting to start" mode. When in this mode, the user is locked out of making any changes.
- Note that the host is not really asking for any sort of "confirmation that it's ok" to start from the guest here. (Hence no
- "cancel" response is possible.) It's really just a way of telling the guests not to make any more changes to the setup; it's
- like we're making sure we've "flushed the queue" of game changes.
- If a guest receives a WOL_GAMEOPT_INFCANCELSTART, he cancels out of "waiting to start" mode. Note that while in the waiting
- mode, normal processing of messages is allowed to take place - the user is simply blocked from doing anything.
- Presumably (hopefully) this phase will last less than a second.
- When the host receives a WOL_GAMEOPT_REQSTART from everyone, he tells everyone to start with a WOL_GAMEOPT_INFGO.
- Because there is a chance of color changes being out of sync, all player colors are sent to all guests at this point.
- There is no chance of other data being out of sync.
- */
- //--------------------------------------------------------------------------
- // Pieced together from Net_New_Dialog() and Net_Join_Dialog().
- //--------------------------------------------------------------------------
- //***********************************************************************************************
- WOL_GameSetupDialog::WOL_GameSetupDialog( WolapiObject* pWO, bool bHost ) : pWO( pWO ), bHost( bHost ),
- HousePrevious( HOUSE_NONE ),
- pILPlayers( NULL ),
- pILScens( NULL ),
- pILDisc( NULL ),
- pEditSend( NULL ),
- pGaugeCount( NULL ),
- pGaugeLevel( NULL ),
- pGaugeCredits( NULL ),
- pGaugeAIPlayers( NULL ),
- pCheckListOptions( NULL ),
- // pTextBtnOk( NULL ),
- pTextBtnCancel( NULL ),
- pTextBtnAcceptStart( NULL ),
- pTextBtnAction( NULL ),
- pStaticDescrip( NULL ),
- pStaticUnit( NULL ),
- pStaticLevel( NULL ),
- pStaticCredits( NULL ),
- pStaticAIPlayers( NULL ),
- pDropListHouse( NULL ),
- pCheckAftermathUnits( NULL ),
- nHostLastParamID( 0 ),
- nGuestLastParamID( 0 ),
- bWaitingToStart( false ),
- bParamsReceived( false ),
- bHostSayGo( false ),
- bExitForGameTrigger( false ),
- pToolTipHead( NULL ),
- pToolTipHitLast( NULL ),
- pTTipAcceptStart( NULL ),
- pTTipCancel( NULL ),
- pTTipAction( NULL ),
- ScenKindCurrent( SCENARIO_UNINITIALIZED ),
- pShpBtnScenarioRA( NULL ),
- pShpBtnScenarioCS( NULL ),
- pShpBtnScenarioAM( NULL ),
- pShpBtnScenarioUser( NULL ),
- bLeaveDueToRulesMismatchTrigger( false ),
- bHostWaitingForGoTrigger( false )
- {
- *szSendBuffer = 0;
- *szHouseBuffer = 0;
- memset( &GParamsLastSent, 0, sizeof( GAMEPARAMS ) );
- *szNameOfHostWhoJustBailedOnUs = 0;
- *szTriggerGameStartInfo = 0;
- }
- //***********************************************************************************************
- WOL_GameSetupDialog::~WOL_GameSetupDialog()
- {
- delete pILPlayers;
- delete pILScens;
- delete pILDisc;
- delete pEditSend;
- delete pGaugeCount;
- delete pGaugeLevel;
- delete pGaugeCredits;
- delete pGaugeAIPlayers;
- delete pCheckListOptions;
- // delete pTextBtnOk;
- delete pTextBtnCancel;
- delete pTextBtnAcceptStart;
- delete pTextBtnAction;
- // delete pStaticDescrip;
- delete pStaticUnit;
- delete pStaticLevel;
- delete pStaticCredits;
- delete pStaticAIPlayers;
- delete pDropListHouse;
- delete pCheckAftermathUnits;
- delete pTTipAcceptStart;
- delete pTTipCancel;
- delete pTTipAction;
- delete pShpBtnScenarioRA;
- delete pShpBtnScenarioCS;
- delete pShpBtnScenarioAM;
- delete pShpBtnScenarioUser;
- }
- //***********************************************************************************************
- RESULT_WOLGSUP WOL_GameSetupDialog::Run()
- {
- Initialize();
- return Show();
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::Initialize()
- {
- //------------------------------------------------------------------------
- // Dialog & button dimensions
- //------------------------------------------------------------------------
- d_dialog_w = 640; // dialog width
- d_dialog_h = 400; // dialog height
- d_dialog_x = 0;
- d_dialog_y = 0;
- d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- d_txt6_h = 6*RESFACTOR+1; // ht of 6-pt text
- int d_text_h = 12;
- d_margin1 = 34; // large margin
- d_color_w = 10 *RESFACTOR;
- d_color_h = 9 *RESFACTOR;
- d_color_x = 294; //54; //d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);
- d_color_y = 89; //142; //d_house_y;
- d_house_w = 60 *RESFACTOR;
- d_house_h = (8 * 5 *RESFACTOR);
- d_house_x = 466; //65; //d_color_x; //d_dialog_cx - (d_house_w / 2);
- d_house_y = d_color_y; // + 36; //d_dialog_y + ( 7 * RESFACTOR ) + d_txt6_h + (2*RESFACTOR);
- if( bHost )
- d_disc_w = 365; //d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;
- else
- d_disc_w = d_dialog_w - ( d_margin1 * 2 );
- d_disc_x = d_dialog_x + d_margin1;
- d_disc_y = 205; //d_dialog_y + d_dialog_h - ( 65 + d_disc_h );
- d_disc_h = 337 - d_disc_y;
- d_playerlist_w = 124*RESFACTOR;
- d_playerlist_h = d_text_h * 4 + 4;
- d_playerlist_x = d_dialog_x + d_margin1;
- d_playerlist_y = 75; //d_dialog_y + d_margin1 + d_txt6_h + 3*RESFACTOR + 18 * RESFACTOR;
- int d_tab_h = 19;
- d_scenariolist_w = 200;
- // d_scenariolist_h = (4 * d_txt6_h) + 3*RESFACTOR; // 4 rows high
- d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_scenariolist_w;
- d_scenariolist_y = d_disc_y + d_tab_h;
- d_scenariolist_h = d_disc_y + d_disc_h - d_scenariolist_y;
- d_gamekind_w = 182;
- d_gamekind_h = 30;
- d_gamekind_x = 52; // 370;
- d_gamekind_y = 153; // d_playerlist_y + d_text_h + 3; // + d_playerlist_h - d_text_h;
- d_count_w = 25*RESFACTOR;
- d_count_h = d_txt6_h;
- d_count_x = 310;
- d_count_y = 138; //d_playerlist_y + d_playerlist_h + d_margin2 + 9*RESFACTOR;
- d_level_w = 25*RESFACTOR;
- d_level_h = d_txt6_h;
- d_level_x = d_count_x;
- d_level_y = d_count_y + d_count_h;
- d_credits_w = 25*RESFACTOR;
- d_credits_h = d_txt6_h;
- d_credits_x = d_count_x;
- d_credits_y = d_level_y + d_level_h;
- d_aiplayers_w = 25*RESFACTOR;
- d_aiplayers_h = d_txt6_h;
- d_aiplayers_x = d_count_x;
- d_aiplayers_y = d_credits_y + d_credits_h;
- #ifdef GERMAN
- d_options_w = 186;
- #else
- d_options_w = 180;
- #endif
- d_options_h = ((6 * 6) + 4)*RESFACTOR + 1;
- d_options_x = d_dialog_x + d_dialog_w - d_options_w - d_margin1;
- d_options_y = 127 - d_txt6_h + 2;
- d_send_w = d_dialog_w - ( d_margin1 * 2 );
- d_send_h = 9*RESFACTOR;
- d_send_x = d_dialog_x + d_margin1;
- d_send_y = d_disc_y + d_disc_h + 5;
- // d_ok_w = 50*RESFACTOR;
- // d_ok_h = 9*RESFACTOR;
- // d_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2);
- // d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - 3*RESFACTOR;
- d_cancel_w = 100;
- d_cancel_h = 9*RESFACTOR;
- d_cancel_x = d_dialog_x + 100; //d_dialog_cx - (d_cancel_w / 2);
- d_cancel_y = 365; //d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - 3*RESFACTOR;
- d_accept_w = 100;
- d_accept_h = 9 *RESFACTOR;
- d_accept_x = d_dialog_x + 210;
- d_accept_y = d_cancel_y; //d_dialog_y + d_dialog_h - 17*RESFACTOR;
- d_action_w = 100;
- d_action_h = 9 *RESFACTOR;
- d_action_x = d_dialog_x + 500;
- d_action_y = d_cancel_y;
- /* int d_load_w = 50*RESFACTOR;
- int d_load_h = 9*RESFACTOR;
- int d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2);
- int d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - 3*RESFACTOR;
- */
- d_amunits_w = 160;
- d_amunits_h = 18;
- d_amunits_x = d_dialog_x + (d_dialog_w / 6) - (d_amunits_w / 2);
- d_amunits_y = 365;
- ToolTipClass* pToolTip = pToolTipHead = pWO->pTTipDiscon;
- pToolTip->next = pWO->pTTipLeave;
- pToolTip = pToolTip->next;
- pToolTip->next = pWO->pTTipRefresh;
- pToolTip = pToolTip->next;
- pToolTip->next = pWO->pTTipSquelch;
- pToolTip = pToolTip->next;
- pToolTip->next = pWO->pTTipBan;
- pToolTip = pToolTip->next;
- pToolTip->next = pWO->pTTipKick;
- pToolTip = pToolTip->next;
- pToolTip->next = pWO->pTTipFindpage;
- pToolTip = pToolTip->next;
- pToolTip->next = pWO->pTTipOptions;
- pToolTip = pToolTip->next;
- pToolTip->next = pWO->pTTipLadder;
- pToolTip = pToolTip->next;
- pToolTip->next = pWO->pTTipHelp;
- pILPlayers = new IconListClass( BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TYPE, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"), true, 2 );
- // ListClass scenariolist(BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"));
- pILScens = new IconListClass( BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TYPE, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"), true, 1 );
- pILDisc = new IconListClass( BUTTON_DISCLIST, d_disc_x, d_disc_y, d_disc_w, d_disc_h, TPF_TYPE, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"), true, 0, 300 );
- pEditSend = new EditClass( BUTTON_SENDEDIT, szSendBuffer, MAXCHATSENDLENGTH, TPF_TEXT, d_send_x, d_send_y, d_send_w, d_send_h );
- // TextButtonClass rejectbtn( BUTTON_REJECT, TXT_REJECT, TPF_BUTTON, d_reject_x, d_reject_y );
- pGaugeCount = new GaugeClass( BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h );
- pGaugeLevel = new GaugeClass( BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h );
- pGaugeCredits = new GaugeClass( BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h );
- pGaugeAIPlayers = new GaugeClass( BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h );
- pCheckListOptions = new CheckListClass( BUTTON_PARAMS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP") );
- // pTextBtnOk = new TextButtonClass( BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, 60*RESFACTOR );
- // TextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, 60*RESFACTOR);
- pTextBtnCancel = new TextButtonClass( BUTTON_CANCEL, TXT_WOL_CANCELGAME, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w );
- pTTipCancel = new ToolTipClass( pTextBtnCancel, TXT_WOL_TTIP_CANCELGAME, d_cancel_x + d_cancel_w/2, d_cancel_y - 6 );
- if( bHost )
- {
- pTextBtnAcceptStart = new TextButtonClass( BUTTON_ACCEPTSTART, TXT_WOL_STARTBUTTON, TPF_BUTTON, d_accept_x, d_accept_y, d_accept_w );
- pTTipAcceptStart = new ToolTipClass( pTextBtnAcceptStart, TXT_WOL_TTIP_START, d_accept_x + d_accept_w/2, d_accept_y - 6 );
- }
- else
- {
- pTextBtnAcceptStart = new TextButtonClass( BUTTON_ACCEPTSTART, TXT_WOL_ACCEPTBUTTON, TPF_BUTTON, d_accept_x, d_accept_y, d_accept_w );
- pTTipAcceptStart = new ToolTipClass( pTextBtnAcceptStart, TXT_WOL_TTIP_ACCEPT, d_accept_x + d_accept_w/2, d_accept_y - 6 );
- }
- pTextBtnAction = new TextButtonClass( BUTTON_ACTION, TXT_WOL_ACTION, TPF_BUTTON, d_action_x, d_action_y, d_action_w );
- pTTipAction = new ToolTipClass( pTextBtnAction, TXT_WOL_TTIP_ACTION, d_action_x + d_action_w/2, d_action_y - 6, true );
- pToolTip = pToolTip->next;
- pToolTip->next = pTTipCancel;
- pToolTip = pToolTip->next;
- pToolTip->next = pTTipAcceptStart;
- pToolTip = pToolTip->next;
- pToolTip->next = pTTipAction;
- pToolTip = pToolTip->next;
- pToolTip->next = NULL;
- if( bHost )
- pTextBtnAcceptStart->Disable();
- // pStaticDescrip is no longer used - can't get the bloody thing to clip text. You'd think a StaticButton control would.
- // pStaticDescrip = new StaticButtonClass( 0, "", TPF_TYPE, d_gamekind_x, d_gamekind_y, d_gamekind_w, d_gamekind_h );
- pStaticUnit = new StaticButtonClass( 0, " ", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y );
- pStaticLevel = new StaticButtonClass( 0, " ", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y );
- pStaticCredits = new StaticButtonClass( 0, " ", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y );
- pStaticAIPlayers = new StaticButtonClass( 0, " ", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y );
- Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT);
- pDropListHouse = new DropListClass( BUTTON_HOUSE, szHouseBuffer, sizeof( szHouseBuffer ),
- TPF_TEXT,
- d_house_x, d_house_y, d_house_w, d_house_h,
- MFCD::Retrieve("BTN-UP.SHP"),
- MFCD::Retrieve("BTN-DN.SHP") );
- // ajw - This checkbox is not used. Could be turned on, though.
- pCheckAftermathUnits = new BigCheckBoxClass( BUTTON_AFTERMATHUNITS, d_amunits_x, d_amunits_y, d_amunits_w, d_amunits_h,
- "Aftermath units enabled", TPF_TEXT, false );
- if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME )
- {
- bAftermathUnits = true;
- int current_drive = CCFileClass::Get_CD_Drive();
- int cd_index = Get_CD_Index(current_drive, 1*60);
- if( cd_index != 3 && cd_index != 5 )
- {
- WOL_PrintMessage( *pILDisc, TXT_WOL_AMDISCNEEDED, WOLCOLORREMAP_LOCALMACHINEMESS );
- }
- }
- else
- {
- bAftermathUnits = false;
- pCheckAftermathUnits->Disable();
- }
- bSlowUnitBuildRate = true;
- #define TABSPACING 38
- pShpBtnScenarioRA = new ShapeButtonClass( BUTTON_SCENARIO_RA, MFCD::Retrieve( "tabra.shp" ), d_scenariolist_x, d_scenariolist_y - d_tab_h );
- pShpBtnScenarioCS = new ShapeButtonClass( BUTTON_SCENARIO_CS, MFCD::Retrieve( "tabcs.shp" ), d_scenariolist_x + TABSPACING, d_scenariolist_y - d_tab_h );
- pShpBtnScenarioAM = new ShapeButtonClass( BUTTON_SCENARIO_AM, MFCD::Retrieve( "tabam.shp" ), d_scenariolist_x + TABSPACING, d_scenariolist_y - d_tab_h );
- int iScenarioUserTabPos;
- if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::CSGAME || pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||
- ( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::RAGAME && Is_Aftermath_Installed() && !pWO->GameInfoCurrent.bTournament ) )
- // Place user tab in the third tab position. (It may still not be present.)
- iScenarioUserTabPos = d_scenariolist_x + TABSPACING * 2;
- else
- iScenarioUserTabPos = d_scenariolist_x + TABSPACING;
- pShpBtnScenarioUser = new ShapeButtonClass( BUTTON_SCENARIO_USER, MFCD::Retrieve( "tabus.shp" ), iScenarioUserTabPos, d_scenariolist_y - d_tab_h );
- // Change draw behavior of tab buttons.
- pShpBtnScenarioRA->ReflectButtonState = true;
- pShpBtnScenarioCS->ReflectButtonState = true;
- pShpBtnScenarioAM->ReflectButtonState = true;
- pShpBtnScenarioUser->ReflectButtonState = true;
- if( !bHost )
- {
- pILScens->Disable();
- pGaugeCount->Disable();
- pGaugeLevel->Disable();
- pGaugeCredits->Disable();
- pGaugeAIPlayers->Disable();
- pCheckListOptions->Disable();
- pCheckAftermathUnits->Disable();
- }
- pWO->LinkToGameDlg( pILDisc, pILPlayers );
- pWO->pGSupDlg = this;
- dwTimeNextParamRefresh = ::timeGetTime();
- }
- //***********************************************************************************************
- RESULT_WOLGSUP WOL_GameSetupDialog::Show()
- {
- // Returns: -1 == return to chat dialog.
- //------------------------------------------------------------------------
- // Dialog variables
- //------------------------------------------------------------------------
- bool bHackFocus = true;
- display = REDRAW_ALL; // redraw level
- bProcess = true; // process while true
- KeyNumType input;
- DWORD timeWaitingToStartTimeout;
- char szScenarioNameDisplay[ 300 ];
- bool bInformParamChange;
- long ok_timer = 0; // for timing OK button
- int i;
- int tabs[] = {77*RESFACTOR}; // tabs for player list box
- int optiontabs[] = {8*RESFACTOR}; // tabs for option list box
- CCFileClass loadfile ("SAVEGAME.NET");
- int load_game = 0; // 1 = load a saved game
- RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
- int cbox_x[] = {
- d_color_x,
- d_color_x + d_color_w,
- d_color_x + (d_color_w * 2),
- d_color_x + (d_color_w * 3),
- d_color_x + (d_color_w * 4),
- d_color_x + (d_color_w * 5),
- d_color_x + (d_color_w * 6),
- d_color_x + (d_color_w * 7),
- };
- bool bRetractHouseDropDown = false;
- if( !pWO->OnEnteringGameSetup() ) // Gets a userlist setup, among other things.
- strcpy( szNameOfHostWhoJustBailedOnUs, TXT_WOL_THEGAMEHOST ); // Will cause immediate exit.
- // If I'm not already listed with a color, give myself a color.
- // (I may have already received my assigned color from the game host.)
- int iItem = pILPlayers->Find( pWO->szMyName ); // (I must be in the list I just got.)
- _ASSERTE( iItem != -1 );
- RemapControlType* pColorRemap = pILPlayers->Get_Item_Color( iItem );
- PlayerColorType Color = PlayerColorTypeOf( pColorRemap );
- // debugprint( "Starting up, I see myself as color %i\n", Color );
- if( Color == PCOLOR_NONE )
- SetPlayerColor( pWO->szMyName, ColorNextAvailable() ); // Unless I'm host, this will be changed quite immediately,
- // but nice to have it be a valid value until then.
- DWORD dwTimeNextPlayerPing = ::timeGetTime() + PING_AND_DISPLAY_WAIT;
- DWORD dwTimeNextPingDisplay = dwTimeNextPlayerPing + 1500; // Stagger ping and ping display periods.
- //------------------------------------------------------------------------
- // Build the button list
- //------------------------------------------------------------------------
- BindControls( true );
- pILPlayers->Set_Tabs(tabs);
- // If we have not already received a param update from a host, set default param values.
- if( !bParamsReceived )
- {
- if( !bHost )
- // Accept button disabled until first params arrive.
- pTextBtnAcceptStart->Disable();
- Special.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag; // Ugh. Use of "Special" global.
- if( bHost ) {
- Session.Options.Credits = Rule.MPDefaultMoney; // init credits & credit buffer
- Session.Options.Bases = Rule.IsMPBasesOn; // init scenario parameters
- Session.Options.Tiberium = Rule.IsMPTiberiumGrow;
- Session.Options.Goodies = Rule.IsMPCrates;
- Session.Options.AIPlayers = 0;
- Session.Options.UnitCount = (SessionClass::CountMax[Session.Options.Bases] + SessionClass::CountMin[Session.Options.Bases]) / 2;
- //first_time = 0;
- }
- //------------------------------------------------------------------------
- // Init other scenario parameters
- //------------------------------------------------------------------------
- Special.IsTGrowth = Session.Options.Tiberium; // Ugh. Use of "Special" global.
- Rule.IsTGrowth = Session.Options.Tiberium;
- Special.IsTSpread = Session.Options.Tiberium; // Ugh. Use of "Special" global.
- Rule.IsTSpread = Session.Options.Tiberium;
- if( bHost )
- {
- //------------------------------------------------------------------------
- // Set up array of lists of available scenarios.
- //------------------------------------------------------------------------
- for( i = 0; i < Session.Scenarios.Count(); i++ )
- {
- // Reworking of the loop previously used for language translation. (What a hack I have inherited...)
- MultiMission* pMMission = Session.Scenarios[ i ];
- const char* szScenarioNameShow = pMMission->Description();
- #if defined( GERMAN ) || defined( FRENCH )
- for( int j = 0; EngMisStr[j] != NULL; j++ )
- {
- if( !strcmp( szScenarioNameShow, EngMisStr[j] ) )
- {
- // Found description in translation array that matches mission.
- szScenarioNameShow = EngMisStr[ j + 1 ];
- break;
- }
- }
- // (If no match found, defaults to English description.)
- #endif
- // Place scenario name in a specific scenario list.
- if( pMMission->Get_Official() )
- {
- if( Is_Mission_Counterstrike( (char*)( Session.Scenarios[i]->Get_Filename() ) ) )
- {
- // debugprint( " ---------------- Adding scenario %s as CS\n", szScenarioNameShow );
- ar_szScenarios[ SCENARIO_CS ].Add( szScenarioNameShow );
- ar_szScenIndexes[ SCENARIO_CS ].Add( (void*)i );
- }
- else if( Is_Mission_Aftermath( (char*)( Session.Scenarios[i]->Get_Filename() ) ) )
- {
- // debugprint( " ---------------- Adding scenario %s as AM\n", szScenarioNameShow );
- // If this is not an Aftermath game channel, we must filter out any AM maps that have
- // special AM units on them.
- if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||
- !bSpecialAftermathScenario( pMMission->Description() ) )
- {
- ar_szScenarios[ SCENARIO_AM ].Add( szScenarioNameShow );
- ar_szScenIndexes[ SCENARIO_AM ].Add( (void*)i );
- }
- }
- else
- {
- // debugprint( " ---------------- Adding scenario %s as RA\n", szScenarioNameShow );
- ar_szScenarios[ SCENARIO_RA ].Add( szScenarioNameShow );
- ar_szScenIndexes[ SCENARIO_RA ].Add( (void*)i );
- }
- }
- else
- {
- // debugprint( " ---------------- Adding scenario %s as User\n", szScenarioNameShow );
- ar_szScenarios[ SCENARIO_USER ].Add( szScenarioNameShow );
- ar_szScenIndexes[ SCENARIO_USER ].Add( (void*)i );
- }
- }
- // Set default scenario list viewing mode and prepare tab buttons.
- /* switch( pWO->GameInfoCurrent.GameKind )
- {
- case CREATEGAMEINFO::RAGAME:
- ScenarioDisplayMode( SCENARIO_RA );
- break;
- case CREATEGAMEINFO::CSGAME:
- ScenarioDisplayMode( SCENARIO_CS );
- break;
- case CREATEGAMEINFO::AMGAME:
- ScenarioDisplayMode( SCENARIO_AM );
- break;
- default:
- // debugprint( "Illegal GameInfoCurrent value." );
- Fatal( "Illegal GameInfoCurrent value." );
- }
- */
- Session.Options.ScenarioIndex = 0; // 1st scenario is selected
- ScenarioDisplayMode( SCENARIO_RA ); // Always start on RedAlert tab. Next line depends on selected item in
- // list matching selected scenario.
- // pStaticDescrip->Set_Text( pILScens->Get_Item( pILScens->Current_Index() ), false );
- strcpy( szScenarioNameDisplay, pILScens->Get_Item( pILScens->Current_Index() ) );
- }
- Seed = rand();
- }
- //------------------------------------------------------------------------
- // Init button states
- //------------------------------------------------------------------------
- pCheckListOptions->Set_Tabs(optiontabs);
- pCheckListOptions->Set_Read_Only(0);
- pCheckListOptions->Add_Item(Text_String(TXT_BASES));
- pCheckListOptions->Add_Item(Text_String(TXT_ORE_SPREADS));
- pCheckListOptions->Add_Item(Text_String(TXT_CRATES));
- pCheckListOptions->Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));
- pCheckListOptions->Add_Item(Text_String(TXT_SHADOW_REGROWS));
- pCheckListOptions->Add_Item(TXT_WOL_SLOWUNITBUILD);
- SetSpecialControlStates();
- //........................................................................
- // House buttons
- //........................................................................
- for (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {
- pDropListHouse->Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));
- }
- pDropListHouse->Set_Selected_Index(Session.House - HOUSE_USSR);
- pDropListHouse->Set_Read_Only (true);
- bInformParamChange = false;
- // PlayingAgainstVersion = VerNum.Version_Number();
- //------------------------------------------------------------------------
- // Init random-number generator, & create a seed to be used for all random
- // numbers from here on out
- //------------------------------------------------------------------------
- srand(time(NULL));
- //------------------------------------------------------------------------
- // Init the version-clipping system
- //------------------------------------------------------------------------
- VerNum.Init_Clipping();
- // Load_Title_Page(true);
- // CCPalette.Set(); //GamePalette.Set();
- //
- // Now init the max range of the AI players slider.
- //
- // pGaugeAIPlayers->Set_Maximum(Rule.MaxPlayers-Session.Players.Count());
- // pGaugeAIPlayers->Set_Value(Session.Options.AIPlayers);
- Sound_Effect( WOLSOUND_ENTERGAME );
- //------------------------------------------------------------------------
- // Processing loop
- //------------------------------------------------------------------------
- while (bProcess) {
- #if(SHOW_MONO)
- Ipx.Mono_Debug_Print(-1,0);
- #endif
- // Check for change of house. Occurs on first loop and when user changes house.
- if( HousePrevious != Session.House )
- {
- if( bHost )
- {
- // Host changed house.
- // Do processing as if we'd received a message from a guest.
- // Set house in our own list.
- SetPlayerHouse( pWO->szMyName, Session.House );
- // Tell guests.
- nHostLastParamID++;
- InformAboutPlayerHouse( pWO->szMyName, Session.House, NULL );
- HousePrevious = Session.House;
- ClearAllAccepts();
- }
- else
- {
- User* pUserHost = pWO->pGameHost();
- if( pUserHost ) // Else we have not received the user list yet and don't know who the host is.
- // We'll keep trying this until we get a host - HousePrevious keeps us triggering until then.
- {
- // debugprint( "Session.House changed.\n" );
- // Tell host we changed our house.
- char szSend[ 20 ];
- sprintf( szSend, "%02u %02u", WOL_GAMEOPT_REQHOUSE, Session.House );
- pWO->SendGameOpt( szSend, pUserHost );
- // Set house in our own list. This is fine because we know that the change must be affirmed by the host.
- SetPlayerHouse( pWO->szMyName, Session.House );
- HousePrevious = Session.House;
- }
- }
- }
- // Regularly ping other players to assess latencies.
- // Display of ping results is on a parallel timer, slightly behind the ping so that we'll be likely to have
- // a fresh average to show. Not too big a deal if OnPings haven't arrived by then (though they should have).
- if( ::timeGetTime() > dwTimeNextPlayerPing )
- {
- pWO->RequestPlayerPings();
- dwTimeNextPlayerPing = ::timeGetTime() + PING_AND_DISPLAY_WAIT;
- }
- if( ::timeGetTime() > dwTimeNextPingDisplay )
- {
- pWO->ListChannelUsers();
- dwTimeNextPingDisplay = ::timeGetTime() + PING_AND_DISPLAY_WAIT;
- }
- if( pWO->bShowRankUpdated )
- {
- pWO->bShowRankUpdated = false;
- pWO->ListChannelUsers();
- }
- // Regularly check for incoming messages from wolapi.
- if( ::timeGetTime() > pWO->dwTimeNextWolapiPump )
- {
- pWO->pChat->PumpMessages();
- pWO->pNetUtil->PumpMessages();
- // Special post-callback processing...
- if( pWO->pChatSink->bGotKickedTrigger )
- {
- // We got kicked out of the channel.
- pWO->OnExitingGameChannel();
- pWO->RejoinLobbyAfterGame();
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_BACKTOCHAT; // Return to chat.
- // Leave the bGotKickedTrigger flag so we can react to it upon reentering the chat dialog.
- //pWO->pChatSink->bGotKickedTrigger = false;
- display = REDRAW_ALL;
- }
- pWO->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;
- }
- if( bHostSayGo )
- {
- // debugprint( "bHostSayGo trigger\n" );
- // We are the host, now ready to tell everyone to GO and start our game.
- HostSaysGo();
- /* Part of old method of game start.
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_STARTGAMEHOST;
- // debugprint( "Host about to exit game setup dialog for game.\n" );
- if( !ExitGameChannel() )
- ResultReturn = RESULT_WOLGSUP_FATALERROR; // Return with an error value.
- break;
- */
- }
- else if( *szNameOfHostWhoJustBailedOnUs ) // Host left channel - cancel setup.
- {
- // debugprint( "Guest about to exit game setup dialog because host bailed on us.\n" );
- if( ExitGameChannel() )
- {
- pWO->RejoinLobbyAfterGame();
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_HOSTLEFT; // Return to chat.
- // Add a message explaining what happened to the saved chat that will be restored in the chat dialog.
- pWO->AddHostLeftMessageToSavedChat( szNameOfHostWhoJustBailedOnUs );
- }
- else
- {
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_FATALERROR; // Return with an error value.
- }
- break;
- }
- else if( bLeaveDueToRulesMismatchTrigger )
- {
- // debugprint( "Guest about to exit game setup dialog because of rules.ini mismatch.\n" );
- if( ExitGameChannel() )
- {
- pWO->RejoinLobbyAfterGame();
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_RULESMISMATCH; // Return to chat.
- // Add a message explaining what happened to the saved chat that will be restored in the chat dialog.
- pWO->AddMessageToSavedChat( TXT_WOL_RULESMISMATCH );
- }
- else
- {
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_FATALERROR; // Return with an error value.
- }
- break;
- }
- else if( *szTriggerGameStartInfo )
- {
- // debugprint( "About to trigger game start.\n" );
- TriggerGameStart( szTriggerGameStartInfo );
- }
- else if( pWO->bSelfDestruct )
- {
- if( pWO->pChatSink->bConnected )
- pWO->Logout();
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_LOGOUT; // As if the user logged himself out.
- }
- if( bExitForGameTrigger )
- {
- // We are now exiting to go into a game.
- bProcess = false;
- if( bHost )
- ResultReturn = RESULT_WOLGSUP_STARTGAMEHOST;
- else
- ResultReturn = RESULT_WOLGSUP_STARTGAME;
- // debugprint( "About to exit game setup dialog for game.\n" );
- if( !ExitGameChannel() )
- ResultReturn = RESULT_WOLGSUP_FATALERROR; // Return with an error value.
- break;
- }
- if( bHost && bWaitingToStart && !bExitForGameTrigger && timeGetTime() > timeWaitingToStartTimeout )
- {
- ClearAllAccepts(); // Results in all required steps to cancel game start.
- WOL_PrintMessage( *pILDisc, TXT_WOL_STARTTIMEOUT, WOLCOLORREMAP_LOCALMACHINEMESS );
- Sound_Effect( WOLSOUND_ERROR );
- }
- // Regularly send game param changes if I'm the host.
- if( bHost && !bHostSayGo && !bExitForGameTrigger && ::timeGetTime() > dwTimeNextParamRefresh )
- {
- if( bParamsUnfresh() )
- {
- nHostLastParamID++;
- SendParams();
- ClearAllAccepts();
- }
- dwTimeNextParamRefresh = ::timeGetTime() + PARAMREFRESHWAIT;
- }
- if( !bProcess ) // Avoid redrawing if we're about to bail.
- break;
- //
- // If we have just received input focus again after running in the background then
- // we need to redraw.
- //
- if (AllSurfaces.SurfacesRestored) {
- AllSurfaces.SurfacesRestored=FALSE;
- display = REDRAW_ALL;
- }
- //.....................................................................
- // Refresh display if needed
- //.....................................................................
- if( bRetractHouseDropDown ) //|| pCheckListOptions->Is_To_Redraw() )
- {
- bRetractHouseDropDown = false;
- if( pDropListHouse->IsDropped )
- {
- pDropListHouse->Collapse();
- if (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;
- }
- }
- // if( pILDisc->Is_To_Redraw() )
- // {
- // pDropListHouse->Flag_To_Redraw();
- // }
- if( display )
- {
- Hide_Mouse();
- /*
- ** Collapse the country list if we are going to redraw the game list
- */
- // if (pILScens->Is_To_Redraw() && pDropListHouse->IsDropped) {
- // pDropListHouse->Collapse();
- // if (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;
- // }
- //..................................................................
- // Redraw backgound & dialog box
- //..................................................................
- if (display >= REDRAW_BACKGROUND) {
- if( pToolTipHitLast && pToolTipHitLast->bShowing )
- pToolTipHitLast->Unshow();
- if( pDropListHouse->IsDropped )
- pDropListHouse->Collapse();
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- //...............................................................
- // Dialog & Field labels
- //...............................................................
- Fancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);
- if( bHost )
- Fancy_Text_Print( TXT_SCENARIOS, d_scenariolist_x + d_scenariolist_w, d_scenariolist_y - 12, scheme, TBLACK, TPF_TYPE | TPF_RIGHT );
- // else
- // Fancy_Text_Print( TXT_SCENARIO_COLON, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);
- Fancy_Text_Print(TXT_COUNT, d_count_x - 2*RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
- Fancy_Text_Print(TXT_LEVEL, d_level_x - 2*RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
- Fancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2*RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
- Fancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
- Fancy_Text_Print(TXT_SIDE_COLON,
- // d_house_x + (d_house_w / 2),
- d_house_x + ( ( d_house_w + 16 ) / 2 ),
- d_house_y - d_txt6_h,
- scheme, TBLACK,
- TPF_CENTER | TPF_TEXT);
- Fancy_Text_Print(TXT_COLOR_COLON,
- d_color_x + d_color_w * 4,
- d_color_y - d_txt6_h,
- scheme, TBLACK,
- TPF_CENTER | TPF_TEXT);
- const char* szGameKind;
- const char* pDIB;
- switch( pWO->GameInfoCurrent.GameKind )
- {
- case CREATEGAMEINFO::RAGAME:
- szGameKind = TXT_WOL_CG_RAGAME;
- pDIB = pWO->OldRAGameTypeInfos[ 0 ].pDIB;
- break;
- case CREATEGAMEINFO::CSGAME:
- szGameKind = TXT_WOL_CG_CSGAME;
- pDIB = pWO->OldRAGameTypeInfos[ 1 ].pDIB;
- break;
- case CREATEGAMEINFO::AMGAME:
- szGameKind = TXT_WOL_CG_AMGAME;
- pDIB = pWO->OldRAGameTypeInfos[ 2 ].pDIB;
- break;
- default:
- // debugprint( "Illegal GameInfoCurrent value." );
- //Fatal( "Illegal GameInfoCurrent value." );
- szGameKind = TXT_WOL_CG_AMGAME;
- pDIB = NULL;
- pWO->bSelfDestruct = true;
- break;
- }
- int iGameInfoSpacingY = 14;
- int iGameInfoSecondColumnX = 0; //170;
- // Game kind.
- Fancy_Text_Print( szGameKind, d_gamekind_x, d_gamekind_y - iGameInfoSpacingY * 1, scheme, TBLACK, TPF_TYPE );
- // Game kind icon.
- CC_Draw_DIB( pDIB, d_gamekind_x - 16, d_gamekind_y - iGameInfoSpacingY * 1 - 2, 100, WINDOW_MAIN );
- // "Tournament."
- if( pWO->GameInfoCurrent.bTournament )
- {
- Fancy_Text_Print( TXT_WOL_CG_TOURNAMENT, d_gamekind_x + iGameInfoSecondColumnX,
- d_gamekind_y + iGameInfoSpacingY * 1, scheme, TBLACK, TPF_TYPE );
- CC_Draw_DIB( pWO->DibIconInfos[ DIBICON_TOURNAMENT ].pDIB, d_gamekind_x + iGameInfoSecondColumnX - 16,
- d_gamekind_y + iGameInfoSpacingY * 1 - 2, 100, WINDOW_MAIN );
- }
- // "Password: ..."
- if( pWO->GameInfoCurrent.bPrivate )
- {
- char szPrivatePassword[ 100 ];
- sprintf( szPrivatePassword, TXT_WOL_PRIVATEPASSWORD, pWO->GameInfoCurrent.szPassword );
- Fancy_Text_Print( szPrivatePassword, d_gamekind_x + iGameInfoSecondColumnX,
- d_gamekind_y + iGameInfoSpacingY * 2, scheme, TBLACK, TPF_TYPE );
- CC_Draw_DIB( pWO->DibIconInfos[ DIBICON_PRIVATE ].pDIB, d_gamekind_x + iGameInfoSecondColumnX - 16,
- d_gamekind_y + iGameInfoSpacingY * 2 - 2, 100, WINDOW_MAIN );
- }
- // "Scenario:" - scenario name is drawn separately.
- //Fancy_Text_Print( TXT_SCENARIO_COLON, d_gamekind_x, d_gamekind_y - iGameInfoSpacingY, scheme, TBLACK, TPF_TYPE );
- }
- //..................................................................
- // Redraw buttons
- //..................................................................
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- //..................................................................
- // Draw the color boxes
- //..................................................................
- if (display >= REDRAW_COLORS ) {
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- LogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,
- cbox_x[i] + 1 + d_color_w - 2 *RESFACTOR, d_color_y + 1 + d_color_h - 2,
- ColorRemaps[i].Box);
- if (i == Session.ColorIdx) {
- Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false);
- } else {
- Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false);
- }
- }
- }
- //..................................................................
- // Draw the messages:
- // - Erase an old message first
- // - If we're in a game, print the game options (if they've been
- // received)
- // - If we've been rejected from a game, print that message
- //..................................................................
- if (display >= REDRAW_MESSAGE) {
- // Draw_Box(d_disc_x, d_disc_y, d_disc_w, d_disc_h, BOXSTYLE_BOX, true);
- // Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);
- // Session.Messages.Draw();
- }
- //..................................................................
- // Update game parameter labels
- //..................................................................
- if (display >= REDRAW_PARMS)
- {
- char txt[80];
- char* szScenarioDesc;
- bool bOfficial;
- char* szScenarioFileName;
- if( !bHost )
- {
- szScenarioDesc = Session.Options.ScenarioDescription;
- bOfficial = Session.ScenarioIsOfficial;
- szScenarioFileName = Session.ScenarioFileName;
- }
- else
- {
- szScenarioDesc = (char*)Session.Scenarios[ Session.Options.ScenarioIndex ]->Description();
- bOfficial = Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Official();
- szScenarioFileName = (char*)Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename();
- }
- if( *szScenarioDesc )
- {
- // Language translation.
- for (int ii = 0; EngMisStr[ii] != NULL; ii++) {
- if (!strcmp( szScenarioDesc, EngMisStr[ii]) ) {
- #if defined(GERMAN) || defined(FRENCH)
- //sprintf(txt, "%s %s", Text_String(TXT_SCENARIO_COLON), EngMisStr[ii+1]);
- sprintf(txt, "%s", EngMisStr[ii+1]);
- #else
- //sprintf(txt, "%s %s", Text_String(TXT_SCENARIO_COLON), Session.Options.ScenarioDescription);
- sprintf(txt, "%s", szScenarioDesc);
- #endif
- break;
- }
- }
- if (EngMisStr[ii] == NULL) {
- sprintf(txt, "%s", szScenarioDesc);
- }
- // pStaticDescrip->Set_Text( txt, false );
- strcpy( szScenarioNameDisplay, txt );
- // Show icon for gamekind of scenario.
- const char* pDIB;
- if( bOfficial )
- {
- if( Is_Mission_Counterstrike( szScenarioFileName ) )
- pDIB = pWO->OldRAGameTypeInfos[ 1 ].pDIB;
- else if( Is_Mission_Aftermath( szScenarioFileName ) )
- pDIB = pWO->OldRAGameTypeInfos[ 2 ].pDIB;
- else
- pDIB = pWO->OldRAGameTypeInfos[ 0 ].pDIB;
- }
- else
- pDIB = pWO->DibIconInfos[ DIBICON_USER ].pDIB;
- DrawScenarioDescripIcon( pDIB );
- }
- else
- {
- //sprintf(txt, "%s %s", Text_String(TXT_SCENARIO_COLON), Text_String(TXT_NOT_FOUND));
- sprintf(txt, "%s", TXT_WOL_SCENARIONAMEWAIT );
- // pStaticDescrip->Set_Text( txt, false );
- strcpy( szScenarioNameDisplay, txt );
- }
- // Print scenario name.
- Conquer_Clip_Text_Print( szScenarioNameDisplay, d_gamekind_x, d_gamekind_y, scheme, TBLACK, TPF_TYPE, d_gamekind_w );
- // pStaticDescrip->Draw_Me();
- sprintf(txt,"%d",Session.Options.UnitCount);
- pStaticUnit->Set_Text(txt);
- pStaticUnit->Draw_Me();
- if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
- sprintf(txt,"%d",BuildLevel);
- } else {
- sprintf(txt, "**");
- }
- pStaticLevel->Set_Text(txt);
- pStaticLevel->Draw_Me();
- sprintf(txt,"%d",Session.Options.Credits);
- pStaticCredits->Set_Text(txt);
- pStaticCredits->Draw_Me();
- sprintf(txt,"%d",Session.Options.AIPlayers);
- pStaticAIPlayers->Set_Text(txt);
- pStaticAIPlayers->Draw_Me();
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- // Force mouse visible, as some beta testers report unexplicable disappearing cursors.
- while( Get_Mouse_State() )
- Show_Mouse();
- // Be nice to other apps.
- Sleep( 50 );
- //.....................................................................
- // Get user input
- //.....................................................................
- if( ( ::GetAsyncKeyState( KN_LMOUSE ) & 0x8000 ) || ( ::GetAsyncKeyState( KN_RMOUSE ) & 0x8000 ) )
- {
- timeToolTipAppear = ::timeGetTime() + TOOLTIPDELAY;
- if( pToolTipHitLast && pToolTipHitLast->bShowing )
- pToolTipHitLast->Unshow();
- }
- input = commands->Input();
- if( bHackFocus )
- {
- pEditSend->Set_Focus();
- pEditSend->Flag_To_Redraw();
- input = commands->Input();
- bHackFocus = false;
- }
- // Tooltips...
- if( pToolTipHead )
- {
- ToolTipClass* pToolTipHit = pToolTipHead->GetToolTipHit();
- if( pToolTipHit == pToolTipHitLast )
- {
- if( pToolTipHit && !pToolTipHit->bShowing && ::timeGetTime() > timeToolTipAppear && !( ( ::GetAsyncKeyState( KN_LMOUSE ) & 0x8000 ) || ( ::GetAsyncKeyState( KN_RMOUSE ) & 0x8000 ) ) )
- {
- pToolTipHit->Show();
- }
- }
- else
- {
- if( pToolTipHitLast && pToolTipHitLast->bShowing )
- pToolTipHitLast->Unshow();
- pToolTipHitLast = pToolTipHit;
- timeToolTipAppear = ::timeGetTime() + TOOLTIPDELAY;
- }
- }
- // Yummy special hack. Luv' that UI system.
- if( input == 2049 ) // Left mouse released, not on control that captured it.
- {
- // Redraw the tabs in case they were what were pressed down on.
- pShpBtnScenarioRA->Flag_To_Redraw();
- pShpBtnScenarioCS->Flag_To_Redraw();
- pShpBtnScenarioAM->Flag_To_Redraw();
- pShpBtnScenarioUser->Flag_To_Redraw();
- }
- //.....................................................................
- // Process input
- //.....................................................................
- switch( input )
- {
- case KN_LMOUSE:
- if( !bWaitingToStart )
- {
- // Check for mouse down on a control when player is not host.
- if( !bHost )
- {
- if ( (
- Get_Mouse_X() >= d_count_x &&
- Get_Mouse_X() <= d_count_x + d_count_w &&
- Get_Mouse_Y() >= d_count_y &&
- Get_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h
- ) || (
- Get_Mouse_X() >= d_options_x &&
- Get_Mouse_X() <= d_options_x + d_options_w &&
- Get_Mouse_Y() >= d_options_y &&
- Get_Mouse_Y() <= d_options_y + d_options_h
- ) || (
- Get_Mouse_X() >= d_scenariolist_x &&
- Get_Mouse_X() <= d_scenariolist_x + d_scenariolist_w &&
- Get_Mouse_Y() >= d_scenariolist_y &&
- Get_Mouse_Y() <= d_scenariolist_y + d_scenariolist_h
- ) )
- {
- //Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200);
- WOL_PrintMessage( *pILDisc, Text_String( TXT_ONLY_HOST_CAN_MODIFY ), WOLCOLORREMAP_LOCALMACHINEMESS );
- Sound_Effect( WOLSOUND_ERROR );
- if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
- break;
- }
- }
- if (Keyboard->MouseQX > cbox_x[0] &&
- Keyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&
- Keyboard->MouseQY > d_color_y &&
- Keyboard->MouseQY < (d_color_y + d_color_h))
- {
- Session.PrefColor = (PlayerColorType)
- ((Keyboard->MouseQX - cbox_x[0]) / d_color_w);
- // Ensure that no one is using this color (to our knowledge).
- if( pILPlayers->FindColor( &ColorRemaps[ Session.PrefColor == PCOLOR_DIALOG_BLUE ? PCOLOR_REALLY_BLUE : Session.PrefColor ] ) == -1 )
- {
- // Show me as the new color.
- // debugprint( "Color box pressed - " );
- SetPlayerColor( pWO->szMyName, Session.PrefColor );
- if( bHost )
- {
- // Tell all guests about the color change.
- InformAboutPlayerColor( pWO->szMyName, Session.PrefColor, NULL );
- }
- else
- {
- RequestPlayerColor( Session.PrefColor );
- }
- }
- }
- }
- break;
- case ( BUTTON_DISCONNECT | KN_BUTTON ):
- if( WWMessageBox().Process( TXT_WOL_CONFIRMLOGOUT, TXT_YES, TXT_NO ) == 0 )
- {
- // debugprint( "Logging out from gsup.\n" );
- ExitGameChannel();
- pWO->Logout();
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_LOGOUT;
- }
- display = REDRAW_ALL;
- bHackFocus = true;
- break;
- case ( BUTTON_REFRESH | KN_BUTTON ): // Always disabled.
- break;
- case ( BUTTON_SQUELCH | KN_BUTTON ):
- pWO->DoSquelch( pILPlayers );
- break;
- case ( BUTTON_BAN | KN_BUTTON ):
- pWO->DoKick( pILPlayers, true );
- // display = REDRAW_ALL;
- break;
- case ( BUTTON_KICK | KN_BUTTON ):
- pWO->DoKick( pILPlayers, false );
- // display = REDRAW_ALL;
- break;
- case ( BUTTON_FINDPAGE | KN_BUTTON ):
- pWO->DoFindPage();
- display = REDRAW_ALL;
- bHackFocus = true;
- break;
- case ( BUTTON_OPTIONS | KN_BUTTON ):
- pWO->DoOptions();
- display = REDRAW_ALL;
- bHackFocus = true;
- break;
- case ( BUTTON_LADDER | KN_BUTTON ):
- pWO->DoLadder();
- display = REDRAW_ALL;
- bHackFocus = true;
- break;
- case ( BUTTON_HELP | KN_BUTTON ):
- pWO->DoHelp();
- display = REDRAW_ALL;
- bHackFocus = true;
- break;
- case ( BUTTON_HOUSE | KN_BUTTON ):
- Session.House = (HousesType)( pDropListHouse->Current_Index() + HOUSE_USSR );
- /*
- // Bloody bloody hell I can't believe there are bugs in RA like the one I deal with here...
- if( strcmp( pDropListHouse->Current_Item(), "Russia" ) == 0 )
- Session.House = HOUSE_USSR;
- else
- {
- Session.House = HouseTypeClass::From_Name( pDropListHouse->Current_Item() ); // Fails on "Russia". (Thinks "USSR".)
- if( Session.House == HOUSE_NONE )
- {
- // debugprint( "Couldn't find house from selected '%s'.\n", pDropListHouse->Current_Item() );
- }
- }
- */
- if( pDropListHouse->IsDropped )
- bRetractHouseDropDown = true;
- else
- if (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND; // Droplist already got contracted.
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- case ( BUTTON_AFTERMATHUNITS | KN_BUTTON ):
- bAftermathUnits = pCheckAftermathUnits->IsOn;
- break;
- case ( BUTTON_SENDEDIT | KN_BUTTON ):
- // Enter has been pressed - was caught by pEditSend control.
- pWO->SendMessage( pEditSend->Get_Text(), *pILPlayers, false );
- // Clear pEditSend, reset focus.
- szSendBuffer[0] = 0;
- pEditSend->Set_Focus();
- // Mark for redraw.
- pEditSend->Flag_To_Redraw();
- break;
- case ( BUTTON_ACTION | KN_BUTTON ):
- // Enter has been pressed - was caught by pEditSend control.
- pWO->SendMessage( pEditSend->Get_Text(), *pILPlayers, true );
- // Clear pEditSend, reset focus.
- szSendBuffer[0] = 0;
- pEditSend->Set_Focus();
- // Mark for redraw.
- pEditSend->Flag_To_Redraw();
- break;
- //..................................................................
- // New Scenario selected.
- //..................................................................
- case (BUTTON_SCENARIOLIST | KN_BUTTON):
- {
- if( pILScens->Count() )
- {
- int iSelectedScenIndex = (int)pILScens->Get_Item_ExtraDataPtr( pILScens->Current_Index() );
- if( iSelectedScenIndex != Session.Options.ScenarioIndex )
- {
- Session.Options.ScenarioIndex = iSelectedScenIndex;
- bInformParamChange = true;
- if( !pILScens->SetSelectType( 1 ) ) // Hack to deal with ListClass "highlighting nothing" problem.
- // SelectType was 0 before call.
- pILScens->Flag_To_Redraw();
- // pStaticDescrip->Set_Text( pILScens->Get_Item( pILScens->Current_Index() ), false );
- strcpy( szScenarioNameDisplay, pILScens->Get_Item( pILScens->Current_Index() ) );
- //if (display < REDRAW_PARMS) display = REDRAW_PARMS;
- display = REDRAW_ALL;
- Sound_Effect(VOC_OPTIONS_CHANGED);
- }
- }
- break;
- }
- //..................................................................
- // User adjusts max # units
- //..................................................................
- case (BUTTON_COUNT | KN_BUTTON):
- Session.Options.UnitCount = pGaugeCount->Get_Value() +
- SessionClass::CountMin[Session.Options.Bases];
- bInformParamChange = true;
- if (display < REDRAW_PARMS) display = REDRAW_PARMS;
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- //..................................................................
- // User adjusts build level
- //..................................................................
- case (BUTTON_LEVEL | KN_BUTTON):
- BuildLevel = pGaugeLevel->Get_Value() + 1;
- if (BuildLevel > MPLAYER_BUILD_LEVEL_MAX) // if it's pegged, max it out
- BuildLevel = MPLAYER_BUILD_LEVEL_MAX;
- bInformParamChange = true;
- if (display < REDRAW_PARMS) display = REDRAW_PARMS;
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- //..................................................................
- // User edits the credits value; retransmit new game options
- // Round the credits to the nearest 500.
- //..................................................................
- case (BUTTON_CREDITS | KN_BUTTON):
- Session.Options.Credits = pGaugeCredits->Get_Value();
- Session.Options.Credits =
- ((Session.Options.Credits + 250) / 500) * 500;
- bInformParamChange = true;
- if (display < REDRAW_PARMS) display = REDRAW_PARMS;
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- //..................................................................
- // User adjusts # of AI players
- //..................................................................
- case (BUTTON_AIPLAYERS | KN_BUTTON):
- Session.Options.AIPlayers = pGaugeAIPlayers->Get_Value();
- // if (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) { // if it's pegged, max it out
- if (Session.Options.AIPlayers + pWO->GameInfoCurrent.iPlayerMax > Rule.MaxPlayers) { // if it's pegged, max it out
- Session.Options.AIPlayers = Rule.MaxPlayers - pWO->GameInfoCurrent.iPlayerMax;
- pGaugeAIPlayers->Set_Value(Session.Options.AIPlayers);
- }
- bInformParamChange = true;
- if (display < REDRAW_PARMS) display = REDRAW_PARMS;
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- //..................................................................
- // Toggle-able options:
- // If 'Bases' gets toggled, we have to change the range of the
- // UnitCount slider.
- // Also, if Tiberium gets toggled, we have to set the flags
- // in SpecialClass.
- //..................................................................
- case ( BUTTON_PARAMS | KN_BUTTON ):
- bRetractHouseDropDown = true;
- if (Special.IsCaptureTheFlag != pCheckListOptions->Is_Checked(3) && !Special.IsCaptureTheFlag) {
- pCheckListOptions->Check_Item(0, true);
- }
- if (Session.Options.Bases != pCheckListOptions->Is_Checked(0)) {
- Session.Options.Bases = pCheckListOptions->Is_Checked(0);
- if (Session.Options.Bases) {
- Session.Options.UnitCount = Fixed_To_Cardinal (
- SessionClass::CountMax[1] -
- SessionClass::CountMin[1],
- Cardinal_To_Fixed(
- SessionClass::CountMax[0]-SessionClass::CountMin[0],
- Session.Options.UnitCount-SessionClass::CountMin[0])) +
- SessionClass::CountMin[1];
- } else {
- pCheckListOptions->Check_Item(3, false);
- Session.Options.UnitCount = Fixed_To_Cardinal (
- SessionClass::CountMax[0] -
- SessionClass::CountMin[0],
- Cardinal_To_Fixed(
- SessionClass::CountMax[1]-SessionClass::CountMin[1],
- Session.Options.UnitCount - SessionClass::CountMin[1])) +
- SessionClass::CountMin[0];
- }
- pGaugeCount->Set_Maximum(
- SessionClass::CountMax[Session.Options.Bases] -
- SessionClass::CountMin[Session.Options.Bases]);
- pGaugeCount->Set_Value(Session.Options.UnitCount -
- SessionClass::CountMin[Session.Options.Bases]);
- }
- Session.Options.Tiberium = pCheckListOptions->Is_Checked(1);
- Special.IsTGrowth = Session.Options.Tiberium; // Ugh. Use of "Special" global.
- Rule.IsTGrowth = Session.Options.Tiberium;
- Special.IsTSpread = Session.Options.Tiberium; // Ugh. Use of "Special" global.
- Rule.IsTSpread = Session.Options.Tiberium;
- Session.Options.Goodies = pCheckListOptions->Is_Checked(2);
- Special.IsCaptureTheFlag = pCheckListOptions->Is_Checked(3); // Ugh. Use of "Special" global.
- Special.IsShadowGrow = pCheckListOptions->Is_Checked(4); // Ugh. Use of "Special" global.
- bSlowUnitBuildRate = pCheckListOptions->Is_Checked(5);
- bInformParamChange = true;
- if (display < REDRAW_PARMS) display = REDRAW_PARMS;
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- case ( BUTTON_ACCEPTSTART | KN_BUTTON ): // 'Accept' or 'Start Game' button.
- if( !bHost )
- {
- // Guest wishes to accept game params.
- User* pUserHost = pWO->pGameHost();
- if( pUserHost ) // Else it's too early to even be thinking about accepting, anyway.
- {
- // Set ourself as accepted. We want to do this immediately so the user has feedback for pressing button.
- // Besides, the host is guaranteed to allow this and set us to "accepted", unless it is simultaneously
- // sending us a new update we haven't received yet. If this is the case, we will get that update in a
- // second and will set ourselves to unaccepted, which will match the unaccepted state on the server.
- // Upshot - We can ignore messages from the server telling us that we, ourself, accepted.
- if( pToolTipHitLast && pToolTipHitLast->bShowing )
- pToolTipHitLast->Unshow();
- pTextBtnAcceptStart->Disable();
- if( SetPlayerAccepted( pWO->szMyName, true ) ) // Else we didn't find ourself in list!
- {
- // debugprint( "Sending accept.\n" );
- // Tell host we accept.
- char szSend[ 20 ];
- sprintf( szSend, "%02u %06u", WOL_GAMEOPT_REQACCEPT, nGuestLastParamID );
- pWO->SendGameOpt( szSend, pUserHost );
- }
- }
- }
- else
- {
- // Host says start the game.
- // If we have changes just made and not yet sent, don't say start, because we're about to send changes
- // that will unaccept everyone.
- if( !bParamsUnfresh() )
- {
- // Force user to put the correct disk in before proceeding. (Not crucial, but can lead to ugly
- // timeouts if the scenario has to be downloaded before game start.)
- if( !Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Official() ||
- Force_Scenario_Available( Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() ) )
- {
- // Go into "waiting to start" mode, tell guests to, and wait for responses.
- bWaitingToStart = true;
- timeWaitingToStartTimeout = ::timeGetTime() + 30000;
- nHostLastParamID++;
- InformAboutStart();
- WWMessageBox().Process( TXT_WOL_WAITINGTOSTART, TXT_NONE );
- BindControls( false );
- SetPlayerReadyToGo( pWO->szMyName, "ready" );
- Sound_Effect( VOC_GAME_CLOSED );
- }
- }
- }
- break;
- case ( BUTTON_SCENARIO_RA | KN_BUTTON ):
- ScenarioDisplayMode( SCENARIO_RA );
- break;
- case ( BUTTON_SCENARIO_CS | KN_BUTTON ):
- ScenarioDisplayMode( SCENARIO_CS );
- break;
- case ( BUTTON_SCENARIO_AM | KN_BUTTON ):
- ScenarioDisplayMode( SCENARIO_AM );
- break;
- case ( BUTTON_SCENARIO_USER | KN_BUTTON ):
- ScenarioDisplayMode( SCENARIO_USER );
- break;
- // case (BUTTON_LOAD | KN_BUTTON):
- // case (BUTTON_OK | KN_BUTTON):
- // break;
- case (KN_ESC):
- if( pDropListHouse->IsDropped )
- bRetractHouseDropDown = true;
- break;
- case ( BUTTON_LEAVE | KN_BUTTON ):
- case ( BUTTON_CANCEL | KN_BUTTON ):
- if( ExitGameChannel() )
- {
- pWO->RejoinLobbyAfterGame();
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_BACKTOCHAT; // Return to chat.
- }
- else
- {
- bProcess = false;
- ResultReturn = RESULT_WOLGSUP_FATALERROR; // Return with an error value.
- }
- break;
- }
- Call_Back();
- }
- if( pToolTipHitLast && pToolTipHitLast->bShowing )
- pToolTipHitLast->Unshow();
- pWO->ClearListPtrs();
- pWO->pGSupDlg = NULL;
- return ResultReturn;
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::SetSpecialControlStates()
- {
- // Set gauges and checklist.
- pCheckListOptions->Check_Item(0, Session.Options.Bases);
- pCheckListOptions->Check_Item(1, Session.Options.Tiberium);
- pCheckListOptions->Check_Item(2, Session.Options.Goodies);
- pCheckListOptions->Check_Item(3, Special.IsCaptureTheFlag); // Ugh. Use of "Special" global.
- pCheckListOptions->Check_Item(4, Special.IsShadowGrow); // Ugh. Use of "Special" global.
- pCheckListOptions->Check_Item(5, bSlowUnitBuildRate); // Ugh. Use of "Special" global.
- pGaugeCount->Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);
- pGaugeCount->Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);
- pGaugeLevel->Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);
- pGaugeLevel->Set_Value(BuildLevel - 1);
- pGaugeCredits->Set_Maximum(Rule.MPMaxMoney);
- pGaugeCredits->Set_Value(Session.Options.Credits);
- if( pWO->GameInfoCurrent.bTournament )
- {
- pGaugeAIPlayers->Set_Maximum( 0 );
- }
- else
- {
- // Note dependency of AIPlayers on number of human players.
- // pGaugeAIPlayers->Set_Maximum(Rule.MaxPlayers-Session.Players.Count());
- pGaugeAIPlayers->Set_Maximum( Rule.MaxPlayers - pWO->GameInfoCurrent.iPlayerMax );
- }
- pGaugeAIPlayers->Set_Value(Session.Options.AIPlayers);
- if( bAftermathUnits )
- pCheckAftermathUnits->Turn_On();
- else
- pCheckAftermathUnits->Turn_Off();
- }
- #define DRAWTABDOWN Turn_On()
- #define DRAWTABUP Turn_Off()
- //***********************************************************************************************
- void WOL_GameSetupDialog::BindControls( bool bBind )
- {
- if( bBind )
- {
- commands = pWO->pShpBtnDiscon;
- pWO->pShpBtnLeave->Add_Tail(*commands);
- pWO->pShpBtnRefresh->Add_Tail(*commands);
- pWO->pShpBtnSquelch->Add_Tail(*commands);
- pWO->pShpBtnBan->Add_Tail(*commands);
- pWO->pShpBtnKick->Add_Tail(*commands);
- pWO->pShpBtnFindpage->Add_Tail(*commands);
- pWO->pShpBtnOptions->Add_Tail(*commands);
- pWO->pShpBtnLadder->Add_Tail(*commands);
- pWO->pShpBtnHelp->Add_Tail(*commands);
- pILPlayers->Add_Tail(*commands);
- if( bHost )
- {
- // Draw order of tabs depends on which one is selected, as we want them to overlap appropriately.
- // Also, the selected tab must appear over the scenario list, while the unselected tabs are below it.
- // This assures that that bottom of the tab overlaps the scenario list border, making it look connected.
- // ajw I could make all maps always available now that they're downloadable. Playing CS map with AM rules
- // would mean switching CDs, though.
- // Would mean no difference between RA and CS games.
- switch( ScenKindCurrent )
- {
- case SCENARIO_RA:
- if( !pWO->GameInfoCurrent.bTournament )
- {
- pShpBtnScenarioUser->Add_Tail(*commands);
- pShpBtnScenarioUser->DRAWTABDOWN;
- }
- if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::CSGAME )
- {
- pShpBtnScenarioCS->Add_Tail(*commands);
- pShpBtnScenarioCS->DRAWTABDOWN;
- }
- else if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||
- ( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::RAGAME && Is_Aftermath_Installed() && !pWO->GameInfoCurrent.bTournament ) )
- {
- pShpBtnScenarioAM->Add_Tail(*commands);
- pShpBtnScenarioAM->DRAWTABDOWN;
- }
- pILScens->Add_Tail(*commands);
- pShpBtnScenarioRA->Add_Tail(*commands);
- pShpBtnScenarioRA->DRAWTABUP;
- break;
- case SCENARIO_CS: // pWO->GameInfoCurrent.GameKind must be CREATEGAMEINFO::CSGAME.
- if( !pWO->GameInfoCurrent.bTournament )
- {
- pShpBtnScenarioUser->Add_Tail(*commands);
- pShpBtnScenarioUser->DRAWTABDOWN;
- }
- pShpBtnScenarioRA->Add_Tail(*commands);
- pShpBtnScenarioRA->DRAWTABDOWN;
- pILScens->Add_Tail(*commands);
- pShpBtnScenarioCS->Add_Tail(*commands);
- pShpBtnScenarioCS->DRAWTABUP;
- break;
- case SCENARIO_AM: // pWO->GameInfoCurrent.GameKind must be CREATEGAMEINFO::AMGAME, or RAGAME with AM installed.
- if( !pWO->GameInfoCurrent.bTournament )
- {
- pShpBtnScenarioUser->Add_Tail(*commands);
- pShpBtnScenarioUser->DRAWTABDOWN;
- }
- pShpBtnScenarioRA->Add_Tail(*commands);
- pShpBtnScenarioRA->DRAWTABDOWN;
- pILScens->Add_Tail(*commands);
- pShpBtnScenarioAM->Add_Tail(*commands);
- pShpBtnScenarioAM->DRAWTABUP;
- break;
- case SCENARIO_USER: // pWO->GameInfoCurrent.bTournament must be false.
- pShpBtnScenarioRA->Add_Tail(*commands);
- pShpBtnScenarioRA->DRAWTABDOWN;
- if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::CSGAME )
- {
- pShpBtnScenarioCS->Add_Tail(*commands);
- pShpBtnScenarioCS->DRAWTABDOWN;
- }
- else if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||
- ( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::RAGAME && Is_Aftermath_Installed() && !pWO->GameInfoCurrent.bTournament ) )
- {
- pShpBtnScenarioAM->Add_Tail(*commands);
- pShpBtnScenarioAM->DRAWTABDOWN;
- }
- pILScens->Add_Tail(*commands);
- pShpBtnScenarioUser->Add_Tail(*commands);
- pShpBtnScenarioUser->DRAWTABUP;
- break;
- }
- }
- // pStaticDescrip->Add_Tail(*commands);
- pEditSend->Add_Tail(*commands);
- pStaticUnit->Add_Tail(*commands);
- pStaticLevel->Add_Tail(*commands);
- pStaticCredits->Add_Tail(*commands);
- pStaticAIPlayers->Add_Tail(*commands);
- pGaugeCount->Add_Tail(*commands);
- pGaugeCredits->Add_Tail(*commands);
- pGaugeAIPlayers->Add_Tail(*commands);
- pGaugeLevel->Add_Tail(*commands);
- pCheckListOptions->Add_Tail(*commands);
- pTextBtnCancel->Add_Tail(*commands);
- pTextBtnAcceptStart->Add_Tail(*commands);
- pTextBtnAction->Add_Tail(*commands);
- pILDisc->Add_Tail(*commands);
- pDropListHouse->Add_Tail(*commands);
- // pCheckAftermathUnits->Add_Tail(*commands);
- }
- else
- {
- pWO->pShpBtnDiscon->Zap();
- pWO->pShpBtnLeave->Zap();
- pWO->pShpBtnRefresh->Zap();
- pWO->pShpBtnSquelch->Zap();
- pWO->pShpBtnBan->Zap();
- pWO->pShpBtnKick->Zap();
- pWO->pShpBtnFindpage->Zap();
- pWO->pShpBtnOptions->Zap();
- pWO->pShpBtnLadder->Zap();
- pWO->pShpBtnHelp->Zap();
- pILPlayers->Zap();
- if( bHost )
- {
- pShpBtnScenarioRA->Zap();
- if( !pWO->GameInfoCurrent.bTournament )
- {
- pShpBtnScenarioUser->Zap();
- }
- if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::CSGAME )
- pShpBtnScenarioCS->Zap();
- else if( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::AMGAME ||
- ( pWO->GameInfoCurrent.GameKind == CREATEGAMEINFO::RAGAME && Is_Aftermath_Installed() && !pWO->GameInfoCurrent.bTournament ) )
- pShpBtnScenarioAM->Zap();
- pILScens->Zap();
- }
- // pStaticDescrip->Zap();
- pEditSend->Zap();
- pStaticUnit->Zap();
- pStaticLevel->Zap();
- pStaticCredits->Zap();
- pStaticAIPlayers->Zap();
- pGaugeCount->Zap();
- pGaugeCredits->Zap();
- pGaugeAIPlayers->Zap();
- pGaugeLevel->Zap();
- pCheckListOptions->Zap();
- pTextBtnCancel->Zap();
- pTextBtnAcceptStart->Zap();
- pTextBtnAction->Zap();
- pILDisc->Zap();
- pDropListHouse->Zap();
- // pCheckAftermathUnits->Zap();
- }
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::ScenarioDisplayMode( SCENARIO_GAMEKIND ScenKind )
- {
- // debugprint( "ScenarioDisplayMode, from %i going into %i mode.\n", ScenKindCurrent, ScenKind );
- // Puts us into mode where we are viewing a particular gamekind of scenario list.
- if( ScenKindCurrent == ScenKind )
- return;
- // Reorder tab buttons.
- BindControls( false );
- ScenKindCurrent = ScenKind;
- BindControls( true );
- // Reset list items.
- pILScens->Clear();
- // debugprint( " * * * * * * ScenKind %i has %i items.\n", ScenKind, ar_szScenarios[ ScenKind ].Count() );
- // Check for the currently selected scenario.
- bool bFoundCurrentSelection = false;
- int iSelect;
- for( int i = 0; i != ar_szScenarios[ ScenKind ].Count(); i++ )
- {
- // Put ScenarioIndex in as extradata to list item.
- int iScenIndex = (int)ar_szScenIndexes[ ScenKind ][ i ];
- int iIndexNew = pILScens->Add_Item( ar_szScenarios[ ScenKind ][ i ], NULL, NULL, ICON_DIB, NULL, (void*)iScenIndex );
- if( iScenIndex == Session.Options.ScenarioIndex && !bFoundCurrentSelection )
- {
- // (Choose first line of what can be multiline description of currently selected scenario.)
- bFoundCurrentSelection = true;
- iSelect = i;
- }
- }
- // If the current scenario selection is in this list, enable the list to show the selection, otherwise,
- // make the listclass selection invisible, because it doesn't indicate the real scenario selection.
- // Basically, problem is that I can't have no selection in ListClass, and I don't want to risk changing
- // it as I'll affect the rest of the code. So I do this horrible hack.
- if( bFoundCurrentSelection )
- {
- pILScens->SetSelectType( 1 ); // Regular selection.
- pILScens->Set_Selected_Index( iSelect );
- }
- else
- pILScens->SetSelectType( 0 ); // Invisible selection.
- // display = REDRAW_ALL;
- pILScens->Flag_To_Redraw();
- pShpBtnScenarioRA->Flag_To_Redraw();
- pShpBtnScenarioCS->Flag_To_Redraw();
- pShpBtnScenarioAM->Flag_To_Redraw();
- pShpBtnScenarioUser->Flag_To_Redraw();
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::ExitGameChannel()
- {
- // debugprint( "ExitGameChannel \n" );
- if( pDropListHouse->IsDropped )
- {
- pDropListHouse->Collapse();
- if (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;
- }
- if( !pWO->ChannelLeave() )
- {
- pWO->GenericErrorMessage();
- return false;
- }
- pWO->OnExitingGameChannel();
- return true;
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::DrawScenarioDescripIcon( const char* pDIB ) const
- {
- CC_Draw_DIB( pDIB, d_gamekind_x - 16, d_gamekind_y - 2, 100, WINDOW_MAIN );
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::SetPlayerColor( const char* szName, PlayerColorType Color )
- {
- // Sets player color - does not verify if it is "okay" to do so.
- // debugprint( "SetPlayerColor %s to %i\n", szName, Color );
- int iItem = pILPlayers->Find( szName );
- if( iItem == -1 )
- {
- // Player name was not found in list.
- // This can happen when player color Informs arrive from the host before I have gotten a userlist.
- // Insert an entry for user - color will be maintained when the userlist arrives.
- // "early insertion"
- // debugprint( "SetPlayerColor could not find name '%s'! Inserting...\n", szName );
- iItem = pILPlayers->Add_Item( szName );
- }
- if( strcmp( pWO->szMyName, szName ) == 0 )
- {
- // I am the player involved.
- Session.ColorIdx = Color;
- if( display < REDRAW_COLORS ) display = REDRAW_COLORS;
- }
- pILPlayers->Set_Item_Color( iItem, &ColorRemaps[ Color == PCOLOR_DIALOG_BLUE ? PCOLOR_REALLY_BLUE : Color ] );
- pILPlayers->Flag_To_Redraw();
- }
- //***********************************************************************************************
- PlayerColorType WOL_GameSetupDialog::GetPlayerColor( const char* szName )
- {
- // Returns player color, if player is found in list, else PCOLOR_NONE.
- int iItem = pILPlayers->Find( szName );
- if( iItem == -1 )
- {
- // Player name was not found in list.
- return PCOLOR_NONE;
- }
- RemapControlType* pRemap = pILPlayers->Get_Item_Color( iItem );
- return PlayerColorTypeOf( pRemap );
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::SetPlayerHouse( const char* szName, HousesType House )
- {
- // Sets player house - does not verify if it is "okay" to do so.
- // debugprint( "SetPlayerHouse %s to %i\n", szName, House );
- int iItem = pILPlayers->Find( szName );
- if( iItem == -1 )
- {
- // Player name was not found in list.
- // This can happen when player house Informs arrive from the host before I have gotten a userlist.
- // Insert an entry for user - house will be maintained when the userlist arrives.
- // "early insertion"
- // debugprint( "SetPlayerHouse could not find name '%s'! Inserting...\n", szName );
- iItem = pILPlayers->Add_Item( szName );
- }
- // Reset item text.
- char szItem[ 100 ];
- pWO->WritePlayerListItem( szItem, szName, House );
- // debugprint ( "%i, %s\n", iItem, szItem );
- pILPlayers->Set_Item( iItem, szItem );
- pILPlayers->Flag_To_Redraw();
- }
- //***********************************************************************************************
- HousesType WOL_GameSetupDialog::GetPlayerHouse( const char* szName )
- {
- // Returns player house for user if found in list, else HOUSE_NONE.
- int iItem = pILPlayers->Find( szName );
- if( iItem == -1 )
- {
- // Player name was not found in list.
- return HOUSE_NONE;
- }
- return pWO->PullPlayerHouse_From( pILPlayers->Get_Item( iItem ) );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::SetPlayerAccepted( const char* szName, bool bAccepted )
- {
- // Sets player's 'accepted' state to true or false.
- // Value is stored in the player list: if there is an accepted icon, player has accepted.
- int iItem = pILPlayers->Find( szName );
- if( iItem == -1 )
- {
- // Player name was not found in list.
- // debugprint( "SetPlayerAccepted() - could not find '%s'.\n", szName );
- return false;
- }
- // debugprint( "SetPlayerAccepted() - set '%s' to %s.\n", szName, bAccepted ? "accepted" : "NOT accepted" );
- return pWO->MarkItemAccepted( iItem, bAccepted );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::IveAccepted()
- {
- // Returns true if I am marked as "accepted".
- int iItem = pILPlayers->Find( pWO->szMyName );
- if( iItem == -1 )
- return false;
- return pWO->bItemMarkedAccepted( iItem );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::SetPlayerReadyToGo( const char* szName, const char* szReadyState )
- {
- // Sets player's 'ready to go' state.
- // Set szReadyState to "ready", "need scenario", or NULL.
- // First two cases are regarded as player being ready to go.
- // Value is stored in the player list in the hidden string field.
- int iItem = pILPlayers->Find( szName );
- if( iItem == -1 )
- {
- // Player name was not found in list.
- // debugprint( "SetPlayerReadyToGo() - could not find '%s'.\n", szName );
- return false;
- }
- // debugprint( "SetPlayerReadyToGo() - set '%s' to %s.\n", szName, szReadyState );
- pWO->MarkItemReadyToGo( iItem, szReadyState );
- return true;
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::ResetReadyToGo()
- {
- // Resets all users to "not ready to go".
- for( int i = 0; i < pILPlayers->Count(); i++ )
- {
- pWO->MarkItemReadyToGo( i, NULL );
- }
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::bPlayerReadyToGo( const char* szName )
- {
- // Returns true if player is marked as "ready to go".
- int iItem = pILPlayers->Find( szName );
- if( iItem == -1 )
- return false;
- return pWO->bItemMarkedReadyToGo( iItem );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::bAllPlayersReadyToGo()
- {
- // Returns true if all players are marked as "ready to go".
- // debugprint( "Checking for all players ready - there are %i\n", pILPlayers->Count() );
- for( int i = 0; i < pILPlayers->Count(); i++ )
- {
- if( !pWO->bItemMarkedReadyToGo( i ) )
- {
- // debugprint( "Item %i NOT ready\n", i );
- return false;
- }
- // debugprint( "Item %i is ready\n", i );
- }
- // debugprint( "Return true\n" );
- return true;
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::ProcessGuestRequest( User* pUser, const char* szRequest )
- {
- // Game host processes a request that arrived as a privategameopt from one of the guests.
- // WOL_GAMEOPT_REQCOLOR format:
- // 2 WOL_GAMEOPT
- // 1 space
- // 2 color
- // 1 null-terminator
- // debugprint( "ProcessGuestRequest. szRequest is '%s', len %i.\n", szRequest, strlen( szRequest ) );
- WOL_GAMEOPT opt = (WOL_GAMEOPT)atoi( szRequest );
- szRequest += 3;
- switch( opt )
- {
- case WOL_GAMEOPT_REQCOLOR:
- {
- PlayerColorType ColorDesired = (PlayerColorType)( atoi( szRequest ) );
- if( pILPlayers->FindColor( &ColorRemaps[ ColorDesired == PCOLOR_DIALOG_BLUE ? PCOLOR_REALLY_BLUE : ColorDesired ] ) == -1 )
- {
- // Color is available.
- SetPlayerColor( (char*)pUser->name, ColorDesired );
- // Tell all guests about the color change.
- InformAboutPlayerColor( (char*)pUser->name, ColorDesired, NULL );
- }
- else
- {
- // Color is not available.
- // debugprint( "Color %i denied to %s\n", ColorDesired, (char*)pUser->name );
- // Tell requestor that his color is still the same.
- RemapControlType* pColorRemapCurrent = pILPlayers->Get_Item_Color( pILPlayers->Find( (char*)pUser->name ) );
- InformAboutPlayerColor( (char*)pUser->name, PlayerColorTypeOf( pColorRemapCurrent ), pUser );
- }
- break;
- }
- case WOL_GAMEOPT_REQHOUSE:
- {
- HousesType HouseChoice = (HousesType)( atoi( szRequest ) );
- // debugprint( "Host received: '%s' changed house to %u.\n", (char*)pUser->name, HouseChoice );
- SetPlayerHouse( (char*)pUser->name, HouseChoice );
- nHostLastParamID++;
- InformAboutPlayerHouse( (char*)pUser->name, HouseChoice, NULL );
- ClearAllAccepts();
- break;
- }
- case WOL_GAMEOPT_REQACCEPT:
- // Does Param ID of accept request match the last param change ID sent? See notes at top.
- if( atoi( szRequest ) == nHostLastParamID )
- {
- // debugprint( "Host received valid accept from '%s'.\n", (char*)pUser->name );
- SetPlayerAccepted( (char*)pUser->name, true );
- InformAboutPlayerAccept( (char*)pUser->name, NULL );
- // We may be ready to start a game now.
- if( bAllGuestsAccept() )
- {
- if( pToolTipHitLast && pToolTipHitLast->bShowing )
- pToolTipHitLast->Unshow();
- pTextBtnAcceptStart->Enable();
- }
- }
- else
- {
- // debugprint( "______________Host received invalid accept from '%s'. ID = %i when it should be %i.\n", (char*)pUser->name,
- // atoi( szRequest ), nHostLastParamID );
- }
- break;
- case WOL_GAMEOPT_REQSTART:
- // Does Param ID of accept request match the last param change ID sent? See notes at top.
- if( atoi( szRequest ) == nHostLastParamID ) // Otherwise ignore - it's old and we don't care. (Incredibly unlikely to happen, actually.)
- {
- // debugprint( "Host received valid WOL_GAMEOPT_REQSTART from '%s'.\n", (char*)pUser->name );
- // WOL_PrintMessage( *pILDisc, "WOL_GAMEOPT_REQSTART response", WOLCOLORREMAP_LOCALMACHINEMESS );
- // WOL_PrintMessage( *pILDisc, (char*)pUser->name, WOLCOLORREMAP_LOCALMACHINEMESS );
- if( bWaitingToStart )
- // If all responses are in, start the game!
- GuestIsReadyToPlay( (char*)pUser->name, "ready" );
- // else
- // debugprint( "Ignoring - I am no longer waiting to start a game.\n" );
- }
- break;
- case WOL_GAMEOPT_REQSTART_BUTNEEDSCENARIO:
- // Does Param ID of accept request match the last param change ID sent? See notes at top.
- if( atoi( szRequest ) == nHostLastParamID ) // Otherwise ignore - it's old and we don't care. (Incredibly unlikely to happen, actually.)
- {
- // debugprint( "Host received valid WOL_GAMEOPT_REQSTART_BUTNEEDSCENARIO from '%s'.\n", (char*)pUser->name );
- if( bWaitingToStart )
- // If all responses are in, start the game!
- GuestIsReadyToPlay( (char*)pUser->name, "need scenario" );
- // else
- // debugprint( "Ignoring - I am no longer waiting to start a game.\n" );
- }
- break;
- case WOL_GAMEOPT_INFGO:
- // I have told myself to start game right now.
- // This is the new method. Avoids apparent "private messages/gameopts are getting delayed" problem in chatserver...
- // (I don't want to end up leaving the channel before guests get my go message.)
- strcpy( szTriggerGameStartInfo, szRequest );
- break;
- default:
- // debugprint( "Unhandled value of %i in ProcessGuestRequest!!!\n", opt );
- break;
- }
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::ProcessInform( char* szInform )
- {
- // Process inform message arriving from game host.
- // debugprint( "ProcessInform: '%s'\n", szInform );
- if( !bHost )
- {
- WOL_GAMEOPT opt = (WOL_GAMEOPT)atoi( szInform );
- szInform += 3;
- switch( opt )
- {
- case WOL_GAMEOPT_INFCOLOR:
- {
- // WOL_GAMEOPT_INFCOLOR format:
- // 2 WOL_GAMEOPT
- // 1 space
- // 2 color
- // 1 space
- // string name of player
- PlayerColorType Color = (PlayerColorType)( atoi( szInform ) );
- szInform += 3;
- SetPlayerColor( szInform, Color ); // (szInform is now sitting at the start of the name string.)
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- }
- case WOL_GAMEOPT_INFHOUSE: // Note: In theory, I could ignore this if it refers to me. I've already set my own house.
- {
- nGuestLastParamID = atoi( szInform );
- szInform += 7;
- HousesType House = (HousesType)( atoi( szInform ) );
- szInform += 3;
- SetPlayerHouse( szInform, House ); // (szInform is now sitting at the start of the name string.)
- ClearAllAccepts();
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- }
- case WOL_GAMEOPT_INFACCEPT: // Note: In theory, I could ignore this if it refers to me.
- // A guest has accepted.
- SetPlayerAccepted( szInform, true ); // (szInform is now sitting at the start of the name string.)
- break;
- case WOL_GAMEOPT_INFPARAMS:
- // Game params have changed.
- bParamsReceived = true;
- if( !AcceptParams( szInform ) )
- bLeaveDueToRulesMismatchTrigger = true;
- SetSpecialControlStates();
- //pILScens->Set_Selected_Index( Session.Options.ScenarioIndex );
- display = REDRAW_ALL;
- ClearAllAccepts();
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- case WOL_GAMEOPT_INFNEWGUESTPLAYERINFO:
- // I have just joined and have received a message with info on all players in game.
- AcceptNewGuestPlayerInfo( szInform );
- Sound_Effect(VOC_OPTIONS_CHANGED);
- break;
- case WOL_GAMEOPT_INFSTART:
- {
- // Host tells us to wait for start of game.
- // debugprint( "Guest received WOL_GAMEOPT_INFSTART.\n" );
- nGuestLastParamID = atoi( szInform );
- // The following check is not necessary. Rules.ini, if manually replaced by a cheater, is not reloaded.
- // So prior checks (that occur on game params receives) are sufficient.
- // szInform += 7;
- // // Check rules.ini compatibility.
- // int iRulesID = atoi( szInform );
- // if( RuleINI.Get_Unique_ID() != iRulesID )
- // {
- // // Rules.ini incompatible. Don't respond to call for start.
- // bLeaveDueToRulesMismatchTrigger = true;
- // break;
- // }
- User* pUserHost = pWO->pGameHost();
- if( pUserHost ) // This better'd be true.
- {
- // Send ack back to host.
- char szSend[ 20 ];
- // Make sure we have the scenario.
- if( !bNeedScenarioDownload() )
- sprintf( szSend, "%02u %06u", WOL_GAMEOPT_REQSTART, nGuestLastParamID );
- else
- sprintf( szSend, "%02u %06u", WOL_GAMEOPT_REQSTART_BUTNEEDSCENARIO, nGuestLastParamID );
- pWO->SendGameOpt( szSend, pUserHost );
- // Enter waiting mode.
- bWaitingToStart = true;
- WWMessageBox().Process( TXT_WOL_WAITINGTOSTART, TXT_NONE );
- BindControls( false );
- // If we are in a modal dialog, we must have arrived here through Call_Back()'s PumpMessages.
- // Set global that will force edit dialogs to stop accepting characters.
- // This is to fix a minor glitch: guests can keep typing into a "page" dialog editbox after the
- // "Launching game..." message has appeared on top of it.
- if( pWO->bPump_In_Call_Back )
- disable_current_msgbox = true;
- }
- else
- {
- // debugprint( "Impossible arose on WOL_GAMEOPT_INFSTART.\n" );
- Fatal( "Impossible arose on WOL_GAMEOPT_INFSTART.\n" );
- }
- Sound_Effect( VOC_GAME_CLOSED );
- break;
- }
- case WOL_GAMEOPT_INFCANCELSTART:
- // Host tells us to cancel waiting for start of game.
- bWaitingToStart = false;
- ClearAllAccepts();
- BindControls( true );
- WOL_PrintMessage( *pILDisc, TXT_WOL_STARTCANCELLED, WOLCOLORREMAP_LOCALMACHINEMESS );
- Sound_Effect( VOC_SYS_ERROR );
- display = REDRAW_ALL;
- // If we are in a modal dialog, we must have arrived here through Call_Back()'s PumpMessages. Set global that will
- // force a cancel out of the dialog.
- if( pWO->bPump_In_Call_Back )
- cancel_current_msgbox = true;
- break;
- case WOL_GAMEOPT_INFGO:
- // Host says start game right now.
- strcpy( szTriggerGameStartInfo, szInform );
- // If we are in a modal dialog, we must have arrived here through Call_Back()'s PumpMessages. Set global that will
- // force a cancel out of the dialog.
- if( pWO->bPump_In_Call_Back )
- cancel_current_msgbox = true;
- break;
- default:
- // debugprint( "Unhandled value of %i in ProcessInform!!!\n", opt );
- //WOL_PrintMessage( *pILDisc, "Error - Unhandled value in ProcessInform!!!", WOLCOLORREMAP_LOCALMACHINEMESS );
- Fatal( "Error - Unhandled value in ProcessInform!" );
- break;
- }
- }
- // debugprint( "* END of ProcessInform: '%s'\n", szInform );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::bParamsUnfresh()
- {
- // Returns true if game setup parameters do not match what they were last time they were sent.
- GAMEPARAMS GParamsNow;
- SetGParamsToCurrent( GParamsNow );
- // if( !( GParamsNow == GParamsLastSent ) )
- // {
- // debugprint( "---- Params Unfresh: OLD...\n" );
- // Debug_GlobalPacketType( GParamsLastSent.GPacket );
- // debugprint( "------------------- NEW...\n" );
- // Debug_GlobalPacketType( GParamsNow.GPacket );
- // debugprint( "old bAftermathUnits = %i\n", GParamsLastSent.bAftermathUnits );
- // debugprint( "new bAftermathUnits = %i\n", GParamsNow.bAftermathUnits );
- // }
- return !( GParamsNow == GParamsLastSent );
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::SendParams()
- {
- // Host only.
- SetGParamsToCurrent( GParamsLastSent );
- char szSend[ 130 + DESCRIP_MAX + 12 + 32 + 100 ];
- sprintf( szSend,
- "%01u "
- "%06u "
- "%03u "
- "%s "
- "%u "
- "%s "
- "%01u "
- "%.32s " // No null-terminator on digest. There may be nothing at all inserted here.
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- "%u "
- ,
- WOL_GAMEOPT_INFPARAMS,
- nHostLastParamID,
- strlen( GParamsLastSent.GPacket.ScenarioInfo.Scenario ),
- GParamsLastSent.GPacket.ScenarioInfo.Scenario,
- GParamsLastSent.GPacket.ScenarioInfo.FileLength,
- GParamsLastSent.GPacket.ScenarioInfo.ShortFileName,
- // strlen( (char*)GParamsLastSent.GPacket.ScenarioInfo.FileDigest ), not null-terminated!
- GParamsLastSent.GPacket.ScenarioInfo.FileDigest[0] ? 1 : 0,
- GParamsLastSent.GPacket.ScenarioInfo.FileDigest,
- GParamsLastSent.GPacket.ScenarioInfo.OfficialScenario,
- GParamsLastSent.GPacket.ScenarioInfo.Credits,
- GParamsLastSent.GPacket.ScenarioInfo.IsBases,
- GParamsLastSent.GPacket.ScenarioInfo.IsTiberium,
- GParamsLastSent.GPacket.ScenarioInfo.IsGoodies,
- GParamsLastSent.GPacket.ScenarioInfo.BuildLevel,
- GParamsLastSent.GPacket.ScenarioInfo.UnitCount,
- GParamsLastSent.GPacket.ScenarioInfo.AIPlayers,
- GParamsLastSent.GPacket.ScenarioInfo.Seed,
- GParamsLastSent.GPacket.ScenarioInfo.Special.IsShadowGrow,
- GParamsLastSent.GPacket.ScenarioInfo.Special.IsSpeedBuild,
- GParamsLastSent.GPacket.ScenarioInfo.Special.IsFromInstall,
- GParamsLastSent.GPacket.ScenarioInfo.Special.IsCaptureTheFlag,
- GParamsLastSent.GPacket.ScenarioInfo.Special.IsInert,
- GParamsLastSent.GPacket.ScenarioInfo.Special.IsThreePoint,
- GParamsLastSent.GPacket.ScenarioInfo.Special.IsTGrowth,
- GParamsLastSent.GPacket.ScenarioInfo.Special.IsTSpread,
- GParamsLastSent.GPacket.ScenarioInfo.GameSpeed,
- GParamsLastSent.GPacket.ScenarioInfo.Version,
- GParamsLastSent.bAftermathUnits, // Not currently used.
- GParamsLastSent.bSlowUnitBuildRate,
- RuleINI.Get_Unique_ID() // Used to verify rules.ini files match.
- );
- pWO->SendGameOpt( szSend, NULL );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::AcceptParams( char* szParams )
- {
- // Reverse of SendParams() process. szParams has already been stripped of 2 bytes header. Guest only.
- // Returns false if rules.ini doesn't match that of the host.
- // (Or if an error occurs due to the packet being incorrect - which happened once in test...)
- char szDelimiter[] = " ";
- char* szToken;
- char* szRemaining;
- szToken = strtok( szParams, szDelimiter );
- nGuestLastParamID = atoi( szToken );
- // Read in length of following string.
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- int iLen = atoi( szToken );
- // Set string pointer to start of string (length is 3 digits).
- szRemaining = szToken + 4;
- // Read in string.
- memcpy( Session.Options.ScenarioDescription, szRemaining, iLen );
- // Null-terminate.
- Session.Options.ScenarioDescription[ iLen ] = 0;
- // Advance string pointer to next param.
- szRemaining += iLen + 1;
- //debugprint( "scenario description is '%s'\n", Session.Options.ScenarioDescription );
- //debugprint( "remaining: '%s'\n", szRemaining );
- szToken = strtok( szRemaining, szDelimiter );
- if( !szToken ) return false;
- Session.ScenarioFileLength = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- strcpy( Session.ScenarioFileName, szToken );
- // // Read in length of following string.
- // szToken = strtok( NULL, szDelimiter );
- // iLen = atoi( szToken );
- // // Set string pointer to start of string (length is 3 digits).
- // szRemaining = szToken + 4;
- // Method changed.
- // Check if there is a digest.
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- iLen = atoi( szToken ); // 1 or 0, indicating if there is a digest following.
- if( iLen )
- {
- // // Set string pointer to start of string (previous field is 1 digit).
- // szRemaining = szToken + 2;
- // iLen = sizeof( Session.ScenarioDigest );
- // // Read in string.
- // memcpy( Session.ScenarioDigest, szRemaining, iLen );
- // // // Null-terminate.
- // // Session.ScenarioDigest[ iLen ] = 0; Digest has no null-terminator!
- // // Advance string pointer to next param.
- // szRemaining += iLen + 1;
- // There is a digest.
- szToken = strtok( NULL, szDelimiter ); // (Digests can't have spaces in the them.)
- //debugprint( "digest: '%s'\n", szToken );
- if( !szToken ) return false;
- strncpy( Session.ScenarioDigest, szToken, sizeof( Session.ScenarioDigest ) );
- }
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Session.ScenarioIsOfficial = (bool)atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Session.Options.Credits = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Session.Options.Bases = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Session.Options.Tiberium = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Session.Options.Goodies = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- BuildLevel = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Session.Options.UnitCount = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Session.Options.AIPlayers = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Seed = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Special.IsShadowGrow = ( atoi( szToken ) == 0 ) ? 0 : 1;
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Special.IsSpeedBuild = ( atoi( szToken ) == 0 ) ? 0 : 1;
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Special.IsFromInstall = ( atoi( szToken ) == 0 ) ? 0 : 1;
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Special.IsCaptureTheFlag = ( atoi( szToken ) == 0 ) ? 0 : 1;
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Special.IsInert = ( atoi( szToken ) == 0 ) ? 0 : 1;
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Special.IsThreePoint = ( atoi( szToken ) == 0 ) ? 0 : 1;
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Special.IsTGrowth = ( atoi( szToken ) == 0 ) ? 0 : 1;
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Special.IsTSpread = ( atoi( szToken ) == 0 ) ? 0 : 1;
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- Options.GameSpeed = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- // "Version" = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- bAftermathUnits = (bool)atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- bSlowUnitBuildRate = (bool)atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- if( !szToken ) return false;
- int iRulesID = atoi( szToken );
- szToken = strtok( NULL, szDelimiter );
- // if( szToken )
- // debugprint( "szToken should be NULL!!!!!!!!\n" );
- return ( RuleINI.Get_Unique_ID() == iRulesID );
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::SetGParamsToCurrent( GAMEPARAMS& GParams )
- {
- // Sets values in a GAMEPARAMS to the current game settings.
- strcpy( GParams.GPacket.ScenarioInfo.Scenario, Session.Scenarios[ Session.Options.ScenarioIndex ]->Description() );
- CCFileClass file( Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() );
- GParams.GPacket.ScenarioInfo.FileLength = file.Size();
- strcpy( GParams.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() );
- // Digest is not null-terminated.
- strncpy( (char*)GParams.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Digest(), sizeof( GParams.GPacket.ScenarioInfo.FileDigest ) );
- GParams.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Official();
- GParams.GPacket.ScenarioInfo.Credits = Session.Options.Credits;
- GParams.GPacket.ScenarioInfo.IsBases = Session.Options.Bases;
- GParams.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;
- GParams.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;
- GParams.GPacket.ScenarioInfo.BuildLevel = BuildLevel;
- GParams.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;
- GParams.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;
- GParams.GPacket.ScenarioInfo.Seed = Seed;
- GParams.GPacket.ScenarioInfo.Special = Special;
- GParams.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
- GParams.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();
- GParams.bAftermathUnits = bAftermathUnits;
- GParams.bSlowUnitBuildRate = bSlowUnitBuildRate;
- }
- //***********************************************************************************************
- bool operator==( const GAMEPARAMS& gp1, const GAMEPARAMS& gp2 )
- {
- return gp1.GPacket == gp2.GPacket &&
- gp1.bAftermathUnits == gp2.bAftermathUnits && gp1.bSlowUnitBuildRate == gp2.bSlowUnitBuildRate;
- }
- //***********************************************************************************************
- bool operator==( const GlobalPacketType& gp1, const GlobalPacketType& gp2 )
- {
- if( strcmp( gp1.ScenarioInfo.Scenario, gp2.ScenarioInfo.Scenario ) != 0 ) return false;
- if( strcmp( gp1.ScenarioInfo.ShortFileName, gp2.ScenarioInfo.ShortFileName ) != 0 ) return false;
- // Digest is not null-terminated...
- if( strncmp( (const char*)gp1.ScenarioInfo.FileDigest, (const char*)gp2.ScenarioInfo.FileDigest, sizeof( gp1.ScenarioInfo.FileDigest ) ) != 0 ) return false;
- if( gp1.ScenarioInfo.FileLength == gp2.ScenarioInfo.FileLength &&
- gp1.ScenarioInfo.OfficialScenario == gp2.ScenarioInfo.OfficialScenario &&
- gp1.ScenarioInfo.Credits == gp2.ScenarioInfo.Credits &&
- gp1.ScenarioInfo.IsBases == gp2.ScenarioInfo.IsBases &&
- gp1.ScenarioInfo.IsTiberium == gp2.ScenarioInfo.IsTiberium &&
- gp1.ScenarioInfo.IsGoodies == gp2.ScenarioInfo.IsGoodies &&
- gp1.ScenarioInfo.BuildLevel == gp2.ScenarioInfo.BuildLevel &&
- gp1.ScenarioInfo.UnitCount == gp2.ScenarioInfo.UnitCount &&
- gp1.ScenarioInfo.AIPlayers == gp2.ScenarioInfo.AIPlayers &&
- gp1.ScenarioInfo.Seed == gp2.ScenarioInfo.Seed &&
- gp1.ScenarioInfo.Special.IsShadowGrow == gp2.ScenarioInfo.Special.IsShadowGrow &&
- gp1.ScenarioInfo.Special.IsSpeedBuild == gp2.ScenarioInfo.Special.IsSpeedBuild &&
- gp1.ScenarioInfo.Special.IsFromInstall == gp2.ScenarioInfo.Special.IsFromInstall &&
- gp1.ScenarioInfo.Special.IsCaptureTheFlag == gp2.ScenarioInfo.Special.IsCaptureTheFlag &&
- gp1.ScenarioInfo.Special.IsInert == gp2.ScenarioInfo.Special.IsInert &&
- gp1.ScenarioInfo.Special.IsThreePoint == gp2.ScenarioInfo.Special.IsThreePoint &&
- gp1.ScenarioInfo.Special.IsTGrowth == gp2.ScenarioInfo.Special.IsTGrowth &&
- gp1.ScenarioInfo.Special.IsTSpread == gp2.ScenarioInfo.Special.IsTSpread &&
- gp1.ScenarioInfo.GameSpeed == gp2.ScenarioInfo.GameSpeed &&
- gp1.ScenarioInfo.Version == gp2.ScenarioInfo.Version )
- return true;
- return false;
- }
- //***********************************************************************************************
- /*
- void Debug_GlobalPacketType( const GlobalPacketType& gp1 ) // ajw debugging
- {
- if( *gp1.ScenarioInfo.Scenario )
- // debugprint( "Scenario = %s\n", (char*)gp1.ScenarioInfo.Scenario );
- else
- // debugprint( "!Scenario string is null\n" );
- if( *gp1.ScenarioInfo.ShortFileName )
- // debugprint( "ShortFileName = %s\n", (char*)gp1.ScenarioInfo.ShortFileName );
- else
- // debugprint( "!ShortFileName string is null\n" );
- // Remember ShortFileName is not null-terminated...
- if( *gp1.ScenarioInfo.FileDigest )
- // debugprint( "FileDigest = %.32s\n", (char*)gp1.ScenarioInfo.FileDigest );
- else
- // debugprint( "!FileDigest string is null\n" );
- // debugprint( "FileLength = %i\n"
- "OfficialScenario = %i\n"
- "Credits = %i\n"
- "IsBases = %i\n"
- "IsTiberium = %i\n"
- "IsGoodies = %i\n"
- "BuildLevel = %i\n"
- "UnitCount = %i\n"
- "AIPlayers = %i\n"
- "Seed = %i\n"
- "Special.IsShadowGrow = %i\n"
- "Special.IsSpeedBuild = %i\n"
- "Special.IsFromInstall = %i\n"
- "Special.IsCaptureTheFlag = %i\n"
- "Special.IsInert = %i\n"
- "Special.IsThreePoint = %i\n"
- "Special.IsTGrowth = %i\n"
- "Special.IsTSpread = %i\n"
- "GameSpeed = %i\n"
- "Version = %i\n",
- gp1.ScenarioInfo.FileLength,
- gp1.ScenarioInfo.OfficialScenario,
- gp1.ScenarioInfo.Credits,
- gp1.ScenarioInfo.IsBases,
- gp1.ScenarioInfo.IsTiberium,
- gp1.ScenarioInfo.IsGoodies,
- gp1.ScenarioInfo.BuildLevel,
- gp1.ScenarioInfo.UnitCount,
- gp1.ScenarioInfo.AIPlayers,
- gp1.ScenarioInfo.Seed,
- gp1.ScenarioInfo.Special.IsShadowGrow,
- gp1.ScenarioInfo.Special.IsSpeedBuild,
- gp1.ScenarioInfo.Special.IsFromInstall,
- gp1.ScenarioInfo.Special.IsCaptureTheFlag,
- gp1.ScenarioInfo.Special.IsInert,
- gp1.ScenarioInfo.Special.IsThreePoint,
- gp1.ScenarioInfo.Special.IsTGrowth,
- gp1.ScenarioInfo.Special.IsTSpread,
- gp1.ScenarioInfo.GameSpeed,
- gp1.ScenarioInfo.Version );
- }
- */
- //***********************************************************************************************
- PlayerColorType PlayerColorTypeOf( RemapControlType* pColorRemap )
- {
- for( PlayerColorType pcolor = PCOLOR_FIRST; pcolor < PCOLOR_COUNT; pcolor++ )
- {
- if( &ColorRemaps[ pcolor ] == pColorRemap )
- return pcolor;
- }
- return PCOLOR_NONE;
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::RequestPlayerColor( PlayerColorType Color )
- {
- // Local player sends a request to the game host asking for a particular color.
- char szSend[ 20 ];
- // WOL_GAMEOPT_REQCOLOR format:
- // 2 WOL_GAMEOPT
- // 1 space
- // 2 color
- sprintf( szSend, "%02u %02u", WOL_GAMEOPT_REQCOLOR, Color );
- _ASSERTE( pWO->pGameHost() );
- return pWO->SendGameOpt( szSend, pWO->pGameHost() );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::InformAboutPlayerColor( const char* szName, PlayerColorType Color, User* pUserPriv )
- {
- // Game host tells guests about a player color assignment.
- // If pUserPriv is not null, indicates user to send message as private to.
- char szSend[ 20 + WOL_NAME_LEN_MAX ];
- // WOL_GAMEOPT_INFCOLOR format:
- // 2 WOL_GAMEOPT
- // 1 space
- // 2 color
- // 1 space
- // string name of player
- if( Color == PCOLOR_NONE )
- {
- // debugprint( "Bad Color for %s in InformAboutPlayerColor.\n", szName );
- *szSend = 0;
- }
- else
- sprintf( szSend, "%02u %02u %s", WOL_GAMEOPT_INFCOLOR, Color, szName );
- return pWO->SendGameOpt( szSend, pUserPriv );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::InformAboutPlayerHouse( const char* szName, HousesType House, User* pUserPriv )
- {
- // Game host tells guests about a player house assignment.
- // If pUserPriv is not null, indicates user to send message as private to.
- char szSend[ 28 + WOL_NAME_LEN_MAX ];
- // WOL_GAMEOPT_INFHOUSE format:
- // 2 WOL_GAMEOPT
- // 1 space
- // 6 param ID
- // 1 space
- // 2 house
- // 1 space
- // string name of player
- if( House == HOUSE_NONE )
- {
- // debugprint( "Bad House for %s in InformAboutPlayerHouse.\n", szName );
- *szSend = 0;
- }
- else
- sprintf( szSend, "%02u %06u %02u %s", WOL_GAMEOPT_INFHOUSE, nHostLastParamID, (short)House, szName );
- return pWO->SendGameOpt( szSend, pUserPriv );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::InformAboutPlayerAccept( const char* szName, User* pUserPriv )
- {
- // Game host tells guests about player accepting game params.
- // If pUserPriv is not null, indicates user to send message as private to.
- char szSend[ 6 + WOL_NAME_LEN_MAX ];
- sprintf( szSend, "%02u %s", WOL_GAMEOPT_INFACCEPT, szName );
- return pWO->SendGameOpt( szSend, pUserPriv );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::InformAboutStart()
- {
- // Game host tells all guests that he wants to start the game.
- // Note that nHostLastParamID is involved here. We want to make sure that guest responses apply
- // to the latest WOL_GAMEOPT_INFSTART, and not to an earlier one we canceled out of.
- char szSend[ 10 ];
- sprintf( szSend, "%02u %06u", WOL_GAMEOPT_INFSTART, nHostLastParamID );
- return pWO->SendGameOpt( szSend, NULL );
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::InformAboutCancelStart()
- {
- // Game host tells all guests that he wants to start the game.
- // Note that nHostLastParamID is involved here. We want to make sure that guest responses apply
- // to the latest WOL_GAMEOPT_INFSTART, and not to an earlier one we canceled out of.
- // debugprint( "InformAboutCancelStart!\n" );
- char szSend[ 10 ];
- sprintf( szSend, "%02u", WOL_GAMEOPT_INFCANCELSTART );
- return pWO->SendGameOpt( szSend, NULL );
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::OnGuestJoin( User* pUser )
- {
- // A guest (not myself) has entered the game channel.
- // debugprint( "OnGuestJoin()\n" );
- char* szPrint = new char[ strlen( TXT_WOL_PLAYERJOINEDGAME ) + strlen( (char*)pUser->name ) + 5 ];
- sprintf( szPrint, TXT_WOL_PLAYERJOINEDGAME, (char*)pUser->name );
- WOL_PrintMessage( *pILDisc, szPrint, WOLCOLORREMAP_LOCALMACHINEMESS );
- delete [] szPrint;
- ClearAllAccepts();
- if( bHost )
- {
- // Send the new guest the current setup. Note that nHostLastParamID doesn't change here.
- // Assign color to new guest.
- PlayerColorType Color = ColorNextAvailable();
- SetPlayerColor( (char*)pUser->name, Color );
- // Previously, I was sending an individual color, house, and acceptedstate message for each other guest.
- // Though convenient code-wise, this causes the initial info to arrive at the new guest in a very slow
- // manner. This is because of the wonderful "anti-flood" feature of the chat server, which prevents a
- // series of messages from a client from being passed on faster than a certain rate.
- // For this reason, a new message that contains all of the info about all of the other guests has been
- // created (WOL_GAMEOPT_INFNEWGUESTPLAYERINFO).
- // WOL_GAMEOPT_INFNEWGUESTPLAYERINFO format (items separated by spaces):
- // WOL_GAMEOPT
- // number of players
- // for each player {
- // length of player name string
- // player name
- // color
- // bool - is there a house field following?
- // (house)
- // // (removed) acceptedness - true for set player accepted, false for do nothing
- // }
- // Build up a big WOL_GAMEOPT_INFNEWGUESTPLAYERINFO message.
- char szSend[ 500 ];
- sprintf( szSend, "%02u %02u", WOL_GAMEOPT_INFNEWGUESTPLAYERINFO, pILPlayers->Count() );
- // Send color and house of all players (including himself) to the new guest.
- for( int i = 0; i < pILPlayers->Count(); i++ )
- {
- char szSendPiece[ 100 ];
- char szPlayerName[ WOL_NAME_LEN_MAX ];
- pWO->PullPlayerName_Into_From( szPlayerName, pILPlayers->Get_Item( i ) );
- // InformAboutPlayerColor( szPlayerName, PlayerColorTypeOf( pILPlayers->Get_Item_Color( i ) ), pUser );
- sprintf( szSendPiece, " %02u %s %02u", strlen( szPlayerName ), szPlayerName,
- PlayerColorTypeOf( pILPlayers->Get_Item_Color( i ) ) );
- if( strcmp( szPlayerName, (char*)pUser->name ) != 0 )
- {
- HousesType House = pWO->PullPlayerHouse_From( pILPlayers->Get_Item( i ) );
- if( House != HOUSE_NONE )
- {
- // InformAboutPlayerHouse( szPlayerName, House, pUser );
- char szSendHouse[ 50 ];
- sprintf( szSendHouse, " 1 %02u", (short)House );
- strcat( szSendPiece, szSendHouse );
- }
- else
- {
- // Player must not have told me what house he is yet. Don't send house value.
- strcat( szSendPiece, " 0" );
- }
- }
- else
- {
- // Player is the new guest himself. Don't send house value.
- strcat( szSendPiece, " 0" );
- }
- // Acceptedness must be false! No need to send.
- // // Send "accepted" status of player. Ignore myself, as I'm the host.
- // if( strcmp( szPlayerName, pWO->szMyName ) != 0 && pWO->bItemMarkedAccepted( i ) )
- // strcat( szSendPiece, " 1" );
- // else
- // strcat( szSendPiece, " 0" );
- strcat( szSend, szSendPiece );
- }
- pWO->SendGameOpt( szSend, pUser );
- // Send everyone the color of the new guest.
- InformAboutPlayerColor( (char*)pUser->name, Color, NULL );
- // Send game params.
- // This is done last because it contains a param ID value, and we need to ensure that the new guest has
- // received everything we are sending him here before he tries to send me an accept.
- // If game params were sent first, he could theoretically receive them, then send an accept, even though he
- // has not received the WOL_GAMEOPT_INFNEWGUESTPLAYERINFO.
- // By doing this I avoid having to have a param ID in WOL_GAMEOPT_INFNEWGUESTPLAYERINFO, which would be hard,
- // since it is a private message.
- // For simplicity, send public.
- SendParams();
- }
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::AcceptNewGuestPlayerInfo( char* szMsg )
- {
- // Process a received WOL_GAMEOPT_INFNEWGUESTPLAYERINFO message.
- // szMsg has already been stripped of 2 bytes header.
- char szDelimiter[] = " ";
- char* szToken;
- char* szRemaining;
- szToken = strtok( szMsg, szDelimiter );
- unsigned int nPlayers = atoi( szToken );
- // We have to assist strtok a bit because of calls below that may also call strtok()...
- szRemaining = szMsg + 3;
- for( unsigned int nPlayer = 0; nPlayer != nPlayers; ++nPlayer )
- {
- // Read in length of following string.
- szToken = strtok( szRemaining, szDelimiter );
- int iLen = atoi( szToken );
- // Set string pointer to start of string (length is 2 digits).
- szRemaining = szToken + 3;
- // Read in string.
- char szPlayerName[ 50 ];
- memcpy( szPlayerName, szRemaining, iLen );
- // Null-terminate.
- szPlayerName[ iLen ] = 0;
- // Advance string pointer to next param.
- szRemaining += iLen + 1;
- // Read color.
- szToken = strtok( szRemaining, szDelimiter );
- PlayerColorType Color = (PlayerColorType)atoi( szToken );
- SetPlayerColor( szPlayerName, Color );
- // SetPlayerColor may call strtok, so we can't use the strtok( NULL, option... in the next call.
- szRemaining += 3;
- // Read whether there is a house field.
- szToken = strtok( szRemaining, szDelimiter );
- bool bHouseField = (bool)atoi( szToken );
- if( bHouseField )
- {
- // Read house.
- szToken = strtok( NULL, szDelimiter );
- HousesType House = (HousesType)atoi( szToken );
- SetPlayerHouse( szPlayerName, House );
- // SetPlayerHouse may call strtok, so we can't use the strtok( NULL, option... in the next call.
- szRemaining += 5;
- }
- else
- szRemaining += 2; // Advance past "0 ".
- // Acceptedness must be false. No need for it in message.
- // // Read acceptedness.
- // szToken = strtok( NULL, szDelimiter );
- // bool bAccepted = (bool)atoi( szToken );
- // if( bAccepted )
- // SetPlayerAccepted( szPlayerName, true );
- }
- szToken = strtok( NULL, szDelimiter );
- // if( szToken )
- // debugprint( "szToken should be NULL!!!!!!!!\n" );
- ClearAllAccepts(); // Most likely a pointless precaution.
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::OnGuestLeave( User* pUser )
- {
- // pUser is about to leave but is still in our player list.
- if( pUser->flags & CHAT_USER_CHANNELOWNER )
- {
- // Host is leaving the channel. We must be a guest, and so must leave also. This will trigger exit.
- strcpy( szNameOfHostWhoJustBailedOnUs, (char*)pUser->name );
- }
- else
- {
- ClearAllAccepts();
- }
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::ClearAllAccepts()
- {
- // Clears all "player has accepted" marks.
- //debugprint( "ClearAllAccepts()\n" );
- for( int i = 0; i < pILPlayers->Count(); i++ )
- {
- User* pUser = (User*)pILPlayers->Get_Item_ExtraDataPtr( i );
- if( pUser && !( pUser->flags & CHAT_USER_CHANNELOWNER ) ) // pUser null if this is an "early insertion" entry on startup
- pWO->MarkItemAccepted( i, false );
- }
- if( pToolTipHitLast && pToolTipHitLast->bShowing )
- pToolTipHitLast->Unshow();
- if( bHost )
- {
- pTextBtnAcceptStart->Disable();
- if( bWaitingToStart )
- {
- // Something has happened that makes starting a game not possible now.
- // Cancel out of waiting mode and tell guests to do the same.
- bWaitingToStart = false;
- InformAboutCancelStart();
- BindControls( true );
- ResetReadyToGo();
- display = REDRAW_ALL;
- }
- else
- pTextBtnAcceptStart->Flag_To_Redraw();
- }
- else
- {
- pTextBtnAcceptStart->Enable();
- pTextBtnAcceptStart->Flag_To_Redraw();
- }
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::bAllGuestsAccept()
- {
- for( int i = 0; i < pILPlayers->Count(); i++ )
- {
- if( !pWO->bItemMarkedAccepted( i ) )
- return false;
- }
- return true;
- }
- //***********************************************************************************************
- PlayerColorType WOL_GameSetupDialog::ColorNextAvailable()
- {
- // Returns the first free player color available.
- // (Totally unoptimized, but hardly ever called.)
- for( int i = 0; i < MAX_MPLAYER_COLORS; i++ )
- {
- if( pILPlayers->FindColor( &ColorRemaps[ i ] ) == -1 )
- {
- return (PlayerColorType)i;
- }
- }
- // debugprint( "ColorNextAvailable is NONE!\n" );
- return PCOLOR_NONE;
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::GuestIsReadyToPlay( const char* szName, const char* szReadyState )
- {
- // A guest has responded to a game start request.
- SetPlayerReadyToGo( szName, szReadyState );
- if( bAllPlayersReadyToGo() )
- {
- // debugprint( "All players ready to go.\n" );
- // We can start the game.
- bHostSayGo = true; // Set trigger to fire function after we're out of callback.
- }
- }
- //***********************************************************************************************
- bool WOL_GameSetupDialog::bNeedScenarioDownload()
- {
- // Returns true if we don't have the scenario and it is allowable as a download.
- if( !bHost )
- {
- if( Find_Local_Scenario( Session.Options.ScenarioDescription,
- Session.ScenarioFileName,
- Session.ScenarioFileLength,
- Session.ScenarioDigest,
- Session.ScenarioIsOfficial ) )
- {
- // debugprint( "bNeedScenarioDownload() returning false.\n" );
- bRequestedScenarioDownload = false;
- return false;
- }
- else
- {
- /* if( !Session.ScenarioIsOfficial )
- {
- bRequestedScenarioDownload = true;
- return true;
- }
- else
- {
- // debugprint( "bNeedScenarioDownload fatal\n" );
- Fatal( "" );
- }
- */
- // debugprint( "Requesting download\n" ); // ajw Shouldn't be happening with am maps when i have am...?
- bRequestedScenarioDownload = true; // All maps are downloadable.
- return true;
- }
- }
- bRequestedScenarioDownload = false;
- return false;
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::HostSaysGo()
- {
- bHostSayGo = false;
- bHostWaitingForGoTrigger = true;
- // debugprint( "HostSaysGo()\n" );
- if( !pWO->RequestGameStart() )
- {
- // debugprint( "Call to RequestGameStart() failed.\n" );
- //Fatal( "Call to RequestGameStart() failed.\n" );
- pWO->bSelfDestruct = true;
- return;
- }
- // Tell guests to start game.
- // debugprint( "Telling guests to start game.\n" );
- // Create WOL_GAMEOPT_INFGO message.
- // This contains the color for each player, which can change about haphazardly at the end of setup,
- // without causing "unacceptedness". This means that the colors everyone thinks everyone else is might not
- // be sync'ed. Host sets everyone straight here.
- char szSend[ ( WOL_NAME_LEN_MAX + 10 ) * 4 + 50 ] = "";
- sprintf( szSend, "%02u", WOL_GAMEOPT_INFGO );
- User* pUser = pWO->pChatSink->pGameUserList;
- while( pUser )
- {
- char szUser[ WOL_NAME_LEN_MAX + 10 ];
- PlayerColorType Color = GetPlayerColor( (char*)pUser->name );
- sprintf( szUser, " %s %02u", (char*)pUser->name, Color ); // What if player left just now, and got removed from list. Ok to continue and fail on game start?
- strcat( szSend, szUser );
- pUser = pUser->next;
- }
- if( !pWO->SendGo( szSend ) )
- {
- // debugprint( "Call to SendGo() failed.\n" );
- //Fatal( "Call to SendGo() failed.\n" );
- pWO->bSelfDestruct = true;
- return;
- }
- /* ...Method changed. It appears that my channelleave may appear to guests before the "go" privategameopt.
- For this reason, I'll wait until I receive a copy of the "go" message sent to myself, before proceeding.
- pWO->pChat->PumpMessages(); // Flush the send out.
- // (ajw - Note: An apparent bug in wolapi means that this pump does not necessarily flush the go gameopts.
- // This is ok in practice, because the host hits pumps later that will flush them.)
- // Pretend we just received szSend, and processed it like a guest would.
- char* szFakeGoMessage = szSend + 3;
- TriggerGameStart( szFakeGoMessage );
- */
- }
- //***********************************************************************************************
- void WOL_GameSetupDialog::TriggerGameStart( char* szGoMessage )
- {
- // Last function before dialog is exited for game start. (Which must occur now.)
- // Host or guest is about to start a game using final data in szGoMessage.
- // debugprint( "TriggerGameStart( %s )\n", szGoMessage );
- // If we are in a modal dialog, we must have arrived here through Call_Back()'s PumpMessages. Set global that will
- // force a cancel out of the dialog.
- if( pWO->bPump_In_Call_Back )
- cancel_current_msgbox = true;
- bHostWaitingForGoTrigger = false;
- bExitForGameTrigger = true;
- // The following is based on Read_Game_Options()...
- // WWGetPrivateProfileString("Options", "Handle", "Noname", Session.Handle, sizeof(Session.Handle), buffer);
- strcpy( Session.Handle, pWO->szMyName );
- // GameName will be the host's name...
- strcpy( Session.GameName, pWO->pGameHostName() );
- // debugprint( "Session.GameName is %s\n", Session.GameName );
- // gotit Session.ColorIdx = (PlayerColorType) WWGetPrivateProfileInt("Options", "Color", 0, buffer);
- // gotit Session.PrefColor = Session.ColorIdx;
- // gotit int temp = WWGetPrivateProfileInt("Options", "Side", 0, buffer);
- // gotit Session.House = (HousesType) ((int)HOUSE_USSR + temp);
- // gotit Session.Options.Credits = WWGetPrivateProfileInt("Options", "Credits", 0, buffer);
- // gotit Session.Options.Bases = WWGetPrivateProfileInt("Options", "Bases", 0, buffer);
- // gotit Session.Options.Tiberium = WWGetPrivateProfileInt("Options", "Tiberium", 0, buffer);
- // gotit Session.Options.Goodies = WWGetPrivateProfileInt("Options", "Crates", 0, buffer);
- // gotit Special.IsShadowGrow = WWGetPrivateProfileInt ("Options", "Shadow", 0, buffer);
- // gotit BuildLevel = WWGetPrivateProfileInt("Options", "BuildLevel", 0, buffer);
- // gotit Session.Options.UnitCount = WWGetPrivateProfileInt("Options", "UnitCount", 0, buffer);
- // gotit Seed = WWGetPrivateProfileInt("Options", "Seed", 0, buffer);
- // gotit Special.IsCaptureTheFlag = WWGetPrivateProfileInt("Options", "CapFlag", 0, buffer);
- // UnitBuildPenalty = WWGetPrivateProfileInt ("Options", "BuildRate", 100, buffer);
- if( bSlowUnitBuildRate )
- UnitBuildPenalty = 250;
- else
- UnitBuildPenalty = 100;
- //PlanetWestwoodGameID = WWGetPrivateProfileInt("Internet", "GameID", 0, buffer);
- PlanetWestwoodGameID = pWO->pChatSink->iGameID;
- // Reset ChatSink's iGameID.
- pWO->pChatSink->iGameID = 0;
- //PlanetWestwoodStartTime = WWGetPrivateProfileInt ("Internet", "StartTime", 0, buffer);
- PlanetWestwoodStartTime = time( NULL );
- //WChatHWND = (HWND) WWGetPrivateProfileInt("Internet", "HWND", (int)FindWindow("OWL_Window", "Westwood Chat"), buffer);
- // gotit Session.Options.AIPlayers = WWGetPrivateProfileInt("Options", "AI", 0, buffer); //Number of AI players
- if (Session.Options.AIPlayers){
- Session.Options.Ghosts = 1;
- }
- if (Session.Options.Tiberium) {
- Special.IsTGrowth = 1;
- Special.IsTSpread = 1;
- } else {
- Special.IsTGrowth = 0;
- Special.IsTSpread = 0;
- }
- // The preceding was based on Read_Game_Options()...
- // Now do whatever we've left out that the horrific Net_Fake_New_Dialog() and Net_Fake_Join_Dialog() used to do for us...
- // Set up the Session.Players list.
- // I think there is dependence on the local player being first, so put him there.
- // Else put them in order listed in the szGoMessage.
- // I will set "ID" based on a player's color, though it seems unclear if this is even used in the game, or what it should be.
- Clear_Vector( &Session.Players );
- // Make the pILPlayers a valid list of players in the game.
- // Players might (incredibly rarely) have joined in the last split-second, and we only want the players listed in
- // the szGoMessage. To test for whether they're in this list, first wipe the colors from all list items.
- // Then we fill them in from info in szGoMessage.
- // We can ignore any list items then that have no color assigned.
- // Also, we'll know that the colors assigned to valid players indeed match up with what every other client has.
- // Remember, all other data should already be sync'ed because it has been implemented in such a way that changes would
- // cause "unacceptedness" of guests to occur.
- // Clear colors in list.
- for( int iItem = 0; iItem < pILPlayers->Count(); iItem++ )
- pILPlayers->Set_Item_Color( iItem, &ColorRemaps[ PCOLOR_NONE ] );
- // Parse szGoMessage to iterate through players.
- char szDelimiter[] = " ";
- char* szToken;
- char szPlayerName[ WOL_NAME_LEN_MAX ];
- szToken = strtok( szGoMessage, szDelimiter );
- while( szToken )
- {
- strcpy( szPlayerName, szToken );
- szToken = strtok( NULL, szDelimiter );
- PlayerColorType Color = (PlayerColorType)atoi( szToken );
- SetPlayerColor( szPlayerName, Color ); // ajw note: inserts if not found.
- szToken = strtok( NULL, szDelimiter );
- }
- // Add myself to Session.Players list.
- _ASSERTE( pILPlayers->Find( pWO->szMyName ) != -1 );
- NodeNameType* pPlayerNew = new NodeNameType;
- strcpy( pPlayerNew->Name, pWO->szMyName ); // "Name" is 12 chars max.
- //pPlayerNew->Address = Session.GAddress;
- pPlayerNew->Player.House = GetPlayerHouse( pWO->szMyName );
- //debugprint( "ME: pPlayerNew->Player.House = %i\n", pPlayerNew->Player.House );
- pPlayerNew->Player.Color = GetPlayerColor( pWO->szMyName );
- // This gets done later.
- // pPlayerNew->Player.ID = (HousesType)( pPlayerNew->Player.Color + HOUSE_MULTI1 );
- Session.Players.Add( pPlayerNew );
- char szHostName[ WOL_NAME_LEN_MAX ] = "Game host";
- // Add all other players to Session.Players list (if they have a valid color - see just above).
- // Also in this step - build the scenario download requests array (used by hosts only).
- memset( Session.ScenarioRequests, 0, sizeof( Session.ScenarioRequests ) );
- Session.RequestCount = 0;
- for( iItem = 0; iItem < pILPlayers->Count(); iItem++ )
- {
- // The following is not very efficient, but doesn't have to be. Better in this case to keep it clear and simple.
- pWO->PullPlayerName_Into_From( szPlayerName, pILPlayers->Get_Item( iItem ) );
- if( strcmp( szPlayerName, pWO->szMyName ) != 0 && GetPlayerColor( szPlayerName ) != PCOLOR_NONE )
- {
- // debugprint( "Creating player node '%s'\n", szPlayerName );
- pPlayerNew = new NodeNameType;
- strcpy( pPlayerNew->Name, szPlayerName );
- // Get player's IP address from pChatSink...
- unsigned long lAddress = ( pWO->pChatSink->GetPlayerGameIP( szPlayerName ) ); //ntohl(
- // debugprint( "IP address is %i, or 0x%x\n", lAddress, lAddress );
- if( pWO->GameInfoCurrent.bTournament )
- {
- // This is a tournament game, and I therefore have only one opponent: this one.
- // for convenience, save a copy of his IP address in case I need it later for disconnect pinging.
- pWO->TournamentOpponentIP = lAddress;
- pWO->bDisconnectPingingCompleted = false;
- }
- NetNumType net;
- NetNodeType node;
- memset( net, 0, 4 );
- memset( node, 0, 6 );
- memcpy( node, &lAddress, 4 );
- //memcpy( node + 2, &lAddress, 4 );
- pPlayerNew->Address.Set_Address( net, node );
- //pPlayerNew->Address = Session.GAddress;
- pPlayerNew->Player.House = GetPlayerHouse( szPlayerName );
- //debugprint( "Player %i: pPlayerNew->Player.House = %i\n", iItem, pPlayerNew->Player.House );
- pPlayerNew->Player.Color = GetPlayerColor( szPlayerName );
- // This gets done later.
- //pPlayerNew->Player.ID = (HousesType)( pPlayerNew->Player.Color + HOUSE_MULTI1 );
- Session.Players.Add( pPlayerNew );
- // If player is the game host, set HostAddress. This global is used when downloading scenarios; who knows where else.
- User* pUser = (User*)pILPlayers->Get_Item_ExtraDataPtr( iItem );
- if( pUser && pUser->flags & CHAT_USER_CHANNELOWNER )
- {
- Session.HostAddress = pPlayerNew->Address;
- strcpy( szHostName, (char*)pUser->name );
- /*
- // debugging
- NetNumType netxxx;
- NetNodeType nodexxx;
- Session.HostAddress.Get_Address( netxxx, nodexxx );
- // debugprint( "Host, ip %i.%i.%i.%i.%i.%i\n", nodexxx[0], nodexxx[1], nodexxx[2], nodexxx[3], nodexxx[4], nodexxx[5] );
- */
- }
- /*
- else
- {
- NetNumType netxxx;
- NetNodeType nodexxx;
- pPlayerNew->Address.Get_Address( netxxx, nodexxx );
- // debugprint( "Player ip %i.%i.%i.%i.%i.%i\n", nodexxx[0], nodexxx[1], nodexxx[2], nodexxx[3], nodexxx[4], nodexxx[5] );
- }
- */
- if( bHost && pWO->bItemMarkedNeedScenario( iItem ) )
- {
- // debugprint( "%s has requested scenario download.\n", szPlayerName );
- Session.ScenarioRequests[ Session.RequestCount++ ] = Session.Players.Count() - 1;
- }
- }
- // else
- // debugprint( "%s excluded from Session.Players\n", szPlayerName );
- }
- // From Init...
- // debugprint( "About to call Open_Socket().\n");
- PacketTransport->Open_Socket( 0 );
- // debugprint( "RA95 - About to call Start_Listening.\n" );
- PacketTransport->Start_Listening();
- /*
- ** Flush out any pending packets from a previous game.
- */
- PacketTransport->Discard_In_Buffers();
- PacketTransport->Discard_Out_Buffers();
- WWDebugString ("RA95 - About to call Init_Network.\n");
- Init_Network();
- Ipx.Set_Timing ( 30, // retry 2 times per second
- -1, // ignore max retries
- 600); // give up after 10 seconds
- // debugprint( "Session.ScenarioFileName is %s.\n", Session.ScenarioFileName );
- /*
- ** Read the scenario name from the .INI and try to match it with a scenario file in our list.
- */
- // gotit WWGetPrivateProfileString("Options", "Scenario", "SCM01EA.INI",
- // Session.Options.ScenarioDescription,
- // sizeof (Session.Options.ScenarioDescription),
- // buffer);
- //WWDebugString ("RA95I - Scenario is ");
- //WWDebugString (Session.Options.ScenarioDescription);
- //WWDebugString ("\n");
- if( !bHost ) // Else ScenarioIndex is already set.
- {
- if( bRequestedScenarioDownload )
- {
- Session.Options.ScenarioIndex = 1;
- if( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )
- {
- // Shouldn't ever happen. We should never have the opportunity to ask for one of these maps to be downloaded.
- bExitForGameTrigger = false;
- *szTriggerGameStartInfo = 0;
- // Trigger the "our host just left the channel" code...
- strcpy( szNameOfHostWhoJustBailedOnUs, szHostName );
- return;
- }
- // Wait for download from game host.
- //debugprint( "Wait for download from game host.\n" );
- if( !Get_Scenario_File_From_Host( Session.ScenarioFileName, 1 ) )
- {
- // debugprint( "Get_Scenario_File_From_Host failed!\n" );
- bExitForGameTrigger = false;
- *szTriggerGameStartInfo = 0;
- // Trigger the "our host just left the channel" code...
- strcpy( szNameOfHostWhoJustBailedOnUs, szHostName );
- return;
- }
- Scen.Scenario = Session.Options.ScenarioIndex;
- // debugprint( "Scen.Scenario = %i\n", Scen.Scenario );
- strcpy( Scen.ScenarioName, Session.ScenarioFileName );
- // debugprint( "Scen.ScenarioName = %s\n", Scen.ScenarioName );
- }
- else
- {
- // Match ScenarioDescription to a ScenarioIndex.
- /* This is how the same code existed previously. Insufficient because Description may match on many scenarios.
- Session.Options.ScenarioIndex = -1;
- for (int i = 0; i < Session.Scenarios.Count(); i++) {
- if (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){
- Session.Options.ScenarioIndex = i;
- break;
- }
- }
- */
- // (We have already done the lookup, in Find_Local_Scenario, above.)
- Session.Options.ScenarioIndex = ScenarioIndex_From_Filename( Session.ScenarioFileName );
- _ASSERTE( Session.Options.ScenarioIndex != -1 );
- Scen.Scenario = Session.Options.ScenarioIndex;
- // debugprint( "Scen.Scenario = %i\n", Scen.Scenario );
- strcpy( Scen.ScenarioName, Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() );
- // debugprint( "Scen.ScenarioName = %s\n", Scen.ScenarioName );
- }
- }
- else // bHost
- {
- Scen.Scenario = Session.Options.ScenarioIndex;
- // debugprint( "Scen.Scenario = %i\n", Scen.Scenario );
- strcpy( Scen.ScenarioName, Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Filename() );
- // debugprint( "Scen.ScenarioName = %s\n", Scen.ScenarioName );
- strcpy( Session.Options.ScenarioDescription, (char*)Session.Scenarios[ Session.Options.ScenarioIndex ]->Description() );
- }
- Options.GameSpeed = 0;
- //Session.MaxAhead = WChatMaxAhead = WWGetPrivateProfileInt("Timing", "MaxAhead", 9, buffer);
- //Session.FrameSendRate = WChatSendRate = WWGetPrivateProfileInt("Timing", "SendRate", 3, buffer);
- Session.MaxAhead = 15; //9;
- //Session.FrameSendRate = 5; //3;
- Session.FrameSendRate = 3; //3;
- // This is from NETDLG processing...
- Session.NumPlayers = Session.Players.Count();
- pWO->GameInfoCurrent.iPlayerCount = Session.Players.Count();
- Ipx.Set_Timing (25, (unsigned long) -1, 1000);
- if( bHost )
- {
- if( Session.Scenarios[ Session.Options.ScenarioIndex ]->Get_Official() )
- {
- if( !Force_Scenario_Available( Scen.ScenarioName ) )
- {
- bExitForGameTrigger = false;
- *szTriggerGameStartInfo = 0;
- pWO->bSelfDestruct = true;
- return;
- }
- }
- if( Session.RequestCount )
- {
- // Send the scenario to any guests that requested a download.
- //debugprint( "Send the scenario to any guests that requested a download.\n" );
- Send_Remote_File( Scen.ScenarioName, 1 );
- }
- }
- Session.CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;
- Ipx.Set_Timing (30, (unsigned long) -1, 600);
- pWO->bEnableNewAftermathUnits = bAftermathUnits;
- bAftermathMultiplayer = bAftermathUnits;
- *pWO->szExternalPager = 0;
- pWO->bDoingDisconnectPinging = false; // Pointlessly making sure.
- *szTriggerGameStartInfo = 0; // This was set in order to trigger my coming here.
- }
- #endif
- #include <string.h>
- //***********************************************************************************************
- bool bSpecialAftermathScenario( const char* szScenarioDescription )
- {
- // Returns true if szScenarioDescription matches one of the descriptions for Aftermath multiplayer
- // scenarios that have special Aftermath-only units *embedded* within them.
- if( strcmp( szScenarioDescription, "Booby Traps (Mega 8 players)" ) == 0 ||
- strcmp( szScenarioDescription, "Central Conflict Extreme (Mega 8 players)" ) == 0 ||
- strcmp( szScenarioDescription, "Circles of Death (Mega 8 players)" ) == 0 ||
- strcmp( szScenarioDescription, "Holy Grounds (Mega 8 players)" ) == 0 ||
- strcmp( szScenarioDescription, "Island Wars Extreme (Mega 8 players)" ) == 0 ||
- strcmp( szScenarioDescription, "King of the Hills Extreme (Mega 8 players)" ) == 0 ||
- strcmp( szScenarioDescription, "The Hills Have Eyes (Mega 8 players)" ) == 0 )
- return true;
- return false;
- }
- //***********************************************************************************************
- int ScenarioIndex_From_Filename( const char* szScenarioFilename )
- {
- #if (0)//PG
- // Returns the scenario index that matches the scenario filename, or -1 if no match found.
- for( int index = 0; index < Session.Scenarios.Count(); index++ )
- {
- if( _stricmp( szScenarioFilename, Session.Scenarios[index]->Get_Filename() ) == 0 )
- return index;
- }
- #endif
- return -1;
- }
|