NETDLG.CPP 329 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824
  1. /*
  2. ** Command & Conquer Red Alert(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: /CounterStrike/NETDLG.CPP 13 10/13/97 2:20p Steve_t $ */
  19. /***********************************************************************************************
  20. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : NETDLG.CPP *
  26. * *
  27. * Programmer : Bill Randolph *
  28. * *
  29. * Start Date : January 23, 1995 *
  30. * *
  31. * Last Update : December 12, 1995 [BRR] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * *
  35. * These routines establish & maintain peer-to-peer connections between this system *
  36. * and all others in the game. Each system finds out the IPX address of the others, *
  37. * and forms a direct connection (IPXConnectionClass) to that system. Systems are *
  38. * found out via broadcast queries. Every system broadcasts its queries, and every *
  39. * system replies to queries it receives. At the point when the game owner signals *
  40. * 'OK', every system must know about all the other systems in the game. *
  41. * *
  42. * How Bridges are handled: *
  43. * Currently, bridges are handled by specifying the destination IPX address of the *
  44. * "server" (game owner's system) on the command-line. This address is used to *
  45. * derive a broadcast address to that destination network, and this system's queries *
  46. * are broadcast over its network & the server's network; replies to the queries come *
  47. * with each system's IPX address attached, so once we have the address, we can form *
  48. * a connection with any system on the bridged net. *
  49. * *
  50. * The flaw in this plan is that we can only cross one bridge. If there are 3 nets *
  51. * bridged (A, B, & C), and the server is on net B, and we're on net A, our broadcasts *
  52. * will reach nets A & B, but not C. The way to circumvent this (if it becomes a problem) *
  53. * would be to have the server tell us what other systems are in its game, not each *
  54. * individual player's system. Thus, each system would find out about all the other systems *
  55. * by interacting with the game's owner system (this would be more involved than what *
  56. * I'm doing here). *
  57. * *
  58. * Here's a list of all the different packets sent over the Global Channel: *
  59. * *
  60. * NET_QUERY_GAME *
  61. * (no other data) *
  62. * NET_ANSWER_GAME *
  63. * Name: game owner's name *
  64. * GameInfo: game's version & open state *
  65. * NET_QUERY_PLAYER *
  66. * Name: name of game we want players to respond for *
  67. * NET_ANSWER_PLAYER *
  68. * Name: player's name *
  69. * PlayerInfo: info about player *
  70. * NET_CHAT_ANNOUNCE *
  71. * Chat: unique id of the local node, so I can tell *
  72. * if this chat announcement is from myself *
  73. * NET_QUERY_JOIN *
  74. * Name: name of player wanting to join *
  75. * PlayerInfo: player's requested house, color, & version range *
  76. * NET_CONFIRM_JOIN *
  77. * PlayerInfo: approves player's house & color *
  78. * NET_REJECT_JOIN *
  79. * Reject.Why: tells why we got rejected *
  80. * NET_GAME_OPTIONS *
  81. * ScenarioInfo: info about scenario *
  82. * NET_SIGN_OFF *
  83. * Name: name of player signing off *
  84. * NET_PING *
  85. * (no other data) *
  86. * NET_GO *
  87. * Delay: value of one-way response time, in frames *
  88. * *
  89. *---------------------------------------------------------------------------------------------*
  90. * Functions: *
  91. * Init_Network -- initializes network stuff *
  92. * Shutdown_Network -- shuts down network stuff *
  93. * Process_Global_Packet -- responds to remote queries *
  94. * Destroy_Connection -- destroys the given connection *
  95. * Remote_Connect -- handles connecting this user to others *
  96. * Net_Join_Dialog -- lets user join an existing game, or start a new one *
  97. * Request_To_Join -- Sends a JOIN request packet to game owner *
  98. * Unjoin_Game -- Cancels joining a game *
  99. * Send_Join_Queries -- sends queries for the Join Dialog *
  100. * Get_Join_Responses -- sends queries for the Join Dialog *
  101. * Net_New_Dialog -- lets user start a new game *
  102. * Get_NewGame_Responses -- processes packets for New Game dialog *
  103. * Compute_Name_CRC -- computes CRC from char string *
  104. * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog *
  105. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  106. // Warning - Most disgusting cpp file of all time. ajw
  107. #include "function.h"
  108. #ifdef WIN32
  109. #ifdef WINSOCK_IPX
  110. #include "WSProto.h"
  111. #else //WINSOCK_IPX
  112. #include "tcpip.h"
  113. #endif //WINSOCK_IPX
  114. #include "ccdde.h"
  115. #else //WIN32
  116. #include "fakesock.h"
  117. #endif //WIN32
  118. #include <time.h>
  119. #include <dos.h>
  120. #include "WolDebug.h"
  121. #define SHOW_MONO 0
  122. //#define OLDWAY 1
  123. #ifdef FRENCH
  124. #define TXT_HACKHACK "Connexion En Cours..."
  125. #endif
  126. #if defined(ENGLISH) || defined(GERMAN)
  127. #define TXT_HACKHACK Text_String(TXT_CONNECTING)
  128. #endif
  129. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  130. bool Is_Mission_126x126 (char *file_name);
  131. bool Is_Mission_Aftermath (char *file_name);
  132. bool Is_Mission_Counterstrike (char *file_name);
  133. bool bSpecialAftermathScenario( const char* szScenarioDescription );
  134. #endif
  135. #ifdef FIXIT_VERSION_3
  136. bool Force_Scenario_Available( const char* szName );
  137. #endif
  138. #ifdef WOLAPI_INTEGRATION
  139. #include "WolStrng.h"
  140. #include "WolapiOb.h"
  141. extern WolapiObject* pWolapi;
  142. #endif
  143. //---------------------------------------------------------------------------
  144. // The possible states of the join-game dialog
  145. //---------------------------------------------------------------------------
  146. typedef enum {
  147. JOIN_REJECTED = -1, // we've been rejected
  148. JOIN_NOTHING, // we're not trying to join a game
  149. JOIN_WAIT_CONFIRM, // we're asking to join, & waiting for confirmation
  150. JOIN_CONFIRMED, // we've been confirmed
  151. JOIN_GAME_START, // the game we've joined is starting
  152. JOIN_GAME_START_LOAD, // the game we've joined is starting; load saved game
  153. } JoinStateType;
  154. //---------------------------------------------------------------------------
  155. // The possible return codes from Get_Join_Responses()
  156. //---------------------------------------------------------------------------
  157. typedef enum {
  158. EV_NONE, // nothing happened
  159. EV_STATE_CHANGE, // Join dialog is in a new state
  160. EV_NEW_GAME, // a new game formed, or is now open
  161. EV_NEW_PLAYER, // a new player was detected
  162. EV_PLAYER_SIGNOFF, // a player has signed off
  163. EV_GAME_SIGNOFF, // a gamed owner has signed off
  164. EV_GAME_OPTIONS, // a game options packet was received
  165. EV_MESSAGE, // a message was received
  166. } JoinEventType;
  167. //---------------------------------------------------------------------------
  168. // The possible reasons we're rejected from joining a game
  169. //---------------------------------------------------------------------------
  170. typedef enum {
  171. REJECT_DUPLICATE_NAME, // player's name is a duplicate
  172. REJECT_GAME_FULL, // game is full
  173. REJECT_VERSION_TOO_OLD, // joiner's version is too old
  174. REJECT_VERSION_TOO_NEW, // joiner's version is too new
  175. REJECT_BY_OWNER, // game owner clicked "reject"
  176. REJECT_DISBANDED, // game was disbanded
  177. REJECT_MISMATCH, // "rules.ini" file mismatch.
  178. } RejectType;
  179. #ifdef ENGLISH
  180. char const *EngMisStr[] = {
  181. "Coastal Influence (Med)",
  182. "Middle Mayhem (Sm)",
  183. "Equal Opportunity (Sm)",
  184. "Marooned II (Med)",
  185. "Keep off the Grass (Sm)",
  186. "Isle of Fury (Lg)",
  187. "Ivory Wastelands (Sm)",
  188. "Shallow Grave (Med)",
  189. "North By Northwest (Lg)",
  190. "First Come, First Serve (Sm)",
  191. "Island Hoppers (Sm)",
  192. "Raraku (Lg)",
  193. "Central Conflict (Lg)",
  194. "Combat Alley (Med)",
  195. "Island Wars (Lg)",
  196. "Desolation (Lg)",
  197. "No Escape (Med)",
  198. "No Man's Land (Med)",
  199. "Normandy (Med)",
  200. "Pond Skirmish (Med)",
  201. "Ridge War (Med)",
  202. "A Path Beyond (Lg)",
  203. "Dugout Isle (Med)",
  204. "Treasure Isle (Med)",
  205. "Africa (Lg)",
  206. "Alaska Anarchy (Lg)",
  207. "All that Glitters... (Lg)",
  208. "Apre's Peace (Lg)",
  209. "Antartica (Lg)",
  210. "Armourgarden (Lg)",
  211. "Austraila (Med)",
  212. "Barrier to Entry (Lg)",
  213. "Bavarian Blast (Med)",
  214. "Be Shore (Med)",
  215. "Bearing Straits (Med)",
  216. "Blow Holes (Lg)",
  217. "Bonsai (Sm)",
  218. "Brother Stalin (Lg)",
  219. "Bullseye (Lg)",
  220. "C&C (Med)",
  221. "Camos Canyon (Med)",
  222. "Camos Coves (Lg)",
  223. "Camos Cross (Lg)",
  224. "Camos Crossing (Sm)",
  225. "Central Arena (Lg)",
  226. "Canyon River (Med)",
  227. "Crossroads (Sm)",
  228. "Czech Mate (Lg)",
  229. "Dday (Med)",
  230. "Disaster Central (Lg)",
  231. "Docklands (Med)",
  232. "East Coast (Med)",
  233. "Eastern Seaboard (Lg)",
  234. "Finger Lake (Lg)",
  235. "Fjords (Med)",
  236. "Floodlands (Lg)",
  237. "Forest under fire (Lg)",
  238. "Four Corners (Lg)",
  239. "Frostbit Fjords (Lg)",
  240. "Glenboig (Sm)",
  241. "Hell Frozen Over (Lg)",
  242. "India (Lg)",
  243. "Indirect Fire (Lg)",
  244. "Island Wars II (Lg)",
  245. "Italy (Lg)",
  246. "Kabalo (Lg)",
  247. "King of the Hills (Lg)",
  248. "Lake Divide (Med)",
  249. "Lakelands (Lg)",
  250. "Land Ladder (Lg)",
  251. "Lotsa Lakes (Lg)",
  252. "Lunar Battlefield (Lg Special)",
  253. "Malibu Fields (Med)",
  254. "Marshland (Med)",
  255. "MyLai Delta (Med)",
  256. "Natural Harbor (Med)",
  257. "No Way Out (Lg)",
  258. "Normandy Landing (Lg)",
  259. "Ore Wars (Med)",
  260. "Oz (Lg)",
  261. "Pilgrim Fathers II (Lg)",
  262. "Pip's Ice Tea (Med)",
  263. "Polar Panic (Lg)",
  264. "Ponds (Med)",
  265. "Putney (Lg)",
  266. "Return to Zion (Lg)",
  267. "Ring of Land (Lg)",
  268. "River Basin (Lg)",
  269. "River Delta (Med)",
  270. "River Islands (Med)",
  271. "River Maze (Sm)",
  272. "Rivers (Sm)",
  273. "Run the Gauntlet (Med)",
  274. "Scappa Flow (Lg)",
  275. "Siberian Slaughter (Lg)",
  276. "Sleepy Valley (Sm)",
  277. "Snake River (Lg)",
  278. "Snow Wars (Lg)",
  279. "Snowball fight (Lg)",
  280. "Snowy Island (Lg)",
  281. "So Near So Far (Sm)",
  282. "South America (Lg)",
  283. "Spring Line (Lg)",
  284. "Star (Lg)",
  285. "Straighter & Narrower (Sm)",
  286. "TerrainSpotting (Sm)",
  287. "The Bay (Lg)",
  288. "The Garden (Lg)",
  289. "The Great Lakes (Med)",
  290. "The Ice Arena (Lg)",
  291. "The Lake District (Lg)",
  292. "The Linked lands (Lg)",
  293. "The Mississippi (Med)",
  294. "The Sticky Bit (Lg)",
  295. "The Valley (Med)",
  296. "The Woods Today (Lg)",
  297. "Things to Come (Lg)",
  298. "Tiger Core (Sm)",
  299. "To the Core (Sm)",
  300. "Tournament Hills (Lg)",
  301. "Tropical Storm (Med)",
  302. "Tundra Trouble (Lg)",
  303. "Uk (Med)",
  304. "Undiscovered Country (Sm)",
  305. "United States (Med)",
  306. "Volcano (Sm)",
  307. "Wastelands (Lg)",
  308. "Water Works (Sm)",
  309. "World Map (Med)",
  310. "Zambezi (Lg)",
  311. "A Pattern of Islands (Lg 8 players)",
  312. "Arena Valley Extreme (Mega 8 players)",
  313. "Around the Rim (Sm 4 players)",
  314. "Ashes to Ashes (Lg 6 players)",
  315. "Artic Wasteland (Mega 8 players)",
  316. "Badajoz (Med 4 players)",
  317. "Baptism of Fire (Lg 6 players)",
  318. "Big Fish, Small Pond (Lg 6 players)",
  319. "Blue Lakes (Lg 8 players)",
  320. "Booby Traps (Mega 8 players)",
  321. "Bridgehead (Lg 6 players)",
  322. "Butterfly Bay (Lg 6 players)",
  323. "Central Conflict Extreme (Mega 8 players)",
  324. "Circles of Death (Mega 8 players)",
  325. "Cold Front (Med 6 players)",
  326. "Cold Pass (Med 4 players)",
  327. "Combat Zones (Mega 8 players)",
  328. "Conflict Cove (Sm 4 players)",
  329. "Culloden Moor (Med 8 players)",
  330. "Damnation Alley (Mega 8 players)",
  331. "Death Valley (Mega 8 players)",
  332. "Deep Six (Mega 8 players)",
  333. "Destruction Derby (Mega 8 players)",
  334. "Diamonds Aren't Forever (Mega 8 players)",
  335. "Elysium (Sm 4 players)",
  336. "Equal Shares (Lg 4 players)",
  337. "Frost Bitten (Mega 8 players)",
  338. "Frozen Valley (Med 6 players)",
  339. "Gettysburg (Sm 4 players)",
  340. "Glacial Valley (Sm 4 players)",
  341. "Gold Coast (Med 6 players)",
  342. "Gold Rush (Lg 4 players)",
  343. "Habitat (Lg 4 players)",
  344. "Hades Frozen Over (Sm 4 players)",
  345. "Hamburger Hill (Mega 8 players)",
  346. "Hastings (Sm 4 players)",
  347. "Hell's Pass (Med 6 players)",
  348. "Holy Grounds (Mega 8 players)",
  349. "Ice Bergs (Med 6 players)",
  350. "Ice Station (Lg 6 players)",
  351. "Ice Queen (Lg 4 players)",
  352. "In the Sun (Med 6 players)",
  353. "Innocents? (Mega 8 players)",
  354. "Islands (Med 8 players)",
  355. "Island Plateau (Lg 4 players)",
  356. "Island Wars Extreme (Mega 8 players)",
  357. "Kananga (Med 6 players)",
  358. "King of the Hills Extreme (Mega 8 players)",
  359. "Lake Land (Lg 8 players)",
  360. "Land Locked (Lg 8 players)",
  361. "Lanes (Med 8 players)",
  362. "Leipzip (Sm 4 players)",
  363. "Meander (Lg 8 players)",
  364. "Mekong (Med 8 players)",
  365. "Middle Ground (Med 8 players)",
  366. "Naval Conquests (Mega 8 players)",
  367. "On your Marks (Med 4 players)",
  368. "Open Warfare (Mega 8 players)",
  369. "Ore Gardens (Lg 8 players)",
  370. "Potholes (Mega 8 players)",
  371. "Puddles (Med 4 players)",
  372. "Random Violence (Mega 8 players)",
  373. "Revenge (Med 8 players)",
  374. "Rias (Med 8 players)",
  375. "River Crossing (Sm 4 players)",
  376. "River Rampage (Mega 8 players)",
  377. "River Rapids (Lg 6 players)",
  378. "Rivers Wild (Mega 8 players)",
  379. "Rorkes Drift (Lg 4 players)",
  380. "Seaside (Med 4 players)",
  381. "Shades (Med 8 players)",
  382. "Smuggler's Cove (Lg 6 players)",
  383. "Snow Garden (Sm 2 players)",
  384. "Stalingrad (Sm 4 players)",
  385. "Sticks & Stones (Med 4 players)",
  386. "Strathearn Valley (Lg 6 players)",
  387. "Super Bridgehead (Mega 8 players)",
  388. "Super Mekong (Mega 8 players)",
  389. "Super Ore Gardens (Mega 8 players)",
  390. "Switch (Med 4 players)",
  391. "The Berg (Mega 8 players)",
  392. "The Boyne (Med 4 players)",
  393. "The Bulge (Sm 4 players)",
  394. "The Cauldron (Lg 6 players)",
  395. "The Finger (Lg 6 players)",
  396. "The Hills Have Eyes (Mega 8 players)",
  397. "The Keyes (Med 6 players)",
  398. "The Lakes (Med 8 players)",
  399. "The Neck (Med 6 players)",
  400. "The Web (Lg 6 players)",
  401. "To the Core (Lg 4 players)",
  402. "Trafalgar (Lg 4 players)",
  403. "Twin Rivers (Sm 4 players)",
  404. "Umtumbo Gorge (Lg 4 players)",
  405. "Watch Your Step Extreme (Mega 8 players)",
  406. "Waterfalls (Lg 8 players)",
  407. "Waterloo Revisited (Lg 6 players)",
  408. "Water Werks (Mega 8 players)",
  409. "Warlord's Lake (Sm 4 players)",
  410. "Zama (Sm 4 players)",
  411. NULL
  412. };
  413. #endif
  414. #ifdef GERMAN
  415. char const *EngMisStr[] = {
  416. "A Path Beyond (Lg)", "Weg ins Jenseits (Gr)",
  417. "Central Conflict (Lg)", "Der zentrale Konflikt (Gr)",
  418. "Coastal Influence (Med)", "Sturm an der K�ste (Mit)",
  419. "Combat Alley (Med)", "Boulevard der Schlachten (Mit)",
  420. "Desolation (Lg)", "Verw�stung (Gr)",
  421. "Dugout Isle (Med)", "Buddelschiff (Mit)",
  422. "Equal Opportunity (Sm)", "Gleiche Chancen (Kl)",
  423. "First Come, First Serve (Sm)", "Wer zuerst kommt... (Kl)",
  424. "Island Hoppers (Sm)", "Inselspringen (Kl)",
  425. "Island Wars (Lg)", "Der Krieg der Eilande (Gr)",
  426. "Isle of Fury (Lg)", "Insel des Zorns (Gr)",
  427. "Ivory Wastelands (Sm)", "Elfenbeinw�ste (Kl)",
  428. "Keep off the Grass (Sm)", "Rasen betreten verboten (Kl)",
  429. "Marooned II (Med)", "Gestrandet (Mit)",
  430. "Middle Mayhem (Sm)", "Mittelsmann (Kl)",
  431. "No Escape (Med)", "Kein Entrinnen (Mit)",
  432. "No Man's Land (Med)", "Niemandsland (Mit)",
  433. "Normandy (Med)", "Normandie (Mit)",
  434. "North By Northwest (Lg)", "Nord auf Nordwest (Gr)",
  435. "Pond Skirmish (Med)", "Teichgepl„nkel (Mit)",
  436. "Raraku (Lg)", "Raraku (Gr)",
  437. "Ridge War (Med)", "Das Tal der Cyborgs (Mit)",
  438. "Shallow Grave (Med)", "Ein enges Grab (Mit)",
  439. "Treasure Isle (Med)", "Die Schatzinsel (Mit)",
  440. "Africa (Lg)", "Afrika (Gr)",
  441. "Alaska Anarchy (Lg)", "Anarchie in Alaska (Gr)",
  442. "All that Glitters... (Lg)", "Alles was gl„nzt... (Gr)",
  443. "Apre's Peace (Lg)", "Apres Frieden (Gr)",
  444. "Antartica (Lg)", "Antarktica (Gr)",
  445. "Armourgarden (Lg)", "Garten der Panzer (Gr)",
  446. "Austraila (Med)", "Koalaland (Mit)",
  447. "Barrier to Entry (Lg)", "Zutritt verboten (Gr)",
  448. "Bavarian Blast (Med)", "Bayrische Blasmusik (Mit)",
  449. "Be Shore (Med)", "Strandl„ufer (Mit)",
  450. "Bearing Straits (Med)", "Die Heringstrasse (Mit)",
  451. "Blow Holes (Lg)", "L”cheriger K„se (Gr)",
  452. "Bonsai (Sm)", "Bonsai (Kl)",
  453. "Brother Stalin (Lg)", "Br�derchen Stalin (Gr)",
  454. "Bullseye (Lg)", "Bullseye (Gr)",
  455. "C&C (Med)", "C&C (Mit)",
  456. "Camos Canyon (Med)", "Camos-Canyon (Mit)",
  457. "Camos Coves (Lg)", "Camos-Grotte (Gr)",
  458. "Camos Cross (Lg)", "Camos-Kreuz (Gr)",
  459. "Camos Crossing (Sm)", "Camos-Kreuzweg (Kl)",
  460. "Central Arena (Lg)", "Spielplatz des Teufels (Gr)",
  461. "Canyon River (Med)", "Canyonfluss (Mit)",
  462. "Crossroads (Sm)", "Kreuzung (Kl)",
  463. "Czech Mate (Lg)", "Tschechische Er”ffnung (Gr)",
  464. "Dday (Med)", "D-Day (Mit)",
  465. "Disaster Central (Lg)", "Endstation Schweinebucht (Gr)",
  466. "Docklands (Med)", "Docklands (Mit)",
  467. "East Coast (Med)", "Ostk�ste (Mit)",
  468. "Eastern Seaboard (Lg)", "Die Passage nach Osten (Gr)",
  469. "Finger Lake (Lg)", "Fingersee (Gr)",
  470. "Fjords (Med)", "Fjorde (Mit)",
  471. "Floodlands (Lg)", "Land unter! (Gr)",
  472. "Forest under fire (Lg)", "Waldsterben im Feuer (Gr)",
  473. "Four Corners (Lg)", "Viereck (Gr)",
  474. "Frostbit Fjords (Lg)", "Frostbeulenfjord (Gr)",
  475. "Glenboig (Sm)", "Glenboig (Kl)",
  476. "Hell Frozen Over (Lg)", "Winter in der H”lle (Gr)",
  477. "India (Lg)", "Indien (Gr)",
  478. "Indirect Fire (Lg)", "Indirekter Beschuss (Gr)",
  479. "Island Wars II (Lg)", "Krieg der Inseln (Gr)",
  480. "Italy (Lg)", "Italien (Gr)",
  481. "Kabalo (Lg)", "Kabalo (Gr)",
  482. "King of the Hills (Lg)", "K”nig des Maulwurfsh�gels (Gr)",
  483. "Lake Divide (Med)", "Wasserscheide (Mit)",
  484. "Lakelands (Lg)", "Seenplatte (Gr)",
  485. "Land Ladder (Lg)", "Das Leiterspiel (Gr)",
  486. "Lotsa Lakes (Lg)", "Mehr Seen (Gr)",
  487. "Lunar Battlefield (Lg Special)", "Schlachtfeld Mond (Gr Spezial)",
  488. "Malibu Fields (Med)", "Malibu (Mit)",
  489. "Marshland (Med)", "Schlammschlacht (Mit)",
  490. "MyLai Delta (Med)", "Das Delta von My Lai (Mit)",
  491. "Natural Harbor (Med)", "Nat�rlicher Hafen (Mit)",
  492. "No Way Out (Lg)", "Kein Entkommen (Gr)",
  493. "Normandy Landing (Lg)", "Landung in der Normandie (Gr)",
  494. "Ore Wars (Med)", "Die Erz-Kriege (Mit)",
  495. "Oz (Lg)", "Das Land Oz (Gr)",
  496. "Pilgrim Fathers II (Lg)", "Die Gr�nderv„ter (Gr)",
  497. "Pip's Ice Tea (Med)", "Pips Eistee (Mit)",
  498. "Polar Panic (Lg)", "Panik am Pol (Gr)",
  499. "Ponds (Med)", "T�mpelspringer (Mit)",
  500. "Putney (Lg)", "Putney (Gr)",
  501. "Return to Zion (Lg)", "R�ckkehr nach Zion (Gr)",
  502. "Ring of Land (Lg)", "Der Landring (Gr)",
  503. "River Basin (Lg)", "Flusslauf (Gr)",
  504. "River Delta (Med)", "Flussdelta (Mit)",
  505. "River Islands (Med)", "Flussinsel (Mit)",
  506. "River Maze (Sm)", "Flussgewirr (Kl)",
  507. "Rivers (Sm)", "Fl�sse (Kl)",
  508. "Run the Gauntlet (Med)", "Spiessrutenlauf (Mit)",
  509. "Scappa Flow (Lg)", "Scapa Flow (Gr)",
  510. "Siberian Slaughter (Lg)", "Sibirisches Gemetzel (Gr)",
  511. "Sleepy Valley (Sm)", "Tal der Ahnungslosen (Kl)",
  512. "Snake River (Lg)", "Am Schlangenfluss (Gr)",
  513. "Snow Wars (Lg)", "Krieg der Flocken (Gr)",
  514. "Snowball fight (Lg)", "Schneeballschlacht (Gr)",
  515. "Snowy Island (Lg)", "Schneeinsel (Gr)",
  516. "So Near So Far (Sm)", "So nah und doch so fern (Kl)",
  517. "South America (Lg)", "S�damerika (Gr)",
  518. "Spring Line (Lg)", "Fr�hlingsgef�hle (Gr)",
  519. "Star (Lg)", "Stern (Gr)",
  520. "Straighter & Narrower (Sm)", "Enger & schmaler (Kl)",
  521. "TerrainSpotting (Sm)", "TerrainSpotting (Kl)",
  522. "The Bay (Lg)", "Die Bucht (Gr)",
  523. "The Garden (Lg)", "Der Garten (Gr)",
  524. "The Great Lakes (Med)", "Die Grossen Seen (Mit)",
  525. "The Ice Arena (Lg)", "Eisarena (Gr)",
  526. "The Lake District (Lg)", "Kalte Seenplatte (Gr)",
  527. "The Linked lands (Lg)", "Die verbundenen L„nder (Gr)",
  528. "The Mississippi (Med)", "Gr�sse von Tom Sawyer (Mit)",
  529. "The Sticky Bit (Lg)", "Der klebrige Teil (Gr)",
  530. "The Valley (Med)", "Das Tal (Mit)",
  531. "The Woods Today (Lg)", "Waldl„ufer (Gr)",
  532. "Things to Come (Lg)", "Was die Zukunft bringt (Gr)",
  533. "Tiger Core (Sm)", "Das Herz des Tigers (Kl)",
  534. "To the Core (Sm)", "Mitten ins Herz (Kl)",
  535. "Tournament Hills (Lg)", "H�gel der Entscheidung (Gr)",
  536. "Tropical Storm (Med)", "Tropenst�rme (Mit)",
  537. "Tundra Trouble (Lg)", "Tauziehen in der Tundra (Gr)",
  538. "Uk (Med)", "GB (Mit)",
  539. "Undiscovered Country (Sm)", "Unentdecktes Land (Kl)",
  540. "United States (Med)", "US (Mit)",
  541. "Volcano (Sm)", "Vulkan (Kl)",
  542. "Wastelands (Lg)", "W�stenei (Gr)",
  543. "Water Works (Sm)", "Wasserwerke (Kl)",
  544. "World Map (Med)", "Weltkarte (Kl)",
  545. "Zambezi (Lg)", "Sambesi (Gr)",
  546. //#if 0
  547. "A Pattern of Islands (Lg 8 players)", "Inselmuster (gross, 8 Spieler)",
  548. "Arena Valley Extreme (Mega 8 players)", "Arenatal (sehr gross, 8 Spieler)",
  549. "Around the Rim (Sm 4 players)", "Um die Kante (klein, 4 Spieler)",
  550. "Ashes to Ashes (Lg 6 players)", "Asche zu Asche (gross, 6 Spieler)",
  551. "Artic Wasteland (Mega 8 players)", "Arktische W�ste (sehr gross, 8 Spieler)",
  552. "Badajoz (Med 4 players)", "Badjoz (mittelgross, 4 Spieler)",
  553. "Baptism of Fire (Lg 6 players)", "Feuertaufe (gross, 6 Spieler)",
  554. "Big Fish, Small Pond (Lg 6 players)", "Grosser Fisch im kleinen Teich (gross, 6 Spieler)",
  555. "Blue Lakes (Lg 8 players)", "Die blauen Seen (gross, 8 Spieler)",
  556. "Booby Traps (Mega 8 players)", "Vorsicht, Falle! (sehr gross, 8 Spieler)",
  557. "Bridgehead (Lg 6 players)", "Br�ckenkopf im Niemandsland (gross, 6 Spieler)",
  558. "Butterfly Bay (Lg 6 players)", "Schmetterlingsbucht (gross, 6 Spieler)",
  559. "Central Conflict Extreme (Mega 8 players)", "Zentraler Konflikt f�r K”nner (sehr gross, 8 Spieler)",
  560. "Circles of Death (Mega 8 players)", "Todeskreise (sehr gross, 8 Spieler)",
  561. "Cold Front (Med 6 players)", "Kaltfront ( mittelgross, 6 Spieler)",
  562. "Cold Pass (Med 4 players)", "Cooler Pass (mittelgross, 4 Spieler)",
  563. "Combat Zones (Mega 8 players)", "Kampfgebiete (sehr gross, 8 Spieler)",
  564. "Conflict Cove (Sm 4 players)", "H”hlenkonflikt (klein, 4 Spieler)",
  565. "Culloden Moor (Med 8 players)", "Culloden-Moor (mittelgross, 8 Spieler)",
  566. "Damnation Alley (Mega 8 players)", "Strasse der Verdammten (sehr gross, 8 Spieler)",
  567. "Death Valley (Mega 8 players)", "Tal des Todes (sehr gross, 8 Spieler)",
  568. "Deep Six (Mega 8 players)", "Tiefe Sechs (sehr gross, 8 Spieler)",
  569. "Destruction Derby (Mega 8 players)", "Destruction Derby (sehr gross, 8 Spieler)",
  570. "Diamonds Aren't Forever (Mega 8 players)", "Verg„ngliche Diamanten (sehr gross, 8 Spieler)",
  571. "Elysium (Sm 4 players)", "Elysium (klein, 4 Spieler)",
  572. "Equal Shares (Lg 4 players)", "Gleiche Anteile (gross, 4 Spieler)",
  573. "Frost Bitten (Mega 8 players)", "Frostbrand (sehr gross, 8 Spieler)",
  574. "Frozen Valley (Med 6 players)", "Eisiges Tal (mittelgross, 6 Spieler)",
  575. "Gettysburg (Sm 4 players)", "Gettysburg (klein, 4 Spieler)",
  576. "Glacial Valley (Sm 4 players)", "Gletschertal (klein, 4 Spieler)",
  577. "Gold Coast (Med 6 players)", "Goldk�ste (mittelgross, 6 Spieler)",
  578. "Gold Rush (Lg 4 players)", "Goldrausch (gross, 4 Spieler)",
  579. "Habitat (Lg 4 players)", "Habitat (gross, 4 Spieler)",
  580. "Hades Frozen Over (Sm 4 players)", "Frostschutz f�r die H”lle (klein, 4 Spieler)",
  581. "Hamburger Hill (Mega 8 players)", "Hamburger Hill (sehr gross, 8 Spieler)",
  582. "Hastings (Sm 4 players)", "Hastings (klein, 4 Spieler)",
  583. "Hell's Pass (Med 6 players)", "H”llenpass (mittelgross, 6 Spieler)",
  584. "Holy Grounds (Mega 8 players)", "Heiliger Boden (sehr gross, 8 Spieler)",
  585. "Ice Bergs (Med 6 players)", "Eisberge (mittelgross, 6 Spieler)",
  586. "Ice Station (Lg 6 players)", "Eisstation (gross, 6 Spieler)",
  587. "Ice Queen (Lg 4 players)", "Eisk”nigin (gross, 4 Spieler)",
  588. "In the Sun (Med 6 players)", "Unter der Sonne (mittelgross, 6 Spieler)",
  589. "Innocents? (Mega 8 players)", "Unschuldig? Wer? (sehr gross, 8 Spieler)",
  590. "Islands (Med 8 players)", "Inseln im Nebel (mittelgross, 8 Spieler)",
  591. "Island Plateau (Lg 4 players)", "Inselplateau (gross, 4 Spieler)",
  592. "Island Wars Extreme (Mega 8 players)", "Extremes Inselspringen (sehr gross, 8 Spieler)",
  593. "Kananga (Med 6 players)", "Kananga (mittelgross, 6 Spieler)",
  594. "King of the Hills Extreme (Mega 8 players)", "K”nig des Maulwurfsh�gels (sehr gross, 8 Spieler)",
  595. "Lake Land (Lg 8 players)", "Seenland (gross, 8 Spieler)",
  596. "Land Locked (Lg 8 players)", "Das Verschlossene Land (gross, 8 Spieler)",
  597. "Lanes (Med 8 players)", "Gassenjungen (mittelgross, 8 Spieler)",
  598. "Leipzip (Sm 4 players)", "Leipzig (klein, 4 Spieler)",
  599. "Meander (Lg 8 players)", "M„ander (gross, 8 Spieler)",
  600. "Mekong (Med 8 players)", "Mekong (mittelgross, 8 Spieler)",
  601. "Middle Ground (Med 8 players)", "Mittelsmann (mittelgross, 8 Spieler)",
  602. "Naval Conquests (Mega 8 players)", "Kommt zur Marine, haben sie gesagt (sehr gross, 8 Spieler)",
  603. "On your Marks (Med 4 players)", "Auf die Pl„tze (mittelgross, 4 Spieler)",
  604. "Open Warfare (Mega 8 players)", "Offener Schlagabtausch (sehr gross, 8 Spieler)",
  605. "Ore Gardens (Lg 8 players)", "Erzparadies (gross, 8 Spieler)",
  606. "Potholes (Mega 8 players)", "Schlagl”cher (sehr gross, 8 Spieler)",
  607. "Puddles (Med 4 players)", "Pf�tzen (mittelgross, 4 Spieler)",
  608. "Random Violence (Mega 8 players)", "Unberechenbare Gewalt (sehr gross, 8 Spieler)",
  609. "Revenge (Med 8 players)", "Rache (mittelgross, 8 Spieler)",
  610. "Rias (Med 8 players)", "Kabul (mittelgross, 8 Spieler)",
  611. "River Crossing (Sm 4 players)", "Die Furt (klein, 4 Spieler)",
  612. "River Rampage (Mega 8 players)", "Flussfahrt (sehr gross, 8 Spieler)",
  613. "River Rapids (Lg 6 players)", "Stromschnellen (gross, 6 Spieler)",
  614. "Rivers Wild (Mega 8 players)", "Wildwasser (sehr gross, 8 Spieler)",
  615. "Rorkes Drift (Lg 4 players)", "Rorkes Drift (gross, 4 Spieler)",
  616. "Seaside (Med 4 players)", "Strandleben (mittelgross, 4 Spieler)",
  617. "Shades (Med 8 players)", "Schattenreich (mittelgross, 8 Spieler)",
  618. "Smuggler's Cove (Lg 6 players)", "Schmugglerh”hle (gross, 6 Spieler)",
  619. "Snow Garden (Sm 2 players)", "Schneegest”ber (klein, 2 Spieler)",
  620. "Stalingrad (Sm 4 players)", "Stalingrad (klein, 4 Spieler)",
  621. "Sticks & Stones (Med 4 players)", "Holz und Steine (mittelgross, 4 Spieler)",
  622. "Strathearn Valley (Lg 6 players)", "Das Tal von Strathearn (gross, 6 Spieler)",
  623. "Super Bridgehead (Mega 8 players)", "Super-Br�ckenkopf (sehr gross, 8 Spieler)",
  624. "Super Mekong (Mega 8 players)", "Super-Mekong (sehr gross, 8 Spieler)",
  625. "Super Ore Gardens (Mega 8 players)", "Super-Erzparadies (sehr gross, 8 Spieler)",
  626. "Switch (Med 4 players)", "Schalter (mittelgross, 4 Spieler)",
  627. "The Berg (Mega 8 players)", "Der Berg (sehr gross, 8 Spieler)",
  628. "The Boyne (Med 4 players)", "Boyne (mittelgross, 4 Spieler)",
  629. "The Bulge (Sm 4 players)", "Die W”lbung (klein, 4 Spieler)",
  630. "The Cauldron (Lg 6 players)", "Der Kessel (gross, 6 Spieler)",
  631. "The Finger (Lg 6 players)", "Der Finger (gross, 6 Spieler)",
  632. "The Hills Have Eyes (Mega 8 players)", "Die H�gel haben Augen (sehr gross, 8 Spieler)",
  633. "The Keyes (Med 6 players)", "Ein Sumpf (mittelgross, 6 Spieler)",
  634. "The Lakes (Med 8 players)", "Die Seen (mittelgross, 8 Spieler)",
  635. "The Neck (Med 6 players)", "Der Hals (mittelgross, 6 Spieler)",
  636. "The Web (Lg 6 players)", "Das Netz (gross, 6 Spieler)",
  637. "To the Core (Lg 4 players)", "Mitten ins Herz (gross, 4 Spieler)",
  638. "Trafalgar (Lg 4 players)", "Trafalgar (gross, 4 Spieler)",
  639. "Twin Rivers (Sm 4 players)", "Zwillingsstr”me (klein, 4 Spieler)",
  640. "Umtumbo Gorge (Lg 4 players)", "Die Umtumbo-Schlucht (gross, 4 Spieler)",
  641. "Watch Your Step Extreme (Mega 8 players)", "Vorsicht, Lebensgefahr (sehr gross, 8 Spieler)",
  642. "Waterfalls (Lg 8 players)", "Wasserfall (gross, 8 Spieler)",
  643. "Waterloo Revisited (Lg 6 players)", "Zu Besuch in Waterloo (gross, 6 Spieler)",
  644. "Water Werks (Mega 8 players)", "Wasserwerk (sehr gross, 8 Spieler)",
  645. "Warlord's Lake (Sm 4 players)", "Der See des Kriegsgottes (klein, 4 Spieler)",
  646. "Zama (Sm 4 players)", "Zama (klein, 4 Spieler)",
  647. //#endif
  648. NULL
  649. };
  650. #endif
  651. #ifdef FRENCH
  652. char const *EngMisStr[] = {
  653. "A Path Beyond (Lg)", "Le Passage (Max)",
  654. "Central Conflict (Lg)", "Conflit Central (Max)",
  655. "Coastal Influence (Med)", "Le Chant des Canons (Moy)",
  656. "Combat Alley (Med)", "Aux Armes! (Moy)",
  657. "Desolation (Lg)", "D‚solation (Max)",
  658. "Dugout Isle (Med)", "L'Ile Maudite (Moy)",
  659. "Equal Opportunity (Sm)", "A Chances Egales (Min)",
  660. "First Come, First Serve (Sm)", "La Loi du Plus Fort (Min)",
  661. "Island Hoppers (Sm)", "D'une Ile … l'autre (Min)",
  662. "Island Wars (Lg)", "Guerres Insulaires (Max)",
  663. "Isle of Fury (Lg)", "L'Ile de la Furie(Max)",
  664. "Ivory Wastelands (Sm)", "Terres d'Ivoire (Min)",
  665. "Keep off the Grass (Sm)", "Hors de mon Chemin (Min)",
  666. "Marooned II (Med)", "Isolement II (Moy)",
  667. "Middle Mayhem (Sm)", "Chaos Interne (Min)",
  668. "No Escape (Med)", "Le PiŠge (Moy)",
  669. "No Man's Land (Med)", "No Man's Land (Moy)",
  670. "Normandy (Med)", "Normandie (Moy)",
  671. "North By Northwest (Lg)", "Nord, Nord-Ouest (Max)",
  672. "Pond Skirmish (Med)", "Bain de Sang (Moy)",
  673. "Raraku (Lg)", "Raraku (Max)",
  674. "Ridge War (Med)", "Guerre au Sommet (Moy)",
  675. "Shallow Grave (Med)", "La Saveur de la Mort (Moy)",
  676. "Treasure Isle (Med)", "L'Ile au Tr‚sor (Moy)",
  677. "Africa (Lg)", "Afrique (Max)",
  678. "Alaska Anarchy (Lg)", "Anarchie en Alaska (Max)",
  679. "All that Glitters... (Lg)", "Tout ce qui brille... (Max)",
  680. "Apre's Peace (Lg)", "Une Paix Durement N‚goci‚e... (Max)",
  681. "Antartica (Lg)", "Antarctique (Max)",
  682. "Armourgarden (Lg)", "La Guerre des Blind‚s (Max)",
  683. "Austraila (Med)", "Australie (Moy)",
  684. "Barrier to Entry (Lg)", "BarriŠre … l'Entr‚e (Max)",
  685. "Bavarian Blast (Med)", "Tonnerre Bavarois (Moy)",
  686. "Be Shore (Med)", "Plages Menac‚es (Moy)",
  687. "Bearing Straits (Med)", "Droit Devant ! (Moy)",
  688. "Blow Holes (Lg)", "CratŠres (Max)",
  689. "Bonsai (Sm)", "Bonsa‹ (Min)",
  690. "Brother Stalin (Lg)", "FrŠre Staline (Max)",
  691. "Bullseye (Lg)", "L'oeil du Taureau (Max)",
  692. "C&C (Med)", "C&C (Moy)",
  693. "Camos Canyon (Med)", "Le Canyon (Moy)",
  694. "Camos Coves (Lg)", "Criques (Max)",
  695. "Camos Cross (Lg)", "La Croix de Guerre (Max)",
  696. "Camos Crossing (Sm)", "La Crois‚e des Chemins (Min)",
  697. "Central Arena (Lg)", "L'ArŠne Diabolique (Max)",
  698. "Canyon River (Med)", "Au Milieu Coule Une RiviŠre (Moy)",
  699. "Crossroads (Sm)", "Carrefours (Min)",
  700. "Czech Mate (Lg)", "TchŠque et Mat (Max)",
  701. "Dday (Med)", "Le Jour J (Moy)",
  702. "Disaster Central (Lg)", "D‚sastre Central (Max)",
  703. "Docklands (Med)", "L'Enfer des Docks (Moy)",
  704. "East Coast (Med)", "C“te Est (Moy)",
  705. "Eastern Seaboard (Lg)", "Rivages de l'Est (Max)",
  706. "Finger Lake (Lg)", "Le Lac de tous les Dangers (Max)",
  707. "Fjords (Med)", "Fjords (Moy)",
  708. "Floodlands (Lg)", "Campagne Lacustre (Max)",
  709. "Forest under fire (Lg)", "Forˆt en flammes (Max)",
  710. "Four Corners (Lg)", "4 Coins (Max)",
  711. "Frostbit Fjords (Lg)", "Fjords Gel‚s (Max)",
  712. "Glenboig (Sm)", "Glenboig (Min)",
  713. "Hell Frozen Over (Lg)", "Enfer de Glace Max)",
  714. "India (Lg)", "Inde (Max)",
  715. "Indirect Fire (Lg)", "Attaque Indirecte (Max)",
  716. "Island Wars II (Lg)", "Guerres Insulaires II (Max)",
  717. "Italy (Lg)", "Italie (Max)",
  718. "Kabalo (Lg)", "Kabalo (Max)",
  719. "King of the Hills (Lg)", "Le Roi des Montagnes (Max)",
  720. "Lake Divide (Med)", "La Guerre du Lac (Moy)",
  721. "Lakelands (Lg)", "Terres Submerg‚es (Max)",
  722. "Land Ladder (Lg)", "Jusqu'au Sommet (Max)",
  723. "Lotsa Lakes (Lg)", "Terres de Lacs (Max)",
  724. "Lunar Battlefield (Lg Special)", "Combat Lunaire (Max Sp‚cial)",
  725. "Malibu Fields (Med)", "Les Champs de Malibu (Moy)",
  726. "Marshland (Med)", "Mar‚cages (Moy)",
  727. "MyLai Delta (Med)", "Le Delta Mylai (Moy)",
  728. "Natural Harbor (Med)", "Port Naturel (Moy)",
  729. "No Way Out (Lg)", "Sans Issue (Max)",
  730. "Normandy Landing (Lg)", "Le D‚barquement (Max)",
  731. "Ore Wars (Med)", "La Guerre du Minerai (Moy)",
  732. "Oz (Lg)", "Oz (Max)",
  733. "Pilgrim Fathers II (Lg)", "Les PŠlerins 2 (Max)",
  734. "Pip's Ice Tea (Med)", "Les Tranch‚es de Glace (Moy)",
  735. "Polar Panic (Lg)", "Panique Polaire (Max)",
  736. "Ponds (Med)", "Les Etangs (Moy)",
  737. "Putney (Lg)", "La Meilleure D‚fense... (Max)",
  738. "Return to Zion (Lg)", "Retour … Sion (Max)",
  739. "Ring of Land (Lg)", "Le Cycle Infernal (Max)",
  740. "River Basin (Lg)", "Confrontation Navale (Max)",
  741. "River Delta (Med)", "Le Delta (Moy)",
  742. "River Islands (Med)", "C“tes … Surveiller de PrŠs (Moy)",
  743. "River Maze (Sm)", "Labyrinthe Fluvial (Min)",
  744. "Rivers (Sm)", "RiviŠres (Min)",
  745. "Run the Gauntlet (Med)", "Relevons le D‚fi ! (Moy)",
  746. "Scappa Flow (Lg)", "Combats Sanglants (Max)",
  747. "Siberian Slaughter (Lg)", "Carnage Sib‚rien (Max)",
  748. "Sleepy Valley (Sm)", "La Vall‚e Endormie (Min)",
  749. "Snake River (Lg)", "La RiviŠre aux Serpents (Max)",
  750. "Snow Wars (Lg)", "Guerres de Neige (Max)",
  751. "Snowball fight (Lg)", "Bataille de Boules de Neige (Max)",
  752. "Snowy Island (Lg)", "L'Ile sous la Neige (Max)",
  753. "So Near So Far (Sm)", "Si Loin, Si Proche (Min)",
  754. "South America (Lg)", "Am‚rique du Sud (Max)",
  755. "Spring Line (Lg)", "Ligne de Front (Max)",
  756. "Star (Lg)", "Etoile (Max)",
  757. "Straighter & Narrower (Sm)", "L'Entonnoir (Min)",
  758. "TerrainSpotting (Sm)", "TerrainSpotting (Min)",
  759. "The Bay (Lg)", "La Baie (Max)",
  760. "The Garden (Lg)", "Le Jardin (Max)",
  761. "The Great Lakes (Med)", "Les Grands Lacs (Moy)",
  762. "The Ice Arena (Lg)", "L'ArŠne de Glace (Max)",
  763. "The Lake District (Lg)", "Un Lac Imprenable (Max)",
  764. "The Linked lands (Lg)", "Passages … Gu‚ (Max)",
  765. "The Mississippi (Med)", "Mississippi (Moy)",
  766. "The Sticky Bit (Lg)", "Marasme (Max)",
  767. "The Valley (Med)", "La Vall‚e (Moy)",
  768. "The Woods Today (Lg)", "Aujoud'hui: la Mort ! (Max)",
  769. "Things to Come (Lg)", "D‚nouement Incertain (Max)",
  770. "Tiger Core (Sm)", "Le Coeur du Tigre (Min)",
  771. "To the Core (Sm)", "Le Coeur du Conflit (Min)",
  772. "Tournament Hills (Lg)", "Combat en Altitude (Max)",
  773. "Tropical Storm (Med)", "Ouragan Tropical (Moy)",
  774. "Tundra Trouble (Lg)", "La Toundra (Max)",
  775. "Uk (Med)", "Royaume Uni (Moy)",
  776. "Undiscovered Country (Sm)", "Terre Inconnue (Min)",
  777. "United States (Med)", "Etats Unis (Moy)",
  778. "Volcano (Sm)", "Le Volcan (Min)",
  779. "Wastelands (Lg)", "Terres D‚sol‚es (Max)",
  780. "Water Works (Sm)", "Jeux d'Eau (Min)",
  781. "World Map (Med)", "Carte du Monde (Moy)",
  782. "Zambezi (Lg)", "ZambŠze (Max)",
  783. //#if 0
  784. "A Pattern of Islands (Lg 8 players)", "Archipel (Max. 8 joueurs)",
  785. "Arena Valley Extreme (Mega 8 players)", "La Vall‚e de l'arŠne (XL 8 joueurs)",
  786. "Around the Rim (Sm 4 players)", "Autour de la crˆte (Min. 4 joueurs)",
  787. "Ashes to Ashes (Lg 6 players)", "R‚duit en cendres (Max. 6 joueurs)",
  788. "Artic Wasteland (Mega 8 players)", "D‚solation arctique (XL 8 joueurs)",
  789. "Badajoz (Med 4 players)", "Badjoz (Moy. 4 joueurs)",
  790. "Baptism of Fire (Lg 6 players)", "Baptˆme du feu (Max. 6 joueurs)",
  791. "Big Fish, Small Pond (Lg 6 players)", "Gros poisson, Min. Mare (Max. 6 joueurs)",
  792. "Blue Lakes (Lg 8 players)", "Lacs bleus (Max. 8 joueurs)",
  793. "Booby Traps (Mega 8 players)", "PiŠges (XL 8 joueurs)",
  794. "Bridgehead (Lg 6 players)", "Tˆte de pont (Max. 6 joueurs)",
  795. "Butterfly Bay (Lg 6 players)", "La baie du papillon (Max. 6 joueurs)",
  796. "Central Conflict Extreme (Mega 8 players)", "Conflit central extrˆme (XL 8 joueurs)",
  797. "Circles of Death (Mega 8 players)", "Les cercles de la mort (XL 8 joueurs)",
  798. "Cold Front (Med 6 players)", "Front froid ( Moy. 6 joueurs)",
  799. "Cold Pass (Med 4 players)", "La Passe Glac‚e (Moy. 4 joueurs)",
  800. "Combat Zones (Mega 8 players)", "Zones de combat (XL 8 joueurs)",
  801. "Conflict Cove (Sm 4 players)", "La Crique du conflit (Min. 4 joueurs)",
  802. "Culloden Moor (Med 8 players)", "La Lande de Culloden (Moy. 8 joueurs)",
  803. "Damnation Alley (Mega 8 players)", "Le chemin de la damnation (XL 8 joueurs)",
  804. "Death Valley (Mega 8 players)", "La vall‚e de la mort (XL 8 joueurs)",
  805. "Deep Six (Mega 8 players)", "Six de profondeur (XL 8 joueurs)",
  806. "Destruction Derby (Mega 8 players)", "Stock car (XL 8 joueurs)",
  807. "Diamonds Aren't Forever (Mega 8 players)", "Les diamants ne sont pas ‚ternels (XL 8 joueurs)",
  808. "Elysium (Sm 4 players)", "Elys‚e (Min. 4 joueurs)",
  809. "Equal Shares (Lg 4 players)", "Parts ‚gales (Max. 4 joueurs)",
  810. "Frost Bitten (Mega 8 players)", "Engelures (XL 8 joueurs)",
  811. "Frozen Valley (Med 6 players)", "La Vall‚e glac‚e (Moy. 6 joueurs)",
  812. "Gettysburg (Sm 4 players)", "Gettysburg (Min. 4 joueurs)",
  813. "Glacial Valley (Sm 4 players)", "Vall‚e de glace (Min. 4 joueurs)",
  814. "Gold Coast (Med 6 players)", "La c“te dor‚e (Moy. 6 joueurs)",
  815. "Gold Rush (Lg 4 players)", "La ru‚e vers l'or (Max. 4 joueurs)",
  816. "Habitat (Lg 4 players)", "Habitat (Max. 4 joueurs)",
  817. "Hades Frozen Over (Sm 4 players)", "Les enfers glac‚s (Min. 4 joueurs)",
  818. "Hamburger Hill (Mega 8 players)", "Hamburger Hill (XL 8 joueurs)",
  819. "Hastings (Sm 4 players)", "Hastings (Min. 4 joueurs)",
  820. "Hell's Pass (Med 6 players)", "La route de l'enfer (Moy. 6 joueurs)",
  821. "Holy Grounds (Mega 8 players)", "Terres saintes (XL 8 joueurs)",
  822. "Ice Bergs (Med 6 players)", "Icebergs (Moy. 6 joueurs)",
  823. "Ice Station (Lg 6 players)", "Station glac‚e (Max. 6 joueurs)",
  824. "Ice Queen (Lg 4 players)", "Reine des glaces (Max. 4 joueurs)",
  825. "In the Sun (Med 6 players)", "Sous le soleil (Moy. 6 joueurs)",
  826. "Innocents? (Mega 8 players)", "Innocents ? (XL 8 joueurs)",
  827. "Islands (Med 8 players)", "Iles (Moy. 8 joueurs)",
  828. "Island Plateau (Lg 4 players)", "Plateau des Œles (Max. 4 joueurs)",
  829. "Island Wars Extreme (Mega 8 players)", "Guerres insulaires extrˆme (XL 8 joueurs)",
  830. "Kananga (Med 6 players)", "Kananga (Moy. 6 joueurs)",
  831. "King of the Hills Extreme (Mega 8 players)", "Roi des collines extrˆme (XL 8 joueurs)",
  832. "Lake Land (Lg 8 players)", "Paysage lacustre (Max. 8 joueurs)",
  833. "Land Locked (Lg 8 players)", "Enclave (Max. 8 joueurs)",
  834. "Lanes (Med 8 players)", "Le parcours du combattant (Moy. 8 joueurs)",
  835. "Leipzip (Sm 4 players)", "Leipzig (Min. 4 joueurs)",
  836. "Meander (Lg 8 players)", "M‚andre (Max. 8 joueurs)",
  837. "Mekong (Med 8 players)", "M‚kong (Moy. 8 joueurs)",
  838. "Middle Ground (Med 8 players)", "Plateau m‚dian (Moy. 8 joueurs)",
  839. "Naval Conquests (Mega 8 players)", "Conquˆtes navales (XL 8 joueurs)",
  840. "On your Marks (Med 4 players)", "A vos marques (Moy. 4 joueurs)",
  841. "Open Warfare (Mega 8 players)", "Guerre ouverte (XL 8 joueurs)",
  842. "Ore Gardens (Lg 8 players)", "Jardins de minerai (Max. 8 joueurs)",
  843. "Potholes (Mega 8 players)", "Nids de poules (XL 8 joueurs)",
  844. "Puddles (Med 4 players)", "Flaques (Moy. 4 joueurs)",
  845. "Random Violence (Mega 8 players)", "Violence al‚atoire (XL 8 joueurs)",
  846. "Revenge (Med 8 players)", "Vengeance (Moy. 8 joueurs)",
  847. "Rias (Med 8 players)", "Rias (Moy. 8 joueurs)",
  848. "River Crossing (Sm 4 players)", "Passage … gu‚ (Min. 4 joueurs)",
  849. "River Rampage (Mega 8 players)", "RiviŠre d‚chaŒn‚e (XL 8 joueurs)",
  850. "River Rapids (Lg 6 players)", "Rapides (Max. 6 joueurs)",
  851. "Rivers Wild (Mega 8 players)", "RiviŠres sauvages (XL 8 joueurs)",
  852. "Rorkes Drift (Lg 4 players)", "L'Exode de Rorkes (Max. 4 joueurs)",
  853. "Seaside (Med 4 players)", "C“te (Moy. 4 joueurs)",
  854. "Shades (Med 8 players)", "Ombres (Moy. 8 joueurs)",
  855. "Smuggler's Cove (Lg 6 players)", "La Crique du contrebandier (Max. 6 joueurs)",
  856. "Snow Garden (Sm 2 players)", "Jardin de neige (Min. 2 joueurs)",
  857. "Stalingrad (Sm 4 players)", "Stalingrad (Min. 4 joueurs)",
  858. "Sticks & Stones (Med 4 players)", "Bƒton & Roches (Moy. 4 joueurs)",
  859. "Strathearn Valley (Lg 6 players)", "La Vall‚e de Strathearn (Max. 6 joueurs)",
  860. "Super Bridgehead (Mega 8 players)", "Super tˆte de pont (XL 8 joueurs)",
  861. "Super Mekong (Mega 8 players)", "Super M‚kong (XL 8 joueurs)",
  862. "Super Ore Gardens (Mega 8 players)", "Super jardin de minerai (XL 8 joueurs)",
  863. "Switch (Med 4 players)", "Permutation (Moy. 4 joueurs)",
  864. "The Berg (Mega 8 players)", "Le Berg (XL 8 joueurs)",
  865. "The Boyne (Med 4 players)", "Le Boyne (Moy. 4 joueurs)",
  866. "The Bulge (Sm 4 players)", "Le bombement (Min. 4 joueurs)",
  867. "The Cauldron (Lg 6 players)", "Le chaudron (Max. 6 joueurs)",
  868. "The Finger (Lg 6 players)", "Le doigt (Max. 6 joueurs)",
  869. "The Hills Have Eyes (Mega 8 players)", "Les collines ont des yeux (XL 8 joueurs)",
  870. "The Keyes (Med 6 players)", "Les Keyes (Moy. 6 joueurs)",
  871. "The Lakes (Med 8 players)", "Les lacs (Moy. 8 joueurs)",
  872. "The Neck (Med 6 players)", "Le goulot (Moy. 6 joueurs)",
  873. "The Web (Lg 6 players)", "La toile (Max. 6 joueurs)",
  874. "To the Core (Lg 4 players)", "Jusqu'au cour (Max. 4 joueurs)",
  875. "Trafalgar (Lg 4 players)", "Trafalgar (Max. 4 joueurs)",
  876. "Twin Rivers (Sm 4 players)", "Les deux riviŠres (Min. 4 joueurs)",
  877. "Umtumbo Gorge (Lg 4 players)", "La Gorge de Umtumbo (Max. 4 joueurs)",
  878. "Watch Your Step Extreme (Mega 8 players)", "Pas-…-pas extrˆme (XL 8 joueurs)",
  879. "Waterfalls (Lg 8 players)", "Chutes d'eau (Max. 8 joueurs)",
  880. "Waterloo Revisited (Lg 6 players)", "Waterloo II (Max. 6 joueurs)",
  881. "Water Werks (Mega 8 players)", "Jeux d'eau (XL 8 joueurs)",
  882. "Warlord's Lake (Sm 4 players)", "Le lac du guerrier (Min. 4 joueurs)",
  883. "Zama (Sm 4 players)", "Zama (Min. 4 joueurs)",
  884. //#endif
  885. NULL
  886. };
  887. #endif
  888. /*
  889. ******************************** Prototypes *********************************
  890. */
  891. static int Net_Join_Dialog(void);
  892. static int Request_To_Join (char *playername, int join_index,
  893. HousesType house, PlayerColorType color);
  894. static void Unjoin_Game(char *namebuf,JoinStateType joinstate,
  895. ListClass *gamelist, ColorListClass *playerlist, int game_index,
  896. int goto_lobby, int msg_x, int msg_y, int msg_h, int send_x, int send_y,
  897. int msg_len);
  898. static void Send_Join_Queries(int curgame, JoinStateType joinstate,
  899. int gamenow, int playernow, int chatnow, char *myname, int init = 0);
  900. static JoinEventType Get_Join_Responses(JoinStateType *joinstate,
  901. ListClass *gamelist, ColorListClass *playerlist, int join_index,
  902. char *my_name, RejectType *why);
  903. static int Net_New_Dialog(void);
  904. static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist,
  905. int *color_used);
  906. void Start_WWChat(ColorListClass *playerlist);
  907. int Update_WWChat(void);
  908. #define PCOLOR_BROWN PCOLOR_GREY
  909. /***********************************************************************************************
  910. * Init_Network -- initializes network stuff *
  911. * *
  912. * INPUT: *
  913. * none. *
  914. * *
  915. * OUTPUT: *
  916. * true = Initialization OK, false = error *
  917. * *
  918. * WARNINGS: *
  919. * none. *
  920. * *
  921. * HISTORY: *
  922. * 02/14/1995 BR : Created. *
  923. *=============================================================================================*/
  924. bool Init_Network (void)
  925. {
  926. NetNumType net;
  927. NetNodeType node;
  928. #ifdef WINSOCK_IPX
  929. assert ( PacketTransport != NULL );
  930. #endif //WINSOCK_IPX
  931. //------------------------------------------------------------------------
  932. // This call allocates all necessary queue buffers, allocates Real-mode
  933. // memory, and commands IPX to start listening on the Global Channel.
  934. //------------------------------------------------------------------------
  935. if (!Ipx.Init()) {
  936. return(false);
  937. }
  938. //------------------------------------------------------------------------
  939. // Set up the IPX manager to cross a bridge
  940. //------------------------------------------------------------------------
  941. if (Session.Type != GAME_INTERNET) {
  942. if (Session.IsBridge) {
  943. Session.BridgeNet.Get_Address(net,node);
  944. Ipx.Set_Bridge(net);
  945. }
  946. }
  947. return(true);
  948. } /* end of Init_Network */
  949. /***********************************************************************************************
  950. * Shutdown_Network -- shuts down network stuff *
  951. * *
  952. * INPUT: *
  953. * none. *
  954. * *
  955. * OUTPUT: *
  956. * none. *
  957. * *
  958. * WARNINGS: *
  959. * none. *
  960. * *
  961. * HISTORY: *
  962. * 02/14/1995 BR : Created. *
  963. *=============================================================================================*/
  964. void Shutdown_Network (void)
  965. {
  966. //
  967. // Note: The thought behind this section of code was that if the program
  968. // terminates early, without an EventClass::EXIT event, it still needs to
  969. // tell the other systems that it's gone, so it would send a SIGN_OFF packet.
  970. // BUT, this causes a sync bug if the systems are running slow and this system
  971. // is running ahead of the others; it will send the NET_SIGN_OFF >>before<<
  972. // the other system execute their EventClass::EXIT event, and the other systems
  973. // will kill the connection at some random Frame # & turn my stuff over to
  974. // the computer possibly at different times.
  975. // BRR, 10/29/96
  976. //
  977. #if 0
  978. //------------------------------------------------------------------------
  979. // If the Players vector contains at least one name, send a sign-off
  980. // packet. If 'Players' is empty, I have no name, so there's no point
  981. // in sending a sign-off.
  982. //------------------------------------------------------------------------
  983. if (Session.Players.Count()) {
  984. //.....................................................................
  985. // Build a sign-off packet & send it
  986. //.....................................................................
  987. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  988. Session.GPacket.Command = NET_SIGN_OFF;
  989. strcpy (Session.GPacket.Name, Session.Players[0]->Name);
  990. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  991. 0, NULL);
  992. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  993. 0, NULL);
  994. if (Session.IsBridge && !Winsock.Get_Connected()) {
  995. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 0,
  996. &Session.BridgeNet);
  997. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 0,
  998. &Session.BridgeNet);
  999. }
  1000. //.....................................................................
  1001. // Wait for the packets to finish going out (or the Global Channel
  1002. // times out)
  1003. //.....................................................................
  1004. for (;;) {
  1005. if (Ipx.Global_Num_Send()==0) {
  1006. break;
  1007. }
  1008. Ipx.Service();
  1009. }
  1010. }
  1011. #endif
  1012. //------------------------------------------------------------------------
  1013. // If I was in a game, I'm not now, so clear the game name
  1014. //------------------------------------------------------------------------
  1015. Session.GameName[0] = 0;
  1016. } /* end of Shutdown_Network */
  1017. /***********************************************************************************************
  1018. * Process_Global_Packet -- responds to remote queries *
  1019. * *
  1020. * The only commands from other systems this routine responds to are NET_QUERY_GAME *
  1021. * and NET_QUERY_PLAYER. The other commands are too context-specific to be able *
  1022. * to handle here, such as joining the game or signing off; but this routine handles *
  1023. * the majority of the program's needs. *
  1024. * *
  1025. * INPUT: *
  1026. * packet ptr to packet to process *
  1027. * address source address of sender *
  1028. * *
  1029. * OUTPUT: *
  1030. * true = packet was processed, false = wasn't *
  1031. * *
  1032. * WARNINGS: *
  1033. * Session.GameName must have been filled in before this function can be called. *
  1034. * *
  1035. * HISTORY: *
  1036. * 02/15/1995 BR : Created. *
  1037. *=============================================================================================*/
  1038. bool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address)
  1039. {
  1040. GlobalPacketType mypacket;
  1041. //------------------------------------------------------------------------
  1042. // If our Players vector is empty, just return.
  1043. //------------------------------------------------------------------------
  1044. if (Session.Players.Count()==0) {
  1045. return (true);
  1046. }
  1047. //------------------------------------------------------------------------
  1048. // Another system asking what game this is
  1049. //------------------------------------------------------------------------
  1050. if (packet->Command==NET_QUERY_GAME && Session.NetStealth==0) {
  1051. //.....................................................................
  1052. // If the game is closed, let every player respond, and let the sender of
  1053. // the query sort it all out. This way, if the game's host exits the game,
  1054. // the game still shows up on other players' dialogs.
  1055. // If the game is open, only the game owner may respond.
  1056. //.....................................................................
  1057. if (strlen(Session.GameName) > 0 && ((!Session.NetOpen) ||
  1058. (Session.NetOpen &&
  1059. !strcmp(Session.Players[0]->Name,Session.GameName)))) {
  1060. memset (&mypacket, 0, sizeof(GlobalPacketType));
  1061. mypacket.Command = NET_ANSWER_GAME;
  1062. strcpy(mypacket.Name, Session.GameName);
  1063. mypacket.GameInfo.IsOpen = Session.NetOpen;
  1064. Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1,
  1065. address);
  1066. }
  1067. return(true);
  1068. }
  1069. //------------------------------------------------------------------------
  1070. // Another system asking what player I am
  1071. //------------------------------------------------------------------------
  1072. else if (packet->Command==NET_QUERY_PLAYER &&
  1073. !strcmp (packet->Name, Session.GameName) &&
  1074. (strlen(Session.GameName) > 0) && Session.NetStealth==0) {
  1075. memset (&mypacket, 0, sizeof(GlobalPacketType)); // changed DRD 9/26
  1076. mypacket.Command = NET_ANSWER_PLAYER;
  1077. strcpy(mypacket.Name, Session.Players[0]->Name);
  1078. mypacket.PlayerInfo.House = Session.House;
  1079. mypacket.PlayerInfo.Color = Session.ColorIdx;
  1080. mypacket.PlayerInfo.NameCRC = Compute_Name_CRC(Session.GameName);
  1081. Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1, address);
  1082. return(true);
  1083. }
  1084. return(false);
  1085. } /* end of Process_Global_Packet */
  1086. /***********************************************************************************************
  1087. * Destroy_Connection -- destroys the given connection *
  1088. * *
  1089. * Call this routine when a connection goes bad, or another player signs off. *
  1090. * *
  1091. * INPUT: *
  1092. * id connection ID to destroy; this should be the HousesType of the player *
  1093. * on this connection *
  1094. * error 0 = user signed off; 1 = connection error; otherwise, no error is shown. *
  1095. * *
  1096. * OUTPUT: *
  1097. * none. *
  1098. * *
  1099. * WARNINGS: *
  1100. * none. *
  1101. * *
  1102. * HISTORY: *
  1103. * 04/22/1995 BR : Created. *
  1104. *=============================================================================================*/
  1105. void Destroy_Connection(int id, int error)
  1106. {
  1107. int i;
  1108. HouseClass *housep;
  1109. char txt[80];
  1110. if (Debug_Print_Events) {
  1111. printf("Destroying connection for house %d (%s)\n",
  1112. id,HouseClass::As_Pointer((HousesType)id)->IniName);
  1113. }
  1114. //------------------------------------------------------------------------
  1115. // Do nothing if the house isn't human.
  1116. //------------------------------------------------------------------------
  1117. housep = HouseClass::As_Pointer((HousesType)id);
  1118. if (!housep || !housep->IsHuman)
  1119. return;
  1120. //------------------------------------------------------------------------
  1121. // Create a message to display to the user
  1122. //------------------------------------------------------------------------
  1123. txt[0] = '\0';
  1124. if (error==1) {
  1125. sprintf(txt,Text_String(TXT_CONNECTION_LOST), housep->IniName);
  1126. } else if (error==0) {
  1127. sprintf(txt,Text_String(TXT_LEFT_GAME), housep->IniName);
  1128. }
  1129. if (strlen(txt)) {
  1130. Session.Messages.Add_Message (NULL,0, txt, housep->RemapColor, TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
  1131. Map.Flag_To_Redraw(false);
  1132. }
  1133. //------------------------------------------------------------------------
  1134. // Remove this player from the Players vector
  1135. //------------------------------------------------------------------------
  1136. for (i = 0; i < Session.Players.Count(); i++) {
  1137. if (!stricmp(Session.Players[i]->Name,housep->IniName)) {
  1138. delete Session.Players[i];
  1139. Session.Players.Delete(Session.Players[i]);
  1140. break;
  1141. }
  1142. }
  1143. //------------------------------------------------------------------------
  1144. // Delete the IPX connection
  1145. //------------------------------------------------------------------------
  1146. Ipx.Delete_Connection(id);
  1147. //------------------------------------------------------------------------
  1148. // Turn the player's house over to the computer's AI
  1149. //------------------------------------------------------------------------
  1150. housep->IsHuman = false;
  1151. housep->IQ = Rule.MaxIQ;
  1152. strcpy (housep->IniName,Text_String(TXT_COMPUTER));
  1153. Session.NumPlayers--;
  1154. //------------------------------------------------------------------------
  1155. // If we're the last player left, tell the user.
  1156. //------------------------------------------------------------------------
  1157. if (Session.NumPlayers == 1) {
  1158. sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
  1159. Session.Messages.Add_Message (NULL, 0, txt, housep->RemapColor,
  1160. TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE);
  1161. Map.Flag_To_Redraw(false);
  1162. }
  1163. } /* end of Destroy_Connection */
  1164. /***********************************************************************************************
  1165. * Remote_Connect -- handles connecting this user to others *
  1166. * *
  1167. * INPUT: *
  1168. * none. *
  1169. * *
  1170. * OUTPUT: *
  1171. * true = connections established; false = not *
  1172. * *
  1173. * WARNINGS: *
  1174. * none. *
  1175. * *
  1176. * HISTORY: *
  1177. * 02/14/1995 BR : Created. *
  1178. *=============================================================================================*/
  1179. bool Remote_Connect(void)
  1180. {
  1181. int rc;
  1182. int stealth; // original state of Session.NetStealth flag
  1183. //------------------------------------------------------------------------
  1184. // Init network timing parameters; these values should work for both a
  1185. // "real" network, and a simulated modem network (ie Kali)
  1186. //------------------------------------------------------------------------
  1187. Ipx.Set_Timing ( 30, // retry 2 times per second
  1188. -1, // ignore max retries
  1189. 600); // give up after 10 seconds
  1190. //------------------------------------------------------------------------
  1191. // Save the original value of the NetStealth flag, so we can turn stealth
  1192. // off for now (during this portion of the dialogs, we must show ourselves)
  1193. //------------------------------------------------------------------------
  1194. stealth = Session.NetStealth;
  1195. Session.NetStealth = 0;
  1196. //------------------------------------------------------------------------
  1197. // Init my game name to 0-length, since I haven't joined any game yet.
  1198. //------------------------------------------------------------------------
  1199. Session.GameName[0] = 0;
  1200. //------------------------------------------------------------------------
  1201. // The game is now "open" for joining. Close it as soon as we exit this
  1202. // routine.
  1203. //------------------------------------------------------------------------
  1204. Session.NetOpen = 1;
  1205. //------------------------------------------------------------------------
  1206. // Keep looping until something useful happens.
  1207. //------------------------------------------------------------------------
  1208. while (1) {
  1209. //.....................................................................
  1210. // Pop up the network Join/New dialog
  1211. //.....................................................................
  1212. rc = Net_Join_Dialog();
  1213. //.....................................................................
  1214. // -1 = user selected Cancel
  1215. //.....................................................................
  1216. if (rc==-1) {
  1217. Session.NetStealth = stealth;
  1218. Session.NetOpen = 0;
  1219. return(false);
  1220. }
  1221. //.....................................................................
  1222. // 0 = user has joined an existing game; save values & return
  1223. //.....................................................................
  1224. else if (rc==0) {
  1225. Session.Write_MultiPlayer_Settings ();
  1226. Session.NetStealth = stealth;
  1227. Session.NetOpen = 0;
  1228. return(true);
  1229. }
  1230. //.....................................................................
  1231. // 1 = user requests New Network Game
  1232. //.....................................................................
  1233. else if (rc==1) {
  1234. //..................................................................
  1235. // Pop up the New Network Game dialog; if user selects OK, return
  1236. // 'true'; otherwise, return to the Join Dialog.
  1237. //..................................................................
  1238. if (Net_New_Dialog()) {
  1239. Session.Write_MultiPlayer_Settings ();
  1240. Session.NetStealth = stealth;
  1241. Session.NetOpen = 0;
  1242. return(true);
  1243. } else {
  1244. continue;
  1245. }
  1246. }
  1247. }
  1248. } /* end of Remote_Connect */
  1249. /***********************************************************************************************
  1250. * Net_Join_Dialog -- lets user join an existing game or start a new one *
  1251. * *
  1252. * This dialog displays an edit field for the player's name, and a list of all non-stealth- *
  1253. * mode games. Clicking once on a game name displays a list of who's in that game. Clicking *
  1254. * "New" takes the user to the Net_New dialog, where he waits for other users to join his *
  1255. * game. All other input is done through this dialog. *
  1256. * *
  1257. * The dialog has several "states": *
  1258. * *
  1259. * 1) Initially, it waits for the user to fill in his/her name and then to select Join or *
  1260. * New; if New is selected, this dialog is exited. *
  1261. * *
  1262. * 2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.*
  1263. * The join request is transmitted to the game's owner, and the message "Waiting for *
  1264. * Confirmation" is displayed, until a confirmation or denial is received from the game's *
  1265. * owner. The user may click Cancel at this point to cancel the join request. *
  1266. * (Once Join is selected, the name editing field is disabled, and becomes a display-only *
  1267. * field. If cancel is selected, it reappears as an edit field.) The user can still click*
  1268. * around & see who's in which games. *
  1269. * *
  1270. * 3) If the join request is denied, the dialog re-initializes to its pre-join state; the *
  1271. * Join & New buttons reappear, & the Name field is available again. *
  1272. * *
  1273. * 4) If join confirmation is obtained, the message changes to show all the current game *
  1274. * settings. The user cannot click around & look at other games any more. *
  1275. * *
  1276. * Any game running in Stealth mode won't show up on this dialog. *
  1277. * *
  1278. * The 'Players' vector matches one-for-one the contents of the list box. The local system *
  1279. * is always listed first; the IPX Address of the local system will NOT be valid in the *
  1280. * Players vector. The Games & Players vectors should be left filled in even after this *
  1281. * routine is exited; their contents are used to form connections to the other players, *
  1282. * after the scenario has been loaded. *
  1283. * *
  1284. * The 'Chat' vector contains the address of everyone who sends me a chat announcement. *
  1285. * The address field is used to send everyone my outgoing messages. The LastTime *
  1286. * field is used as a timeout; if enough time goes by & we don't hear from this node, *
  1287. * we ping him, requesting a CHAT_ANNOUNCE if he's still in chat. If we don't hear *
  1288. * from him after that, we remove him from our list. *
  1289. * *
  1290. * INPUT: *
  1291. * none. *
  1292. * *
  1293. * OUTPUT: *
  1294. * -1 = cancel, 0 = OK, 1 = New net game requested *
  1295. * *
  1296. * WARNINGS: *
  1297. * none. *
  1298. * *
  1299. * HISTORY: *
  1300. * 02/14/1995 BR : Created. *
  1301. *=============================================================================================*/
  1302. static int Net_Join_Dialog(void)
  1303. {
  1304. //------------------------------------------------------------------------
  1305. // Dialog & button dimensions
  1306. //------------------------------------------------------------------------
  1307. int d_dialog_w = 320 *RESFACTOR; // dialog width
  1308. int d_dialog_h = 200 *RESFACTOR; // dialog height
  1309. int d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2); // dialog x-coord
  1310. int d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2); // centered y-coord
  1311. int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
  1312. int d_txt6_h = 6 *RESFACTOR+1; // ht of 6-pt text
  1313. int d_margin1 = 17 *RESFACTOR; // large margin
  1314. int d_margin2 = 7 *RESFACTOR; // small margin
  1315. int d_name_w = 70 *RESFACTOR;
  1316. int d_name_h = 9 *RESFACTOR;
  1317. int d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2);
  1318. int d_name_y = d_dialog_y + d_margin2 + d_txt6_h + (2*RESFACTOR);
  1319. #ifdef OLDWAY
  1320. int d_gdi_w = 40 *RESFACTOR;
  1321. int d_gdi_h = 9 *RESFACTOR;
  1322. int d_gdi_x = d_dialog_cx - d_gdi_w;
  1323. int d_gdi_y = d_name_y;
  1324. int d_nod_w = 40 *RESFACTOR;
  1325. int d_nod_h = 9 *RESFACTOR;
  1326. int d_nod_x = d_dialog_cx;
  1327. int d_nod_y = d_name_y;
  1328. #else
  1329. int d_house_w = 60 *RESFACTOR;
  1330. int d_house_h = (8 * 5 *RESFACTOR);
  1331. int d_house_x = d_dialog_cx - (d_house_w / 2);
  1332. int d_house_y = d_name_y;
  1333. #endif
  1334. int d_color_w = 10 *RESFACTOR;
  1335. int d_color_h = 9 *RESFACTOR;
  1336. int d_color_y = d_name_y;
  1337. int d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3);
  1338. int d_gamelist_w = 155 *RESFACTOR;
  1339. int d_gamelist_h = ((6 * 6) + 3) *RESFACTOR; // 6 rows high
  1340. int d_gamelist_x = d_dialog_x + d_margin1 - 2*RESFACTOR;
  1341. int d_gamelist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;
  1342. //BG int d_playerlist_w = 113 *RESFACTOR;
  1343. int d_playerlist_w = 118 *RESFACTOR;
  1344. int d_playerlist_h = ((6 * 6) + 3) *RESFACTOR; // 6 rows high
  1345. int d_playerlist_x = d_dialog_x + d_dialog_w - (d_margin1 + d_playerlist_w - 2*RESFACTOR);
  1346. int d_playerlist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;
  1347. int d_count_w = 25 *RESFACTOR;
  1348. int d_count_h = d_txt6_h;
  1349. int d_count_x = d_gamelist_x + (d_gamelist_w / 2);
  1350. int d_count_y = d_gamelist_y + d_gamelist_h + d_margin2;
  1351. int d_level_w = 25 *RESFACTOR;
  1352. int d_level_h = d_txt6_h;
  1353. int d_level_x = d_gamelist_x + (d_gamelist_w / 2);
  1354. int d_level_y = d_count_y + d_count_h;
  1355. int d_credits_w = 25 *RESFACTOR;
  1356. int d_credits_h = d_txt6_h;
  1357. int d_credits_x = d_gamelist_x + (d_gamelist_w / 2);
  1358. int d_credits_y = d_level_y + d_level_h;
  1359. int d_aiplayers_w = 25 *RESFACTOR;
  1360. int d_aiplayers_h = d_txt6_h;
  1361. int d_aiplayers_x = d_gamelist_x + (d_gamelist_w / 2);
  1362. int d_aiplayers_y = d_credits_y + d_level_h;
  1363. int d_options_w = d_playerlist_w;
  1364. int d_options_h = ((5 * 6) + 4) *RESFACTOR;
  1365. int d_options_x = d_playerlist_x;
  1366. int d_options_y = d_playerlist_y + d_playerlist_h + d_margin2 - (2*RESFACTOR);
  1367. int d_message1_w = d_dialog_w - (d_margin1 * 2) + 4*RESFACTOR;
  1368. int d_message1_h = (14 * d_txt6_h) +3*RESFACTOR;
  1369. int d_message1_x = d_dialog_x + (d_dialog_w-d_message1_w)/2;
  1370. int d_message1_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message1_h);
  1371. int d_message2_w = d_message1_w;
  1372. int d_message2_h = (8 * d_txt6_h) + 3*RESFACTOR;
  1373. int d_message2_x = d_message1_x;
  1374. int d_message2_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message2_h);
  1375. #ifdef FRENCH //VG2
  1376. int d_join_w = 60 *RESFACTOR;
  1377. #else
  1378. int d_join_w = 40 *RESFACTOR;
  1379. #endif
  1380. int d_join_h = 9 *RESFACTOR;
  1381. int d_join_x = d_dialog_x + (d_dialog_w / 6) - (d_join_w / 2);
  1382. int d_join_y = d_dialog_y + d_dialog_h - d_join_h - 8*RESFACTOR;
  1383. int d_cancel_w = 50 *RESFACTOR;
  1384. int d_cancel_h = 9 *RESFACTOR;
  1385. int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
  1386. int d_cancel_y = d_join_y;
  1387. #ifdef FRENCH
  1388. int d_new_w = 60 *RESFACTOR;
  1389. #else
  1390. int d_new_w = 40 *RESFACTOR;
  1391. #endif
  1392. int d_new_h = 9 *RESFACTOR;
  1393. int d_new_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_new_w / 2);
  1394. int d_new_y = d_join_y;
  1395. int d_send_w = d_message1_w;
  1396. int d_send_h = 9 *RESFACTOR;
  1397. int d_send_x = d_message1_x;
  1398. int d_send_y = d_message1_y + d_message1_h;
  1399. //------------------------------------------------------------------------
  1400. // Button Enumerations
  1401. //------------------------------------------------------------------------
  1402. enum {
  1403. BUTTON_NAME = 100,
  1404. #ifdef OLDWAY
  1405. BUTTON_GDI,
  1406. BUTTON_NOD,
  1407. #else
  1408. BUTTON_HOUSE,
  1409. #endif
  1410. BUTTON_GAMELIST,
  1411. BUTTON_PLAYERLIST,
  1412. BUTTON_JOIN,
  1413. BUTTON_CANCEL,
  1414. BUTTON_NEW,
  1415. BUTTON_COUNT,
  1416. BUTTON_LEVEL,
  1417. BUTTON_CREDITS,
  1418. BUTTON_AI_PLAYERS,
  1419. BUTTON_OPTIONS,
  1420. };
  1421. //------------------------------------------------------------------------
  1422. // Redraw values: in order from "top" to "bottom" layer of the dialog
  1423. //------------------------------------------------------------------------
  1424. typedef enum {
  1425. REDRAW_NONE = 0,
  1426. REDRAW_PARMS,
  1427. REDRAW_MESSAGE,
  1428. REDRAW_COLORS,
  1429. REDRAW_BUTTONS,
  1430. REDRAW_BACKGROUND,
  1431. REDRAW_ALL = REDRAW_BACKGROUND
  1432. } RedrawType;
  1433. //------------------------------------------------------------------------
  1434. // Dialog variables
  1435. //------------------------------------------------------------------------
  1436. RedrawType display = REDRAW_ALL; // redraw level
  1437. bool process = true; // process while true
  1438. KeyNumType input;
  1439. int cbox_x[] = {
  1440. d_color_x,
  1441. d_color_x + d_color_w,
  1442. d_color_x + (d_color_w * 2),
  1443. d_color_x + (d_color_w * 3),
  1444. d_color_x + (d_color_w * 4),
  1445. d_color_x + (d_color_w * 5),
  1446. d_color_x + (d_color_w * 6),
  1447. d_color_x + (d_color_w * 7),
  1448. };
  1449. char housetext[25] = ""; // buffer for house droplist
  1450. int isdropped = 0;
  1451. JoinStateType joinstate = JOIN_NOTHING; // current "state" of this dialog
  1452. char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
  1453. int playertabs[] = {71 *RESFACTOR}; // tabs for player list box
  1454. int optiontabs[] = {8}; // tabs for player list box
  1455. int game_index = -1; // index of currently-selected game
  1456. int join_index = -1; // index of game we're joining
  1457. int rc = 0; // -1 = user cancelled, 1 = New
  1458. JoinEventType event; // event from incoming packet
  1459. int i; // loop counter
  1460. char txt[128];
  1461. char const *p;
  1462. int parms_received = 0; // 1 = game options received
  1463. int found;
  1464. NodeNameType *who; // node to add to Players
  1465. RejectType why; // reason for rejection
  1466. TTimerClass<SystemTimerClass> lastclick_timer; // time b/w send periods
  1467. int lastclick_idx = 0; // index of item last clicked on
  1468. RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
  1469. Session.Options.ScenarioDescription[0] = 0; //Flag that we dont know the scenario name yet
  1470. char * item;
  1471. unsigned long starttime;
  1472. int load_game = 0; // 1 = load saved game
  1473. int goto_lobby;
  1474. bool messages_have_focus = true; // Gadget focus starts on the message system
  1475. //------------------------------------------------------------------------
  1476. // Buttons
  1477. //------------------------------------------------------------------------
  1478. GadgetClass *commands; // button list
  1479. EditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT,
  1480. d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);
  1481. #ifdef OLDWAY
  1482. TextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w);
  1483. TextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w);
  1484. #else
  1485. Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT);
  1486. DropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext),
  1487. TPF_TEXT,
  1488. d_house_x, d_house_y, d_house_w, d_house_h,
  1489. MFCD::Retrieve("BTN-UP.SHP"),
  1490. MFCD::Retrieve("BTN-DN.SHP"));
  1491. #endif
  1492. ListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"));
  1493. ColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"));
  1494. TextButtonClass joinbtn(BUTTON_JOIN, TXT_JOIN, TPF_BUTTON, d_join_x, d_join_y, d_join_w);
  1495. TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w);
  1496. TextButtonClass newbtn(BUTTON_NEW, TXT_NEW, TPF_BUTTON, d_new_x, d_new_y, d_new_w);
  1497. GaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);
  1498. GaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);
  1499. GaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);
  1500. GaugeClass aiplayersgauge(BUTTON_AI_PLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);
  1501. CheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"));
  1502. StaticButtonClass descrip(0, "", TPF_CENTER|TPF_TEXT, d_dialog_x + 16*RESFACTOR, d_name_y, d_dialog_w - 32*RESFACTOR, d_txt6_h+1);
  1503. StaticButtonClass staticcount(0, " ", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y);
  1504. StaticButtonClass staticlevel(0, " ", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y);
  1505. StaticButtonClass staticcredits(0, " ", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y);
  1506. StaticButtonClass staticaiplayers(0, " ", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y);
  1507. //------------------------------------------------------------------------
  1508. // Init the button states
  1509. //------------------------------------------------------------------------
  1510. //........................................................................
  1511. // Name & Color
  1512. //........................................................................
  1513. Session.ColorIdx = Session.PrefColor; // init my preferred color
  1514. strcpy (namebuf, Session.Handle); // set my name
  1515. name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);
  1516. if (Session.ColorIdx == PCOLOR_DIALOG_BLUE) {
  1517. name_edt.Set_Color(&ColorRemaps[PCOLOR_REALLY_BLUE]);
  1518. } else {
  1519. name_edt.Set_Color(&ColorRemaps[Session.ColorIdx]);
  1520. }
  1521. //........................................................................
  1522. // List boxes
  1523. //........................................................................
  1524. playerlist.Set_Tabs(playertabs);
  1525. playerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);
  1526. optionlist.Set_Tabs(optiontabs);
  1527. optionlist.Set_Read_Only(1);
  1528. optionlist.Add_Item(Text_String(TXT_BASES));
  1529. optionlist.Add_Item(Text_String(TXT_ORE_SPREADS));
  1530. optionlist.Add_Item(Text_String(TXT_CRATES));
  1531. optionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));
  1532. optionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));
  1533. optionlist.Check_Item(0, Rule.IsMPBasesOn);
  1534. optionlist.Check_Item(1, Rule.IsMPTiberiumGrow);
  1535. optionlist.Check_Item(2, Rule.IsMPCrates);
  1536. optionlist.Check_Item(3, Rule.IsMPCaptureTheFlag);
  1537. optionlist.Check_Item(4, Rule.IsMPShadowGrow);
  1538. //........................................................................
  1539. // House buttons
  1540. //........................................................................
  1541. #ifdef OLDWAY
  1542. if (Session.House==HOUSE_GOOD) {
  1543. gdibtn.Turn_On();
  1544. } else {
  1545. nodbtn.Turn_On();
  1546. }
  1547. #else
  1548. for (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) {
  1549. // for (HousesType house = HOUSE_FIRST; house <= HOUSE_TURKEY; house++) {
  1550. housebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name()));
  1551. }
  1552. housebtn.Set_Selected_Index(Session.House - HOUSE_USSR);
  1553. housebtn.Set_Read_Only (true);
  1554. #endif
  1555. //........................................................................
  1556. // Option gauges
  1557. //........................................................................
  1558. countgauge.Use_Thumb(0);
  1559. countgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);
  1560. countgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);
  1561. levelgauge.Use_Thumb(0);
  1562. levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);
  1563. levelgauge.Set_Value(BuildLevel - 1);
  1564. creditsgauge.Use_Thumb(0);
  1565. creditsgauge.Set_Maximum(Rule.MPMaxMoney);
  1566. creditsgauge.Set_Value(Session.Options.Credits);
  1567. aiplayersgauge.Use_Thumb(0);
  1568. aiplayersgauge.Set_Maximum(Session.Options.AIPlayers);
  1569. aiplayersgauge.Set_Value(Session.Options.AIPlayers);
  1570. Fancy_Text_Print("", 0, 0, scheme, TBLACK, TPF_TEXT);
  1571. Session.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,
  1572. MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,
  1573. 20, MAX_MESSAGE_LENGTH - 5, d_message2_w);
  1574. Session.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,
  1575. TPF_TEXT, NULL, '_', d_message2_w);
  1576. Session.WWChat = 0;
  1577. lastclick_timer = 0;
  1578. //------------------------------------------------------------------------
  1579. // Clear the list of games, players, and the chat list
  1580. //------------------------------------------------------------------------
  1581. Clear_Vector(&Session.Games);
  1582. Clear_Vector(&Session.Players);
  1583. Clear_Vector(&Session.Chat);
  1584. //------------------------------------------------------------------------
  1585. // Add myself to the Chat vector
  1586. //------------------------------------------------------------------------
  1587. who = new NodeNameType;
  1588. strcpy(who->Name, namebuf);
  1589. who->Chat.LastTime = 0;
  1590. who->Chat.LastChance = 0;
  1591. who->Chat.Color = Session.GPacket.Chat.Color;
  1592. Session.Chat.Add (who);
  1593. //------------------------------------------------------------------------
  1594. // Create the "Lobby" game name on the games list, and create a bogus
  1595. // node for the gamelist, so Games[i] will always match gamelist[i]
  1596. //------------------------------------------------------------------------
  1597. who = new NodeNameType;
  1598. strcpy(who->Name, "");
  1599. who->Game.IsOpen = 0;
  1600. who->Game.LastTime = 0;
  1601. Session.Games.Add (who);
  1602. item = new char [MPLAYER_NAME_MAX];
  1603. strcpy(item, Text_String(TXT_LOBBY));
  1604. gamelist.Add_Item(item);
  1605. gamelist.Set_Selected_Index(0);
  1606. game_index = 0;
  1607. //------------------------------------------------------------------------
  1608. // Send game-name query & chat announcement; also, initialize timers.
  1609. //------------------------------------------------------------------------
  1610. Send_Join_Queries (game_index, joinstate, 1, 0, 1, namebuf, 1);
  1611. Load_Title_Page(true);
  1612. CCPalette.Set(); //GamePalette.Set();
  1613. //------------------------------------------------------------------------
  1614. // Init Mono Output
  1615. //------------------------------------------------------------------------
  1616. #if(SHOW_MONO)
  1617. Ipx.Configure_Debug(-1, sizeof (GlobalHeaderType), sizeof(NetCommandType), GlobalPacketNames, 0, 13);
  1618. Ipx.Mono_Debug_Print(-1,1);
  1619. #endif
  1620. #ifdef WIN32
  1621. //char *fred;
  1622. #endif
  1623. //------------------------------------------------------------------------
  1624. // Processing loop
  1625. //------------------------------------------------------------------------
  1626. while (process) {
  1627. #if(SHOW_MONO)
  1628. Ipx.Mono_Debug_Print(-1,0);
  1629. #endif
  1630. /*
  1631. ** Kludge to make sure we redraw the message input line when it loses focus.
  1632. ** If we dont do this then the cursor doesnt disappear.
  1633. */
  1634. if (messages_have_focus) {
  1635. if (name_edt.Has_Focus()) {
  1636. if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
  1637. messages_have_focus = false;
  1638. }
  1639. } else {
  1640. if (!name_edt.Has_Focus()) {
  1641. messages_have_focus = true;
  1642. }
  1643. }
  1644. /*
  1645. ** Collapse the country list if we are going to redraw the game list
  1646. */
  1647. if (gamelist.Is_To_Redraw() && housebtn.IsDropped) {
  1648. housebtn.Collapse();
  1649. if (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND;
  1650. }
  1651. #ifdef WIN32
  1652. /*
  1653. ** If we have just received input focus again after running in the background then
  1654. ** we need to redraw.
  1655. */
  1656. if (AllSurfaces.SurfacesRestored) {
  1657. AllSurfaces.SurfacesRestored=FALSE;
  1658. display = REDRAW_ALL;
  1659. }
  1660. #endif
  1661. //.....................................................................
  1662. // Refresh display if needed
  1663. //.....................................................................
  1664. if (display) {
  1665. Hide_Mouse();
  1666. //..................................................................
  1667. // Redraw backgound & dialog box
  1668. //..................................................................
  1669. if (display >= REDRAW_BACKGROUND) {
  1670. housebtn.Collapse();
  1671. Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
  1672. //...............................................................
  1673. // Dialog & Field labels
  1674. //...............................................................
  1675. Fancy_Text_Print(TXT_CHANNEL_GAMES, d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  1676. Fancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  1677. //...............................................................
  1678. // For game-browsing, label the name, side, & color buttons:
  1679. //...............................................................
  1680. if (joinstate < JOIN_CONFIRMED) {
  1681. Fancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  1682. #ifdef OLDWAY
  1683. Fancy_Text_Print(TXT_SIDE_COLON,
  1684. d_gdi_x + d_gdi_w,
  1685. d_gdi_y - d_txt6_h,
  1686. scheme, TBLACK,
  1687. TPF_CENTER | TPF_TEXT);
  1688. #else
  1689. Fancy_Text_Print(TXT_SIDE_COLON,
  1690. d_house_x + (d_house_w / 2),
  1691. d_house_y - d_txt6_h,
  1692. scheme, TBLACK,
  1693. TPF_CENTER | TPF_TEXT);
  1694. #endif
  1695. Fancy_Text_Print(TXT_COLOR_COLON,
  1696. d_dialog_x + ((d_dialog_w / 4) * 3),
  1697. d_color_y - d_txt6_h,
  1698. scheme, TBLACK,
  1699. TPF_CENTER | TPF_TEXT);
  1700. } else {
  1701. //...............................................................
  1702. // If we're joined to a game, just print the player's name & side.
  1703. //...............................................................
  1704. #ifdef OLDWAY
  1705. if (Session.House==HOUSE_GOOD) {
  1706. sprintf(txt,Text_String(TXT_S_PLAYING_S),namebuf, Text_String(TXT_ALLIES));
  1707. } else {
  1708. sprintf(txt,Text_String(TXT_S_PLAYING_S),namebuf, Text_String(TXT_SOVIET));
  1709. }
  1710. #else //OLDWAY
  1711. sprintf (txt, Text_String(TXT_S_PLAYING_S), namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));
  1712. #endif //OLDWAY
  1713. Fancy_Text_Print(txt,d_dialog_cx, d_dialog_y + d_margin2 + (1*RESFACTOR),
  1714. (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx],
  1715. TBLACK, TPF_CENTER | TPF_TEXT);
  1716. }
  1717. //...............................................................
  1718. // Rebuild the button list
  1719. //...............................................................
  1720. cancelbtn.Zap();
  1721. gamelist.Zap();
  1722. playerlist.Zap();
  1723. #ifdef OLDWAY
  1724. gdibtn.Zap();
  1725. nodbtn.Zap();
  1726. #else
  1727. housebtn.Zap();
  1728. #endif
  1729. name_edt.Zap();
  1730. joinbtn.Zap();
  1731. newbtn.Zap();
  1732. countgauge.Zap();
  1733. levelgauge.Zap();
  1734. creditsgauge.Zap();
  1735. aiplayersgauge.Zap();
  1736. staticcount.Zap();
  1737. staticlevel.Zap();
  1738. staticcredits.Zap();
  1739. staticaiplayers.Zap();
  1740. commands = &cancelbtn;
  1741. gamelist.Add_Tail(*commands);
  1742. playerlist.Add_Tail(*commands);
  1743. //...............................................................
  1744. // Only add the name edit field, the House, Join & New buttons if
  1745. // we're doing nothing, or we've just been rejected.
  1746. //...............................................................
  1747. if (joinstate < JOIN_CONFIRMED) {
  1748. #ifdef OLDWAY
  1749. gdibtn.Add_Tail(*commands);
  1750. nodbtn.Add_Tail(*commands);
  1751. #else
  1752. housebtn.Add_Tail(*commands);
  1753. #endif
  1754. name_edt.Add_Tail(*commands);
  1755. joinbtn.Add_Tail(*commands);
  1756. newbtn.Add_Tail(*commands);
  1757. } else {
  1758. countgauge.Add_Tail(*commands);
  1759. levelgauge.Add_Tail(*commands);
  1760. creditsgauge.Add_Tail(*commands);
  1761. aiplayersgauge.Add_Tail(*commands);
  1762. staticcount.Add_Tail(*commands);
  1763. staticlevel.Add_Tail(*commands);
  1764. staticcredits.Add_Tail(*commands);
  1765. staticaiplayers.Add_Tail(*commands);
  1766. optionlist.Add_Tail(*commands);
  1767. descrip.Add_Tail(*commands);
  1768. }
  1769. }
  1770. //..................................................................
  1771. // Redraw buttons
  1772. //..................................................................
  1773. if (display >= REDRAW_BUTTONS) {
  1774. aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());
  1775. if (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {
  1776. aiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());
  1777. }
  1778. commands->Draw_All();
  1779. }
  1780. //..................................................................
  1781. // Draw the color boxes
  1782. //..................................................................
  1783. if (display >= REDRAW_COLORS && joinstate < JOIN_CONFIRMED) {
  1784. for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
  1785. LogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,
  1786. cbox_x[i] + 1 + d_color_w - 2 *RESFACTOR, d_color_y + 1 + d_color_h - 2,
  1787. ColorRemaps[i].Box);
  1788. // (i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box);
  1789. if (i == Session.ColorIdx) {
  1790. Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false);
  1791. } else {
  1792. Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false);
  1793. }
  1794. }
  1795. }
  1796. //..................................................................
  1797. // Draw the message system; erase old messages first
  1798. //..................................................................
  1799. if (display >= REDRAW_MESSAGE) {
  1800. if (joinstate==JOIN_CONFIRMED) {
  1801. Draw_Box(d_message2_x, d_message2_y, d_message2_w, d_message2_h, BOXSTYLE_BOX, true);
  1802. } else {
  1803. Draw_Box(d_message1_x, d_message1_y, d_message1_w, d_message1_h, BOXSTYLE_BOX, true);
  1804. }
  1805. Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);
  1806. Session.Messages.Draw();
  1807. }
  1808. //..................................................................
  1809. // Redraw the game options
  1810. //..................................................................
  1811. if (display >= REDRAW_PARMS && parms_received && joinstate >= JOIN_CONFIRMED) {
  1812. //...............................................................
  1813. // Scenario title
  1814. //...............................................................
  1815. // LogicPage->Fill_Rect(d_dialog_x + 16 *RESFACTOR, d_name_y, d_dialog_x + d_dialog_w - 16 *RESFACTOR, d_name_y + d_txt6_h, BLACK);
  1816. p = Text_String(TXT_SCENARIO_COLON);
  1817. if (Session.Options.ScenarioDescription[0]) {
  1818. // EW - Scenario language translation goes here!!!!!!!! VG
  1819. for (int ii = 0; EngMisStr[ii] != NULL; ii++) {
  1820. if (!strcmp(Session.Options.ScenarioDescription, EngMisStr[ii])) {
  1821. #if defined(GERMAN) || defined(FRENCH)
  1822. sprintf(txt, "%s %s", p, EngMisStr[ii+1]);
  1823. #else
  1824. sprintf(txt, "%s %s", p, Session.Options.ScenarioDescription);
  1825. #endif
  1826. break;
  1827. }
  1828. }
  1829. if (EngMisStr[ii] == NULL) {
  1830. sprintf(txt, "%s %s", p, Session.Options.ScenarioDescription);
  1831. }
  1832. descrip.Set_Text(txt);
  1833. // sprintf(txt, "%s %s", p, Session.Options.ScenarioDescription);
  1834. // descrip.Set_Text(txt);
  1835. // Fancy_Text_Print("%s %s", d_dialog_cx, d_name_y, scheme, BLACK, TPF_TEXT | TPF_CENTER, p, Session.Options.ScenarioDescription);
  1836. } else {
  1837. sprintf(txt, "%s %s", p, Text_String(TXT_NOT_FOUND));
  1838. descrip.Set_Text(txt);
  1839. // Fancy_Text_Print("%s %s", d_dialog_cx, d_name_y, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_TEXT | TPF_CENTER, p, Text_String(TXT_NOT_FOUND));
  1840. }
  1841. //...............................................................
  1842. // Unit count, tech level, credits, ai players
  1843. //...............................................................
  1844. // LogicPage->Fill_Rect(d_count_x + d_count_w + 2 *RESFACTOR, d_count_y, d_count_x + d_count_w + 35 *RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK);
  1845. Fancy_Text_Print(TXT_COUNT, d_count_x - 2 *RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
  1846. sprintf(txt,"%d",Session.Options.UnitCount);
  1847. staticcount.Set_Text(txt);
  1848. staticcount.Draw_Me();
  1849. // Fancy_Text_Print(txt, d_count_x + d_count_w + 2 *RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT);
  1850. Fancy_Text_Print(TXT_LEVEL, d_level_x - 2 *RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
  1851. if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
  1852. sprintf(txt,"%d",BuildLevel);
  1853. } else {
  1854. sprintf(txt, "**");
  1855. }
  1856. staticlevel.Set_Text(txt);
  1857. staticlevel.Draw_Me();
  1858. // Fancy_Text_Print(txt, d_level_x + d_level_w + 2 *RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT);
  1859. Fancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2 *RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
  1860. sprintf(txt,"%d",Session.Options.Credits);
  1861. staticcredits.Set_Text(txt);
  1862. staticcredits.Draw_Me();
  1863. // Fancy_Text_Print(txt, d_credits_x + d_credits_w + 2 *RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT);
  1864. Fancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2 * RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
  1865. sprintf(txt,"%d",Session.Options.AIPlayers);
  1866. staticaiplayers.Set_Text(txt);
  1867. staticaiplayers.Draw_Me();
  1868. // Fancy_Text_Print(txt, d_aiplayers_x + d_aiplayers_w + 2 *RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT);
  1869. }
  1870. Show_Mouse();
  1871. display = REDRAW_NONE;
  1872. }
  1873. //.....................................................................
  1874. // Get user input
  1875. //.....................................................................
  1876. input = commands->Input();
  1877. if (input & KN_BUTTON) {
  1878. housebtn.Collapse();
  1879. display = REDRAW_BACKGROUND;
  1880. }
  1881. //.....................................................................
  1882. // Process input
  1883. //.....................................................................
  1884. switch (input) {
  1885. //..................................................................
  1886. // Mouse Click:
  1887. // If we're joined to a game, display an error if the user tries to
  1888. // modify a read-only control.
  1889. // If user clicks on a color button:
  1890. // - If we've joined a game, don't allow a new color selection
  1891. // - otherwise, select that color
  1892. // - Change the color of the user's name & message field to match
  1893. // the newly-selected color.
  1894. //..................................................................
  1895. case KN_LMOUSE:
  1896. if (joinstate > JOIN_NOTHING) {
  1897. if ( (Get_Mouse_X() >= d_count_x &&
  1898. Get_Mouse_X() <= d_count_x + d_count_w &&
  1899. Get_Mouse_Y() >= d_count_y &&
  1900. Get_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h) ||
  1901. (Get_Mouse_X() >= d_options_x &&
  1902. Get_Mouse_X() <= d_options_x + d_options_w &&
  1903. Get_Mouse_Y() >= d_options_y &&
  1904. Get_Mouse_Y() <= d_options_y + d_options_h) ) {
  1905. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200);
  1906. Sound_Effect(VOC_SYS_ERROR);
  1907. display = REDRAW_MESSAGE;
  1908. }
  1909. break;
  1910. }
  1911. if (Keyboard->MouseQX > cbox_x[0] &&
  1912. Keyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&
  1913. Keyboard->MouseQY > d_color_y &&
  1914. Keyboard->MouseQY < (d_color_y + d_color_h)) {
  1915. Session.PrefColor = (PlayerColorType)
  1916. ((Keyboard->MouseQX - cbox_x[0]) / d_color_w);
  1917. Session.ColorIdx = Session.PrefColor;
  1918. if (Session.ColorIdx == PCOLOR_DIALOG_BLUE) {
  1919. name_edt.Set_Color (&ColorRemaps[PCOLOR_REALLY_BLUE]);
  1920. } else {
  1921. name_edt.Set_Color (&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?
  1922. PCOLOR_REALLY_BLUE : Session.ColorIdx]);
  1923. }
  1924. name_edt.Flag_To_Redraw();
  1925. Session.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?
  1926. PCOLOR_REALLY_BLUE : Session.ColorIdx);
  1927. display = REDRAW_COLORS;
  1928. }
  1929. break;
  1930. //..................................................................
  1931. // User clicks on the game list:
  1932. //..................................................................
  1933. case (BUTTON_GAMELIST | KN_BUTTON):
  1934. //...............................................................
  1935. // Handle a double-click
  1936. //...............................................................
  1937. if (lastclick_timer < 30 && gamelist.Current_Index() == lastclick_idx) {
  1938. //............................................................
  1939. // If we're in a game, & the item clicked on is a different
  1940. // game, un-join the game we're in.
  1941. //............................................................
  1942. if ((joinstate==JOIN_CONFIRMED || joinstate==JOIN_WAIT_CONFIRM) &&
  1943. lastclick_idx != game_index) {
  1944. if (gamelist.Current_Index() == 0) {
  1945. goto_lobby = 1;
  1946. } else {
  1947. goto_lobby = 0;
  1948. }
  1949. Unjoin_Game(namebuf, joinstate, &gamelist, &playerlist,
  1950. game_index, goto_lobby, d_message1_x, d_message1_y, d_txt6_h,
  1951. d_send_x, d_send_y, MAX_MESSAGE_LENGTH);
  1952. joinstate = JOIN_NOTHING;
  1953. display = REDRAW_ALL;
  1954. //.........................................................
  1955. // Clear the Player vector & the player list box, since
  1956. // our game_index has changed.
  1957. //.........................................................
  1958. Clear_Listbox (&playerlist);
  1959. Clear_Vector (&Session.Players);
  1960. game_index = gamelist.Current_Index();
  1961. }
  1962. //............................................................
  1963. // If we clicked on another game, join that game.
  1964. //............................................................
  1965. if (joinstate != JOIN_CONFIRMED &&
  1966. joinstate != JOIN_WAIT_CONFIRM && lastclick_idx > 0) {
  1967. gamelist.Set_Selected_Index(lastclick_idx);
  1968. game_index = lastclick_idx;
  1969. name_edt.Clear_Focus();
  1970. name_edt.Flag_To_Redraw();
  1971. strcpy (Session.Handle,namebuf);
  1972. #ifndef OLDWAY
  1973. Session.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);
  1974. #endif
  1975. join_index = gamelist.Current_Index();
  1976. parms_received = 0;
  1977. if (Request_To_Join (namebuf, join_index, Session.House,
  1978. Session.ColorIdx)) {
  1979. joinstate = JOIN_WAIT_CONFIRM;
  1980. } else {
  1981. display = REDRAW_ALL;
  1982. }
  1983. }
  1984. //............................................................
  1985. // Otherwise, we must have joined the lobby
  1986. //............................................................
  1987. if (game_index == 0) {
  1988. Clear_Listbox (&playerlist);
  1989. Session.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,
  1990. MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,
  1991. 20, MAX_MESSAGE_LENGTH - 5, d_message2_w);
  1992. Session.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?
  1993. PCOLOR_REALLY_BLUE : Session.ColorIdx,
  1994. TPF_TEXT, NULL, '_', d_message2_w);
  1995. Session.WWChat = 0;
  1996. display = REDRAW_ALL;
  1997. }
  1998. } else {
  1999. //...............................................................
  2000. // Handle a single-click
  2001. //...............................................................
  2002. //............................................................
  2003. // If no double-click occurred, set the last-clicked index
  2004. // & double-click timer.
  2005. //............................................................
  2006. lastclick_timer = 0;
  2007. lastclick_idx = gamelist.Current_Index();
  2008. //............................................................
  2009. // If we've joined a game, don't allow the selected item to
  2010. // change
  2011. //............................................................
  2012. if (joinstate==JOIN_CONFIRMED || joinstate==JOIN_WAIT_CONFIRM) {
  2013. gamelist.Set_Selected_Index(game_index);
  2014. }
  2015. //............................................................
  2016. // If we're not in a game, and the user clicks on a different
  2017. // entry, clear the player list & send a player query;
  2018. // init the click timer, to detect a double-click of this item.
  2019. //............................................................
  2020. else if (gamelist.Current_Index() != game_index) {
  2021. Clear_Listbox (&playerlist);
  2022. Clear_Vector (&Session.Players);
  2023. game_index = gamelist.Current_Index();
  2024. Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);
  2025. }
  2026. }
  2027. break;
  2028. #ifdef OLDWAY
  2029. //..................................................................
  2030. // House Buttons: set the player's desired House
  2031. //..................................................................
  2032. case (BUTTON_GDI | KN_BUTTON):
  2033. Session.House = HOUSE_GOOD;
  2034. gdibtn.Turn_On();
  2035. nodbtn.Turn_Off();
  2036. break;
  2037. case (BUTTON_NOD | KN_BUTTON):
  2038. Session.House = HOUSE_BAD;
  2039. gdibtn.Turn_Off();
  2040. nodbtn.Turn_On();
  2041. break;
  2042. #else
  2043. #endif
  2044. //..................................................................
  2045. // JOIN: send a join request packet & switch to waiting-for-
  2046. // confirmation mode.
  2047. //..................................................................
  2048. case (BUTTON_JOIN | KN_BUTTON):
  2049. name_edt.Clear_Focus();
  2050. name_edt.Flag_To_Redraw();
  2051. strcpy (Session.Handle,namebuf);
  2052. #ifndef OLDWAY
  2053. Session.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);
  2054. #endif
  2055. join_index = gamelist.Current_Index();
  2056. parms_received = 0;
  2057. if (Request_To_Join (namebuf, join_index, Session.House,
  2058. Session.ColorIdx)) {
  2059. joinstate = JOIN_WAIT_CONFIRM;
  2060. } else {
  2061. display = REDRAW_MESSAGE;
  2062. }
  2063. break;
  2064. //..................................................................
  2065. // ESC / CANCEL: send a SIGN_OFF
  2066. // - If we're part of a game, stay in this dialog; otherwise, exit
  2067. //..................................................................
  2068. case (KN_ESC):
  2069. case (BUTTON_CANCEL | KN_BUTTON):
  2070. if (housebtn.IsDropped) {
  2071. housebtn.Collapse();
  2072. }
  2073. //...............................................................
  2074. // If we're joined to a game, make extra sure the other players in
  2075. // that game know I'm exiting; send my SIGN_OFF as an ack-required
  2076. // packet. Don't send this to myself (index 0).
  2077. //...............................................................
  2078. if (joinstate == JOIN_CONFIRMED) {
  2079. Unjoin_Game(namebuf, joinstate, &gamelist, &playerlist,
  2080. game_index, 1, d_message1_x, d_message1_y, d_txt6_h, d_send_x,
  2081. d_send_y, MAX_MESSAGE_LENGTH);
  2082. joinstate = JOIN_NOTHING;
  2083. display = REDRAW_ALL;
  2084. } else {
  2085. //...............................................................
  2086. // If I'm not joined to a game, send a SIGN_OFF to all players
  2087. // in my Chat vector (but not to myself, index 0)
  2088. //...............................................................
  2089. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  2090. Session.GPacket.Command = NET_SIGN_OFF;
  2091. strcpy(Session.GPacket.Name,namebuf);
  2092. for (i = 1; i < Session.Chat.Count(); i++) {
  2093. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1, &(Session.Chat[i]->Address));
  2094. Ipx.Service();
  2095. }
  2096. //............................................................
  2097. // Now broadcast a SIGN_OFF just to be thorough
  2098. //............................................................
  2099. Ipx.Send_Global_Message (&Session.GPacket,
  2100. sizeof (GlobalPacketType), 0, NULL);
  2101. if (Session.IsBridge) {
  2102. Ipx.Send_Global_Message (&Session.GPacket,
  2103. sizeof(GlobalPacketType), 0, &Session.BridgeNet);
  2104. }
  2105. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  2106. //............................................................
  2107. // exit the dialog
  2108. //............................................................
  2109. process = false;
  2110. rc = -1;
  2111. }
  2112. break;
  2113. //..................................................................
  2114. // NEW: bail out with return code 1
  2115. //..................................................................
  2116. case (BUTTON_NEW | KN_BUTTON):
  2117. //...............................................................
  2118. // Force user to enter a name
  2119. //...............................................................
  2120. if (strlen(namebuf)==0) {
  2121. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NAME_ERROR), PCOLOR_BROWN, TPF_TEXT, 1200);
  2122. Sound_Effect(VOC_SYS_ERROR);
  2123. display = REDRAW_MESSAGE;
  2124. break;
  2125. }
  2126. //...............................................................
  2127. // Ensure name is unique
  2128. //...............................................................
  2129. found = 0;
  2130. for (i = 1; i < Session.Games.Count(); i++) {
  2131. if (!stricmp(Session.Games[i]->Name, namebuf)) {
  2132. found = 1;
  2133. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_GAMENAME_MUSTBE_UNIQUE), PCOLOR_BROWN, TPF_TEXT, 1200);
  2134. Sound_Effect(VOC_SYS_ERROR);
  2135. display = REDRAW_MESSAGE;
  2136. break;
  2137. }
  2138. }
  2139. if (found) {
  2140. break;
  2141. }
  2142. //...............................................................
  2143. // Save player & game name
  2144. //...............................................................
  2145. strcpy(Session.Handle,namebuf);
  2146. strcpy(Session.GameName,namebuf);
  2147. #ifndef OLDWAY
  2148. Session.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR);
  2149. #endif
  2150. name_edt.Clear_Focus();
  2151. name_edt.Flag_To_Redraw();
  2152. rc = 1;
  2153. process = false;
  2154. break;
  2155. //..................................................................
  2156. // Default: manage the inter-player messages
  2157. //..................................................................
  2158. default:
  2159. if (Session.Messages.Manage()) {
  2160. display = REDRAW_MESSAGE;
  2161. }
  2162. //...............................................................
  2163. // Service keyboard input for any message being edited.
  2164. //...............................................................
  2165. i = Session.Messages.Input(input);
  2166. //...............................................................
  2167. // If 'Input' returned 1, it means refresh the message display.
  2168. // (We have to redraw the edit line, to erase the cursor.)
  2169. //...............................................................
  2170. if (i==1) {
  2171. Hide_Mouse();
  2172. Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h,
  2173. BOXSTYLE_BOX, true);
  2174. Session.Messages.Draw();
  2175. Show_Mouse();
  2176. } else if (i==2) {
  2177. //...............................................................
  2178. // If 'Input' returned 2, it means redraw the message display.
  2179. // Rather than setting 'display', which would redraw all msgs,
  2180. // we only need to erase & redraw the edit box here.
  2181. //...............................................................
  2182. Hide_Mouse();
  2183. Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h,
  2184. BOXSTYLE_BOX, true);
  2185. Session.Messages.Draw();
  2186. Show_Mouse();
  2187. } else if (i==3 || i==4) {
  2188. //...............................................................
  2189. // If 'Input' returned 3, it means send the current message.
  2190. //...............................................................
  2191. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  2192. Session.GPacket.Command = NET_MESSAGE;
  2193. strcpy (Session.GPacket.Name, namebuf);
  2194. if (i==3) {
  2195. strcpy (Session.GPacket.Message.Buf,
  2196. Session.Messages.Get_Edit_Buf());
  2197. } else {
  2198. strcpy (Session.GPacket.Message.Buf,
  2199. Session.Messages.Get_Overflow_Buf());
  2200. Session.Messages.Clear_Overflow_Buf();
  2201. }
  2202. Session.GPacket.Message.Color = Session.ColorIdx;
  2203. Session.GPacket.Message.NameCRC =
  2204. Compute_Name_CRC(Session.GameName);
  2205. //............................................................
  2206. // If we're joined in a game, send the message to every player
  2207. // in our player list. Skip the local system (index 0).
  2208. //............................................................
  2209. if (joinstate == JOIN_CONFIRMED) {
  2210. for (i = 1; i < Session.Players.Count(); i++) {
  2211. Ipx.Send_Global_Message (&Session.GPacket,
  2212. sizeof(GlobalPacketType),
  2213. 1, &(Session.Players[i]->Address));
  2214. Ipx.Service();
  2215. }
  2216. } else {
  2217. //............................................................
  2218. // Otherwise, send the message to all players in our chat list.
  2219. //............................................................
  2220. for (i = 1; i < Session.Chat.Count(); i++) {
  2221. Ipx.Send_Global_Message (&Session.GPacket,
  2222. sizeof(GlobalPacketType),
  2223. 1, &(Session.Chat[i]->Address));
  2224. Ipx.Service();
  2225. }
  2226. if (Obfuscate(Session.GPacket.Message.Buf) == 0x72A47EF6) {
  2227. Session.WWChat = 1;
  2228. Clear_Listbox (&playerlist);
  2229. Start_WWChat(&playerlist);
  2230. }
  2231. }
  2232. //............................................................
  2233. // Add the message to our own list, since we're not in the
  2234. // player list on this dialog.
  2235. //............................................................
  2236. Session.Messages.Add_Message (Session.GPacket.Name,
  2237. (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?
  2238. PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,
  2239. Session.GPacket.Message.Buf,
  2240. (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,
  2241. TPF_TEXT, -1);
  2242. Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,
  2243. TPF_TEXT, NULL, '_', d_message2_w);
  2244. display = REDRAW_MESSAGE;
  2245. }
  2246. #ifdef OBSOLETE
  2247. //
  2248. // This is for the old drop-down list of houses, not used any more.
  2249. //
  2250. if (housebtn.IsDropped) {
  2251. isdropped = 1;
  2252. } else if (isdropped) {
  2253. display = REDRAW_ALL;
  2254. }
  2255. #endif
  2256. break;
  2257. }
  2258. //.....................................................................
  2259. // Resend our query packets
  2260. //.....................................................................
  2261. Send_Join_Queries(game_index, joinstate, 0, 0, 0, namebuf);
  2262. //.....................................................................
  2263. // Process incoming packets
  2264. //.....................................................................
  2265. event = Get_Join_Responses(&joinstate, &gamelist, &playerlist,
  2266. join_index, namebuf, &why);
  2267. //.....................................................................
  2268. // If we've changed state, redraw everything; if we're starting the game,
  2269. // break out of the loop. If we've just joined, send out a player query
  2270. // so I'll get added to the list instantly.
  2271. //.....................................................................
  2272. if (event == EV_STATE_CHANGE) {
  2273. display = REDRAW_ALL;
  2274. if (joinstate==JOIN_GAME_START || joinstate == JOIN_GAME_START_LOAD) {
  2275. if (joinstate==JOIN_GAME_START_LOAD) {
  2276. load_game = 1;
  2277. }
  2278. /*
  2279. ** Special new kludge for counterstrike.
  2280. **
  2281. ** Find local scenario will fail to match a counterstrike mission
  2282. ** unless the CS CD is in the drive. So....
  2283. **
  2284. ** If Counterstrike is installed and this is an official map and
  2285. ** the file name matches a counterstrike map then tell the host
  2286. ** that I have the scenario so he can continue while we make
  2287. ** sure the local user has the Counterstrike CD in the drive.
  2288. **
  2289. */
  2290. // This is duplicated for Aftermath scenarios. ajw
  2291. bool ready_packet_was_sent = false;
  2292. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  2293. if (Session.ScenarioIsOfficial &&
  2294. ( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||
  2295. (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) {
  2296. #else
  2297. if ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) {
  2298. #endif
  2299. CCFileClass check_file ( Session.ScenarioFileName );
  2300. if ( !check_file.Is_Available() ) {
  2301. int current_drive = CCFileClass::Get_CD_Drive();
  2302. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  2303. int index = Get_CD_Index(current_drive, 1*60);
  2304. bool needcd = false;
  2305. if (Is_Mission_Counterstrike(Session.ScenarioFileName)) {
  2306. if (index != 2 && index != 3) {
  2307. RequiredCD = 2;
  2308. needcd = true;
  2309. }
  2310. }
  2311. if (Is_Mission_Aftermath(Session.ScenarioFileName)) {
  2312. if (index != 3) {
  2313. RequiredCD = 3;
  2314. needcd = true;
  2315. }
  2316. }
  2317. if (needcd) {
  2318. #else
  2319. if ( Get_CD_Index(current_drive, 1*60) != 2 ){
  2320. RequiredCD = 2;
  2321. #endif
  2322. /*
  2323. ** We should have the scenario but the wrong disk is in.
  2324. ** Tell the host that I am ready to go anyway.
  2325. */
  2326. memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));
  2327. Session.GPacket.Command = NET_READY_TO_GO;
  2328. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  2329. 1, &Session.HostAddress);
  2330. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);
  2331. ready_packet_was_sent = true;
  2332. if (!Force_CD_Available (RequiredCD)){
  2333. Emergency_Exit(EXIT_FAILURE);
  2334. }
  2335. /*
  2336. ** Update the internal list of scenarios to include the counterstrike
  2337. ** list.
  2338. */
  2339. Session.Read_Scenario_Descriptions();
  2340. }
  2341. }
  2342. }
  2343. /*
  2344. ** If the scenario that the host wants to play doesn't exist locally then we
  2345. ** need to request that it is sent. If we can identify the scenario locally then
  2346. ** we need to fix up the file name so we load the right one.
  2347. */
  2348. Ipx.Set_Timing (25, (unsigned long) -1, 1000);
  2349. if (Find_Local_Scenario (Session.Options.ScenarioDescription,
  2350. Session.ScenarioFileName,
  2351. Session.ScenarioFileLength,
  2352. Session.ScenarioDigest,
  2353. Session.ScenarioIsOfficial)) {
  2354. Session.Options.ScenarioIndex = 1; //We dont care what it
  2355. //is as long as it isnt -1
  2356. /*
  2357. ** We have the scenario. Tell the host that I am ready to go.
  2358. */
  2359. if ( !ready_packet_was_sent ){
  2360. memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));
  2361. Session.GPacket.Command = NET_READY_TO_GO;
  2362. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  2363. 1, &Session.HostAddress);
  2364. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);
  2365. }
  2366. } else {
  2367. #ifndef FIXIT_VERSION_3 // Removed restriction on downloading official maps.
  2368. /*
  2369. ** Oh dear. Thats a scenario I don't have. Request that the host sends the
  2370. ** scenario to me provided it's not an official scenario.
  2371. **
  2372. ** If the file is received OK then we will get a true return value and the
  2373. ** actual file name to load will be in Session.ScenarioFileName
  2374. */
  2375. if (Session.ScenarioIsOfficial) {
  2376. Session.Options.ScenarioIndex = -1;
  2377. } else {
  2378. #endif
  2379. Session.Options.ScenarioIndex = 1; //We dont care what it
  2380. //is as long as it isnt -1
  2381. #ifdef FIXIT_VERSION_3
  2382. if( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )
  2383. break;
  2384. #endif
  2385. if (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 1)) {
  2386. break;
  2387. } else {
  2388. /*
  2389. ** Make sure we dont time-out because of the download
  2390. */
  2391. }
  2392. #ifndef FIXIT_VERSION_3
  2393. }
  2394. #endif
  2395. }
  2396. Ipx.Set_Timing (30, (unsigned long) -1, 600);
  2397. strcpy (Scen.ScenarioName, Session.ScenarioFileName);
  2398. rc = 0;
  2399. process = false;
  2400. } else if (joinstate==JOIN_CONFIRMED) {
  2401. //..................................................................
  2402. // If we're newly-confirmed, add myself to the Players list, and
  2403. // immediately send out a player query
  2404. //..................................................................
  2405. //...............................................................
  2406. // Clear the player list, then add myself to the list.
  2407. //...............................................................
  2408. Clear_Listbox(&playerlist);
  2409. Clear_Vector (&Session.Players);
  2410. item = new char [MPLAYER_NAME_MAX + 64];
  2411. #ifdef OLDWAY
  2412. if (Session.House==HOUSE_GOOD) {
  2413. sprintf(item,"%s\t%s",namebuf, Text_String(TXT_ALLIES));
  2414. } else {
  2415. sprintf(item,"%s\t%s",namebuf, Text_String(TXT_SOVIET));
  2416. }
  2417. #else //OLDWAY
  2418. sprintf (item, "%s\t%s", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));
  2419. #endif //OLDWAY
  2420. playerlist.Add_Item(item,
  2421. (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);
  2422. who = new NodeNameType;
  2423. strcpy(who->Name, namebuf);
  2424. who->Player.House = Session.House;
  2425. who->Player.Color = Session.ColorIdx;
  2426. Session.Players.Add (who);
  2427. Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);
  2428. //...............................................................
  2429. // Re-init the message system to its new smaller size
  2430. //...............................................................
  2431. Session.Messages.Init (d_message2_x + 1 *RESFACTOR, d_message2_y + 1 *RESFACTOR, 8,
  2432. MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,
  2433. 20, MAX_MESSAGE_LENGTH - 5, d_message2_w);
  2434. Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?
  2435. PCOLOR_REALLY_BLUE : Session.ColorIdx,
  2436. TPF_TEXT, NULL, '_', d_message2_w);
  2437. } else if (joinstate==JOIN_REJECTED) {
  2438. //..................................................................
  2439. // If we've been rejected, clear any messages we may have been
  2440. // typing, add a message stating why we were rejected, and send a
  2441. // chat announcement.
  2442. //..................................................................
  2443. Session.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14,
  2444. MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1,
  2445. 20, MAX_MESSAGE_LENGTH - 5, d_message2_w);
  2446. Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?
  2447. PCOLOR_REALLY_BLUE : Session.ColorIdx,
  2448. TPF_TEXT, NULL, '_', d_message2_w);
  2449. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_REQUEST_DENIED), PCOLOR_BROWN, TPF_TEXT, 1200);
  2450. Sound_Effect(VOC_SYS_ERROR);
  2451. item = NULL;
  2452. if (why==REJECT_DUPLICATE_NAME) {
  2453. item = (char *)Text_String(TXT_NAME_MUSTBE_UNIQUE);
  2454. }
  2455. else if (why==REJECT_GAME_FULL) {
  2456. item = (char *)Text_String(TXT_GAME_FULL);
  2457. }
  2458. else if (why==REJECT_VERSION_TOO_OLD) {
  2459. item = (char *)Text_String(TXT_YOURGAME_OUTDATED);
  2460. }
  2461. else if (why==REJECT_VERSION_TOO_NEW) {
  2462. item = (char *)Text_String(TXT_DESTGAME_OUTDATED);
  2463. }
  2464. else if (why==REJECT_MISMATCH) {
  2465. item = (char *)Text_String(TXT_MISMATCH);
  2466. }
  2467. else if (why==REJECT_DISBANDED) {
  2468. item = (char *)Text_String(TXT_GAME_CANCELLED);
  2469. }
  2470. if (item) {
  2471. Session.Messages.Add_Message(NULL, 0, item, PCOLOR_BROWN, TPF_TEXT, 1200);
  2472. }
  2473. Send_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);
  2474. display = REDRAW_ALL;
  2475. }
  2476. } else if (event == EV_GAME_OPTIONS) {
  2477. //.....................................................................
  2478. // If the game options have changed, print them.
  2479. //.....................................................................
  2480. countgauge.Set_Maximum(
  2481. SessionClass::CountMax[Session.Options.Bases] -
  2482. SessionClass::CountMin[Session.Options.Bases]);
  2483. countgauge.Set_Value(Session.Options.UnitCount -
  2484. SessionClass::CountMin[Session.Options.Bases]);
  2485. levelgauge.Set_Value(BuildLevel - 1);
  2486. creditsgauge.Set_Value(Session.Options.Credits);
  2487. if (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {
  2488. aiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());
  2489. } else {
  2490. aiplayersgauge.Set_Value(Session.Options.AIPlayers);
  2491. }
  2492. optionlist.Check_Item(0,Session.Options.Bases);
  2493. optionlist.Check_Item(1,Session.Options.Tiberium);
  2494. optionlist.Check_Item(2,Session.Options.Goodies);
  2495. optionlist.Check_Item(3,Special.IsCaptureTheFlag);
  2496. optionlist.Check_Item(4,Special.IsShadowGrow);
  2497. optionlist.Flag_To_Redraw();
  2498. Sound_Effect(VOC_OPTIONS_CHANGED);
  2499. parms_received = 1;
  2500. display = REDRAW_PARMS;
  2501. } else if (event == EV_MESSAGE) {
  2502. //.....................................................................
  2503. // Draw an incoming message
  2504. //.....................................................................
  2505. display = REDRAW_MESSAGE;
  2506. Sound_Effect(VOC_INCOMING_MESSAGE);
  2507. } else if (event == EV_NEW_GAME) {
  2508. //.....................................................................
  2509. // If a new game has formed, or an existing game has changed state
  2510. // (from open to closed or closed to open), redraw the message system.
  2511. //.....................................................................
  2512. display = REDRAW_MESSAGE;
  2513. } else if (event == EV_NEW_PLAYER || event == EV_PLAYER_SIGNOFF) {
  2514. aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());
  2515. if (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) {
  2516. aiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count());
  2517. }
  2518. } else if (event == EV_GAME_SIGNOFF) {
  2519. //.....................................................................
  2520. // EV_GAME_SIGNOFF:
  2521. // A game before the one I've selected is gone, so we have a new index
  2522. // now. 'game_index' must be kept set to the currently-selected list
  2523. // item, so we send out queries for the currently-selected game. It's
  2524. // therefore imperative that we detect any changes to the game list.
  2525. // If we're joined in a game, we must decrement our game_index to keep
  2526. // it aligned with the game we're joined to.
  2527. //.....................................................................
  2528. if (joinstate==JOIN_CONFIRMED) {
  2529. game_index--;
  2530. join_index--;
  2531. gamelist.Set_Selected_Index(join_index);
  2532. } else {
  2533. gamelist.Flag_To_Redraw();
  2534. Clear_Listbox(&playerlist);
  2535. Clear_Vector (&Session.Players);
  2536. game_index = gamelist.Current_Index();
  2537. Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);
  2538. }
  2539. }
  2540. //.....................................................................
  2541. // Service the Ipx connections
  2542. //.....................................................................
  2543. Ipx.Service();
  2544. if (process) {
  2545. //.....................................................................
  2546. // Clean out the Game List; if an old entry is found:
  2547. // - Remove it
  2548. // - Clear the player list
  2549. // - Send queries for the new selected game, if there is one
  2550. //.....................................................................
  2551. for (i = 1; i < Session.Games.Count(); i++) {
  2552. if (TickCount - Session.Games[i]->Game.LastTime > 400) {
  2553. delete Session.Games[i];
  2554. Session.Games.Delete(Session.Games[i]);
  2555. item = (char *)(gamelist.Get_Item (i));
  2556. gamelist.Remove_Item (item);
  2557. delete [] item;
  2558. gamelist.Flag_To_Redraw();
  2559. if (i <= game_index) {
  2560. if (joinstate==JOIN_CONFIRMED) {
  2561. game_index--;
  2562. join_index--;
  2563. gamelist.Set_Selected_Index(join_index);
  2564. } else {
  2565. gamelist.Flag_To_Redraw();
  2566. Clear_Listbox(&playerlist);
  2567. Clear_Vector (&Session.Players);
  2568. game_index = gamelist.Current_Index();
  2569. Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);
  2570. }
  2571. }
  2572. }
  2573. }
  2574. //.....................................................................
  2575. // If I've changed my name or color, make sure those changes go into
  2576. // the Chat vector.
  2577. //.....................................................................
  2578. strcpy(Session.Chat[0]->Name, namebuf);
  2579. Session.Chat[0]->Chat.Color = Session.ColorIdx;
  2580. if (Session.Chat[0]->Chat.Color == PCOLOR_DIALOG_BLUE) {
  2581. Session.Chat[0]->Chat.Color = PCOLOR_REALLY_BLUE;
  2582. }
  2583. //.....................................................................
  2584. // Clean out the chat vector. If we find a node that we haven't heard
  2585. // from in 6 seconds, delete that node.
  2586. // If we haven't heard from a node in 5 seconds, send him a request
  2587. // for a chat announcement; he then has 1 second to reply.
  2588. //.....................................................................
  2589. for (i = 1; i < Session.Chat.Count(); i++) {
  2590. if (TickCount - Session.Chat[i]->Chat.LastTime > 360) {
  2591. delete Session.Chat[i];
  2592. Session.Chat.Delete(Session.Chat[i]);
  2593. } else if (TickCount - Session.Chat[i]->Chat.LastTime > 300 &&
  2594. Session.Chat[i]->Chat.LastChance == 0) {
  2595. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  2596. Session.GPacket.Name[0] = 0;
  2597. Session.GPacket.Command = NET_CHAT_REQUEST;
  2598. Ipx.Send_Global_Message (&Session.GPacket,
  2599. sizeof(GlobalPacketType), 0, &(Session.Chat[i]->Address));
  2600. Ipx.Service();
  2601. Session.Chat[i]->Chat.LastChance = 1;
  2602. }
  2603. }
  2604. //.....................................................................
  2605. // Manage the Lobby list:
  2606. // If the user has selected the 1st Game ("Lobby"), the names of all
  2607. // users in the Chat area show up in the Players list box.
  2608. // Users can be changing their names and their colors at any time, so
  2609. // we scan the Chat list each time to see if anything's changed; if
  2610. // so, we redraw the player list.
  2611. // (If WWChat is on, the Chat list is ignored, and the playerlist
  2612. // contains custom names.)
  2613. //.....................................................................
  2614. if (game_index == 0) {
  2615. if (!Session.WWChat) {
  2616. while (Session.Chat.Count() > playerlist.Count()) {
  2617. item = new char [MPLAYER_NAME_MAX];
  2618. item[0] = 0;
  2619. playerlist.Add_Item(item);
  2620. playerlist.Flag_To_Redraw();
  2621. }
  2622. while (playerlist.Count() > Session.Chat.Count()) {
  2623. item = (char *)playerlist.Get_Item(0);
  2624. playerlist.Remove_Item(item);
  2625. delete [] item;
  2626. playerlist.Flag_To_Redraw();
  2627. }
  2628. for (i = 0; i < Session.Chat.Count(); i++) {
  2629. if (stricmp(Session.Chat[i]->Name,playerlist.Get_Item(i)) ||
  2630. &ColorRemaps[ (Session.Chat[i]->Chat.Color == PCOLOR_DIALOG_BLUE) ?
  2631. PCOLOR_REALLY_BLUE : Session.Chat[i]->Chat.Color] !=
  2632. playerlist.Colors[i]) {
  2633. playerlist.Colors[i] =
  2634. &ColorRemaps[Session.Chat[i]->Chat.Color];
  2635. if (playerlist.Colors[i] == &ColorRemaps[PCOLOR_DIALOG_BLUE]) {
  2636. playerlist.Colors[i] = &ColorRemaps[PCOLOR_REALLY_BLUE];
  2637. }
  2638. strcpy((char *)playerlist.Get_Item(i), Session.Chat[i]->Name);
  2639. playerlist.Flag_To_Redraw();
  2640. }
  2641. }
  2642. } else {
  2643. if (stricmp(Session.Chat[0]->Name,playerlist.Get_Item(0)) ||
  2644. &ColorRemaps[Session.Chat[0]->Chat.Color] !=
  2645. playerlist.Colors[0]) {
  2646. playerlist.Colors[0] = &ColorRemaps[Session.Chat[0]->Chat.Color];
  2647. strcpy((char *)playerlist.Get_Item(0), Session.Chat[0]->Name);
  2648. playerlist.Flag_To_Redraw();
  2649. }
  2650. if (Update_WWChat()) {
  2651. display = REDRAW_MESSAGE;
  2652. }
  2653. }
  2654. }
  2655. }
  2656. //.....................................................................
  2657. // Service the sounds & score; GameActive must be false at this point,
  2658. // so Call_Back() doesn't intercept global messages from me!
  2659. //.....................................................................
  2660. Call_Back();
  2661. } // end of while
  2662. //------------------------------------------------------------------------
  2663. // Establish connections with all other players.
  2664. //------------------------------------------------------------------------
  2665. if (rc == 0) {
  2666. //.....................................................................
  2667. // If the other guys are playing a scenario I don't have (sniff), I can't
  2668. // play. Try to bail gracefully.
  2669. //.....................................................................
  2670. if (Session.Options.ScenarioIndex==-1) {
  2671. WWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
  2672. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  2673. Session.GPacket.Command = NET_SIGN_OFF;
  2674. strcpy (Session.GPacket.Name, namebuf);
  2675. //..................................................................
  2676. // Don't send myself the message.
  2677. //..................................................................
  2678. for (i = 1; i < Session.Players.Count(); i++) {
  2679. Ipx.Send_Global_Message (&Session.GPacket,
  2680. sizeof(GlobalPacketType), 1,
  2681. &(Session.Players[i]->Address));
  2682. Ipx.Service();
  2683. }
  2684. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  2685. 0, NULL);
  2686. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  2687. 0, NULL);
  2688. if (Session.IsBridge) {
  2689. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),
  2690. 0, &Session.BridgeNet);
  2691. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),
  2692. 0, &Session.BridgeNet);
  2693. }
  2694. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  2695. rc = -1;
  2696. } else {
  2697. //---------------------------------------------------------------------
  2698. // Prepare to load the scenario.
  2699. //---------------------------------------------------------------------
  2700. //..................................................................
  2701. // Set the number of players in this game, and the scenario number.
  2702. //..................................................................
  2703. Session.NumPlayers = Session.Players.Count();
  2704. }
  2705. //.....................................................................
  2706. // Wait a while, polling the IPX service routines, to give our ACK
  2707. // a chance to get to the other system. If he doesn't get our ACK,
  2708. // he'll be waiting the whole time we load MIX files.
  2709. //.....................................................................
  2710. i = max(Ipx.Global_Response_Time() * 2, 60);
  2711. starttime = TickCount;
  2712. while (TickCount - starttime < i) {
  2713. Ipx.Service();
  2714. }
  2715. }
  2716. //------------------------------------------------------------------------
  2717. // Init network timing values, using previous response times as a measure
  2718. // of what our retry delta & timeout should be.
  2719. //------------------------------------------------------------------------
  2720. // Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
  2721. // Ipx.Global_Response_Time() * 4);
  2722. Ipx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));
  2723. //------------------------------------------------------------------------
  2724. // Clear all lists, but NOT the Games & Players vectors.
  2725. //------------------------------------------------------------------------
  2726. Clear_Listbox(&gamelist);
  2727. Clear_Listbox(&playerlist);
  2728. //------------------------------------------------------------------------
  2729. // Remove the chat edit box
  2730. //------------------------------------------------------------------------
  2731. Session.Messages.Remove_Edit();
  2732. //------------------------------------------------------------------------
  2733. // Restore screen
  2734. //------------------------------------------------------------------------
  2735. Hide_Mouse();
  2736. Load_Title_Page(true);
  2737. Show_Mouse();
  2738. //------------------------------------------------------------------------
  2739. // Load a game if the game owner told us to
  2740. //------------------------------------------------------------------------
  2741. if (load_game) {
  2742. if (!Load_Game (-1)) {
  2743. WWMessageBox().Process (TXT_ERROR_LOADING_GAME);
  2744. rc = -1;
  2745. }
  2746. Frame++;
  2747. }
  2748. //------------------------------------------------------------------------
  2749. // Clear the Players & Games vectors if we're not joined to a game.
  2750. // Clear the Chat vector regardless.
  2751. //------------------------------------------------------------------------
  2752. if (rc != 0) {
  2753. Clear_Vector(&Session.Games);
  2754. Clear_Vector(&Session.Players);
  2755. }
  2756. Clear_Vector(&Session.Chat);
  2757. return(rc);
  2758. } /* end of Net_Join_Dialog */
  2759. /***************************************************************************
  2760. * Request_To_Join -- Sends a JOIN request packet to game owner *
  2761. * *
  2762. * Regardless of the return code, the Join Dialog will need to be redrawn *
  2763. * after calling this routine. *
  2764. * *
  2765. * INPUT: *
  2766. * playername player's name *
  2767. * join_index index of game we're joining *
  2768. * house requested house *
  2769. * color requested color *
  2770. * *
  2771. * OUTPUT: *
  2772. * 1 = Packet sent, 0 = wasn't *
  2773. * *
  2774. * WARNINGS: *
  2775. * none. *
  2776. * *
  2777. * HISTORY: *
  2778. *=========================================================================*/
  2779. static int Request_To_Join (char *playername, int join_index,
  2780. HousesType house, PlayerColorType color)
  2781. {
  2782. //------------------------------------------------------------------------
  2783. // Validate join_index
  2784. //------------------------------------------------------------------------
  2785. if (join_index < 1) {
  2786. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_MUST_SELECT_GAME), PCOLOR_BROWN, TPF_TEXT, 1200);
  2787. Sound_Effect(VOC_SYS_ERROR);
  2788. return(false);
  2789. }
  2790. if ( (Session.Games.Count()<=1) || join_index > Session.Games.Count()) {
  2791. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NOTHING_TO_JOIN), PCOLOR_BROWN, TPF_TEXT, 1200);
  2792. Sound_Effect(VOC_SYS_ERROR);
  2793. return(false);
  2794. }
  2795. //------------------------------------------------------------------------
  2796. // Force user to enter a name
  2797. //------------------------------------------------------------------------
  2798. if (strlen(playername)==0) {
  2799. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NAME_ERROR), PCOLOR_BROWN, TPF_TEXT, 1200);
  2800. Sound_Effect(VOC_SYS_ERROR);
  2801. return(false);
  2802. }
  2803. //------------------------------------------------------------------------
  2804. // The game must be open
  2805. //------------------------------------------------------------------------
  2806. if (!Session.Games[join_index]->Game.IsOpen) {
  2807. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_GAME_IS_CLOSED), PCOLOR_BROWN, TPF_TEXT, 1200);
  2808. Sound_Effect(VOC_SYS_ERROR);
  2809. return (false);
  2810. }
  2811. //------------------------------------------------------------------------
  2812. // Send packet to game's owner
  2813. //------------------------------------------------------------------------
  2814. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  2815. Session.GPacket.Command = NET_QUERY_JOIN;
  2816. strcpy (Session.GPacket.Name, playername);
  2817. Session.GPacket.PlayerInfo.House = house;
  2818. Session.GPacket.PlayerInfo.Color = color;
  2819. #ifdef FIXIT_VERSION_3
  2820. // Guest sends host his version.
  2821. // Added to the transmitted _min_ version number is a bit indicating presence of Aftermath expansion.
  2822. if( Is_Aftermath_Installed() )
  2823. {
  2824. // debugprint( "Guest tells host 'I have Aftermath'\n" );
  2825. Session.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version() | 0x80000000;
  2826. }
  2827. else
  2828. {
  2829. // debugprint( "Guest tells host 'I don't have Aftermath'\n" );
  2830. Session.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version();
  2831. }
  2832. #else
  2833. Session.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version();
  2834. #endif
  2835. Session.GPacket.PlayerInfo.MaxVersion = VerNum.Max_Version();
  2836. Session.GPacket.PlayerInfo.CheatCheck = RuleINI.Get_Unique_ID();
  2837. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,
  2838. &(Session.Games[join_index]->Address));
  2839. return(true);
  2840. } /* end of Request_To_Join */
  2841. /***************************************************************************
  2842. * Unjoin_Game -- Cancels joining a game *
  2843. * *
  2844. * INPUT: *
  2845. * namebuf current player name *
  2846. * joinstate current join state *
  2847. * gamelist ListBox of game names *
  2848. * playerlist ListBox of player names *
  2849. * game_index index in 'gamelist' of game we're leaving *
  2850. * goto_lobby true = we're going to the lobby *
  2851. * msg_x message system x-coord *
  2852. * msg_y message system y-coord *
  2853. * msg_h message system char height *
  2854. * send_x message system send x-coord *
  2855. * send_y message system send y-coord *
  2856. * msg_len message system max msg length *
  2857. * *
  2858. * OUTPUT: *
  2859. * *
  2860. * WARNINGS: *
  2861. * *
  2862. * HISTORY: *
  2863. * 12/12/1995 BRR : Created. *
  2864. *=========================================================================*/
  2865. static void Unjoin_Game(char *namebuf,JoinStateType joinstate,
  2866. ListClass *gamelist, ColorListClass *playerlist, int game_index,
  2867. int goto_lobby, int msg_x, int msg_y, int msg_h, int send_x, int send_y,
  2868. int msg_len)
  2869. {
  2870. int i;
  2871. char *item;
  2872. //------------------------------------------------------------------------
  2873. // Fill in a SIGN_OFF packet
  2874. //------------------------------------------------------------------------
  2875. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  2876. Session.GPacket.Command = NET_SIGN_OFF;
  2877. strcpy(Session.GPacket.Name,namebuf);
  2878. //------------------------------------------------------------------------
  2879. // If we're joined to a game, make extra sure the other players in
  2880. // that game know I'm exiting; send my SIGN_OFF as an ack-required
  2881. // packet. Don't send this to myself (index 0).
  2882. //------------------------------------------------------------------------
  2883. for (i = 1; i < Session.Players.Count(); i++) {
  2884. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,
  2885. &(Session.Players[i]->Address));
  2886. Ipx.Service();
  2887. }
  2888. if (joinstate == JOIN_WAIT_CONFIRM || joinstate == JOIN_CONFIRMED) {
  2889. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1,
  2890. &(Session.Games[game_index]->Address));
  2891. }
  2892. //------------------------------------------------------------------------
  2893. // Re-init the message system to its new larger size
  2894. //------------------------------------------------------------------------
  2895. Session.Messages.Init (msg_x + 1, msg_y + 1, 14,
  2896. msg_len, msg_h, send_x + 1, send_y + 1, 1,
  2897. 20, msg_len - 5);
  2898. Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?
  2899. PCOLOR_REALLY_BLUE : Session.ColorIdx,
  2900. TPF_TEXT, NULL, '_');
  2901. //------------------------------------------------------------------------
  2902. // Remove myself from the player list, and reset my game name
  2903. //------------------------------------------------------------------------
  2904. if (playerlist->Count()) {
  2905. item = (char *)(playerlist->Get_Item(0));
  2906. playerlist->Remove_Item(item);
  2907. delete [] item;
  2908. playerlist->Flag_To_Redraw();
  2909. }
  2910. if (Session.Players.Count() > 0) {
  2911. delete Session.Players[0];
  2912. Session.Players.Delete(Session.Players[0]);
  2913. }
  2914. Session.GameName[0] = 0;
  2915. //------------------------------------------------------------------------
  2916. // Highlight "Lobby" on the Game list, Announce I'm ready to chat
  2917. //------------------------------------------------------------------------
  2918. if (goto_lobby) {
  2919. gamelist->Set_Selected_Index(0);
  2920. Send_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);
  2921. }
  2922. } // end of Unjoin_Game
  2923. /***********************************************************************************************
  2924. * Send_Join_Queries -- sends queries for the Join Dialog *
  2925. * *
  2926. * This routine [re]sends the queries related to the Join Dialog: *
  2927. * - NET_QUERY_GAME *
  2928. * - NET_QUERY_PLAYER for the game currently selected (if there is one) *
  2929. * *
  2930. * The queries are "staggered" in time so they aren't all sent at once; otherwise, we'd *
  2931. * be inundated with reply packets & we'd miss some (even though the replies will require *
  2932. * ACK's). *
  2933. * *
  2934. * INPUT: *
  2935. * curgame index of currently-selected game; -1 = none *
  2936. * joinstate our current joinstate *
  2937. * gamenow if 1, will immediately send the game query *
  2938. * playernow if 1, will immediately send the player query for currently-selected game *
  2939. * chatnow if 1, will immediately send the chat announcement *
  2940. * myname user's name *
  2941. * init initialize the timers *
  2942. * *
  2943. * OUTPUT: *
  2944. * none. *
  2945. * *
  2946. * WARNINGS: *
  2947. * none. *
  2948. * *
  2949. * HISTORY: *
  2950. * 02/14/1995 BR : Created. *
  2951. * 04/15/1995 BRR : Created. *
  2952. *=============================================================================================*/
  2953. static void Send_Join_Queries(int curgame, JoinStateType joinstate,
  2954. int gamenow, int playernow, int chatnow, char *myname, int init)
  2955. {
  2956. //........................................................................
  2957. // These values control the timeouts for sending various types of packets;
  2958. // they're designed such that they'll rarely occur simultaneously.
  2959. //........................................................................
  2960. enum {
  2961. GAME_QUERY_TIME = 120,
  2962. PLAYER_QUERY_TIME = 35,
  2963. CHAT_ANNOUNCE_TIME = 83,
  2964. };
  2965. static CDTimerClass<SystemTimerClass> game_timer; // time between NET_QUERY_GAME's
  2966. static CDTimerClass<SystemTimerClass> player_timer; // time between NET_QUERY_PLAYERS's
  2967. static CDTimerClass<SystemTimerClass> chat_timer; // time between NET_CHAT_ANNOUNCE's
  2968. //------------------------------------------------------------------------
  2969. // Initialize timers
  2970. //------------------------------------------------------------------------
  2971. if (init) {
  2972. game_timer = GAME_QUERY_TIME;
  2973. player_timer = PLAYER_QUERY_TIME;
  2974. chat_timer = CHAT_ANNOUNCE_TIME;
  2975. }
  2976. //------------------------------------------------------------------------
  2977. // Send the game-name query if the time has expired, or we're told to do
  2978. // it right now
  2979. //------------------------------------------------------------------------
  2980. if (!game_timer || gamenow) {
  2981. game_timer = GAME_QUERY_TIME;
  2982. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  2983. Session.GPacket.Command = NET_QUERY_GAME;
  2984. Ipx.Send_Global_Message (&Session.GPacket,
  2985. sizeof(GlobalPacketType), 0, NULL);
  2986. //.....................................................................
  2987. // If the user specified a remote server address, broadcast over that
  2988. // network, too.
  2989. //.....................................................................
  2990. if (Session.IsBridge) {
  2991. Ipx.Send_Global_Message (&Session.GPacket,
  2992. sizeof(GlobalPacketType), 0, &Session.BridgeNet);
  2993. }
  2994. }
  2995. //------------------------------------------------------------------------
  2996. // Send the player query for the game currently clicked on, if the time has
  2997. // expired and there is a currently-selected game, or we're told to do it
  2998. // right now
  2999. //------------------------------------------------------------------------
  3000. if ( ((curgame > 0) && (curgame < Session.Games.Count()) &&
  3001. !player_timer) || playernow) {
  3002. player_timer = PLAYER_QUERY_TIME;
  3003. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  3004. Session.GPacket.Command = NET_QUERY_PLAYER;
  3005. strcpy (Session.GPacket.Name, Session.Games[curgame]->Name);
  3006. Ipx.Send_Global_Message (&Session.GPacket,
  3007. sizeof(GlobalPacketType), 0, NULL);
  3008. //.....................................................................
  3009. // If the user specified a remote server address, broadcast over that
  3010. // network, too.
  3011. //.....................................................................
  3012. if (Session.IsBridge) {
  3013. Ipx.Send_Global_Message (&Session.GPacket,
  3014. sizeof(GlobalPacketType), 0, &Session.BridgeNet);
  3015. }
  3016. }
  3017. //------------------------------------------------------------------------
  3018. // Send the chat announcement
  3019. //------------------------------------------------------------------------
  3020. if ((!chat_timer && joinstate!=JOIN_CONFIRMED) || chatnow) {
  3021. chat_timer = CHAT_ANNOUNCE_TIME;
  3022. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  3023. Session.GPacket.Command = NET_CHAT_ANNOUNCE;
  3024. strcpy (Session.GPacket.Name, myname);
  3025. Session.GPacket.Chat.ID = Session.UniqueID;
  3026. Session.GPacket.Chat.Color = Session.ColorIdx;
  3027. Ipx.Send_Global_Message (&Session.GPacket,
  3028. sizeof(GlobalPacketType), 0, NULL);
  3029. if (Session.IsBridge) {
  3030. Ipx.Send_Global_Message (&Session.GPacket,
  3031. sizeof(GlobalPacketType), 0, &Session.BridgeNet);
  3032. }
  3033. }
  3034. } /* end of Send_Join_Queries */
  3035. /***********************************************************************************************
  3036. * Get_Join_Responses -- sends queries for the Join Dialog *
  3037. * *
  3038. * This routine polls the Global Channel to see if there are any incoming packets; *
  3039. * if so, it processes them. This routine can change the state of the Join Dialog, or *
  3040. * the contents of the list boxes, based on what the packet is. *
  3041. * *
  3042. * The list boxes are passed in as pointers; they can't be made globals, because they *
  3043. * can't be constructed, because they require shape pointers to the arrow buttons, and *
  3044. * the mix files won't have been initialized when the global variables' constructors are *
  3045. * called. *
  3046. * *
  3047. * This routine sets the globals *
  3048. * Session.House (from NET_CONFIRM_JOIN) *
  3049. * Session.ColorIdx (from NET_CONFIRM_JOIN) *
  3050. * Session.Options.Bases (from NET_GAME_OPTIONS) *
  3051. * Session.Options.Tiberium (from NET_GAME_OPTIONS) *
  3052. * Session.Options.Goodies (from NET_GAME_OPTIONS) *
  3053. * Session.Options.Ghosts (from NET_GAME_OPTIONS) *
  3054. * ScenarioIdx (from NET_GAME_OPTIONS; -1 = scenario not found) *
  3055. * *
  3056. * INPUT: *
  3057. * joinstate current state of Join Dialog *
  3058. * gamelist list box containing game names *
  3059. * playerlist list box containing player names for the currently-selected game *
  3060. * join_index index of the game we've joined or are asking to join *
  3061. * my_name name of local system *
  3062. * why ptr: filled in with reason for rejection from a game *
  3063. * *
  3064. * OUTPUT: *
  3065. * Event that occurred *
  3066. * *
  3067. * WARNINGS: *
  3068. * none. *
  3069. * *
  3070. * HISTORY: *
  3071. * 02/14/1995 BR : Created. *
  3072. * 04/15/1995 BRR : Created. *
  3073. *=============================================================================================*/
  3074. static JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,
  3075. ColorListClass *playerlist, int join_index, char *my_name, RejectType *why)
  3076. {
  3077. int rc;
  3078. char * item; // general-purpose string
  3079. NodeNameType *who; // node to add to Games or Players
  3080. int i;
  3081. int found;
  3082. JoinEventType retcode = EV_NONE;
  3083. char txt[80];
  3084. //------------------------------------------------------------------------
  3085. // If there is no incoming packet, just return
  3086. //------------------------------------------------------------------------
  3087. rc = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,
  3088. &Session.GAddress, &Session.GProductID);
  3089. if (!rc || Session.GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER0)
  3090. return(EV_NONE);
  3091. //------------------------------------------------------------------------
  3092. // If we're joined in a game, handle the packet in a standard way; otherwise,
  3093. // don't answer standard queries.
  3094. //------------------------------------------------------------------------
  3095. if ( (*joinstate)==JOIN_CONFIRMED &&
  3096. Process_Global_Packet(&Session.GPacket,&Session.GAddress)!=0) {
  3097. return(EV_NONE);
  3098. }
  3099. //------------------------------------------------------------------------
  3100. // NET_ANSWER_GAME: Another system is answering our GAME query, so add that
  3101. // system to our list box if it's new.
  3102. //------------------------------------------------------------------------
  3103. if (Session.GPacket.Command==NET_ANSWER_GAME) {
  3104. //.....................................................................
  3105. // See if this name is unique
  3106. //.....................................................................
  3107. retcode = EV_NONE;
  3108. found = 0;
  3109. for (i = 1; i < Session.Games.Count(); i++) {
  3110. if (!strcmp(Session.Games[i]->Name, Session.GPacket.Name)) {
  3111. found = 1;
  3112. //...............................................................
  3113. // If name was found, update the node's time stamp & IsOpen flag.
  3114. //...............................................................
  3115. Session.Games[i]->Game.LastTime = TickCount;
  3116. if (Session.Games[i]->Game.IsOpen != Session.GPacket.GameInfo.IsOpen) {
  3117. item = (char *)gamelist->Get_Item(i);
  3118. if (Session.GPacket.GameInfo.IsOpen) {
  3119. sprintf(item,Text_String(TXT_THATGUYS_GAME),
  3120. Session.GPacket.Name);
  3121. }
  3122. else {
  3123. sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),
  3124. Session.GPacket.Name);
  3125. }
  3126. Session.Games[i]->Game.IsOpen = Session.GPacket.GameInfo.IsOpen;
  3127. gamelist->Flag_To_Redraw();
  3128. //............................................................
  3129. // If this game has gone from closed to open, copy the
  3130. // responder's address into our Game slot, since the guy
  3131. // responding to this must be game owner.
  3132. //............................................................
  3133. if (Session.Games[i]->Game.IsOpen) {
  3134. Session.Games[i]->Address = Session.GAddress;
  3135. }
  3136. //............................................................
  3137. // If we're in chat mode, print a message that the state of
  3138. // this game has changed.
  3139. //............................................................
  3140. if (*joinstate < JOIN_CONFIRMED) {
  3141. if (Session.Games[i]->Game.IsOpen) {
  3142. sprintf(txt,Text_String(TXT_S_FORMED_NEW_GAME),
  3143. Session.Games[Session.Games.Count()-1]->Name);
  3144. Sound_Effect(VOC_GAME_FORMING);
  3145. }
  3146. else {
  3147. sprintf(txt,Text_String(TXT_GAME_NOW_IN_PROGRESS),
  3148. Session.Games[Session.Games.Count()-1]->Name);
  3149. Sound_Effect(VOC_GAME_CLOSED);
  3150. }
  3151. Session.Messages.Add_Message(NULL, 0, txt, PCOLOR_BROWN, TPF_TEXT, 1200);
  3152. retcode = EV_NEW_GAME;
  3153. }
  3154. }
  3155. break;
  3156. }
  3157. }
  3158. //.....................................................................
  3159. // name not found (or addresses are different); add it to 'Games'
  3160. //.....................................................................
  3161. if (found==0) {
  3162. //..................................................................
  3163. // Create a new node structure, fill it in, add it to 'Games'
  3164. //..................................................................
  3165. who = new NodeNameType;
  3166. strcpy(who->Name, Session.GPacket.Name);
  3167. who->Address = Session.GAddress;
  3168. who->Game.IsOpen = Session.GPacket.GameInfo.IsOpen;
  3169. who->Game.LastTime = TickCount;
  3170. Session.Games.Add (who);
  3171. //..................................................................
  3172. // Create a string for "xxx's Game", leaving room for brackets around
  3173. // the string if it's a closed game
  3174. //..................................................................
  3175. item = new char [MPLAYER_NAME_MAX + 64];
  3176. if (Session.GPacket.GameInfo.IsOpen) {
  3177. sprintf(item,Text_String(TXT_THATGUYS_GAME),Session.GPacket.Name);
  3178. }
  3179. else {
  3180. sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),
  3181. Session.GPacket.Name);
  3182. }
  3183. gamelist->Add_Item(item);
  3184. //..................................................................
  3185. // If this player's in the Chat vector, remove him from there
  3186. //..................................................................
  3187. for (i = 1; i < Session.Chat.Count(); i++) {
  3188. if (Session.Chat[i]->Address==Session.GAddress) {
  3189. delete Session.Chat[i];
  3190. Session.Chat.Delete(Session.Chat[i]);
  3191. break;
  3192. }
  3193. }
  3194. //..................................................................
  3195. // If this game is open, display a message stating that it's
  3196. // now available.
  3197. //..................................................................
  3198. if (Session.GPacket.GameInfo.IsOpen && (*joinstate) < JOIN_CONFIRMED) {
  3199. sprintf(txt,Text_String(TXT_S_FORMED_NEW_GAME),
  3200. Session.GPacket.Name);
  3201. Session.Messages.Add_Message(NULL, 0, txt, PCOLOR_BROWN, TPF_TEXT, 1200);
  3202. Sound_Effect(VOC_GAME_FORMING);
  3203. }
  3204. retcode = EV_NEW_GAME;
  3205. }
  3206. }
  3207. //------------------------------------------------------------------------
  3208. // NET_ANSWER_PLAYER: Another system is answering our PLAYER query, so add
  3209. // it to our player list box & the Player Vector if it's new
  3210. //------------------------------------------------------------------------
  3211. else if (Session.GPacket.Command==NET_ANSWER_PLAYER) {
  3212. //.....................................................................
  3213. // See if this name is unique
  3214. //.....................................................................
  3215. retcode = EV_NONE;
  3216. found = 0;
  3217. for (i = 0; i < Session.Players.Count(); i++) {
  3218. //..................................................................
  3219. // If the address is already present, re-copy their name, color &
  3220. // house into the existing entry, in case they've changed it without
  3221. // our knowledge; set the 'found' flag so we won't create a new entry.
  3222. //..................................................................
  3223. if (Session.Players[i]->Address==Session.GAddress) {
  3224. strcpy(Session.Players[i]->Name, Session.GPacket.Name);
  3225. Session.Players[i]->Player.House = Session.GPacket.PlayerInfo.House;
  3226. Session.Players[i]->Player.Color = Session.GPacket.PlayerInfo.Color;
  3227. playerlist->Colors[i] =
  3228. &ColorRemaps[Session.GPacket.PlayerInfo.Color];
  3229. if (playerlist->Colors[i] == &ColorRemaps[PCOLOR_DIALOG_BLUE]) {
  3230. playerlist->Colors[i] = &ColorRemaps[PCOLOR_REALLY_BLUE];
  3231. }
  3232. found = 1;
  3233. break;
  3234. }
  3235. }
  3236. //.....................................................................
  3237. // Don't add this player if he's not part of the game that's selected.
  3238. //.....................................................................
  3239. i = gamelist->Current_Index();
  3240. if (Session.Games.Count() && Session.GPacket.PlayerInfo.NameCRC !=
  3241. Compute_Name_CRC(Session.Games[i]->Name)) {
  3242. found = 1;
  3243. }
  3244. //.....................................................................
  3245. // Don't add this player if it's myself. (We must check the name
  3246. // since the address of myself in 'Players' won't be valid.)
  3247. //.....................................................................
  3248. if (!strcmp (my_name,Session.GPacket.Name)) {
  3249. found = 1;
  3250. }
  3251. //.....................................................................
  3252. // name not found, or address didn't match; add to player list box
  3253. // & Players Vector
  3254. //.....................................................................
  3255. if (found==0) {
  3256. //..................................................................
  3257. // Create & add a node to the Vector
  3258. //..................................................................
  3259. who = new NodeNameType;
  3260. strcpy(who->Name, Session.GPacket.Name);
  3261. who->Address = Session.GAddress;
  3262. who->Player.House = Session.GPacket.PlayerInfo.House;
  3263. who->Player.Color = Session.GPacket.PlayerInfo.Color;
  3264. Session.Players.Add (who);
  3265. //..................................................................
  3266. // Create & add a string to the list box
  3267. //..................................................................
  3268. item = new char [MPLAYER_NAME_MAX + 64];
  3269. #ifdef OLDWAY
  3270. if (Session.GPacket.PlayerInfo.House==HOUSE_GOOD) {
  3271. sprintf(item,"%s\t%s",Session.GPacket.Name, Text_String(TXT_ALLIES));
  3272. } else {
  3273. sprintf(item,"%s\t%s",Session.GPacket.Name, Text_String(TXT_SOVIET));
  3274. }
  3275. #else //OLDWAY
  3276. sprintf (item, "%s\t%s", Session.GPacket.Name, Text_String(HouseTypeClass::As_Reference(Session.GPacket.PlayerInfo.House).Full_Name()));
  3277. #endif //OLDWAY
  3278. playerlist->Add_Item(item,
  3279. (who->Player.Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[who->Player.Color]);
  3280. //..................................................................
  3281. // If this player's in the Chat vector, remove him from there
  3282. //..................................................................
  3283. for (i = 1; i < Session.Chat.Count(); i++) {
  3284. if (Session.Chat[i]->Address==Session.GAddress) {
  3285. delete Session.Chat[i];
  3286. Session.Chat.Delete(Session.Chat[i]);
  3287. break;
  3288. }
  3289. }
  3290. //..................................................................
  3291. // If this player has joined our game, play a special sound.
  3292. //..................................................................
  3293. if ((*joinstate)>=JOIN_CONFIRMED) {
  3294. Sound_Effect(VOC_PLAYER_JOINED);
  3295. }
  3296. retcode = EV_NEW_PLAYER;
  3297. }
  3298. }
  3299. //------------------------------------------------------------------------
  3300. // NET_CONFIRM_JOIN: The game owner has confirmed our JOIN query; mark us
  3301. // as being confirmed, and start answering queries from other systems
  3302. //------------------------------------------------------------------------
  3303. else if (Session.GPacket.Command==NET_CONFIRM_JOIN) {
  3304. if ( (*joinstate) != JOIN_CONFIRMED) {
  3305. strcpy (Session.GameName, Session.GPacket.Name);
  3306. Session.House = Session.GPacket.PlayerInfo.House;
  3307. Session.ColorIdx = Session.GPacket.PlayerInfo.Color;
  3308. (*joinstate) = JOIN_CONFIRMED;
  3309. retcode = EV_STATE_CHANGE;
  3310. }
  3311. }
  3312. //------------------------------------------------------------------------
  3313. // NET_REJECT_JOIN: The game owner has turned down our JOIN query; restore
  3314. // the dialog state to its first pop-up state.
  3315. //------------------------------------------------------------------------
  3316. else if (Session.GPacket.Command==NET_REJECT_JOIN) {
  3317. //.....................................................................
  3318. // If we're confirmed in a game, broadcast a sign-off to tell all other
  3319. // systems that I'm no longer a part of any game; this way, I'll be
  3320. // properly removed from their dialogs.
  3321. //.....................................................................
  3322. if ( (*joinstate) == JOIN_CONFIRMED) {
  3323. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  3324. Session.GPacket.Command = NET_SIGN_OFF;
  3325. strcpy (Session.GPacket.Name,my_name);
  3326. for (i = 1; i < Session.Players.Count(); i++) {
  3327. Ipx.Send_Global_Message (&Session.GPacket,
  3328. sizeof(GlobalPacketType), 1,
  3329. &(Session.Players[i]->Address));
  3330. Ipx.Service();
  3331. }
  3332. Ipx.Send_Global_Message (&Session.GPacket,
  3333. sizeof (GlobalPacketType), 0, NULL);
  3334. if (Session.IsBridge) {
  3335. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),
  3336. 0, &Session.BridgeNet);
  3337. }
  3338. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  3339. Session.GameName[0] = 0;
  3340. //..................................................................
  3341. // remove myself from the player list
  3342. //..................................................................
  3343. item = (char *)(playerlist->Get_Item(0));
  3344. playerlist->Remove_Item(item);
  3345. delete [] item;
  3346. playerlist->Flag_To_Redraw();
  3347. delete Session.Players[0];
  3348. Session.Players.Delete(Session.Players[0]);
  3349. (*joinstate) = JOIN_REJECTED;
  3350. (*why) = REJECT_BY_OWNER;
  3351. retcode = EV_STATE_CHANGE;
  3352. }
  3353. //.....................................................................
  3354. // If we're waiting for confirmation & got rejected, tell the user why
  3355. //.....................................................................
  3356. else if ((*joinstate) == JOIN_WAIT_CONFIRM) {
  3357. (*why) = (RejectType)Session.GPacket.Reject.Why;
  3358. (*joinstate) = JOIN_REJECTED;
  3359. retcode = EV_STATE_CHANGE;
  3360. }
  3361. }
  3362. //------------------------------------------------------------------------
  3363. // NET_GAME_OPTIONS: The game owner has changed the game options & is
  3364. // sending us the new values.
  3365. //------------------------------------------------------------------------
  3366. else if (Session.GPacket.Command==NET_GAME_OPTIONS) {
  3367. if ( (*joinstate)==JOIN_CONFIRMED || (*joinstate)==JOIN_WAIT_CONFIRM) {
  3368. Session.Options.Credits = Session.GPacket.ScenarioInfo.Credits;
  3369. Session.Options.Bases = Session.GPacket.ScenarioInfo.IsBases;
  3370. Session.Options.Tiberium = Session.GPacket.ScenarioInfo.IsTiberium;
  3371. Session.Options.Goodies = Session.GPacket.ScenarioInfo.IsGoodies;
  3372. // Session.Options.Ghosts = Session.GPacket.ScenarioInfo.IsGhosties;
  3373. Session.Options.AIPlayers = Session.GPacket.ScenarioInfo.AIPlayers;
  3374. BuildLevel = Session.GPacket.ScenarioInfo.BuildLevel;
  3375. Session.Options.UnitCount = Session.GPacket.ScenarioInfo.UnitCount;
  3376. Seed = Session.GPacket.ScenarioInfo.Seed;
  3377. Special = Session.GPacket.ScenarioInfo.Special;
  3378. Options.GameSpeed = Session.GPacket.ScenarioInfo.GameSpeed;
  3379. #ifdef FIXIT_VERSION_3
  3380. // Guest receives game version number from host.
  3381. // Added to the transmitted version number is a bit indicating presence of Aftermath expansion.
  3382. unsigned long lVersion = Session.GPacket.ScenarioInfo.Version & ~0x80000000; // Actual version number.
  3383. Session.CommProtocol = VerNum.Version_Protocol( lVersion );
  3384. bAftermathMultiplayer = Session.GPacket.ScenarioInfo.Version & 0x80000000;
  3385. // if( bAftermathMultiplayer )
  3386. // debugprint( "Guest hears host say 'This is an Aftermath game'\n" );
  3387. // else
  3388. // debugprint( "Guest hears host say 'This is NOT an Aftermath game'\n" );
  3389. #else
  3390. Session.CommProtocol = VerNum.Version_Protocol(Session.GPacket.ScenarioInfo.Version);
  3391. PlayingAgainstVersion = Session.GPacket.ScenarioInfo.Version;
  3392. #endif
  3393. if (Session.Options.Tiberium) {
  3394. Special.IsTGrowth = 1;
  3395. Rule.IsTGrowth = 1;
  3396. Special.IsTSpread = 1;
  3397. Rule.IsTSpread = 1;
  3398. } else {
  3399. Special.IsTGrowth = 0;
  3400. Rule.IsTGrowth = 0;
  3401. Special.IsTSpread = 0;
  3402. Rule.IsTSpread = 0;
  3403. }
  3404. /*...............................................................
  3405. Copy the information about the scenario that the host wants to
  3406. play so ee can request this scenario from the host if we don't
  3407. have it locally.
  3408. ...............................................................*/
  3409. strcpy (Session.Options.ScenarioDescription, Session.GPacket.ScenarioInfo.Scenario);
  3410. strcpy (Session.ScenarioFileName, Session.GPacket.ScenarioInfo.ShortFileName);
  3411. #ifdef WOLAPI_INTEGRATION
  3412. strncpy (Session.ScenarioDigest, (char*)Session.GPacket.ScenarioInfo.FileDigest, sizeof (Session.GPacket.ScenarioInfo.FileDigest));
  3413. #else
  3414. strcpy (Session.ScenarioDigest, (char*)Session.GPacket.ScenarioInfo.FileDigest);
  3415. #endif
  3416. Session.ScenarioIsOfficial = Session.GPacket.ScenarioInfo.OfficialScenario;
  3417. Session.ScenarioFileLength = Session.GPacket.ScenarioInfo.FileLength;
  3418. retcode = EV_GAME_OPTIONS;
  3419. }
  3420. }
  3421. //------------------------------------------------------------------------
  3422. // NET_SIGN_OFF: Another system is signing off: search for that system in
  3423. // both the game list & player list, & remove it if found
  3424. //------------------------------------------------------------------------
  3425. else if (Session.GPacket.Command==NET_SIGN_OFF) {
  3426. //.....................................................................
  3427. // Remove this name from the list of games
  3428. //.....................................................................
  3429. for (i = 1; i < Session.Games.Count(); i++) {
  3430. if (!strcmp(Session.Games[i]->Name, Session.GPacket.Name) &&
  3431. Session.Games[i]->Address==Session.GAddress) {
  3432. //...............................................................
  3433. // If the system signing off is the currently-selected list
  3434. // item, clear the player list since that game is no longer
  3435. // forming.
  3436. //...............................................................
  3437. if (i==gamelist->Current_Index()) {
  3438. Clear_Listbox (playerlist);
  3439. Clear_Vector (&Session.Players);
  3440. }
  3441. //...............................................................
  3442. // If the system signing off was the owner of our game, mark
  3443. // ourselves as rejected
  3444. //...............................................................
  3445. if ( (*joinstate) > JOIN_NOTHING && i==join_index) {
  3446. (*joinstate) = JOIN_REJECTED;
  3447. retcode = EV_STATE_CHANGE;
  3448. (*why) = REJECT_DISBANDED;
  3449. }
  3450. //...............................................................
  3451. // Set my return code
  3452. //...............................................................
  3453. if (retcode == EV_NONE) {
  3454. if (i <= gamelist->Current_Index()) {
  3455. retcode = EV_GAME_SIGNOFF;
  3456. }
  3457. else {
  3458. retcode = EV_PLAYER_SIGNOFF;
  3459. }
  3460. }
  3461. //...............................................................
  3462. // Remove game name from game list
  3463. //...............................................................
  3464. delete Session.Games[i];
  3465. Session.Games.Delete(Session.Games[i]);
  3466. item = (char *)(gamelist->Get_Item (i));
  3467. gamelist->Remove_Item (item);
  3468. delete [] item;
  3469. gamelist->Flag_To_Redraw();
  3470. }
  3471. }
  3472. //.....................................................................
  3473. // Remove this name from the list of players
  3474. //.....................................................................
  3475. for (i = 0; i < Session.Players.Count(); i++) {
  3476. //..................................................................
  3477. // Name found; remove it
  3478. //..................................................................
  3479. if (Session.Players[i]->Address==Session.GAddress) {
  3480. item = (char *)(playerlist->Get_Item(i));
  3481. playerlist->Remove_Item(item);
  3482. delete [] item;
  3483. delete Session.Players[i];
  3484. Session.Players.Delete(Session.Players[i]);
  3485. playerlist->Flag_To_Redraw();
  3486. //...............................................................
  3487. // If this player has left our game, play a special sound.
  3488. //...............................................................
  3489. if ((*joinstate)>=JOIN_CONFIRMED) {
  3490. Sound_Effect(VOC_PLAYER_LEFT);
  3491. }
  3492. if (retcode == EV_NONE) {
  3493. retcode = EV_PLAYER_SIGNOFF;
  3494. }
  3495. }
  3496. }
  3497. //.....................................................................
  3498. // Remove this name from the chat list
  3499. //.....................................................................
  3500. for (i = 1; i < Session.Chat.Count(); i++) {
  3501. //..................................................................
  3502. // Name found; remove it
  3503. //..................................................................
  3504. if (Session.Chat[i]->Address==Session.GAddress) {
  3505. delete Session.Chat[i];
  3506. Session.Chat.Delete(Session.Chat[i]);
  3507. if (retcode == EV_NONE) {
  3508. retcode = EV_PLAYER_SIGNOFF;
  3509. }
  3510. }
  3511. }
  3512. }
  3513. //------------------------------------------------------------------------
  3514. // NET_GO: The game's owner is signalling us to start playing.
  3515. //------------------------------------------------------------------------
  3516. else if (Session.GPacket.Command==NET_GO) {
  3517. if ( (*joinstate)==JOIN_CONFIRMED) {
  3518. Session.MaxAhead = Session.GPacket.ResponseTime.OneWay;
  3519. (*joinstate) = JOIN_GAME_START;
  3520. retcode = EV_STATE_CHANGE;
  3521. Session.HostAddress = Session.GAddress;
  3522. }
  3523. }
  3524. //------------------------------------------------------------------------
  3525. // NET_LOADGAME: The game's owner is signalling us to start playing.
  3526. //------------------------------------------------------------------------
  3527. else if (Session.GPacket.Command==NET_LOADGAME) {
  3528. if ( (*joinstate)==JOIN_CONFIRMED) {
  3529. Session.MaxAhead = Session.GPacket.ResponseTime.OneWay;
  3530. (*joinstate) = JOIN_GAME_START_LOAD;
  3531. retcode = EV_STATE_CHANGE;
  3532. }
  3533. }
  3534. //------------------------------------------------------------------------
  3535. // NET_CHAT_ANNOUNCE: Someone is ready to chat; add them to our list, if
  3536. // they aren't already on it, and it's not myself.
  3537. //------------------------------------------------------------------------
  3538. else if (Session.GPacket.Command==NET_CHAT_ANNOUNCE) {
  3539. found = 0;
  3540. //.....................................................................
  3541. // If this packet is from myself, don't add it to the list
  3542. //.....................................................................
  3543. if (Session.GPacket.Chat.ID == Session.UniqueID) {
  3544. found = 1;
  3545. }
  3546. //.....................................................................
  3547. // Otherwise, see if we already have this address stored in our list
  3548. // If so, update that node's time values & name (in case the user
  3549. // changed it), and return.
  3550. //.....................................................................
  3551. else {
  3552. for (i = 0; i < Session.Chat.Count(); i++) {
  3553. if (Session.Chat[i]->Address==Session.GAddress) {
  3554. strcpy (Session.Chat[i]->Name, Session.GPacket.Name);
  3555. Session.Chat[i]->Chat.LastTime = TickCount;
  3556. Session.Chat[i]->Chat.LastChance = 0;
  3557. Session.Chat[i]->Chat.Color = Session.GPacket.Chat.Color;
  3558. found = 1;
  3559. break;
  3560. }
  3561. }
  3562. }
  3563. //.....................................................................
  3564. // Add a new node to the list
  3565. //.....................................................................
  3566. if (!found) {
  3567. who = new NodeNameType;
  3568. strcpy (who->Name, Session.GPacket.Name);
  3569. who->Address = Session.GAddress;
  3570. who->Chat.LastTime = TickCount;
  3571. who->Chat.LastChance = 0;
  3572. who->Chat.Color = Session.GPacket.Chat.Color;
  3573. Session.Chat.Add (who);
  3574. }
  3575. }
  3576. //------------------------------------------------------------------------
  3577. // NET_CHAT_REQUEST: Someone is requesting a CHAT_ANNOUNCE from us; send
  3578. // one to him directly.
  3579. //------------------------------------------------------------------------
  3580. else if (Session.GPacket.Command==NET_CHAT_REQUEST) {
  3581. if ((*joinstate) != JOIN_WAIT_CONFIRM && (*joinstate) != JOIN_CONFIRMED) {
  3582. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  3583. Session.GPacket.Command = NET_CHAT_ANNOUNCE;
  3584. strcpy(Session.GPacket.Name, my_name);
  3585. Session.GPacket.Chat.ID = Session.UniqueID;
  3586. Session.GPacket.Chat.Color = Session.ColorIdx;
  3587. Ipx.Send_Global_Message (&Session.GPacket,
  3588. sizeof(GlobalPacketType), 1, &Session.GAddress);
  3589. Ipx.Service();
  3590. }
  3591. }
  3592. //------------------------------------------------------------------------
  3593. // NET_MESSAGE: Someone is sending us a message
  3594. //------------------------------------------------------------------------
  3595. else if (Session.GPacket.Command==NET_MESSAGE) {
  3596. //.....................................................................
  3597. // If we're in a game, the sender must be in our game.
  3598. //.....................................................................
  3599. if ( (*joinstate)==JOIN_CONFIRMED) {
  3600. if (Session.GPacket.Message.NameCRC ==
  3601. Compute_Name_CRC(Session.GameName)) {
  3602. Session.Messages.Add_Message (Session.GPacket.Name,
  3603. (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?
  3604. PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,
  3605. Session.GPacket.Message.Buf,
  3606. (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?
  3607. PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,
  3608. TPF_TEXT, -1);
  3609. }
  3610. }
  3611. //.....................................................................
  3612. // Otherwise, we're in the chat room; display any old message.
  3613. //.....................................................................
  3614. else {
  3615. Session.Messages.Add_Message (Session.GPacket.Name,
  3616. Session.GPacket.Message.Color,
  3617. Session.GPacket.Message.Buf,
  3618. (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?
  3619. PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,
  3620. TPF_TEXT, -1);
  3621. }
  3622. retcode = EV_MESSAGE;
  3623. }
  3624. //------------------------------------------------------------------------
  3625. // NET_PING: Someone is pinging me to get a response time measure (will only
  3626. // happen after I've joined a game). Do nothing; the IPX Manager will handle
  3627. // sending an ACK, and updating the response time measurements.
  3628. //------------------------------------------------------------------------
  3629. else if (Session.GPacket.Command==NET_PING) {
  3630. retcode = EV_NONE;
  3631. }
  3632. //------------------------------------------------------------------------
  3633. // Default case: nothing happened. (This case will be hit every time I
  3634. // receive my own NET_QUERY_GAME or NET_QUERY_PLAYER packets.)
  3635. //------------------------------------------------------------------------
  3636. else {
  3637. retcode = EV_NONE;
  3638. }
  3639. return(retcode);
  3640. } /* end of Get_Join_Responses */
  3641. /***********************************************************************************************
  3642. * Net_New_Dialog -- lets user start a new game *
  3643. * *
  3644. * This dialog shows a list of who's requesting to join this game, and lets *
  3645. * the game initiator selectively approve each user. *
  3646. * *
  3647. * The 'Players' vector matches one-for-one the contents of the list box. The local system *
  3648. * is always listed first; the IPX Address of the local system will NOT be valid in the *
  3649. * Players vector. The Games & Players vectors should be left filled in even after this *
  3650. * routine is exited; their contents are used to form connections to the other players, *
  3651. * after the scenario has been loaded. *
  3652. * *
  3653. * INPUT: *
  3654. * none. *
  3655. * *
  3656. * OUTPUT: *
  3657. * true = success, false = cancel *
  3658. * *
  3659. * WARNINGS: *
  3660. * Session.GameName must contain this player's name. *
  3661. * *
  3662. * HISTORY: *
  3663. * 02/14/1995 BR : Created. *
  3664. *=============================================================================================*/
  3665. static int Net_New_Dialog(void)
  3666. {
  3667. typedef enum {
  3668. NUM_MESSAGES = 10
  3669. } NumMessagesType;
  3670. //------------------------------------------------------------------------
  3671. // Dialog & button dimensions
  3672. //------------------------------------------------------------------------
  3673. int d_dialog_w = 320 *RESFACTOR; // dialog width
  3674. int d_dialog_h = 200 *RESFACTOR; // dialog height
  3675. int d_dialog_x = ((320 *RESFACTOR- d_dialog_w) / 2); // dialog x-coord
  3676. int d_dialog_y = ((200 *RESFACTOR- d_dialog_h) / 2); // centered y-coord
  3677. int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
  3678. int d_txt6_h = 6*RESFACTOR+1; // ht of 6-pt text
  3679. int d_margin1 = 5*RESFACTOR; // margin width/height
  3680. int d_margin2 = 2*RESFACTOR; // margin width/height
  3681. //BG int d_playerlist_w = 118*RESFACTOR;
  3682. int d_playerlist_w = 124*RESFACTOR;
  3683. int d_playerlist_h = (6 * d_txt6_h) + 3*RESFACTOR; // 6 rows high
  3684. int d_playerlist_x = d_dialog_x + d_margin1 + d_margin1 + 5*RESFACTOR;
  3685. int d_playerlist_y = d_dialog_y + d_margin1 + d_txt6_h + 3*RESFACTOR;
  3686. int d_scenariolist_w = 162*RESFACTOR;
  3687. int d_scenariolist_h = (6 * d_txt6_h) + 3*RESFACTOR; // 6 rows high
  3688. int d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_scenariolist_w - (5*RESFACTOR);
  3689. int d_scenariolist_y = d_playerlist_y;
  3690. int d_reject_w = 55*RESFACTOR;
  3691. int d_reject_h = 9*RESFACTOR;
  3692. int d_reject_x = d_playerlist_x + (d_playerlist_w / 2) - (d_reject_w / 2);
  3693. int d_reject_y = d_playerlist_y + d_playerlist_h + d_margin2;
  3694. int d_count_w = 25*RESFACTOR;
  3695. int d_count_h = d_txt6_h;
  3696. int d_count_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged)
  3697. int d_count_y = d_reject_y + d_reject_h /*KO+ d_margin2*/;
  3698. int d_level_w = 25*RESFACTOR;
  3699. int d_level_h = d_txt6_h;
  3700. int d_level_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged)
  3701. int d_level_y = d_count_y + d_count_h;
  3702. int d_credits_w = 25*RESFACTOR;
  3703. int d_credits_h = d_txt6_h;
  3704. int d_credits_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged)
  3705. int d_credits_y = d_level_y + d_level_h;
  3706. int d_aiplayers_w = 25*RESFACTOR;
  3707. int d_aiplayers_h = d_txt6_h;
  3708. int d_aiplayers_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged)
  3709. int d_aiplayers_y = d_credits_y + d_credits_h;
  3710. int d_options_w = 106*RESFACTOR;
  3711. int d_options_h = ((5 * 6) + 4)*RESFACTOR;
  3712. int d_options_x = d_scenariolist_x + ((d_scenariolist_w - d_options_w) / 2);
  3713. int d_options_y = d_scenariolist_y + d_scenariolist_h + d_margin1;
  3714. int d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;
  3715. int d_message_h = (NUM_MESSAGES * d_txt6_h) + 3*RESFACTOR; // 10 rows high
  3716. int d_message_x = d_dialog_x + d_margin1 + 10*RESFACTOR;
  3717. int d_message_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message_h);
  3718. // int d_message_y = d_options_y + d_options_h + d_margin1;
  3719. int d_send_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR;
  3720. int d_send_h = 9*RESFACTOR;
  3721. int d_send_x = d_dialog_x + d_margin1 + 10*RESFACTOR;
  3722. int d_send_y = d_message_y + d_message_h;
  3723. int d_ok_w = 50*RESFACTOR;
  3724. int d_ok_h = 9*RESFACTOR;
  3725. int d_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2);
  3726. int d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - 3*RESFACTOR;
  3727. int d_cancel_w = 50*RESFACTOR;
  3728. int d_cancel_h = 9*RESFACTOR;
  3729. int d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
  3730. int d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - 3*RESFACTOR;
  3731. int d_load_w = 50*RESFACTOR;
  3732. int d_load_h = 9*RESFACTOR;
  3733. int d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2);
  3734. int d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - 3*RESFACTOR;
  3735. //------------------------------------------------------------------------
  3736. // Button Enumerations
  3737. //------------------------------------------------------------------------
  3738. enum {
  3739. BUTTON_PLAYERLIST = 100,
  3740. BUTTON_SCENARIOLIST,
  3741. BUTTON_REJECT,
  3742. BUTTON_COUNT,
  3743. BUTTON_LEVEL,
  3744. BUTTON_CREDITS,
  3745. BUTTON_AIPLAYERS,
  3746. BUTTON_OPTIONS,
  3747. BUTTON_OK,
  3748. BUTTON_LOAD,
  3749. BUTTON_CANCEL,
  3750. };
  3751. //------------------------------------------------------------------------
  3752. // Redraw values: in order from "top" to "bottom" layer of the dialog
  3753. //------------------------------------------------------------------------
  3754. typedef enum {
  3755. REDRAW_NONE = 0,
  3756. REDRAW_PARMS,
  3757. REDRAW_MESSAGE,
  3758. REDRAW_BUTTONS,
  3759. REDRAW_BACKGROUND,
  3760. REDRAW_ALL = REDRAW_BACKGROUND
  3761. } RedrawType;
  3762. //------------------------------------------------------------------------
  3763. // Dialog variables
  3764. //------------------------------------------------------------------------
  3765. RedrawType display = REDRAW_ALL; // redraw level
  3766. bool process = true; // process while true
  3767. KeyNumType input;
  3768. int transmit; // 1 = re-transmit new game options
  3769. long ok_timer = 0; // for timing OK button
  3770. int index; // index for rejecting a player
  3771. int rc;
  3772. int i,j;
  3773. char *item;
  3774. int tabs[] = {77*RESFACTOR}; // tabs for player list box
  3775. int optiontabs[] = {8*RESFACTOR}; // tabs for option list box
  3776. NodeNameType *who; // node to add to Players
  3777. long ping_timer = 0; // for sending Ping packets
  3778. int color_used[MAX_MPLAYER_COLORS]; // 1 = color has been used
  3779. char txt[80];
  3780. JoinEventType whahoppa; // event generated by received packets
  3781. static int first_time = 1; // 1 = 1st time this dialog is run
  3782. CCFileClass loadfile ("SAVEGAME.NET");
  3783. int load_game = 0; // 1 = load a saved game
  3784. RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
  3785. //------------------------------------------------------------------------
  3786. // Buttons
  3787. //------------------------------------------------------------------------
  3788. GadgetClass *commands; // button list
  3789. ColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"));
  3790. 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"));
  3791. TextButtonClass rejectbtn(BUTTON_REJECT, TXT_REJECT, TPF_BUTTON, d_reject_x, d_reject_y);
  3792. GaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h);
  3793. GaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h);
  3794. GaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h);
  3795. GaugeClass aiplayersgauge(BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h);
  3796. CheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"));
  3797. TextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, 60*RESFACTOR);
  3798. TextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, 60*RESFACTOR);
  3799. TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, 60*RESFACTOR);
  3800. StaticButtonClass staticunit(0, " ", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y);
  3801. StaticButtonClass staticlevel(0, " ", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y);
  3802. StaticButtonClass staticcredits(0, " ", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y);
  3803. StaticButtonClass staticaiplayers(0, " ", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y);
  3804. //------------------------------------------------------------------------
  3805. // Build the button list
  3806. //------------------------------------------------------------------------
  3807. commands = &playerlist;
  3808. scenariolist.Add_Tail(*commands);
  3809. rejectbtn.Add_Tail(*commands);
  3810. staticunit.Add_Tail(*commands);
  3811. staticlevel.Add_Tail(*commands);
  3812. staticcredits.Add_Tail(*commands);
  3813. staticaiplayers.Add_Tail(*commands);
  3814. countgauge.Add_Tail(*commands);
  3815. creditsgauge.Add_Tail(*commands);
  3816. aiplayersgauge.Add_Tail(*commands);
  3817. levelgauge.Add_Tail(*commands);
  3818. optionlist.Add_Tail(*commands);
  3819. okbtn.Add_Tail(*commands);
  3820. cancelbtn.Add_Tail(*commands);
  3821. if (loadfile.Is_Available()) {
  3822. #ifdef FIXIT_MULTI_SAVE
  3823. // loadbtn.Add_Tail(*commands);
  3824. #endif
  3825. } else {
  3826. cancelbtn.X = loadbtn.X;
  3827. }
  3828. playerlist.Set_Tabs(tabs);
  3829. //------------------------------------------------------------------------
  3830. // Init dialog values, only the first time through
  3831. //------------------------------------------------------------------------
  3832. Special.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag;
  3833. if (first_time) {
  3834. Session.Options.Credits = Rule.MPDefaultMoney; // init credits & credit buffer
  3835. Session.Options.Bases = Rule.IsMPBasesOn; // init scenario parameters
  3836. Session.Options.Tiberium = Rule.IsMPTiberiumGrow;
  3837. Session.Options.Goodies = Rule.IsMPCrates;
  3838. Session.Options.AIPlayers = 0;
  3839. Session.Options.UnitCount =
  3840. (SessionClass::CountMax[Session.Options.Bases] +
  3841. SessionClass::CountMin[Session.Options.Bases]) / 2;
  3842. first_time = 0;
  3843. }
  3844. //------------------------------------------------------------------------
  3845. // Init button states
  3846. //------------------------------------------------------------------------
  3847. optionlist.Set_Tabs(optiontabs);
  3848. optionlist.Set_Read_Only(0);
  3849. optionlist.Add_Item(Text_String(TXT_BASES));
  3850. optionlist.Add_Item(Text_String(TXT_ORE_SPREADS));
  3851. optionlist.Add_Item(Text_String(TXT_CRATES));
  3852. optionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG));
  3853. optionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS));
  3854. optionlist.Check_Item(0, Session.Options.Bases);
  3855. optionlist.Check_Item(1, Session.Options.Tiberium);
  3856. optionlist.Check_Item(2, Session.Options.Goodies);
  3857. optionlist.Check_Item(3, Special.IsCaptureTheFlag);
  3858. optionlist.Check_Item(4, Special.IsShadowGrow);
  3859. countgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]);
  3860. countgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]);
  3861. levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);
  3862. levelgauge.Set_Value(BuildLevel - 1);
  3863. creditsgauge.Set_Maximum(Rule.MPMaxMoney);
  3864. creditsgauge.Set_Value(Session.Options.Credits);
  3865. //------------------------------------------------------------------------
  3866. // Init other scenario parameters
  3867. //------------------------------------------------------------------------
  3868. Special.IsTGrowth = Session.Options.Tiberium;
  3869. Rule.IsTGrowth = Session.Options.Tiberium;
  3870. Special.IsTSpread = Session.Options.Tiberium;
  3871. Rule.IsTSpread = Session.Options.Tiberium;
  3872. transmit = 0;
  3873. //------------------------------------------------------------------------
  3874. // Init scenario description list box
  3875. //------------------------------------------------------------------------
  3876. for (i = 0; i < Session.Scenarios.Count(); i++) {
  3877. for (j = 0; EngMisStr[j] != NULL; j++) {
  3878. if (!strcmp(Session.Scenarios[i]->Description(), EngMisStr[j])) {
  3879. #ifdef FIXIT_CSII // ajw Added Aftermath installed checks (before, it was assumed).
  3880. // Add mission if it's available to us.
  3881. if( !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||
  3882. ( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )
  3883. #endif
  3884. #if defined(GERMAN) || defined(FRENCH)
  3885. scenariolist.Add_Item(EngMisStr[j+1]);
  3886. #else
  3887. scenariolist.Add_Item(EngMisStr[j]);
  3888. #endif
  3889. break;
  3890. }
  3891. }
  3892. if ( EngMisStr[j] == NULL) {
  3893. #ifdef FIXIT_CSII // ajw Added Aftermath installed checks (before, it was assumed). Added officialness check.
  3894. // Add mission if it's available to us.
  3895. if( !Session.Scenarios[i]->Get_Official() ||
  3896. !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) ||
  3897. ( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) )
  3898. #endif
  3899. {
  3900. scenariolist.Add_Item(Session.Scenarios[i]->Description());
  3901. }
  3902. }
  3903. }
  3904. Session.Options.ScenarioIndex = 0; // 1st scenario is selected
  3905. #ifdef FIXIT_VERSION_3
  3906. bAftermathMultiplayer = Is_Aftermath_Installed();
  3907. // debugprint( "Host decides that, initially, bAftermathMultiplayer is %i\n", bAftermathMultiplayer );
  3908. #else
  3909. PlayingAgainstVersion = VerNum.Version_Number();
  3910. #endif
  3911. //------------------------------------------------------------------------
  3912. // Init player color-used flags
  3913. //------------------------------------------------------------------------
  3914. for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
  3915. color_used[i] = 0; // init all colors to available
  3916. }
  3917. color_used[Session.ColorIdx] = 1; // set my color to used
  3918. playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, scheme);
  3919. //------------------------------------------------------------------------
  3920. // Init random-number generator, & create a seed to be used for all random
  3921. // numbers from here on out
  3922. //------------------------------------------------------------------------
  3923. srand(time(NULL));
  3924. Seed = rand();
  3925. //------------------------------------------------------------------------
  3926. // Init the message display system
  3927. //------------------------------------------------------------------------
  3928. Session.Messages.Init(d_message_x + 1*RESFACTOR, d_message_y + 1*RESFACTOR, NUM_MESSAGES,
  3929. MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1*RESFACTOR, d_send_y + 1*RESFACTOR, 1,
  3930. 20, MAX_MESSAGE_LENGTH - 5, d_message_w);
  3931. Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?
  3932. PCOLOR_REALLY_BLUE : Session.ColorIdx,
  3933. TPF_TEXT, NULL, '_', d_message_w);
  3934. //------------------------------------------------------------------------
  3935. // Init the version-clipping system
  3936. //------------------------------------------------------------------------
  3937. VerNum.Init_Clipping();
  3938. //------------------------------------------------------------------------
  3939. // Clear the list of players
  3940. //------------------------------------------------------------------------
  3941. Clear_Vector(&Session.Players);
  3942. //------------------------------------------------------------------------
  3943. // Add myself to the list, and to the Players vector.
  3944. //------------------------------------------------------------------------
  3945. item = new char [MPLAYER_NAME_MAX + 64];
  3946. #ifdef OLDWAY
  3947. if (Session.House==HOUSE_GOOD) {
  3948. sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_ALLIES));
  3949. } else {
  3950. sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_SOVIET));
  3951. }
  3952. #else //OLDWAY
  3953. sprintf (item, "%s\t%s", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));
  3954. #endif //OLDWAY
  3955. playerlist.Add_Item(item,
  3956. (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);
  3957. who = new NodeNameType;
  3958. strcpy(who->Name, Session.Handle);
  3959. who->Player.House = Session.House;
  3960. who->Player.Color = Session.ColorIdx;
  3961. Session.Players.Add (who);
  3962. Load_Title_Page(true);
  3963. CCPalette.Set(); //GamePalette.Set();
  3964. //
  3965. // Now init the max range of the AI players slider.
  3966. //
  3967. aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());
  3968. aiplayersgauge.Set_Value(Session.Options.AIPlayers);
  3969. //------------------------------------------------------------------------
  3970. // Processing loop
  3971. //------------------------------------------------------------------------
  3972. while (process) {
  3973. #if(SHOW_MONO)
  3974. Ipx.Mono_Debug_Print(-1,0);
  3975. #endif
  3976. #ifdef WIN32
  3977. /*
  3978. ** If we have just received input focus again after running in the background then
  3979. ** we need to redraw.
  3980. */
  3981. if (AllSurfaces.SurfacesRestored) {
  3982. AllSurfaces.SurfacesRestored=FALSE;
  3983. display = REDRAW_ALL;
  3984. }
  3985. #endif
  3986. //.....................................................................
  3987. // Refresh display if needed
  3988. //.....................................................................
  3989. if (display) {
  3990. Hide_Mouse();
  3991. //..................................................................
  3992. // Redraw backgound & dialog box
  3993. //..................................................................
  3994. if (display >= REDRAW_BACKGROUND) {
  3995. Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
  3996. //...............................................................
  3997. // Dialog & Field labels
  3998. //...............................................................
  3999. Fancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);
  4000. Fancy_Text_Print(TXT_SCENARIOS, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER);
  4001. Fancy_Text_Print(TXT_COUNT, d_count_x - 2*RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
  4002. Fancy_Text_Print(TXT_LEVEL, d_level_x - 2*RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
  4003. Fancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2*RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
  4004. Fancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT);
  4005. }
  4006. //..................................................................
  4007. // Redraw buttons
  4008. //..................................................................
  4009. if (display >= REDRAW_BUTTONS) {
  4010. /*
  4011. ** Zap, Zap, Zap
  4012. */
  4013. playerlist.Zap();
  4014. scenariolist.Zap();
  4015. rejectbtn.Zap();
  4016. staticunit.Zap();
  4017. staticlevel.Zap();
  4018. staticcredits.Zap();
  4019. staticaiplayers.Zap();
  4020. countgauge.Zap();
  4021. creditsgauge.Zap();
  4022. aiplayersgauge.Zap();
  4023. levelgauge.Zap();
  4024. optionlist.Zap();
  4025. okbtn.Zap();
  4026. cancelbtn.Zap();
  4027. loadbtn.Zap();
  4028. /*
  4029. ** Hack hack, hack
  4030. */
  4031. commands = &playerlist;
  4032. scenariolist.Add_Tail(*commands);
  4033. rejectbtn.Add_Tail(*commands);
  4034. staticunit.Add_Tail(*commands);
  4035. staticlevel.Add_Tail(*commands);
  4036. staticcredits.Add_Tail(*commands);
  4037. staticaiplayers.Add_Tail(*commands);
  4038. countgauge.Add_Tail(*commands);
  4039. creditsgauge.Add_Tail(*commands);
  4040. aiplayersgauge.Add_Tail(*commands);
  4041. levelgauge.Add_Tail(*commands);
  4042. optionlist.Add_Tail(*commands);
  4043. okbtn.Add_Tail(*commands);
  4044. cancelbtn.Add_Tail(*commands);
  4045. #ifdef FIXIT_VERSION_3
  4046. if( loadfile.Is_Available() ) {
  4047. #else
  4048. if (loadfile.Is_Available() && PlayingAgainstVersion > VERSION_RED_ALERT_104 ) {
  4049. #endif
  4050. #ifdef FIXIT_MULTI_SAVE
  4051. loadbtn.Add_Tail(*commands);
  4052. #endif
  4053. }
  4054. commands->Draw_All();
  4055. }
  4056. //..................................................................
  4057. // Draw the messages:
  4058. // - Erase an old message first
  4059. // - If we're in a game, print the game options (if they've been
  4060. // received)
  4061. // - If we've been rejected from a game, print that message
  4062. //..................................................................
  4063. if (display >= REDRAW_MESSAGE) {
  4064. Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h, BOXSTYLE_BOX, true);
  4065. Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true);
  4066. Session.Messages.Draw();
  4067. }
  4068. //..................................................................
  4069. // Update game parameter labels
  4070. //..................................................................
  4071. if (display >= REDRAW_PARMS) {
  4072. // LogicPage->Fill_Rect(d_count_x + d_count_w + 2*RESFACTOR, d_count_y, d_count_x + d_count_w + 35*RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK);
  4073. sprintf(txt,"%d",Session.Options.UnitCount);
  4074. staticunit.Set_Text(txt);
  4075. staticunit.Draw_Me();
  4076. // Fancy_Text_Print(txt, d_count_x + d_count_w + 2*RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT);
  4077. if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
  4078. sprintf(txt,"%d",BuildLevel);
  4079. } else {
  4080. sprintf(txt, "**");
  4081. }
  4082. staticlevel.Set_Text(txt);
  4083. staticlevel.Draw_Me();
  4084. // Fancy_Text_Print(txt, d_level_x + d_level_w + 2*RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT);
  4085. sprintf(txt,"%d",Session.Options.Credits);
  4086. staticcredits.Set_Text(txt);
  4087. staticcredits.Draw_Me();
  4088. // Fancy_Text_Print(txt, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT);
  4089. sprintf(txt,"%d",Session.Options.AIPlayers);
  4090. staticaiplayers.Set_Text(txt);
  4091. staticaiplayers.Draw_Me();
  4092. // Fancy_Text_Print(txt, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT);
  4093. }
  4094. Show_Mouse();
  4095. display = REDRAW_NONE;
  4096. }
  4097. //.....................................................................
  4098. // Get user input
  4099. //.....................................................................
  4100. input = commands->Input();
  4101. //.....................................................................
  4102. // Process input
  4103. //.....................................................................
  4104. switch (input) {
  4105. //..................................................................
  4106. // New Scenario selected.
  4107. //..................................................................
  4108. #ifdef FIXIT_VERSION_3 // All scenarios now allowable as downloads. ajw
  4109. case (BUTTON_SCENARIOLIST | KN_BUTTON):
  4110. if (scenariolist.Current_Index() != Session.Options.ScenarioIndex)
  4111. {
  4112. Session.Options.ScenarioIndex = scenariolist.Current_Index();
  4113. transmit = 1;
  4114. }
  4115. break;
  4116. #else // FIXIT_VERSION_3
  4117. case (BUTTON_SCENARIOLIST | KN_BUTTON):
  4118. if (scenariolist.Current_Index() != Session.Options.ScenarioIndex) {
  4119. #ifdef FIXIT_CSII // checked - ajw
  4120. if ((PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) &&
  4121. #else
  4122. if (PlayingAgainstVersion < VERSION_RED_ALERT_107 &&
  4123. #endif
  4124. Session.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){
  4125. scenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);
  4126. Session.Messages.Add_Message(NULL, 0,
  4127. (char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);
  4128. Sound_Effect(VOC_SYS_ERROR);
  4129. if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
  4130. #ifdef FIXIT_CSII // checked - ajw
  4131. }else
  4132. if (PlayingAgainstVersion < VERSION_AFTERMATH_CS &&
  4133. Is_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){
  4134. scenariolist.Set_Selected_Index (Session.Options.ScenarioIndex);
  4135. Session.Messages.Add_Message(NULL, 0,
  4136. (char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200);
  4137. Sound_Effect(VOC_SYS_ERROR);
  4138. if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE;
  4139. #endif
  4140. } else {
  4141. Session.Options.ScenarioIndex = scenariolist.Current_Index();
  4142. transmit = 1;
  4143. }
  4144. }
  4145. break;
  4146. #endif // FIXIT_VERSION_3
  4147. //..................................................................
  4148. // Reject the currently-selected player (don't allow rejecting myself,
  4149. // who will be the first entry in the list)
  4150. //..................................................................
  4151. case (BUTTON_REJECT | KN_BUTTON):
  4152. index = playerlist.Current_Index();
  4153. if (index == 0) {
  4154. Session.Messages.Add_Message(NULL, 0,
  4155. (char *)Text_String(TXT_CANT_REJECT_SELF), PCOLOR_BROWN, TPF_TEXT, 1200);
  4156. Sound_Effect(VOC_SYS_ERROR);
  4157. display = REDRAW_MESSAGE;
  4158. break;
  4159. } else if (index < 0 || index >= playerlist.Count()) {
  4160. Session.Messages.Add_Message(NULL, 0,
  4161. (char *)Text_String(TXT_SELECT_PLAYER_REJECT),
  4162. PCOLOR_BROWN, TPF_TEXT, 1200);
  4163. Sound_Effect(VOC_SYS_ERROR);
  4164. display = REDRAW_MESSAGE;
  4165. break;
  4166. }
  4167. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4168. Session.GPacket.Command = NET_REJECT_JOIN;
  4169. Ipx.Send_Global_Message (&Session.GPacket,
  4170. sizeof (GlobalPacketType), 1,
  4171. &(Session.Players[index]->Address));
  4172. break;
  4173. //..................................................................
  4174. // User adjusts max # units
  4175. //..................................................................
  4176. case (BUTTON_COUNT | KN_BUTTON):
  4177. Session.Options.UnitCount = countgauge.Get_Value() +
  4178. SessionClass::CountMin[Session.Options.Bases];
  4179. transmit = 1;
  4180. display = REDRAW_PARMS;
  4181. break;
  4182. //..................................................................
  4183. // User adjusts build level
  4184. //..................................................................
  4185. case (BUTTON_LEVEL | KN_BUTTON):
  4186. BuildLevel = levelgauge.Get_Value() + 1;
  4187. if (BuildLevel > MPLAYER_BUILD_LEVEL_MAX) // if it's pegged, max it out
  4188. BuildLevel = MPLAYER_BUILD_LEVEL_MAX;
  4189. transmit = 1;
  4190. display = REDRAW_PARMS;
  4191. break;
  4192. //..................................................................
  4193. // User edits the credits value; retransmit new game options
  4194. // Round the credits to the nearest 500.
  4195. //..................................................................
  4196. case (BUTTON_CREDITS | KN_BUTTON):
  4197. Session.Options.Credits = creditsgauge.Get_Value();
  4198. Session.Options.Credits =
  4199. ((Session.Options.Credits + 250) / 500) * 500;
  4200. transmit = 1;
  4201. display = REDRAW_PARMS;
  4202. break;
  4203. //..................................................................
  4204. // User adjusts # of AI players
  4205. //..................................................................
  4206. case (BUTTON_AIPLAYERS | KN_BUTTON):
  4207. Session.Options.AIPlayers = aiplayersgauge.Get_Value();
  4208. if (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) { // if it's pegged, max it out
  4209. Session.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();
  4210. aiplayersgauge.Set_Value(Session.Options.AIPlayers);
  4211. }
  4212. transmit = 1;
  4213. display = REDRAW_PARMS;
  4214. break;
  4215. //..................................................................
  4216. // Toggle-able options:
  4217. // If 'Bases' gets toggled, we have to change the range of the
  4218. // UnitCount slider.
  4219. // Also, if Tiberium gets toggled, we have to set the flags
  4220. // in SpecialClass.
  4221. //..................................................................
  4222. case (BUTTON_OPTIONS | KN_BUTTON):
  4223. if (Special.IsCaptureTheFlag != optionlist.Is_Checked(3) && !Special.IsCaptureTheFlag) {
  4224. optionlist.Check_Item(0, true);
  4225. }
  4226. if (Session.Options.Bases != optionlist.Is_Checked(0)) {
  4227. Session.Options.Bases = optionlist.Is_Checked(0);
  4228. if (Session.Options.Bases) {
  4229. Session.Options.UnitCount = Fixed_To_Cardinal (
  4230. SessionClass::CountMax[1] -
  4231. SessionClass::CountMin[1],
  4232. Cardinal_To_Fixed(
  4233. SessionClass::CountMax[0]-SessionClass::CountMin[0],
  4234. Session.Options.UnitCount-SessionClass::CountMin[0])) +
  4235. SessionClass::CountMin[1];
  4236. } else {
  4237. optionlist.Check_Item(3, false);
  4238. Session.Options.UnitCount = Fixed_To_Cardinal (
  4239. SessionClass::CountMax[0] -
  4240. SessionClass::CountMin[0],
  4241. Cardinal_To_Fixed(
  4242. SessionClass::CountMax[1]-SessionClass::CountMin[1],
  4243. Session.Options.UnitCount - SessionClass::CountMin[1])) +
  4244. SessionClass::CountMin[0];
  4245. }
  4246. countgauge.Set_Maximum(
  4247. SessionClass::CountMax[Session.Options.Bases] -
  4248. SessionClass::CountMin[Session.Options.Bases]);
  4249. countgauge.Set_Value(Session.Options.UnitCount -
  4250. SessionClass::CountMin[Session.Options.Bases]);
  4251. }
  4252. Session.Options.Tiberium = optionlist.Is_Checked(1);
  4253. Special.IsTGrowth = Session.Options.Tiberium;
  4254. Rule.IsTGrowth = Session.Options.Tiberium;
  4255. Special.IsTSpread = Session.Options.Tiberium;
  4256. Rule.IsTSpread = Session.Options.Tiberium;
  4257. Session.Options.Goodies = optionlist.Is_Checked(2);
  4258. Special.IsCaptureTheFlag = optionlist.Is_Checked(3);
  4259. Special.IsShadowGrow = optionlist.Is_Checked(4);
  4260. transmit = 1;
  4261. display = REDRAW_PARMS;
  4262. break;
  4263. //..................................................................
  4264. // OK: exit loop with TRUE status
  4265. //..................................................................
  4266. case (BUTTON_LOAD | KN_BUTTON):
  4267. case (BUTTON_OK | KN_BUTTON):
  4268. //...............................................................
  4269. // If a new player has joined in the last second, don't allow
  4270. // an OK; force a wait longer than 1 second (to give all players
  4271. // a chance to know about this new guy)
  4272. //...............................................................
  4273. i = max(Ipx.Global_Response_Time() * 2, 60);
  4274. while (TickCount - ok_timer < i) {
  4275. Ipx.Service();
  4276. }
  4277. //...............................................................
  4278. // If there are at least 2 players, go ahead & play; error otherwise
  4279. //...............................................................
  4280. if (Session.Players.Count() > 1 ) {
  4281. // if (Session.Players.Count() + Session.Options.AIPlayers > 1 ) {
  4282. rc = TRUE;
  4283. process = FALSE;
  4284. } else {
  4285. Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_ONE), PCOLOR_BROWN, TPF_TEXT, 1200);
  4286. Sound_Effect(VOC_SYS_ERROR);
  4287. display = REDRAW_MESSAGE;
  4288. }
  4289. if (input==(BUTTON_LOAD | KN_BUTTON)) {
  4290. load_game = 1;
  4291. } else {
  4292. load_game = 0;
  4293. }
  4294. break;
  4295. //..................................................................
  4296. // CANCEL: send a SIGN_OFF, bail out with error code
  4297. //..................................................................
  4298. case (KN_ESC):
  4299. case (BUTTON_CANCEL | KN_BUTTON):
  4300. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4301. Session.GPacket.Command = NET_SIGN_OFF;
  4302. strcpy (Session.GPacket.Name, Session.Handle);
  4303. //...............................................................
  4304. // Broadcast my sign-off over my network
  4305. //...............................................................
  4306. Ipx.Send_Global_Message (&Session.GPacket,
  4307. sizeof (GlobalPacketType), 0, NULL);
  4308. Ipx.Send_Global_Message (&Session.GPacket,
  4309. sizeof (GlobalPacketType), 0, NULL);
  4310. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  4311. //...............................................................
  4312. // Broadcast my sign-off over a bridged network if there is one
  4313. //...............................................................
  4314. if (Session.IsBridge) {
  4315. Ipx.Send_Global_Message (&Session.GPacket,
  4316. sizeof(GlobalPacketType), 0, &Session.BridgeNet);
  4317. Ipx.Send_Global_Message (&Session.GPacket,
  4318. sizeof(GlobalPacketType), 0, &Session.BridgeNet);
  4319. }
  4320. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  4321. //...............................................................
  4322. // And now, just be absolutely sure, send my sign-off to each
  4323. // player in my game. (If there's a bridge between us, the other
  4324. // player will have specified my address, so he can cross the
  4325. // bridge; but I may not have specified a bridge address, so the
  4326. // only way I have of crossing the bridge is to send a packet
  4327. // directly to him.)
  4328. // Don't send this message to myself.
  4329. //...............................................................
  4330. for (i = 1; i < Session.Players.Count(); i++) {
  4331. Ipx.Send_Global_Message (&Session.GPacket,
  4332. sizeof(GlobalPacketType), 1, &(Session.Players[i]->Address));
  4333. Ipx.Service();
  4334. }
  4335. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  4336. Session.GameName[0] = 0;
  4337. process = false;
  4338. rc = false;
  4339. break;
  4340. //..................................................................
  4341. // Default: manage the inter-player messages
  4342. //..................................................................
  4343. default:
  4344. if (Session.Messages.Manage()) {
  4345. display = REDRAW_MESSAGE;
  4346. }
  4347. //...............................................................
  4348. // Re-draw the messages & service keyboard input for any message
  4349. // being edited.
  4350. //...............................................................
  4351. i = Session.Messages.Input(input);
  4352. //...............................................................
  4353. // If 'Input' returned 1, it means refresh the message display.
  4354. //...............................................................
  4355. if (i==1) {
  4356. Hide_Mouse();
  4357. Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h,
  4358. BOXSTYLE_BOX, true); // (erase the cursor)
  4359. Session.Messages.Draw();
  4360. Show_Mouse();
  4361. } else if (i==2) {
  4362. //...............................................................
  4363. // If 'Input' returned 2, it means redraw the message display.
  4364. //...............................................................
  4365. Hide_Mouse();
  4366. Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h,
  4367. BOXSTYLE_BOX, true); // (erase the cursor)
  4368. Session.Messages.Draw();
  4369. Show_Mouse();
  4370. } else if (i==3 || i==4) {
  4371. //...............................................................
  4372. // If 'input' returned 3, it means send the current message.
  4373. //...............................................................
  4374. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4375. Session.GPacket.Command = NET_MESSAGE;
  4376. strcpy (Session.GPacket.Name, Session.Handle);
  4377. if (i==3) {
  4378. strcpy (Session.GPacket.Message.Buf,
  4379. Session.Messages.Get_Edit_Buf());
  4380. } else {
  4381. strcpy (Session.GPacket.Message.Buf,
  4382. Session.Messages.Get_Overflow_Buf());
  4383. Session.Messages.Clear_Overflow_Buf();
  4384. }
  4385. Session.GPacket.Message.Color = Session.ColorIdx;
  4386. Session.GPacket.Message.NameCRC =
  4387. Compute_Name_CRC(Session.GameName);
  4388. //............................................................
  4389. // Send the message to every player in our player list, except
  4390. // myself.
  4391. //............................................................
  4392. for (i = 1; i < Session.Players.Count(); i++) {
  4393. Ipx.Send_Global_Message (&Session.GPacket,
  4394. sizeof(GlobalPacketType), 1,
  4395. &(Session.Players[i]->Address));
  4396. Ipx.Service();
  4397. }
  4398. //............................................................
  4399. // Add the message to our own list, since we're not in the
  4400. // player list on this dialog.
  4401. // If there's no message with this ID already displayed, just
  4402. // add a new message; if there is one, concatenate it.
  4403. //............................................................
  4404. Session.Messages.Add_Message (Session.GPacket.Name,
  4405. (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?
  4406. PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,
  4407. Session.GPacket.Message.Buf,
  4408. (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx,
  4409. TPF_TEXT, -1);
  4410. Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ?
  4411. PCOLOR_REALLY_BLUE : Session.ColorIdx,
  4412. TPF_TEXT, NULL, '_', d_message_w);
  4413. display = REDRAW_MESSAGE;
  4414. }
  4415. break;
  4416. }
  4417. //.....................................................................
  4418. // Process incoming packets
  4419. //.....................................................................
  4420. #ifndef FIXIT_VERSION_3
  4421. int oldversion = PlayingAgainstVersion;
  4422. #endif
  4423. whahoppa = Get_NewGame_Responses(&playerlist, color_used);
  4424. if (whahoppa == EV_NEW_PLAYER) {
  4425. ok_timer = TickCount;
  4426. aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());
  4427. Session.Options.AIPlayers = aiplayersgauge.Get_Value();
  4428. if (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) { // if it's pegged, max it out
  4429. Session.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();
  4430. aiplayersgauge.Set_Value(Session.Options.AIPlayers);
  4431. }
  4432. #ifdef FIXIT_VERSION_3 // All scenarios now allowable for download, regardless of if CS scen. or 126x126 scen.
  4433. if (display < REDRAW_PARMS) display = REDRAW_PARMS;
  4434. #else // FIXIT_VERSION_3
  4435. if (oldversion == PlayingAgainstVersion){
  4436. if (display < REDRAW_PARMS) display = REDRAW_PARMS;
  4437. }else{
  4438. /*
  4439. ** If a CS scenario was selected and we now have a red alert only player
  4440. ** in the mix then deselect the cs scenario.
  4441. */
  4442. #ifdef FIXIT_CSII // checked - ajw
  4443. if ((PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) &&
  4444. #else
  4445. if (PlayingAgainstVersion < VERSION_RED_ALERT_107 &&
  4446. #endif
  4447. Session.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){
  4448. scenariolist.Set_Selected_Index (0);
  4449. Session.Options.ScenarioIndex = scenariolist.Current_Index();
  4450. }
  4451. #ifdef FIXIT_CSII // checked - ajw
  4452. /*
  4453. ** If an AM mega scenario was selected and we now have a non-AM
  4454. ** player in the mix then deselect the mega scenario.
  4455. */
  4456. if (PlayingAgainstVersion < VERSION_AFTERMATH_CS &&
  4457. Is_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){
  4458. scenariolist.Set_Selected_Index (0);
  4459. Session.Options.ScenarioIndex = scenariolist.Current_Index();
  4460. }
  4461. #endif
  4462. display = REDRAW_BACKGROUND;
  4463. }
  4464. #endif // FIXIT_VERSION_3
  4465. transmit = 1;
  4466. } else if (whahoppa == EV_MESSAGE) {
  4467. display = REDRAW_MESSAGE;
  4468. } else if (whahoppa == EV_PLAYER_SIGNOFF) {
  4469. aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count());
  4470. Session.Options.AIPlayers = aiplayersgauge.Get_Value();
  4471. if (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) { // if it's pegged, max it out
  4472. Session.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count();
  4473. aiplayersgauge.Set_Value(Session.Options.AIPlayers);
  4474. display = REDRAW_PARMS;
  4475. }
  4476. transmit = 1;
  4477. }
  4478. //.....................................................................
  4479. // If our Transmit flag is set, we need to send out a game option packet
  4480. // Don't send it to myself.
  4481. //.....................................................................
  4482. if (transmit) {
  4483. for (i = 1; i < Session.Players.Count(); i++) {
  4484. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4485. Session.GPacket.Command = NET_GAME_OPTIONS;
  4486. /*
  4487. ** Set up the scenario info so the remote player can match the scenario on his machine
  4488. ** or request a download if it doesnt exist
  4489. */
  4490. strcpy (Session.GPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description());
  4491. CCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());
  4492. Session.GPacket.ScenarioInfo.FileLength = file.Size();
  4493. #ifdef WOLAPI_INTEGRATION
  4494. strcpy( Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() );
  4495. #else
  4496. strncpy (Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(Session.GPacket.ScenarioInfo.ShortFileName));
  4497. #endif
  4498. strncpy ((char*)Session.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof (Session.GPacket.ScenarioInfo.FileDigest));
  4499. Session.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();
  4500. Session.GPacket.ScenarioInfo.Credits = Session.Options.Credits;
  4501. Session.GPacket.ScenarioInfo.IsBases = Session.Options.Bases;
  4502. Session.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;
  4503. Session.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;
  4504. Session.GPacket.ScenarioInfo.BuildLevel = BuildLevel;
  4505. Session.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;
  4506. Session.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;
  4507. Session.GPacket.ScenarioInfo.Seed = Seed;
  4508. Session.GPacket.ScenarioInfo.Special = Special;
  4509. Session.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
  4510. #ifdef FIXIT_VERSION_3
  4511. Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();
  4512. // Host encodes whether or not this is an Aftermath game in the highest bit.
  4513. if( bAftermathMultiplayer )
  4514. {
  4515. // debugprint( "Host tells guests 'This is an Aftermath game'\n" );
  4516. Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version() | 0x80000000;
  4517. }
  4518. else
  4519. {
  4520. // debugprint( "Host tells guests 'This is NOT an Aftermath game'\n" );
  4521. Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();
  4522. }
  4523. #else
  4524. Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();
  4525. #endif
  4526. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  4527. 1, &(Session.Players[i]->Address) );
  4528. }
  4529. Sound_Effect(VOC_OPTIONS_CHANGED);
  4530. transmit = 0;
  4531. }
  4532. //.....................................................................
  4533. // Ping every player in my game, to force the Global Channel to measure
  4534. // the connection response time. Don't ping myself (index 0).
  4535. //.....................................................................
  4536. if (TickCount - ping_timer > 15) {
  4537. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4538. Session.GPacket.Command = NET_PING;
  4539. for (i = 1; i < Session.Players.Count(); i++) {
  4540. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  4541. 1, &(Session.Players[i]->Address) );
  4542. }
  4543. ping_timer = TickCount;
  4544. }
  4545. //.....................................................................
  4546. // Service the Ipx connections
  4547. //.....................................................................
  4548. Ipx.Service();
  4549. //.....................................................................
  4550. // Service the sounds & score; GameActive must be false at this point,
  4551. // so Call_Back() doesn't intercept global messages from me!
  4552. //.....................................................................
  4553. Call_Back();
  4554. }
  4555. //------------------------------------------------------------------------
  4556. // Prepare to load the scenario
  4557. //------------------------------------------------------------------------
  4558. if (rc) {
  4559. //.....................................................................
  4560. // Set the player count & scenario number
  4561. //.....................................................................
  4562. Session.NumPlayers = Session.Players.Count();
  4563. Scen.Scenario = Session.Options.ScenarioIndex;
  4564. strcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());
  4565. //.....................................................................
  4566. // Compute frame delay value for packet transmissions:
  4567. // - Divide global channel's response time by 8 (2 to convert to 1-way
  4568. // value, 4 more to convert from ticks to frames)
  4569. //.....................................................................
  4570. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  4571. Session.MaxAhead = max( ((((Ipx.Global_Response_Time() / 8) +
  4572. (Session.FrameSendRate - 1)) / Session.FrameSendRate) *
  4573. Session.FrameSendRate), (Session.FrameSendRate * 2) );
  4574. }
  4575. else {
  4576. Session.MaxAhead = max( (Ipx.Global_Response_Time() / 8),
  4577. NETWORK_MIN_MAX_AHEAD );
  4578. }
  4579. Ipx.Set_Timing (25, (unsigned long) -1, 1000);
  4580. //.....................................................................
  4581. // Send all players the NET_GO packet. Wait until all ACK's have been
  4582. // received.
  4583. //.....................................................................
  4584. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4585. if (load_game)
  4586. Session.GPacket.Command = NET_LOADGAME;
  4587. else
  4588. Session.GPacket.Command = NET_GO;
  4589. Session.GPacket.ResponseTime.OneWay = Session.MaxAhead;
  4590. for (i = 1; i < Session.Players.Count(); i++) {
  4591. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  4592. 1, &(Session.Players[i]->Address) );
  4593. }
  4594. //.....................................................................
  4595. // Wait for all the ACK's to come in.
  4596. //.....................................................................
  4597. while (Ipx.Global_Num_Send() > 0) {
  4598. Ipx.Service();
  4599. }
  4600. /*
  4601. ** Wait for the go responses from each player in case someone needs the scenario
  4602. ** file to be sent.
  4603. */
  4604. int responses[20]; //In big trub if more than 20 players
  4605. memset (responses, 0, sizeof (responses));
  4606. int num_responses = 0;
  4607. bool send_scenario = false;
  4608. #ifdef WIN32
  4609. WWDebugString ("RA95 - About to wait for 'GO' response.");
  4610. #endif
  4611. CDTimerClass<SystemTimerClass> response_timer; // timeout timer for waiting for responses
  4612. response_timer = 60*10; // Wait for 10 seconds. If we dont hear by then assume someone crashed
  4613. do {
  4614. Ipx.Service();
  4615. int retcode = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,
  4616. &Session.GAddress, &Session.GProductID);
  4617. if (retcode && Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {
  4618. for ( i=1 ; i<Session.Players.Count() ; i++ ) {
  4619. if (Session.Players[i]->Address == Session.GAddress) {
  4620. if (!responses[i]) {
  4621. if (Session.GPacket.Command == NET_REQ_SCENARIO) {
  4622. responses[i] = Session.GPacket.Command;
  4623. send_scenario = true;
  4624. num_responses++;
  4625. }
  4626. if (Session.GPacket.Command == NET_READY_TO_GO) {
  4627. responses[i] = Session.GPacket.Command;
  4628. num_responses++;
  4629. }
  4630. }
  4631. }
  4632. }
  4633. }
  4634. } while ( num_responses < Session.Players.Count()-1 && response_timer );
  4635. #ifdef FIXIT_VERSION_3
  4636. if( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() )
  4637. {
  4638. if( !Force_Scenario_Available( Scen.ScenarioName ) )
  4639. Emergency_Exit(EXIT_FAILURE);
  4640. }
  4641. #endif
  4642. /*
  4643. ** If one of the machines requested that the scenario be sent then send it.
  4644. */
  4645. if (send_scenario) {
  4646. memset (Session.ScenarioRequests, 0, sizeof (Session.ScenarioRequests));
  4647. Session.RequestCount = 0;
  4648. for ( i=1 ; i<Session.Players.Count() ; i++ ) {
  4649. if (responses[i] == NET_REQ_SCENARIO) {
  4650. Session.ScenarioRequests[Session.RequestCount++] = i;
  4651. }
  4652. }
  4653. Send_Remote_File (Scen.ScenarioName, 1);
  4654. }
  4655. }
  4656. //------------------------------------------------------------------------
  4657. // Init network timing values, using previous response times as a measure
  4658. // of what our retry delta & timeout should be.
  4659. //------------------------------------------------------------------------
  4660. //Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1, Ipx.Global_Response_Time() * 4);
  4661. Ipx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));
  4662. //------------------------------------------------------------------------
  4663. // Clear all lists, but NOT the Games or Players vectors.
  4664. //------------------------------------------------------------------------
  4665. while (scenariolist.Count()) {
  4666. scenariolist.Remove_Item(scenariolist.Get_Item(0));
  4667. }
  4668. Clear_Listbox(&playerlist);
  4669. //------------------------------------------------------------------------
  4670. // Remove the chat edit box
  4671. //------------------------------------------------------------------------
  4672. Session.Messages.Remove_Edit();
  4673. //------------------------------------------------------------------------
  4674. // Restore screen
  4675. //------------------------------------------------------------------------
  4676. Hide_Mouse();
  4677. Load_Title_Page(true);
  4678. //#ifdef WIN32
  4679. // Load_Uncompress(CCFileClass("TITLE.CPS"), SysMemPage, SysMemPage, CCPalette);
  4680. // SysMemPage.Scale(SeenPage);
  4681. //#else
  4682. // Load_Uncompress(CCFileClass("TITLE.CPS"), HidPage, HidPage, CCPalette);
  4683. // HidPage.Blit(SeenPage);
  4684. //#endif //WIN32
  4685. Show_Mouse();
  4686. if (load_game) {
  4687. if (!Load_Game (-1)) {
  4688. WWMessageBox().Process (TXT_ERROR_LOADING_GAME);
  4689. rc = false;
  4690. }
  4691. Frame++;
  4692. }
  4693. //------------------------------------------------------------------------
  4694. // Clear the Players vector if we're not starting a game.
  4695. //------------------------------------------------------------------------
  4696. if (!rc) {
  4697. Clear_Vector(&Session.Players);
  4698. }
  4699. // while (optionlist.Count()>0) {
  4700. // item = (char *)optionlist.Get_Item(0);
  4701. // delete [] item;
  4702. // optionlist.Remove_Item(item);
  4703. // }
  4704. return(rc);
  4705. } /* end of Net_New_Dialog */
  4706. /***************************************************************************
  4707. * Get_NewGame_Responses -- processes packets for New Game dialog *
  4708. * *
  4709. * This routine can modify the contents of the given list box, as well *
  4710. * as the contents of the Players Vector global. *
  4711. * *
  4712. * INPUT: *
  4713. * playerlist list of players in this game *
  4714. * color_used array of color-used flags *
  4715. * *
  4716. * OUTPUT: *
  4717. * EV_NONE = nothing happened *
  4718. * EV_NEW_PLAYER = a new player has joined; false otherwise *
  4719. * EV_PLAYER_SIGNOFF = a player has left *
  4720. * EV_MESSAGE = a message was received *
  4721. * *
  4722. * WARNINGS: *
  4723. * none. *
  4724. * *
  4725. * HISTORY: *
  4726. * 04/18/1995 BRR : Created. *
  4727. *=========================================================================*/
  4728. static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist,
  4729. int *color_used)
  4730. {
  4731. int rc;
  4732. char * item; // general-purpose string
  4733. NodeNameType *who; // node to add to Players Vector
  4734. int i;
  4735. int found;
  4736. JoinEventType retval = EV_NONE;
  4737. int resend;
  4738. unsigned long version; // version # to use
  4739. //------------------------------------------------------------------------
  4740. // If there is no incoming packet, just return
  4741. //------------------------------------------------------------------------
  4742. rc = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,
  4743. &Session.GAddress, &Session.GProductID);
  4744. if (!rc || Session.GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER0) {
  4745. return(EV_NONE);
  4746. }
  4747. //------------------------------------------------------------------------
  4748. // Try to handle the packet in a standard way
  4749. //------------------------------------------------------------------------
  4750. if (Process_Global_Packet(&Session.GPacket,&Session.GAddress) != 0) {
  4751. return(EV_NONE);
  4752. } else if (Session.GPacket.Command==NET_QUERY_JOIN) {
  4753. //------------------------------------------------------------------------
  4754. // NET_QUERY_JOIN:
  4755. //------------------------------------------------------------------------
  4756. //.....................................................................
  4757. // See if this name is unique:
  4758. // - If the name matches, but the address is different, reject this player
  4759. // - If the name & address match, this packet must be a re-send of a
  4760. // previous request; in this case, do nothing. The other player must have
  4761. // received my CONFIRM_JOIN packet (since it was sent with an ACK
  4762. // required), so we can ignore this resend.
  4763. //.....................................................................
  4764. found = 0;
  4765. resend = 0;
  4766. for (i = 1; i < Session.Players.Count(); i++) {
  4767. if (!strcmp(Session.Players[i]->Name,Session.GPacket.Name)) {
  4768. if (Session.Players[i]->Address != Session.GAddress) {
  4769. found = 1;
  4770. }
  4771. else {
  4772. resend = 1;
  4773. }
  4774. break;
  4775. }
  4776. }
  4777. //.....................................................................
  4778. // If his name is the same as mine, treat it like a duplicate name
  4779. //.....................................................................
  4780. if (!strcmp (Session.Players[0]->Name, Session.GPacket.Name)) {
  4781. found = 1;
  4782. }
  4783. //.....................................................................
  4784. // Reject if name is a duplicate
  4785. //.....................................................................
  4786. if (found) {
  4787. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4788. Session.GPacket.Command = NET_REJECT_JOIN;
  4789. Session.GPacket.Reject.Why = (int)REJECT_DUPLICATE_NAME;
  4790. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  4791. 1, &Session.GAddress);
  4792. return(EV_NONE);
  4793. }
  4794. //.....................................................................
  4795. // Reject if there are too many players
  4796. //.....................................................................
  4797. else if ( (Session.Players.Count() >= Session.MaxPlayers) && !resend) {
  4798. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4799. Session.GPacket.Command = NET_REJECT_JOIN;
  4800. Session.GPacket.Reject.Why = (int)REJECT_GAME_FULL;
  4801. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  4802. 1, &Session.GAddress);
  4803. return(EV_NONE);
  4804. }
  4805. /*
  4806. ** Don't allow joining if the rules.ini file doesn't appear to match.
  4807. */
  4808. else if (Session.GPacket.PlayerInfo.CheatCheck != RuleINI.Get_Unique_ID() && !resend) {
  4809. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4810. Session.GPacket.Command = NET_REJECT_JOIN;
  4811. Session.GPacket.Reject.Why = (int)REJECT_MISMATCH;
  4812. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 1, &Session.GAddress);
  4813. return(EV_NONE);
  4814. }
  4815. //.....................................................................
  4816. // If this packet is NOT a resend, accept the player. Grant him the
  4817. // requested color if possible.
  4818. //.....................................................................
  4819. else if (!resend) {
  4820. //..................................................................
  4821. // Check the player's version range against our own, to see if
  4822. // there's an overlap region
  4823. //..................................................................
  4824. #ifdef FIXIT_VERSION_3
  4825. // Added to the transmitted _min_ version number is a bit indicating presence of Aftermath expansion.
  4826. bool bGuestHasAftermath = Session.GPacket.PlayerInfo.MinVersion & 0x80000000;
  4827. if( bGuestHasAftermath )
  4828. // debugprint( "Host hears guest say 'I have Aftermath'\n" );
  4829. ;
  4830. else
  4831. {
  4832. // debugprint( "Host hears guest say 'I don't have Aftermath'\n" );
  4833. if( bAftermathMultiplayer )
  4834. {
  4835. // debugprint( "Host decides this is no longer an Aftermath game!\n" );
  4836. bAftermathMultiplayer = false;
  4837. }
  4838. }
  4839. Session.GPacket.PlayerInfo.MinVersion &= ~0x80000000; // Strip special bit.
  4840. #endif
  4841. version = VerNum.Clip_Version (Session.GPacket.PlayerInfo.MinVersion,
  4842. Session.GPacket.PlayerInfo.MaxVersion);
  4843. #ifndef FIXIT_VERSION_3
  4844. PlayingAgainstVersion = version;
  4845. #endif
  4846. // TCTCTC save off version number
  4847. //..................................................................
  4848. // Reject player if his version is too old
  4849. //..................................................................
  4850. if (version == 0) {
  4851. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4852. Session.GPacket.Command = NET_REJECT_JOIN;
  4853. Session.GPacket.Reject.Why = (int)REJECT_VERSION_TOO_OLD;
  4854. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  4855. 1, &Session.GAddress);
  4856. return(EV_NONE);
  4857. }
  4858. //..................................................................
  4859. // Reject player if his version is too new
  4860. //..................................................................
  4861. else if (version == 0xffffffff) {
  4862. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4863. Session.GPacket.Command = NET_REJECT_JOIN;
  4864. Session.GPacket.Reject.Why = (int)REJECT_VERSION_TOO_NEW;
  4865. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  4866. 1, &Session.GAddress);
  4867. return(EV_NONE);
  4868. }
  4869. //..................................................................
  4870. // If the player is accepted, our mutually-accepted version may be
  4871. // different; set the CommProtocol accordingly.
  4872. //..................................................................
  4873. else {
  4874. Session.CommProtocol = VerNum.Version_Protocol(version);
  4875. }
  4876. //..................................................................
  4877. // Add node to the Vector list
  4878. //..................................................................
  4879. who = new NodeNameType;
  4880. strcpy(who->Name, Session.GPacket.Name);
  4881. who->Address = Session.GAddress;
  4882. who->Player.House = Session.GPacket.PlayerInfo.House;
  4883. Session.Players.Add (who);
  4884. //..................................................................
  4885. // Set player's color; if requested color isn't used, give it to him;
  4886. // otherwise, give him the 1st available color. Mark the color we
  4887. // give him as used.
  4888. //..................................................................
  4889. if (color_used[Session.GPacket.PlayerInfo.Color] == 0) {
  4890. who->Player.Color = Session.GPacket.PlayerInfo.Color;
  4891. }
  4892. else {
  4893. for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
  4894. if (color_used[i]==0) {
  4895. who->Player.Color = (PlayerColorType)i;
  4896. break;
  4897. }
  4898. }
  4899. }
  4900. color_used[who->Player.Color] = 1;
  4901. //..................................................................
  4902. // Add player name to the list box
  4903. //..................................................................
  4904. item = new char [MPLAYER_NAME_MAX + 64];
  4905. #ifdef OLDWAY
  4906. if (Session.GPacket.PlayerInfo.House==HOUSE_GOOD) {
  4907. sprintf(item,"%s\t%s",Session.GPacket.Name, Text_String(TXT_ALLIES));
  4908. }
  4909. else {
  4910. sprintf(item,"%s\t%s",Session.GPacket.Name, Text_String(TXT_SOVIET));
  4911. }
  4912. #else //OLDWAY
  4913. sprintf (item, "%s\t%s", Session.GPacket.Name,
  4914. Text_String(HouseTypeClass::As_Reference(Session.GPacket.PlayerInfo.House).Full_Name()));
  4915. #endif //OLDWAY
  4916. playerlist->Add_Item(item,
  4917. (who->Player.Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[who->Player.Color]);
  4918. //..................................................................
  4919. // Send a confirmation packet
  4920. //..................................................................
  4921. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  4922. Session.GPacket.Command = NET_CONFIRM_JOIN;
  4923. strcpy(Session.GPacket.Name,Session.Handle);
  4924. Session.GPacket.PlayerInfo.House = who->Player.House;
  4925. Session.GPacket.PlayerInfo.Color = who->Player.Color;
  4926. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  4927. 1, &Session.GAddress);
  4928. //..................................................................
  4929. // Play a special sound.
  4930. //..................................................................
  4931. Sound_Effect(VOC_PLAYER_JOINED);
  4932. retval = EV_NEW_PLAYER;
  4933. }
  4934. }
  4935. //------------------------------------------------------------------------
  4936. // NET_SIGN_OFF: Another system is signing off: search for that system in
  4937. // the player list, & remove it if found
  4938. //------------------------------------------------------------------------
  4939. else if (Session.GPacket.Command==NET_SIGN_OFF) {
  4940. for (i = 0; i < Session.Players.Count(); i++) {
  4941. //..................................................................
  4942. // Name found; remove it
  4943. //..................................................................
  4944. if (!strcmp (Session.Players[i]->Name, Session.GPacket.Name) &&
  4945. Session.Players[i]->Address==Session.GAddress) {
  4946. //...............................................................
  4947. // Remove from the list box
  4948. //...............................................................
  4949. item = (char *)(playerlist->Get_Item(i));
  4950. playerlist->Remove_Item(item);
  4951. playerlist->Flag_To_Redraw();
  4952. delete [] item;
  4953. //...............................................................
  4954. // Mark his color as available
  4955. //...............................................................
  4956. color_used[Session.Players[i]->Player.Color] = 0;
  4957. //...............................................................
  4958. // Delete from the Vector list
  4959. //...............................................................
  4960. delete Session.Players[i];
  4961. Session.Players.Delete(Session.Players[i]);
  4962. //...............................................................
  4963. // Play a special sound.
  4964. //...............................................................
  4965. Sound_Effect(VOC_PLAYER_LEFT);
  4966. retval = EV_PLAYER_SIGNOFF;
  4967. break;
  4968. }
  4969. }
  4970. }
  4971. //------------------------------------------------------------------------
  4972. // NET_MESSAGE: Someone is sending us a message
  4973. //------------------------------------------------------------------------
  4974. else if (Session.GPacket.Command==NET_MESSAGE) {
  4975. Session.Messages.Add_Message (Session.GPacket.Name,
  4976. (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?
  4977. PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,
  4978. Session.GPacket.Message.Buf,
  4979. (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ?
  4980. PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color,
  4981. TPF_TEXT, -1);
  4982. Sound_Effect(VOC_INCOMING_MESSAGE);
  4983. retval = EV_MESSAGE;
  4984. }
  4985. return(retval);
  4986. } /* end of Get_NewGame_Responses */
  4987. /***************************************************************************
  4988. * Compute_Name_CRC -- computes CRC from char string *
  4989. * *
  4990. * INPUT: *
  4991. * name string to create CRC for *
  4992. * *
  4993. * OUTPUT: *
  4994. * CRC *
  4995. * *
  4996. * WARNINGS: *
  4997. * none. *
  4998. * *
  4999. * HISTORY: *
  5000. * 06/29/1995 BRR : Created. *
  5001. *=========================================================================*/
  5002. unsigned long Compute_Name_CRC(char *name)
  5003. {
  5004. char buf[80];
  5005. unsigned long crc = 0L;
  5006. int i;
  5007. strcpy (buf, name);
  5008. strupr (buf);
  5009. for (i = 0; i < strlen(buf); i++) {
  5010. Add_CRC (&crc, (unsigned long)buf[i]);
  5011. }
  5012. return (crc);
  5013. } /* end of Compute_Name_CRC */
  5014. /***************************************************************************
  5015. * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog *
  5016. * *
  5017. * INPUT: *
  5018. * reconn 1 = reconnect, 0 = waiting for first-time connection *
  5019. * fresh 1 = draw from scratch, 0 = only update time counter *
  5020. * oldest_index IPX connection index of oldest connection *
  5021. * (only used for reconnection) *
  5022. * timeval value to print in the countdown field *
  5023. * *
  5024. * OUTPUT: *
  5025. * none. *
  5026. * *
  5027. * WARNINGS: *
  5028. * none. *
  5029. * *
  5030. * HISTORY: *
  5031. * 07/08/1995 BRR : Created. *
  5032. *=========================================================================*/
  5033. void Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index,
  5034. unsigned long timeval)
  5035. {
  5036. static int x,y,w,h;
  5037. int id;
  5038. char buf1[40] = {0};
  5039. char buf2[40] = {0};
  5040. char const *buf3 = "";
  5041. int d_txt6_h = 6 * RESFACTOR+1;
  5042. int d_margin = 5 * RESFACTOR;
  5043. RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
  5044. #ifdef WIN32
  5045. /*
  5046. ** If we have just received input focus again after running in the background then
  5047. ** we need to redraw.
  5048. */
  5049. if (AllSurfaces.SurfacesRestored) {
  5050. AllSurfaces.SurfacesRestored=FALSE;
  5051. fresh = true;
  5052. }
  5053. #endif
  5054. //------------------------------------------------------------------------
  5055. // Draw the dialog from scratch
  5056. //------------------------------------------------------------------------
  5057. if (fresh) {
  5058. Fancy_Text_Print("", 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  5059. switch ( Session.Type) {
  5060. case GAME_IPX:
  5061. case GAME_INTERNET:
  5062. case GAME_MODEM:
  5063. case GAME_NULL_MODEM:
  5064. if (reconn) {
  5065. id = Ipx.Connection_ID(oldest_index);
  5066. sprintf(buf1,Text_String(TXT_RECONNECTING_TO),
  5067. Ipx.Connection_Name(id));
  5068. } else {
  5069. sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));
  5070. }
  5071. break;
  5072. #if(TEN)
  5073. case GAME_TEN:
  5074. if (reconn) {
  5075. id = Ten->Connection_ID(oldest_index);
  5076. sprintf(buf1,Text_String(TXT_RECONNECTING_TO),
  5077. Ten->Connection_Name(id));
  5078. }
  5079. else {
  5080. sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));
  5081. }
  5082. #endif // TEN
  5083. #if(MPATH)
  5084. case GAME_MPATH:
  5085. if (reconn) {
  5086. id = MPath->Connection_ID(oldest_index);
  5087. sprintf(buf1,Text_String(TXT_RECONNECTING_TO),
  5088. MPath->Connection_Name(id));
  5089. }
  5090. else {
  5091. sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));
  5092. }
  5093. #endif // MPATH
  5094. }
  5095. sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);
  5096. buf3 = Text_String(TXT_PRESS_ESC);
  5097. w = max(String_Pixel_Width(buf1),String_Pixel_Width(buf2));
  5098. #ifdef FIXIT_VERSION_3
  5099. char szNewCancelMessage[ 300 ];
  5100. sprintf( szNewCancelMessage, "%s%s", buf3, TXT_WOL_CANCELMEANSFORFEIT );
  5101. if( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )
  5102. {
  5103. w = max(String_Pixel_Width(szNewCancelMessage), w); // * RESFACTOR; why was it ever multiplied by this!!!?
  5104. w += (d_margin * 12);
  5105. }
  5106. else
  5107. {
  5108. w = max(String_Pixel_Width(buf3), w) * RESFACTOR;
  5109. w += (d_margin * 5);
  5110. }
  5111. #else
  5112. w = max(String_Pixel_Width(buf3), w) * RESFACTOR;
  5113. w += (d_margin * 5);
  5114. #endif
  5115. h = (d_txt6_h * 3) + (d_margin * 6);
  5116. x = 160*RESFACTOR - (w / 2);
  5117. y = 100*RESFACTOR - (h / 2);
  5118. Hide_Mouse();
  5119. Set_Logic_Page(SeenBuff);
  5120. Dialog_Box(x, y, w, h);
  5121. Fancy_Text_Print (buf1, 160*RESFACTOR, y + (d_margin * 2), scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  5122. Fancy_Text_Print (buf2, 160*RESFACTOR, y + (d_margin * 2) + d_txt6_h + d_margin, scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  5123. #ifdef FIXIT_VERSION_3
  5124. if( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )
  5125. Fancy_Text_Print (szNewCancelMessage, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  5126. else
  5127. Fancy_Text_Print (buf3, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  5128. #else
  5129. Fancy_Text_Print (buf3, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT);
  5130. #endif
  5131. Show_Mouse();
  5132. }
  5133. //------------------------------------------------------------------------
  5134. // Just update the timeout value on the dialog
  5135. //------------------------------------------------------------------------
  5136. else {
  5137. Hide_Mouse();
  5138. Set_Logic_Page(SeenBuff);
  5139. sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);
  5140. int fillx = 160*RESFACTOR - (String_Pixel_Width (buf2) / 2) -6;
  5141. LogicPage->Fill_Rect (fillx, y + (d_margin * 2) + d_txt6_h + d_margin,
  5142. fillx + String_Pixel_Width (buf2) + 12,
  5143. y + (d_margin * 2) + d_txt6_h + d_margin + d_txt6_h +1*RESFACTOR,
  5144. BLACK);
  5145. Fancy_Text_Print (buf2, 160*RESFACTOR, y + (d_margin * 2) + d_txt6_h + d_margin, scheme, BLACK, TPF_CENTER | TPF_TEXT);
  5146. Show_Mouse();
  5147. }
  5148. } /* end of Net_Reconnect_Dialog */
  5149. #define MAX_CHAT_NAME 12
  5150. #define MAX_CHAT_PHRASE 45
  5151. struct WWPerson {
  5152. char Name[MAX_CHAT_NAME];
  5153. char Phrase[MAX_CHAT_PHRASE];
  5154. PlayerColorType Color;
  5155. unsigned long LastTime;
  5156. };
  5157. struct WWPerson WWPersons[] = {
  5158. { {66,105,108,108,32,82,0,0,0,0,0,0,},
  5159. {72,101,121,44,32,105,115,110,39,116,32,116,104,105,115,32,99,111,111,108,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5160. { {66,105,108,108,32,82,0,0,0,0,0,0,},
  5161. {72,101,121,44,32,119,97,110,116,32,115,111,109,101,32,115,101,97,102,111,111,100,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5162. { {66,97,114,114,121,32,71,0,0,0,0,0,},
  5163. {71,114,101,97,116,46,32,74,117,115,116,32,103,114,101,97,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5164. { {66,97,114,114,121,32,71,0,0,0,0,0,},
  5165. {87,111,110,100,101,114,102,117,108,46,32,80,101,114,102,101,99,116,44,32,105,110,32,102,97,99,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5166. { {66,105,108,108,32,80,0,0,0,0,0,0,},
  5167. {89,111,117,32,99,97,108,108,32,116,104,105,115,32,65,73,63,32,32,83,104,101,101,115,104,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5168. { {66,105,108,108,32,80,0,0,0,0,0,0,},
  5169. {66,105,108,108,115,32,114,117,108,101,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5170. { {66,114,101,116,116,32,83,0,0,0,0,0,},
  5171. {84,97,107,101,32,116,104,105,115,32,111,117,116,44,32,110,111,119,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5172. { {66,114,101,116,116,32,83,0,0,0,0,0,},
  5173. {87,104,121,32,99,97,110,39,116,32,121,111,117,32,102,105,116,32,97,110,121,32,109,111,114,101,32,108,101,116,116,101,114,115,32,111,110,32,116,104,101,32,108,0,0,},PCOLOR_GREEN,0},
  5174. { {66,114,101,116,116,32,83,0,0,0,0,0,},
  5175. {69,100,44,32,73,32,119,97,110,116,32,116,111,32,116,97,108,107,32,116,111,32,121,111,117,32,97,98,111,117,116,32,116,104,105,115,46,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5176. { {66,114,101,116,116,32,83,0,0,0,0,0,},
  5177. {69,100,44,32,99,111,109,101,32,116,111,32,109,121,32,111,102,102,105,99,101,44,32,110,111,119,33,32,32,91,99,114,97,99,107,33,93,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5178. { {80,101,110,105,110,97,32,70,0,0,0,0,},
  5179. {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,115,116,97,112,108,101,114,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5180. { {80,101,110,105,110,97,32,70,0,0,0,0,},
  5181. {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,116,104,101,115,97,117,114,117,115,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5182. { {80,101,110,105,110,97,32,70,0,0,0,0,},
  5183. {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,112,101,110,99,105,108,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5184. { {77,105,108,111,32,66,0,0,0,0,0,0,},
  5185. {72,101,121,32,83,116,101,118,101,44,32,99,97,110,32,119,101,32,109,101,101,116,32,105,110,32,121,111,117,114,32,111,102,102,105,99,101,63,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5186. { {77,105,108,111,32,66,0,0,0,0,0,0,},
  5187. {83,116,101,118,101,44,32,105,116,39,108,108,32,111,110,108,121,32,116,97,107,101,32,97,32,109,105,110,117,116,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5188. { {82,111,98,32,83,0,0,0,0,0,0,0,},
  5189. {77,105,108,111,44,32,100,105,97,108,32,50,52,57,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5190. { {69,108,115,98,101,116,104,32,87,0,0,0,},
  5191. {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,119,105,116,104,32,97,110,32,69,45,76,45,83,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5192. { {69,108,115,98,101,116,104,32,87,0,0,0,},
  5193. {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,110,111,116,32,39,69,108,115,98,97,114,102,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5194. { {69,108,115,98,101,116,104,32,87,0,0,0,},
  5195. {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,110,111,116,32,39,69,108,102,98,117,116,116,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5196. { {75,97,114,101,110,32,71,0,0,0,0,0,},
  5197. {84,104,105,115,32,105,115,32,115,111,111,111,32,119,101,105,114,100,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5198. { {75,97,114,101,110,32,71,0,0,0,0,0,},
  5199. {68,117,104,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5200. { {80,104,105,108,32,71,0,0,0,0,0,0,},
  5201. {72,101,121,44,32,105,116,32,119,111,114,107,101,100,32,111,110,32,109,121,32,99,111,109,112,117,116,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5202. { {80,104,105,108,32,71,0,0,0,0,0,0,},
  5203. {84,104,105,115,32,116,104,105,110,103,32,105,115,32,99,108,101,97,114,108,121,32,97,32,119,97,115,116,101,32,111,102,32,109,101,109,111,114,121,46,0,0,0,0,0,},PCOLOR_GREEN,0},
  5204. { {74,111,101,32,66,0,0,0,0,0,0,0,},
  5205. {72,109,109,44,32,73,32,115,101,101,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5206. { {74,111,101,32,66,0,0,0,0,0,0,0,},
  5207. {65,104,104,44,32,121,101,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5208. { {77,97,114,105,97,32,68,77,77,76,0,0,},
  5209. {78,111,116,32,97,110,111,116,104,101,114,32,105,110,115,116,97,108,108,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5210. { {77,97,114,105,97,32,68,77,77,76,0,0,},
  5211. {72,65,32,72,65,32,72,65,32,72,65,32,72,65,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5212. { {77,105,107,101,32,76,0,0,0,0,0,0,},
  5213. {84,104,105,115,32,105,115,32,114,101,97,108,108,121,32,99,111,111,108,33,32,32,71,111,115,104,32,103,117,121,115,33,32,32,87,111,119,33,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5214. { {77,105,107,101,32,76,0,0,0,0,0,0,},
  5215. {87,111,119,33,32,32,89,111,117,32,103,117,121,115,32,97,114,101,32,116,104,101,32,103,114,101,97,116,101,115,116,33,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5216. { {77,105,107,101,32,71,0,0,0,0,0,0,},
  5217. {71,114,97,121,102,105,115,104,32,102,111,114,32,108,117,110,99,104,32,97,103,97,105,110,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5218. { {77,105,107,101,32,71,0,0,0,0,0,0,},
  5219. {84,104,105,115,32,105,115,32,108,97,109,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5220. { {71,108,101,110,110,32,83,0,0,0,0,0,},
  5221. {84,104,105,115,32,116,104,105,110,103,39,115,32,98,117,103,103,101,100,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5222. { {71,108,101,110,110,32,83,0,0,0,0,0,},
  5223. {83,104,105,112,32,105,116,33,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5224. { {83,116,101,118,101,32,87,0,0,0,0,0,},
  5225. {79,75,32,101,118,101,114,121,111,110,101,44,32,111,117,116,32,111,102,32,109,121,32,111,102,102,105,99,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5226. { {69,100,32,68,0,0,0,0,0,0,0,0,},
  5227. {65,32,103,111,111,100,32,99,104,97,116,32,112,114,111,103,114,97,109,32,105,115,32,108,105,107,101,32,97,32,110,105,110,106,97,46,46,46,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5228. { {69,100,32,68,0,0,0,0,0,0,0,0,},
  5229. {65,32,103,111,111,100,32,110,105,110,106,97,32,105,115,32,108,105,107,101,32,97,32,110,105,110,106,97,46,46,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5230. { {69,114,105,107,32,89,0,0,0,0,0,0,},
  5231. {73,32,119,101,97,114,32,100,101,115,105,103,110,101,114,32,106,101,97,110,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5232. { {69,114,105,107,32,89,0,0,0,0,0,0,},
  5233. {72,101,121,32,66,105,108,108,44,32,116,104,105,115,32,116,104,105,110,103,32,107,101,101,112,115,32,99,114,97,25,26,24,104,105,110,103,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5234. { {74,101,102,102,32,70,0,0,0,0,0,0,},
  5235. {84,104,105,115,32,105,115,32,97,98,115,111,108,117,116,101,108,121,32,116,104,101,32,98,101,115,116,32,101,118,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5236. { {74,101,102,102,32,70,0,0,0,0,0,0,},
  5237. {84,104,105,115,32,105,115,32,97,98,115,111,108,117,116,101,108,121,32,116,104,101,32,119,111,114,115,116,32,101,118,101,114,33,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5238. { {82,105,99,107,32,78,0,0,0,0,0,0,},
  5239. {83,111,117,110,100,115,32,108,105,107,101,32,97,32,100,114,105,118,101,114,32,112,114,111,98,108,101,109,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5240. { {83,99,111,116,116,32,66,0,0,0,0,0,},
  5241. {73,32,110,101,101,100,32,116,104,105,115,32,102,111,114,32,76,79,76,50,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5242. { {83,116,101,118,101,32,84,0,0,0,0,0,},
  5243. {84,104,105,115,32,115,101,101,109,115,32,114,97,116,104,101,114,32,115,105,108,108,121,44,32,97,99,116,117,97,108,108,121,46,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5244. { {80,97,117,108,32,77,0,0,0,0,0,0,},
  5245. {78,111,32,46,46,46,46,32,32,87,32,65,32,89,33,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5246. { {82,105,99,107,32,80,0,0,0,0,0,0,},
  5247. {65,72,32,72,65,32,72,65,32,72,65,33,33,32,32,72,65,72,65,33,33,32,32,65,72,72,32,72,65,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5248. { {74,111,101,32,75,0,0,0,0,0,0,0,},
  5249. {83,116,97,108,105,110,32,107,105,108,108,101,100,32,109,121,32,102,97,116,104,101,114,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5250. { {74,111,101,32,75,0,0,0,0,0,0,0,},
  5251. {73,32,104,111,112,101,32,121,111,117,39,114,101,32,112,114,111,117,100,32,111,102,32,121,111,117,114,115,101,108,102,44,32,66,105,108,108,46,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5252. { {66,105,103,32,87,105,108,108,121,0,0,0,},
  5253. {65,110,121,98,111,100,121,32,102,101,114,32,97,32,115,112,105,116,116,105,110,39,32,99,111,110,116,101,115,116,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5254. { {69,114,105,99,32,87,0,0,0,0,0,0,},
  5255. {75,97,114,97,116,101,32,105,115,32,103,111,111,100,32,98,117,116,32,121,111,117,32,117,115,101,32,105,116,32,102,111,114,32,101,118,105,108,33,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5256. { {84,101,100,32,77,0,0,0,0,0,0,0,},
  5257. {72,97,46,32,32,70,117,110,110,121,46,32,32,84,104,105,115,32,105,115,32,102,117,110,110,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5258. { {68,97,109,111,110,32,82,0,0,0,0,0,},
  5259. {73,32,98,108,97,109,101,32,116,104,101,32,70,114,101,110,99,104,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5260. { {68,119,105,103,104,116,32,79,0,0,0,0,},
  5261. {79,104,44,32,109,97,110,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5262. { {75,105,97,32,72,0,0,0,0,0,0,0,},
  5263. {73,111,110,32,99,97,110,110,111,110,32,114,101,97,100,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5264. { {75,105,97,32,72,0,0,0,0,0,0,0,},
  5265. {83,101,108,101,99,116,32,116,97,114,103,101,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5266. { {66,114,117,99,101,32,74,0,0,0,0,0,},
  5267. {73,32,97,109,32,116,104,101,32,71,101,110,105,101,32,111,102,32,116,104,101,32,108,97,109,112,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5268. { {76,97,117,114,97,32,87,0,0,0,0,0,},
  5269. {71,111,32,97,119,97,121,44,32,66,105,108,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5270. { {68,97,118,105,100,32,68,0,0,0,0,0,},
  5271. {72,109,109,109,46,46,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5272. { {77,105,107,101,32,76,105,0,0,0,0,0,},
  5273. {67,97,108,108,32,109,101,32,78,97,116,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5274. { {68,101,110,122,105,108,32,76,0,0,0,0,},
  5275. {84,104,105,115,32,119,111,117,108,100,32,98,101,32,98,101,116,116,101,114,32,111,110,32,116,104,101,32,77,97,99,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5276. { {71,114,101,103,32,72,0,0,0,0,0,0,},
  5277. {66,117,116,32,100,111,101,115,32,105,116,32,102,105,116,32,105,110,116,111,32,50,32,77,66,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5278. { {74,111,110,97,116,104,97,110,32,76,0,0,},
  5279. {73,32,116,104,105,110,107,32,73,32,110,101,101,100,32,97,32,104,97,105,114,99,117,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5280. { {65,100,97,109,32,73,0,0,0,0,0,0,},
  5281. {87,104,97,116,101,118,101,114,46,32,32,66,101,101,102,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5282. { {75,117,114,116,32,79,0,0,0,0,0,0,},
  5283. {70,105,120,32,105,116,32,121,111,117,114,115,101,108,102,46,32,32,73,39,109,32,98,117,115,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5284. { {74,111,115,101,112,104,32,72,0,0,0,0,},
  5285. {60,73,99,121,32,103,108,97,114,101,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5286. { {77,97,116,116,32,72,0,0,0,0,0,0,},
  5287. {73,39,109,32,110,101,118,101,114,32,103,111,111,100,32,119,105,116,104,32,99,108,101,118,101,114,32,111,110,32,116,104,101,32,115,112,111,116,46,46,46,0,0,0,0,},PCOLOR_GREEN,0},
  5288. { {67,104,114,105,115,32,82,0,0,0,0,0,},
  5289. {73,32,108,111,118,101,32,109,121,32,106,111,98,46,32,32,89,101,97,104,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5290. { {80,97,116,32,67,0,0,0,0,0,0,0,},
  5291. {73,39,109,32,97,32,112,114,111,102,101,115,115,105,111,110,97,108,32,121,111,100,101,108,108,101,114,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5292. { {73,97,110,32,76,0,0,0,0,0,0,0,},
  5293. {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5294. { {74,97,99,107,32,77,0,0,0,0,0,0,},
  5295. {73,32,108,105,118,101,32,97,98,111,117,116,32,97,32,98,108,111,99,107,32,102,114,111,109,32,116,104,101,32,112,114,111,112,111,115,101,100,32,115,105,116,101,46,0,},PCOLOR_GREEN,0},
  5296. { {74,101,102,102,32,66,0,0,0,0,0,0,},
  5297. {84,104,101,121,32,97,108,108,32,108,111,111,107,32,108,105,107,101,32,97,110,116,115,32,102,114,111,109,32,117,112,32,104,101,114,101,46,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0},
  5298. };
  5299. CDTimerClass<SystemTimerClass> wwperson_timer;
  5300. void Start_WWChat(ColorListClass *playerlist)
  5301. {
  5302. char *item;
  5303. int i;
  5304. HousesType house;
  5305. //------------------------------------------------------------------------
  5306. // Ensure a different sequence each time
  5307. //------------------------------------------------------------------------
  5308. Scen.RandomNumber = rand();
  5309. //------------------------------------------------------------------------
  5310. // Add myself to the player list
  5311. //------------------------------------------------------------------------
  5312. item = new char [MPLAYER_NAME_MAX + 64];
  5313. #ifdef OLDWAY
  5314. if (Session.House==HOUSE_GOOD) {
  5315. sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_ALLIES));
  5316. }
  5317. else {
  5318. sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_SOVIET));
  5319. }
  5320. #else //OLDWAY
  5321. sprintf (item, "%s\t%s", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));
  5322. #endif //OLDWAY
  5323. playerlist->Add_Item(item,
  5324. (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);
  5325. //------------------------------------------------------------------------
  5326. // Add everyone else to the list
  5327. //------------------------------------------------------------------------
  5328. for (i = 0; i < sizeof(WWPersons) / sizeof(struct WWPerson); i++) {
  5329. //.....................................................................
  5330. // Add the 1st entry to the list no matter what; for entries after the
  5331. // 1st, only add the name if it's different from the previous name.
  5332. //.....................................................................
  5333. if (i==0 || strcmp(WWPersons[i].Name, WWPersons[i-1].Name)) {
  5334. WWPersons[i].Color = (PlayerColorType)(Random_Pick(0,(int)(PCOLOR_LAST - 1)));
  5335. if (Percent_Chance(50)) {
  5336. house = HOUSE_GREECE;
  5337. } else {
  5338. house = HOUSE_USSR;
  5339. }
  5340. // house = (HousesType)Random_Pick((int)HOUSE_GOOD,(int)HOUSE_BAD);
  5341. item = new char [MPLAYER_NAME_MAX + 64];
  5342. if (house != HOUSE_USSR && house != HOUSE_UKRAINE) {
  5343. sprintf(item,"%s\t%s", WWPersons[i].Name, Text_String(TXT_ALLIES));
  5344. } else {
  5345. sprintf(item,"%s\t%s", WWPersons[i].Name, Text_String(TXT_SOVIET));
  5346. }
  5347. playerlist->Add_Item(item,
  5348. (WWPersons[i].Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[WWPersons[i].Color]);
  5349. }
  5350. //.....................................................................
  5351. // If this entry's name is the same as the previous, copy the color
  5352. // value from the previous entry.
  5353. //.....................................................................
  5354. else if (i > 0) {
  5355. WWPersons[i].Color = WWPersons[i-1].Color;
  5356. }
  5357. }
  5358. //wwperson_timer = 240;
  5359. wwperson_timer = Random_Pick(90,360);
  5360. } // end of Start_WWChat
  5361. int Update_WWChat(void)
  5362. {
  5363. int i;
  5364. int j;
  5365. //------------------------------------------------------------------------
  5366. // Do nothing if it's too soon.
  5367. //------------------------------------------------------------------------
  5368. if (wwperson_timer > 0) {
  5369. return(0);
  5370. }
  5371. //wwperson_timer = 240;
  5372. wwperson_timer = Random_Pick(90,360);
  5373. //------------------------------------------------------------------------
  5374. // Even after the timer's gone off, there's only a 1/8 chance we'll
  5375. // print a message.
  5376. //------------------------------------------------------------------------
  5377. if (Percent_Chance(12)) {
  5378. return(0);
  5379. }
  5380. //------------------------------------------------------------------------
  5381. // Randomly select a message to "send"; ensure we pick a message that
  5382. // hasn't been recently displayed.
  5383. //------------------------------------------------------------------------
  5384. j = sizeof(WWPersons) / sizeof(struct WWPerson);
  5385. i = Random_Pick (0, j - 1);
  5386. if ((TickCount - WWPersons[i].LastTime) < 1800 &&
  5387. WWPersons[i].LastTime != 0) {
  5388. return(0);
  5389. }
  5390. Session.Messages.Add_Message (WWPersons[i].Name,
  5391. 0,
  5392. WWPersons[i].Phrase, WWPersons[i].Color,
  5393. TPF_TEXT, -1);
  5394. WWPersons[i].LastTime = TickCount;
  5395. return (1);
  5396. } // end of Update_WWChat
  5397. #if(0)
  5398. /*****************************************************************************/
  5399. void Start_Logging(void)
  5400. {
  5401. FILE *fp;
  5402. static char *ColorNames[6] = {
  5403. "Yellow",
  5404. "Red",
  5405. "BlueGreen",
  5406. "Orange",
  5407. "Green",
  5408. "Blue",
  5409. };
  5410. int i;
  5411. int id;
  5412. HousesType house;
  5413. char *housenames[] = {
  5414. "ALLIES",
  5415. "SOVIET",
  5416. "Neutral",
  5417. "Special",
  5418. "Multi1",
  5419. "Multi2",
  5420. "Multi3",
  5421. "Multi4",
  5422. };
  5423. time_t t;
  5424. fp = fopen("NETPLAY.LOG","at");
  5425. if (!fp)
  5426. return;
  5427. /*
  5428. ** Print game header
  5429. */
  5430. t = time(NULL);
  5431. fprintf (fp,"==============================================================\n");
  5432. fprintf (fp,"Date: %s",ctime(&t));
  5433. fprintf (fp,"Scenario: %s\n",
  5434. Session.Scenarios[Session.Options.ScenarioIndex].Description());
  5435. fprintf (fp,"Total # players: %d\n",Session.NumPlayers);
  5436. fprintf (fp,"==============================================================\n");
  5437. /*
  5438. ** Print connection info
  5439. */
  5440. /*
  5441. ** Print player data
  5442. */
  5443. fprintf(fp,"Local Player:\n");
  5444. fprintf (fp," Name:%s\n", Session.Handle);
  5445. fprintf (fp," Color:%s\n", ColorNames[Session.ColorIdx]);
  5446. fprintf (fp," House:%s\n", housenames[Session.House]);
  5447. fprintf (fp,"\n");
  5448. for (i = 0; i < Ipx.Num_Connections(); i++) {
  5449. id = Ipx.Connection_ID(i);
  5450. house = (HouseClass)id;
  5451. fprintf(fp,"Connection %d:\n",i);
  5452. fprintf (fp," Name:%s\n", Ipx.Connection_Name(id));
  5453. fprintf (fp," Color:%s\n",
  5454. ColorNames[HouseClass::As_Pointer(house)->RemapColor);
  5455. fprintf (fp," House:%s\n", housenames[house]);
  5456. fprintf (fp,"\n");
  5457. }
  5458. /*
  5459. ** Print game options
  5460. */
  5461. fprintf(fp,"Game Options:\n");
  5462. fprintf(fp," Bases:%d\n",Session.Options.Bases);
  5463. fprintf(fp," Credits:%d\n",Session.Options.Credits);
  5464. fprintf(fp," Tiberium:%d\n",Session.Options.Tiberium);
  5465. fprintf(fp," Crates:%d\n",Session.Options.Goodies);
  5466. fprintf(fp," AI Players:%d\n",Session.Options.AIPlayers);
  5467. fprintf(fp," Build Level:%d\n",BuildLevel);
  5468. fprintf(fp," Unit Count:%d\n",Session.Options.UnitCount);
  5469. fprintf(fp," Seed:%d\n",Seed);
  5470. fprintf (fp,"\n");
  5471. fclose(fp);
  5472. } /* end of Start_Logging */
  5473. void Log_Message(char *msg)
  5474. {
  5475. FILE *fp;
  5476. fp = fopen("NETPLAY.LOG","at");
  5477. if (!fp)
  5478. return;
  5479. fprintf(fp,"%s (Frame:%d)\n",msg,Frame);
  5480. fclose(fp);
  5481. flushall();
  5482. } /* end of Log_Message */
  5483. #endif
  5484. #ifndef WOLAPI_INTEGRATION // Rest of file ifdeffed out.
  5485. extern bool Spawn_WChat(bool can_launch);
  5486. /***********************************************************************************************
  5487. * Net_Fake_New_Dialog -- lets user start a new game *
  5488. * *
  5489. * This dialog shows a list of who's requesting to join this game, and lets *
  5490. * the game initiator selectively approve each user. *
  5491. * *
  5492. * The 'Players' vector matches one-for-one the contents of the list box. The local system *
  5493. * is always listed first; the IPX Address of the local system will NOT be valid in the *
  5494. * Players vector. The Games & Players vectors should be left filled in even after this *
  5495. * routine is exited; their contents are used to form connections to the other players, *
  5496. * after the scenario has been loaded. *
  5497. * *
  5498. * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ *
  5499. * ³ New Network Game ³ *
  5500. * ³ ³ *
  5501. * ³ Players Scenario ³ *
  5502. * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ *
  5503. * ³ ³ Boffo ³.³ ³ Green Acres ³.³ ³ *
  5504. * ³ ³ Bozo ÃÄ´ ³ Brown Sewers ÃÄ´ ³ *
  5505. * ³ ³ Bonzo ³ ³ ³ ... ³ ³ ³ *
  5506. * ³ ³ ÃÄ´ ³ ÃÄ´ ³ *
  5507. * ³ ³ ³.³ ³ ³.³ ³ *
  5508. * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ *
  5509. * ³ [Reject] Count:--- ## ³ *
  5510. * ³ Level:--- ## ³ *
  5511. * ³ ³ *
  5512. * ³ Credits: _____ ³ *
  5513. * ³ [ Bases ] [ Crates ] ³ *
  5514. * ³ [ Tiberium ] [ AI Players ] ³ *
  5515. * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ *
  5516. * ³ ³ ³ ³ *
  5517. * ³ ³ ³ ³ *
  5518. * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ *
  5519. * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ *
  5520. * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ *
  5521. * ³ [OK] [Cancel] ³ *
  5522. * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ *
  5523. * *
  5524. * INPUT: *
  5525. * none. *
  5526. * *
  5527. * OUTPUT: *
  5528. * true = success, false = cancel *
  5529. * *
  5530. * WARNINGS: *
  5531. * Session.GameName must contain this player's name. *
  5532. * *
  5533. * HISTORY: *
  5534. * 02/14/1995 BR : Created. *
  5535. *=============================================================================================*/
  5536. static int Net_Fake_New_Dialog(void)
  5537. {
  5538. #ifdef WIN32
  5539. //------------------------------------------------------------------------
  5540. // Dialog & button dimensions
  5541. //------------------------------------------------------------------------
  5542. int d_dialog_w = 120 *RESFACTOR; // dialog width
  5543. int d_dialog_h = 80 *RESFACTOR; // dialog height
  5544. int d_dialog_x = ((320 *RESFACTOR- d_dialog_w) / 2); // dialog x-coord
  5545. int d_dialog_y = ((200 *RESFACTOR- d_dialog_h) / 2); // centered y-coord
  5546. int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
  5547. int d_txt6_h = 6*RESFACTOR+1; // ht of 6-pt text
  5548. int d_margin1 = 5*RESFACTOR; // margin width/height
  5549. int d_margin2 = 2*RESFACTOR; // margin width/height
  5550. int d_playerlist_w = 118*RESFACTOR;
  5551. int d_playerlist_h = ((6 * 6) + 3)*RESFACTOR; // 6 rows high
  5552. //int d_playerlist_x = d_dialog_x + d_margin1 + d_margin1;
  5553. int d_playerlist_x = 500*RESFACTOR;
  5554. int d_playerlist_y = d_dialog_y + d_margin1 + d_txt6_h;
  5555. #if (GERMAN | FRENCH)
  5556. int d_cancel_w = 50*RESFACTOR;
  5557. #else
  5558. int d_cancel_w = 40*RESFACTOR;
  5559. #endif
  5560. int d_cancel_h = 9*RESFACTOR;
  5561. int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
  5562. int d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;
  5563. //------------------------------------------------------------------------
  5564. // Button Enumerations
  5565. //------------------------------------------------------------------------
  5566. enum {
  5567. BUTTON_PLAYERLIST = 100,
  5568. BUTTON_CANCEL,
  5569. };
  5570. //------------------------------------------------------------------------
  5571. // Redraw values: in order from "top" to "bottom" layer of the dialog
  5572. //------------------------------------------------------------------------
  5573. typedef enum {
  5574. REDRAW_NONE = 0,
  5575. REDRAW_PARMS,
  5576. REDRAW_MESSAGE,
  5577. REDRAW_BUTTONS,
  5578. REDRAW_BACKGROUND,
  5579. REDRAW_ALL = REDRAW_BACKGROUND
  5580. } RedrawType;
  5581. //------------------------------------------------------------------------
  5582. // Dialog variables
  5583. //------------------------------------------------------------------------
  5584. RedrawType display = REDRAW_ALL; // redraw level
  5585. bool process = true; // process while true
  5586. KeyNumType input;
  5587. int transmit; // 1 = re-transmit new game options
  5588. long ok_timer = 0; // for timing OK button
  5589. int rc;
  5590. int i;
  5591. char *item;
  5592. int tabs[] = {77}; // tabs for player list box
  5593. int optiontabs[] = {8}; // tabs for option list box
  5594. NodeNameType *who; // node to add to Players
  5595. long ping_timer = 0; // for sending Ping packets
  5596. int color_used[MAX_MPLAYER_COLORS]; // 1 = color has been used
  5597. JoinEventType whahoppa; // event generated by received packets
  5598. CCFileClass loadfile ("SAVEGAME.NET");
  5599. int load_game = 0; // 1 = load a saved game
  5600. RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
  5601. int width;
  5602. int height;
  5603. bool player_joined = false;
  5604. CountDownTimerClass join_timer;
  5605. Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
  5606. Format_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height);
  5607. //------------------------------------------------------------------------
  5608. // Buttons
  5609. //------------------------------------------------------------------------
  5610. GadgetClass *commands; // button list
  5611. ColorListClass playerlist(BUTTON_PLAYERLIST,
  5612. d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
  5613. TPF_TEXT,
  5614. MFCD::Retrieve("BTN-UP.SHP"),
  5615. MFCD::Retrieve("BTN-DN.SHP"));
  5616. TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,
  5617. //#if (GERMAN | FRENCH)
  5618. // d_cancel_x, d_cancel_y);
  5619. //#else
  5620. d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
  5621. //#endif
  5622. //------------------------------------------------------------------------
  5623. // Build the button list
  5624. //------------------------------------------------------------------------
  5625. commands = &playerlist;
  5626. cancelbtn.Add_Tail(*commands);
  5627. playerlist.Set_Tabs(tabs);
  5628. //------------------------------------------------------------------------
  5629. // Init other scenario parameters
  5630. //------------------------------------------------------------------------
  5631. Rule.IsTGrowth = Special.IsTGrowth;
  5632. Special.IsTSpread = Session.Options.Tiberium;
  5633. Rule.IsTSpread = Special.IsTSpread;
  5634. transmit = 0;
  5635. //------------------------------------------------------------------------
  5636. // Init player color-used flags
  5637. //------------------------------------------------------------------------
  5638. for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
  5639. color_used[i] = 0; // init all colors to available
  5640. }
  5641. color_used[Session.ColorIdx] = 1; // set my color to used
  5642. playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, scheme);
  5643. //------------------------------------------------------------------------
  5644. // Init random-number generator, & create a seed to be used for all random
  5645. // numbers from here on out
  5646. //------------------------------------------------------------------------
  5647. // randomize();
  5648. Seed = rand();
  5649. //------------------------------------------------------------------------
  5650. // Init the version-clipping system
  5651. //------------------------------------------------------------------------
  5652. VerNum.Init_Clipping();
  5653. //------------------------------------------------------------------------
  5654. // Clear the list of players
  5655. //------------------------------------------------------------------------
  5656. Clear_Vector(&Session.Players);
  5657. //------------------------------------------------------------------------
  5658. // Add myself to the list, and to the Players vector.
  5659. //------------------------------------------------------------------------
  5660. item = new char [MPLAYER_NAME_MAX + 64];
  5661. #ifdef OLDWAY
  5662. if (Session.House==HOUSE_GOOD) {
  5663. sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_ALLIES));
  5664. }
  5665. else {
  5666. sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_SOVIET));
  5667. }
  5668. #else //OLDWAY
  5669. sprintf (item, "%s\t%s", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));
  5670. #endif //OLDWAY
  5671. playerlist.Add_Item(item,
  5672. (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);
  5673. /*
  5674. ** Process the message loop until we are in focus.
  5675. */
  5676. CDTimerClass<SystemTimerClass> focus_timer; // Timer to allow a wait after client joins
  5677. focus_timer = 5*60;
  5678. WWDebugString ("RA95 - About to enter wait for focus loop.\n");
  5679. SetForegroundWindow ( MainWindow );
  5680. ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
  5681. if (!GameInFocus) {
  5682. do {
  5683. Keyboard->Check();
  5684. if (!focus_timer){
  5685. WWDebugString ("RA95 - Calling SetForgroundWindow.\n");
  5686. SetForegroundWindow ( MainWindow );
  5687. WWDebugString ("RA95 - Calling ShowWindow.\n");
  5688. ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
  5689. focus_timer = 5*60;
  5690. }
  5691. }while (!GameInFocus);
  5692. AllSurfaces.SurfacesRestored=FALSE;
  5693. }
  5694. who = new NodeNameType;
  5695. strcpy(who->Name, Session.Handle);
  5696. who->Player.House = Session.House;
  5697. who->Player.Color = Session.ColorIdx;
  5698. Session.Players.Add (who);
  5699. if (LogicPage != &SeenBuff && LogicPage!= &HidPage) {
  5700. Set_Logic_Page (SeenBuff);
  5701. }
  5702. Load_Title_Page(true);
  5703. CCPalette.Set(); //GamePalette.Set();
  5704. //------------------------------------------------------------------------
  5705. // Processing loop
  5706. //------------------------------------------------------------------------
  5707. while (process) {
  5708. #if(SHOW_MONO)
  5709. Ipx.Mono_Debug_Print(-1,0);
  5710. #endif
  5711. #ifdef WIN32
  5712. /*
  5713. ** If we have just received input focus again after running in the background then
  5714. ** we need to redraw.
  5715. */
  5716. if (AllSurfaces.SurfacesRestored) {
  5717. AllSurfaces.SurfacesRestored=FALSE;
  5718. display = REDRAW_ALL;
  5719. }
  5720. #endif
  5721. //.....................................................................
  5722. // Refresh display if needed
  5723. //.....................................................................
  5724. if (display) {
  5725. Hide_Mouse();
  5726. //..................................................................
  5727. // Redraw backgound & dialog box
  5728. //..................................................................
  5729. if (display >= REDRAW_BACKGROUND) {
  5730. Load_Title_Page(true);
  5731. CCPalette.Set(); //GamePalette.Set();
  5732. Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
  5733. //...............................................................
  5734. // Dialog & Field labels
  5735. //...............................................................
  5736. Fancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);
  5737. }
  5738. //..................................................................
  5739. // Redraw buttons
  5740. //..................................................................
  5741. if (display >= REDRAW_BUTTONS) {
  5742. commands->Draw_All();
  5743. }
  5744. Show_Mouse();
  5745. display = REDRAW_NONE;
  5746. }
  5747. //.....................................................................
  5748. // Get user input
  5749. //.....................................................................
  5750. input = commands->Input();
  5751. //.....................................................................
  5752. // Process input
  5753. //.....................................................................
  5754. switch (input) {
  5755. case (KN_ESC):
  5756. case (BUTTON_CANCEL | KN_BUTTON):
  5757. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  5758. Session.GPacket.Command = NET_SIGN_OFF;
  5759. strcpy (Session.GPacket.Name, Session.Handle);
  5760. //...............................................................
  5761. // Broadcast my sign-off over my network
  5762. //...............................................................
  5763. Ipx.Send_Global_Message (&Session.GPacket,
  5764. sizeof (GlobalPacketType), 0, NULL);
  5765. Ipx.Send_Global_Message (&Session.GPacket,
  5766. sizeof (GlobalPacketType), 0, NULL);
  5767. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  5768. //...............................................................
  5769. // And now, just be absolutely sure, send my sign-off to each
  5770. // player in my game. (If there's a bridge between us, the other
  5771. // player will have specified my address, so he can cross the
  5772. // bridge; but I may not have specified a bridge address, so the
  5773. // only way I have of crossing the bridge is to send a packet
  5774. // directly to him.)
  5775. // Don't send this message to myself.
  5776. //...............................................................
  5777. for (i = 1; i < Session.Players.Count(); i++) {
  5778. Ipx.Send_Global_Message (&Session.GPacket,
  5779. sizeof(GlobalPacketType), 1, &(Session.Players[i]->Address));
  5780. Ipx.Service();
  5781. }
  5782. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  5783. Session.GameName[0] = 0;
  5784. process = false;
  5785. rc = false;
  5786. Send_Data_To_DDE_Server ("Hello", strlen("Hello"), DDEServerClass::DDE_CONNECTION_FAILED);
  5787. GameStatisticsPacketSent = false;
  5788. Spawn_WChat(false);
  5789. break;
  5790. //..................................................................
  5791. // Default: manage the inter-player messages
  5792. //..................................................................
  5793. default:
  5794. if (Session.Players.Count() > 1) {
  5795. /*
  5796. ** Wait for several secs after receiving request to join before sending
  5797. ** start game packet
  5798. */
  5799. if (!player_joined) {
  5800. player_joined = true;
  5801. join_timer.Set (3*60, true);
  5802. break;
  5803. } else {
  5804. if (join_timer.Time()) break;
  5805. }
  5806. //...............................................................
  5807. // If a new player has joined in the last second, don't allow
  5808. // an OK; force a wait longer than 1 second (to give all players
  5809. // a chance to know about this new guy)
  5810. //...............................................................
  5811. i = MAX(Ipx.Global_Response_Time() * 2, 60*2);
  5812. while (TickCount - ok_timer < i) {
  5813. Ipx.Service();
  5814. }
  5815. //...............................................................
  5816. // If there are at least 2 players, go ahead & play; error otherwise
  5817. //...............................................................
  5818. if (Session.Solo || Session.Players.Count() > 1 || Session.Options.Ghosts) {
  5819. rc = TRUE;
  5820. process = FALSE;
  5821. } else {
  5822. WWMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);
  5823. display = REDRAW_ALL;
  5824. Sound_Effect(VOC_SYS_ERROR);
  5825. }
  5826. //if (input==(BUTTON_LOAD | KN_BUTTON))
  5827. // load_game = 1;
  5828. break;
  5829. }
  5830. break;
  5831. }
  5832. //.....................................................................
  5833. // Process incoming packets
  5834. //.....................................................................
  5835. whahoppa = Get_NewGame_Responses(&playerlist, color_used);
  5836. if (whahoppa == EV_NEW_PLAYER) {
  5837. ok_timer = TickCount;
  5838. transmit = 1;
  5839. }
  5840. else if (whahoppa == EV_MESSAGE) {
  5841. display = REDRAW_MESSAGE;
  5842. }
  5843. //.....................................................................
  5844. // If our Transmit flag is set, we need to send out a game option packet
  5845. // Don't send it to myself.
  5846. //.....................................................................
  5847. if (transmit) {
  5848. for (i = 1; i < Session.Players.Count(); i++) {
  5849. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  5850. Session.GPacket.Command = NET_GAME_OPTIONS;
  5851. /*
  5852. ** Set up the scenario info so the remote player can match the scenario on his machine
  5853. ** or request a download if it doesnt exist
  5854. */
  5855. strcpy (Session.GPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description());
  5856. CCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());
  5857. // ajw - I don't understand why this check is done here and not later.
  5858. if ( !file.Is_Available() ) {
  5859. /*
  5860. ** Special new kludge for counterstrike.
  5861. **
  5862. ** The only time the file can be unavailable is if its a counterstrike
  5863. ** mission and the CS CD is not in the drive so
  5864. ** make sure the counterstrike CD is in the drive.
  5865. **
  5866. ** If Counterstrike is installed and
  5867. ** the file name matches a counterstrike map then force the CD
  5868. ** to be there.
  5869. **
  5870. */
  5871. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  5872. if ( Expansion_CS_Present() || Expansion_AM_Present() ) {
  5873. if ( toupper (Session.ScenarioFileName [2]) == 'M' ){
  5874. int current_drive = CCFileClass::Get_CD_Drive();
  5875. int index = Get_CD_Index(current_drive, 1*60);
  5876. bool needcd = false;
  5877. if (Is_Mission_Counterstrike(Session.ScenarioFileName) && index!=2 && index!=3) {
  5878. needcd = true;
  5879. RequiredCD = 2;
  5880. }
  5881. if (Is_Mission_Aftermath(Session.ScenarioFileName) && index!=3) {
  5882. needcd = true;
  5883. RequiredCD = 3;
  5884. }
  5885. if (needcd) {
  5886. #else
  5887. if ( Expansion_CS_Present() ) {
  5888. if ( toupper (Session.ScenarioFileName [2]) == 'M' ){
  5889. int scen_num;
  5890. sscanf ( Session.ScenarioFileName, "SCM%02d", &scen_num );
  5891. int current_drive = CCFileClass::Get_CD_Drive();
  5892. if ( scen_num>24 && Get_CD_Index(current_drive, 1*60) != 2){
  5893. RequiredCD = 2;
  5894. #endif
  5895. if (!Force_CD_Available (RequiredCD)){
  5896. Emergency_Exit(EXIT_FAILURE);
  5897. }
  5898. /*
  5899. ** Update the internal list of scenarios to include the counterstrike
  5900. ** list.
  5901. */
  5902. Session.Read_Scenario_Descriptions();
  5903. }
  5904. }
  5905. }
  5906. /*
  5907. ** See if that file is available now. Its fatal if it isnt.
  5908. */
  5909. if ( !file.Is_Available() ) {
  5910. WWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
  5911. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  5912. Session.GPacket.Command = NET_SIGN_OFF;
  5913. strcpy (Session.GPacket.Name, Session.Handle);
  5914. //..................................................................
  5915. // Don't send myself the message.
  5916. //..................................................................
  5917. for (i = 1; i < Session.Players.Count(); i++) {
  5918. Ipx.Send_Global_Message (&Session.GPacket,
  5919. sizeof(GlobalPacketType), 1,
  5920. &(Session.Players[i]->Address));
  5921. Ipx.Service();
  5922. }
  5923. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  5924. 0, NULL);
  5925. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  5926. 0, NULL);
  5927. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  5928. Clear_Listbox(&playerlist);
  5929. //------------------------------------------------------------------------
  5930. // Restore screen
  5931. //------------------------------------------------------------------------
  5932. Hide_Mouse();
  5933. Load_Title_Page(true);
  5934. Show_Mouse();
  5935. //------------------------------------------------------------------------
  5936. // Clear the Players vector if we're not starting a game.
  5937. //------------------------------------------------------------------------
  5938. Clear_Vector(&Session.Players);
  5939. return (false);
  5940. }
  5941. }
  5942. Session.GPacket.ScenarioInfo.FileLength = file.Size();
  5943. #ifdef WOLAPI_INTEGRATION
  5944. strcpy( Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() );
  5945. #else
  5946. strncpy (Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(Session.GPacket.ScenarioInfo.ShortFileName));
  5947. #endif
  5948. strncpy ((char*)Session.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof (Session.GPacket.ScenarioInfo.FileDigest));
  5949. Session.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();
  5950. Session.GPacket.ScenarioInfo.Credits = Session.Options.Credits;
  5951. Session.GPacket.ScenarioInfo.IsBases = Session.Options.Bases;
  5952. Session.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium;
  5953. Session.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies;
  5954. //Session.GPacket.ScenarioInfo.IsGhosties = Session.Options.Ghosts;
  5955. Session.GPacket.ScenarioInfo.BuildLevel = BuildLevel;
  5956. Session.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount;
  5957. Session.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers;
  5958. Session.GPacket.ScenarioInfo.Seed = Seed;
  5959. Session.GPacket.ScenarioInfo.Special = Special;
  5960. Session.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
  5961. Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version();
  5962. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  5963. 1, &(Session.Players[i]->Address) );
  5964. }
  5965. Sound_Effect(VOC_OPTIONS_CHANGED);
  5966. transmit = 0;
  5967. }
  5968. //.....................................................................
  5969. // Ping every player in my game, to force the Global Channel to measure
  5970. // the connection response time. Don't ping myself (index 0).
  5971. //.....................................................................
  5972. if (TickCount - ping_timer > 15) {
  5973. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  5974. Session.GPacket.Command = NET_PING;
  5975. for (i = 1; i < Session.Players.Count(); i++) {
  5976. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  5977. 1, &(Session.Players[i]->Address) );
  5978. }
  5979. ping_timer = TickCount;
  5980. }
  5981. //.....................................................................
  5982. // Service the Ipx connections
  5983. //.....................................................................
  5984. Ipx.Service();
  5985. //.....................................................................
  5986. // Service the sounds & score; GameActive must be false at this point,
  5987. // so Call_Back() doesn't intercept global messages from me!
  5988. //.....................................................................
  5989. Call_Back();
  5990. }
  5991. //------------------------------------------------------------------------
  5992. // Prepare to load the scenario
  5993. //------------------------------------------------------------------------
  5994. if (rc) {
  5995. //.....................................................................
  5996. // Set the player count & scenario number
  5997. //.....................................................................
  5998. Session.NumPlayers = Session.Players.Count();
  5999. Scen.Scenario = Session.Options.ScenarioIndex;
  6000. strcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename());
  6001. //.....................................................................
  6002. // Compute frame delay value for packet transmissions:
  6003. // - Divide global channel's response time by 8 (2 to convert to 1-way
  6004. // value, 4 more to convert from ticks to frames)
  6005. //.....................................................................
  6006. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  6007. Session.MaxAhead = MAX( ((((Ipx.Global_Response_Time() / 8) +
  6008. (Session.FrameSendRate - 1)) / Session.FrameSendRate) *
  6009. Session.FrameSendRate), (Session.FrameSendRate * 2) );
  6010. }
  6011. else {
  6012. Session.MaxAhead = MAX( (Ipx.Global_Response_Time() / 8),
  6013. NETWORK_MIN_MAX_AHEAD );
  6014. }
  6015. //.....................................................................
  6016. // Send all players the NET_GO packet. Wait until all ACK's have been
  6017. // received.
  6018. //.....................................................................
  6019. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  6020. if (load_game)
  6021. Session.GPacket.Command = NET_LOADGAME;
  6022. else
  6023. Session.GPacket.Command = NET_GO;
  6024. Session.GPacket.ResponseTime.OneWay = Session.MaxAhead;
  6025. for (i = 1; i < Session.Players.Count(); i++) {
  6026. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  6027. 1, &(Session.Players[i]->Address) );
  6028. }
  6029. //.....................................................................
  6030. // Wait for all the ACK's to come in.
  6031. //.....................................................................
  6032. while (Ipx.Global_Num_Send() > 0) {
  6033. Ipx.Service();
  6034. }
  6035. /*
  6036. ** Wait for the go responses from each player in case someone needs the scenario
  6037. ** file to be sent.
  6038. */
  6039. int responses[20]; //In big trub if more than 20 players
  6040. memset (responses, 0, sizeof (responses));
  6041. int num_responses = 0;
  6042. bool send_scenario = false;
  6043. WWDebugString ("RA95 - About to wait for 'GO' response.\n");
  6044. CDTimerClass<SystemTimerClass> response_timer; // timeout timer for waiting for responses
  6045. response_timer = 60*30; // Wait for 30 seconds. If we dont hear by then assume someone crashed
  6046. do {
  6047. Ipx.Service();
  6048. int retcode = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen,
  6049. &Session.GAddress, &Session.GProductID);
  6050. if (retcode && Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) {
  6051. for ( i=1 ; i<Session.Players.Count() ; i++ ) {
  6052. if (Session.Players[i]->Address == Session.GAddress) {
  6053. if (!responses[i]) {
  6054. if (Session.GPacket.Command == NET_REQ_SCENARIO) {
  6055. responses[i] = Session.GPacket.Command;
  6056. send_scenario = true;
  6057. num_responses++;
  6058. }
  6059. if (Session.GPacket.Command == NET_READY_TO_GO) {
  6060. responses[i] = Session.GPacket.Command;
  6061. num_responses++;
  6062. }
  6063. }
  6064. }
  6065. }
  6066. }
  6067. } while ( num_responses < Session.Players.Count()-1 && response_timer );
  6068. WWDebugString ("RA95 - Exited response wait loop.\n");
  6069. /*
  6070. ** If one of the machines requested that the scenario be sent then send it.
  6071. */
  6072. if (send_scenario) {
  6073. memset (Session.ScenarioRequests, 0, sizeof (Session.ScenarioRequests));
  6074. Session.RequestCount = 0;
  6075. for ( i=1 ; i<Session.Players.Count() ; i++ ) {
  6076. if (responses[i] == NET_REQ_SCENARIO) {
  6077. Session.ScenarioRequests[Session.RequestCount++] = i;
  6078. }
  6079. }
  6080. Send_Remote_File (Scen.ScenarioName, 1);
  6081. }
  6082. }
  6083. //.....................................................................
  6084. // Wait a while, polling the IPX service routines, to give our ACK
  6085. // a chance to get to the other system. If he doesn't get our ACK,
  6086. // he'll be waiting the whole time we load MIX files.
  6087. //.....................................................................
  6088. i = MAX(Ipx.Global_Response_Time() * 2, 60*2);
  6089. int starttime = TickCount;
  6090. while (TickCount - starttime < i) {
  6091. Ipx.Service();
  6092. }
  6093. //------------------------------------------------------------------------
  6094. // Init network timing values, using previous response times as a measure
  6095. // of what our retry delta & timeout should be.
  6096. //------------------------------------------------------------------------
  6097. //Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
  6098. // Ipx.Global_Response_Time() * 4);
  6099. Ipx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));
  6100. Clear_Listbox(&playerlist);
  6101. //------------------------------------------------------------------------
  6102. // Restore screen
  6103. //------------------------------------------------------------------------
  6104. Hide_Mouse();
  6105. Load_Title_Page(true);
  6106. Show_Mouse();
  6107. if (load_game) {
  6108. if (!Load_Game (-1)) {
  6109. WWMessageBox().Process (TXT_ERROR_LOADING_GAME);
  6110. rc = false;
  6111. }
  6112. Frame++;
  6113. }
  6114. //------------------------------------------------------------------------
  6115. // Clear the Players vector if we're not starting a game.
  6116. //------------------------------------------------------------------------
  6117. if (!rc) {
  6118. Clear_Vector(&Session.Players);
  6119. }
  6120. // while (optionlist.Count()>0) {
  6121. // item = (char *)optionlist.Get_Item(0);
  6122. // delete [] item;
  6123. // optionlist.Remove_Item(item);
  6124. // }
  6125. return(rc);
  6126. #else //WIN32
  6127. return (0);
  6128. #endif //WIN32
  6129. } /* end of Net_Fake_New_Dialog */
  6130. /***********************************************************************************************
  6131. * Net_Join_Dialog -- lets user join an existing game or start a new one *
  6132. * *
  6133. * This dialog displays an edit field for the player's name, and a list of all non-stealth- *
  6134. * mode games. Clicking once on a game name displays a list of who's in that game. Clicking *
  6135. * "New" takes the user to the Net_New dialog, where he waits for other users to join his *
  6136. * game. All other input is done through this dialog. *
  6137. * *
  6138. * The dialog has several "states": *
  6139. * *
  6140. * 1) Initially, it waits for the user to fill in his/her name and then to select Join or *
  6141. * New; if New is selected, this dialog is exited. *
  6142. * *
  6143. * 2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.*
  6144. * The join request is transmitted to the game's owner, and the message "Waiting for *
  6145. * Confirmation" is displayed, until a confirmation or denial is received from the game's *
  6146. * owner. The user may click Cancel at this point to cancel the join request. *
  6147. * (Once Join is selected, the name editing field is disabled, and becomes a display-only *
  6148. * field. If cancel is selected, it reappears as an edit field.) The user can still click*
  6149. * around & see who's in which games. *
  6150. * *
  6151. * 3) If the join request is denied, the dialog re-initializes to its pre-join state; the *
  6152. * Join & New buttons reappear, & the Name field is available again. *
  6153. * *
  6154. * 4) If join confirmation is obtained, the message changes to show all the current game *
  6155. * settings. The user cannot click around & look at other games any more. *
  6156. * *
  6157. * Any game running in Stealth mode won't show up on this dialog. *
  6158. * *
  6159. * The 'Players' vector matches one-for-one the contents of the list box. The local system *
  6160. * is always listed first; the IPX Address of the local system will NOT be valid in the *
  6161. * Players vector. The Games & Players vectors should be left filled in even after this *
  6162. * routine is exited; their contents are used to form connections to the other players, *
  6163. * after the scenario has been loaded. *
  6164. * *
  6165. * The 'Chat' vector contains the address of everyone who sends me a chat announcement. *
  6166. * The address field is used to send everyone my outgoing messages. The LastTime *
  6167. * field is used as a timeout; if enough time goes by & we don't hear from this node, *
  6168. * we ping him, requesting a CHAT_ANNOUNCE if he's still in chat. If we don't hear *
  6169. * from him after that, we remove him from our list. *
  6170. * *
  6171. * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ *
  6172. * ³ Network Games ³ *
  6173. * ³ ³ *
  6174. * ³ Your Name: ____________ ³ *
  6175. * ³ House: [GDI] [NOD] ³ *
  6176. * ³ Desired Color: [ ][ ][ ][ ] ³ *
  6177. * ³ ³ *
  6178. * ³ Games Players ³ *
  6179. * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ *
  6180. * ³ ³(Bill's Game )³.³ ³ Peter Parker GDI ³.³ ³ *
  6181. * ³ ³ Peter Parker's Game ÃÄ´ ³ Mary Jane GDI ÃÄ´ ³ *
  6182. * ³ ³(Magnum PI's Game )³ ³ ³ JJ Jameson NOD ³ ³ ³ *
  6183. * ³ ³ ÃÄ´ ³ ÃÄ´ ³ *
  6184. * ³ ³ ³.³ ³ ³.³ ³ *
  6185. * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ *
  6186. * ³ Scenario: Big Long Description ³ *
  6187. * ³ Starting Credits: xxxx ³ *
  6188. * ³ Count: --- Level: --- ³ *
  6189. * ³ Bases: ON Crates: ON ³ *
  6190. * ³ Tiberium: ON AI Players: ON ³ *
  6191. * ³ ³ *
  6192. * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ *
  6193. * ³ ³ ³ ³ *
  6194. * ³ ³ ³ ³ *
  6195. * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ *
  6196. * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ *
  6197. * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ *
  6198. * ³ [Join] [Cancel] [New] ³ *
  6199. * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ *
  6200. * *
  6201. * INPUT: *
  6202. * none. *
  6203. * *
  6204. * OUTPUT: *
  6205. * -1 = cancel, 0 = OK, 1 = New net game requested *
  6206. * *
  6207. * WARNINGS: *
  6208. * none. *
  6209. * *
  6210. * HISTORY: *
  6211. * 02/14/1995 BR : Created. *
  6212. *=============================================================================================*/
  6213. static int Net_Fake_Join_Dialog(void)
  6214. {
  6215. #ifdef WIN32
  6216. //------------------------------------------------------------------------
  6217. // Dialog & button dimensions
  6218. //------------------------------------------------------------------------
  6219. int d_dialog_w = 120 *RESFACTOR; // dialog width
  6220. int d_dialog_h = 80 *RESFACTOR; // dialog height
  6221. int d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2); // dialog x-coord
  6222. int d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2); // centered y-coord
  6223. int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
  6224. int d_txt6_h = 6 *RESFACTOR+1; // ht of 6-pt text
  6225. int d_margin1 = 5 *RESFACTOR; // large margin
  6226. int d_margin2 = 7 *RESFACTOR; // small margin
  6227. int d_gamelist_w = 160 *RESFACTOR;
  6228. int d_gamelist_h = ((6 * 6) + 3) *RESFACTOR; // 6 rows high
  6229. // int d_gamelist_x = d_dialog_x + d_margin1 + d_margin1;
  6230. int d_gamelist_x = 500*RESFACTOR; //d_dialog_x + d_margin1 + d_margin1;
  6231. int d_gamelist_y = 50 + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;
  6232. int d_playerlist_w = 118 *RESFACTOR;
  6233. int d_playerlist_h = ((6 * 6) + 3) *RESFACTOR; // 6 rows high
  6234. //int d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_playerlist_w;
  6235. int d_playerlist_x = 500*RESFACTOR;
  6236. int d_playerlist_y = 50+ d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/;
  6237. #if (GERMAN | FRENCH)
  6238. int d_cancel_w = 50*RESFACTOR;
  6239. #else
  6240. int d_cancel_w = 40*RESFACTOR;
  6241. #endif
  6242. int d_cancel_h = 9*RESFACTOR;
  6243. int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
  6244. int d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;
  6245. //------------------------------------------------------------------------
  6246. // Button Enumerations
  6247. //------------------------------------------------------------------------
  6248. enum {
  6249. BUTTON_GAMELIST = 100,
  6250. BUTTON_PLAYERLIST,
  6251. BUTTON_CANCEL,
  6252. };
  6253. //------------------------------------------------------------------------
  6254. // Redraw values: in order from "top" to "bottom" layer of the dialog
  6255. //------------------------------------------------------------------------
  6256. typedef enum {
  6257. REDRAW_NONE = 0,
  6258. REDRAW_PARMS,
  6259. REDRAW_MESSAGE,
  6260. REDRAW_COLORS,
  6261. REDRAW_BUTTONS,
  6262. REDRAW_BACKGROUND,
  6263. REDRAW_ALL = REDRAW_BACKGROUND
  6264. } RedrawType;
  6265. //------------------------------------------------------------------------
  6266. // Dialog variables
  6267. //------------------------------------------------------------------------
  6268. RedrawType display = REDRAW_ALL; // redraw level
  6269. bool process = true; // process while true
  6270. KeyNumType input;
  6271. char housetext[25] = ""; // buffer for house droplist
  6272. int isdropped = 0;
  6273. JoinStateType joinstate = JOIN_NOTHING; // current "state" of this dialog
  6274. char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
  6275. int playertabs[] = {77 *RESFACTOR}; // tabs for player list box
  6276. int optiontabs[] = {8}; // tabs for player list box
  6277. int game_index = -1; // index of currently-selected game
  6278. int join_index = -1; // index of game we're joining
  6279. int rc = 0; // -1 = user cancelled, 1 = New
  6280. JoinEventType event; // event from incoming packet
  6281. int i; // loop counter
  6282. int parms_received = 0; // 1 = game options received
  6283. NodeNameType *who; // node to add to Players
  6284. RejectType why; // reason for rejection
  6285. TTimerClass<SystemTimerClass> lastclick_timer; // time b/w send periods
  6286. int lastclick_idx = 0; // index of item last clicked on
  6287. RemapControlType * scheme = GadgetClass::Get_Color_Scheme();
  6288. int ready_to_go = 0;
  6289. Session.Options.ScenarioDescription[0] = 0; //Flag that we dont know the scenario name yet
  6290. int width;
  6291. int height;
  6292. Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
  6293. Format_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height);
  6294. char * item;
  6295. unsigned long starttime;
  6296. int load_game = 0; // 1 = load saved game
  6297. //------------------------------------------------------------------------
  6298. // Buttons
  6299. //------------------------------------------------------------------------
  6300. GadgetClass *commands; // button list
  6301. ListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,
  6302. TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"));
  6303. ColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
  6304. TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP"));
  6305. TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON,
  6306. //#if (GERMAN | FRENCH)
  6307. // d_cancel_x, d_cancel_y);
  6308. //#else
  6309. d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
  6310. //#endif
  6311. //------------------------------------------------------------------------
  6312. // Init the button states
  6313. //------------------------------------------------------------------------
  6314. //........................................................................
  6315. // Name & Color
  6316. //........................................................................
  6317. Session.ColorIdx = Session.PrefColor; // init my preferred color
  6318. strcpy (namebuf, Session.Handle); // set my name
  6319. //........................................................................
  6320. // List boxes
  6321. //........................................................................
  6322. playerlist.Set_Tabs(playertabs);
  6323. playerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL);
  6324. Fancy_Text_Print("", 0, 0, scheme, TBLACK,
  6325. TPF_CENTER | TPF_TEXT);
  6326. lastclick_timer = 0;
  6327. //------------------------------------------------------------------------
  6328. // Clear the list of games, players, and the chat list
  6329. //------------------------------------------------------------------------
  6330. Clear_Vector(&Session.Games);
  6331. Clear_Vector(&Session.Players);
  6332. Clear_Vector(&Session.Chat);
  6333. //------------------------------------------------------------------------
  6334. // Add myself to the Chat vector
  6335. //------------------------------------------------------------------------
  6336. who = new NodeNameType;
  6337. strcpy(who->Name, namebuf);
  6338. who->Chat.LastTime = 0;
  6339. who->Chat.LastChance = 0;
  6340. who->Chat.Color = Session.GPacket.Chat.Color;
  6341. Session.Chat.Add (who);
  6342. //------------------------------------------------------------------------
  6343. // Create the "Lobby" game name on the games list, and create a bogus
  6344. // node for the gamelist, so Games[i] will always match gamelist[i]
  6345. //------------------------------------------------------------------------
  6346. who = new NodeNameType;
  6347. strcpy(who->Name, "");
  6348. who->Game.IsOpen = 0;
  6349. who->Game.LastTime = 0;
  6350. Session.Games.Add (who);
  6351. item = new char [MPLAYER_NAME_MAX];
  6352. strcpy(item, Text_String(TXT_LOBBY));
  6353. gamelist.Add_Item(item);
  6354. gamelist.Set_Selected_Index(0);
  6355. game_index = 0;
  6356. //------------------------------------------------------------------------
  6357. // Send game-name query & chat announcement; also, initialize timers.
  6358. //------------------------------------------------------------------------
  6359. Send_Join_Queries (game_index, joinstate, 1, 0, 1, namebuf, 1);
  6360. /*
  6361. ** Process the message loop until we are in focus.
  6362. */
  6363. CDTimerClass<SystemTimerClass> focus_timer; // Timer to allow a wait after client joins
  6364. focus_timer = 5*60;
  6365. WWDebugString ("RA95 - About to enter wait for focus loop.\n");
  6366. SetForegroundWindow ( MainWindow );
  6367. ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
  6368. if (!GameInFocus) {
  6369. do {
  6370. Keyboard->Check();
  6371. if (!focus_timer){
  6372. WWDebugString ("RA95 - Calling SetForgroundWindow.\n");
  6373. SetForegroundWindow ( MainWindow );
  6374. WWDebugString ("RA95 - Calling ShowWindow.\n");
  6375. ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
  6376. focus_timer = 5*60;
  6377. }
  6378. }while (!GameInFocus);
  6379. AllSurfaces.SurfacesRestored=FALSE;
  6380. }
  6381. if (LogicPage != &SeenBuff && LogicPage!= &HidPage) {
  6382. Set_Logic_Page (SeenBuff);
  6383. }
  6384. Load_Title_Page(true);
  6385. CCPalette.Set(); //GamePalette.Set();
  6386. //------------------------------------------------------------------------
  6387. // Processing loop
  6388. //------------------------------------------------------------------------
  6389. while (process) {
  6390. #ifdef WIN32
  6391. /*
  6392. ** If we have just received input focus again after running in the background then
  6393. ** we need to redraw.
  6394. */
  6395. if (AllSurfaces.SurfacesRestored) {
  6396. AllSurfaces.SurfacesRestored=FALSE;
  6397. display = REDRAW_ALL;
  6398. }
  6399. #endif
  6400. //.....................................................................
  6401. // Refresh display if needed
  6402. //.....................................................................
  6403. if (display) {
  6404. Hide_Mouse();
  6405. //..................................................................
  6406. // Redraw backgound & dialog box
  6407. //..................................................................
  6408. if (display >= REDRAW_BACKGROUND) {
  6409. Load_Title_Page(true);
  6410. CCPalette.Set(); //GamePalette.Set();
  6411. Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
  6412. //...............................................................
  6413. // Dialog & Field labels
  6414. //...............................................................
  6415. Fancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT);
  6416. //...............................................................
  6417. // Rebuild the button list
  6418. //...............................................................
  6419. cancelbtn.Zap();
  6420. gamelist.Zap();
  6421. playerlist.Zap();
  6422. commands = &cancelbtn;
  6423. gamelist.Add_Tail(*commands);
  6424. playerlist.Add_Tail(*commands);
  6425. }
  6426. //..................................................................
  6427. // Redraw buttons
  6428. //..................................................................
  6429. if (display >= REDRAW_BUTTONS) {
  6430. commands->Draw_All();
  6431. }
  6432. Show_Mouse();
  6433. display = REDRAW_NONE;
  6434. }
  6435. //.....................................................................
  6436. // Get user input
  6437. //.....................................................................
  6438. input = commands->Input();
  6439. //.....................................................................
  6440. // Process input
  6441. //.....................................................................
  6442. switch (input) {
  6443. //..................................................................
  6444. // ESC / CANCEL: send a SIGN_OFF
  6445. // - If we're part of a game, stay in this dialog; otherwise, exit
  6446. //..................................................................
  6447. case (KN_ESC):
  6448. case (BUTTON_CANCEL | KN_BUTTON):
  6449. //...............................................................
  6450. // If we're joined to a game, make extra sure the other players in
  6451. // that game know I'm exiting; send my SIGN_OFF as an ack-required
  6452. // packet. Don't send this to myself (index 0).
  6453. //...............................................................
  6454. if (joinstate == JOIN_CONFIRMED) {
  6455. Unjoin_Game(namebuf, joinstate, &gamelist, &playerlist,
  6456. game_index, 1, 0, 0, d_txt6_h, 0,
  6457. 0, MAX_MESSAGE_LENGTH);
  6458. joinstate = JOIN_NOTHING;
  6459. display = REDRAW_ALL;
  6460. }
  6461. //...............................................................
  6462. // If I'm not joined to a game, send a SIGN_OFF to all players
  6463. // in my Chat vector (but not to myself, index 0)
  6464. //...............................................................
  6465. else {
  6466. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  6467. Session.GPacket.Command = NET_SIGN_OFF;
  6468. strcpy(Session.GPacket.Name,namebuf);
  6469. for (i = 1; i < Session.Chat.Count(); i++) {
  6470. Ipx.Send_Global_Message (&Session.GPacket,
  6471. sizeof(GlobalPacketType),
  6472. 1, &(Session.Chat[i]->Address));
  6473. Ipx.Service();
  6474. }
  6475. //............................................................
  6476. // Now broadcast a SIGN_OFF just to be thorough
  6477. //............................................................
  6478. Ipx.Send_Global_Message (&Session.GPacket,
  6479. sizeof (GlobalPacketType), 0, NULL);
  6480. if (Session.IsBridge) {
  6481. Ipx.Send_Global_Message (&Session.GPacket,
  6482. sizeof(GlobalPacketType), 0, &Session.BridgeNet);
  6483. }
  6484. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  6485. //............................................................
  6486. // exit the dialog
  6487. //............................................................
  6488. Send_Data_To_DDE_Server ("Hello", strlen("Hello"), DDEServerClass::DDE_CONNECTION_FAILED);
  6489. GameStatisticsPacketSent = false;
  6490. Spawn_WChat(false);
  6491. process = false;
  6492. rc = -1;
  6493. }
  6494. break;
  6495. //..................................................................
  6496. // JOIN: send a join request packet & switch to waiting-for-
  6497. // confirmation mode.
  6498. //..................................................................
  6499. default:
  6500. if (joinstate == JOIN_NOTHING && gamelist.Count() >1 ) {
  6501. gamelist.Set_Selected_Index(1); //lastclick_idx);
  6502. game_index = 1;
  6503. strcpy (Session.Handle,namebuf);
  6504. //Session.House = (HousesType)housebtn.Current_Index();
  6505. join_index = gamelist.Current_Index();
  6506. parms_received = 0;
  6507. if (Request_To_Join (namebuf, join_index, Session.House,
  6508. Session.ColorIdx)) {
  6509. joinstate = JOIN_WAIT_CONFIRM;
  6510. } else {
  6511. display = REDRAW_ALL;
  6512. }
  6513. }
  6514. break;
  6515. }
  6516. //.....................................................................
  6517. // Resend our query packets
  6518. //.....................................................................
  6519. Send_Join_Queries(game_index, joinstate, 0, 0, 0, namebuf);
  6520. //.....................................................................
  6521. // Process incoming packets
  6522. //.....................................................................
  6523. event = Get_Join_Responses(&joinstate, &gamelist, &playerlist,
  6524. join_index, namebuf, &why);
  6525. //.....................................................................
  6526. // If we've changed state, redraw everything; if we're starting the game,
  6527. // break out of the loop. If we've just joined, send out a player query
  6528. // so I'll get added to the list instantly.
  6529. //.....................................................................
  6530. if (event == EV_STATE_CHANGE) {
  6531. display = REDRAW_ALL;
  6532. if (joinstate==JOIN_GAME_START || joinstate == JOIN_GAME_START_LOAD) {
  6533. if (joinstate==JOIN_GAME_START_LOAD) load_game = 1;
  6534. bool ready_packet_was_sent = false;
  6535. if (!load_game){
  6536. /*
  6537. ** Special new kludge for counterstrike.
  6538. **
  6539. ** Find local scenario will fail to match a counterstrike mission
  6540. ** unless the CS CD is in the drive. So....
  6541. **
  6542. ** If Counterstrike is installed and this is an official map and
  6543. ** the file name matches a counterstrike map then tell the host
  6544. ** that I have the scenario so he can continue while we make
  6545. ** sure the local user has the Counterstrike CD in the drive.
  6546. **
  6547. */
  6548. // This is duplicated for Aftermath scenarios. ajw
  6549. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  6550. if (Session.ScenarioIsOfficial &&
  6551. ( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) ||
  6552. (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) {
  6553. #else
  6554. if ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) {
  6555. #endif
  6556. CCFileClass check_file ( Session.ScenarioFileName );
  6557. if ( !check_file.Is_Available() ) {
  6558. int current_drive = CCFileClass::Get_CD_Drive();
  6559. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  6560. int index = Get_CD_Index(current_drive, 1*60);
  6561. bool needcd = false;
  6562. if (Is_Mission_Counterstrike(Session.ScenarioFileName)) {
  6563. if (index != 2 && index != 3) {
  6564. RequiredCD = 2;
  6565. needcd = true;
  6566. }
  6567. }
  6568. if (Is_Mission_Aftermath(Session.ScenarioFileName)) {
  6569. if (index != 3) {
  6570. RequiredCD = 3;
  6571. needcd = true;
  6572. }
  6573. }
  6574. if (needcd) {
  6575. #else
  6576. if ( Get_CD_Index(current_drive, 1*60) != 2 ){
  6577. RequiredCD = 2;
  6578. #endif
  6579. /*
  6580. ** We should have the scenario but the wrong disk is in.
  6581. ** Tell the host that I am ready to go anyway.
  6582. */
  6583. memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));
  6584. Session.GPacket.Command = NET_READY_TO_GO;
  6585. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  6586. 1, &Session.HostAddress);
  6587. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);
  6588. ready_packet_was_sent = true;
  6589. if (!Force_CD_Available (RequiredCD)){
  6590. Emergency_Exit(EXIT_FAILURE);
  6591. }
  6592. CCFileClass testfile ( Session.ScenarioFileName );
  6593. /*
  6594. ** Update the internal list of scenarios to include the counterstrike
  6595. ** list.
  6596. */
  6597. Session.Read_Scenario_Descriptions();
  6598. /*
  6599. ** See if that scenario is available now. Its pretty fatal if it isnt.
  6600. */
  6601. Session.Options.ScenarioIndex = -1;
  6602. for (i = 0; i < Session.Scenarios.Count(); i++) {
  6603. if (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){
  6604. Session.Options.ScenarioIndex = i;
  6605. break;
  6606. }
  6607. }
  6608. }
  6609. }
  6610. }
  6611. /*
  6612. ** If the scenario that the host wants to play doesnt exist locally then we
  6613. ** need to request that it is sent. If we can identify the scenario locally then
  6614. ** we need to fix up the file name so we load the right one.
  6615. */
  6616. if (Find_Local_Scenario (Session.Options.ScenarioDescription,
  6617. Session.ScenarioFileName,
  6618. Session.ScenarioFileLength,
  6619. Session.ScenarioDigest,
  6620. Session.ScenarioIsOfficial)) {
  6621. Session.Options.ScenarioIndex = 1; //We dont care what it
  6622. //is as long as it isnt -1
  6623. /*
  6624. ** We have the scenario. Tell the host that I am ready to go.
  6625. */
  6626. if ( !ready_packet_was_sent ){
  6627. memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));
  6628. Session.GPacket.Command = NET_READY_TO_GO;
  6629. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  6630. 1, &Session.HostAddress);
  6631. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);
  6632. }
  6633. } else {
  6634. #ifndef FIXIT_VERSION_3 // Removed restriction on downloading official maps.
  6635. /*
  6636. ** Oh dear. Thats a scenario I dont have. Request that the host sends the
  6637. ** scenario to me provided its not an official Westwood scenario.
  6638. **
  6639. ** If the file is received OK then we will get a true return value and the
  6640. ** actual file name to load will be in Session.ScenarioFileName
  6641. */
  6642. if (Session.ScenarioIsOfficial) {
  6643. Session.Options.ScenarioIndex = -1;
  6644. } else {
  6645. #endif
  6646. Session.Options.ScenarioIndex = 1; //We dont care what it
  6647. //is as long as it isnt -1
  6648. #ifdef FIXIT_VERSION_3
  6649. if( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) )
  6650. break;
  6651. #endif
  6652. if (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 1)) {
  6653. break;
  6654. } else {
  6655. /*
  6656. ** Make sure we dont time-out because of the download
  6657. */
  6658. }
  6659. #ifndef FIXIT_VERSION_3
  6660. }
  6661. #endif
  6662. }
  6663. }else{
  6664. /*
  6665. ** Make sure we respond to the host in a load game
  6666. */
  6667. memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket));
  6668. Session.GPacket.Command = NET_READY_TO_GO;
  6669. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  6670. 1, &Session.HostAddress);
  6671. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0);
  6672. }
  6673. strcpy (Scen.ScenarioName, Session.ScenarioFileName);
  6674. rc = 0;
  6675. process = false;
  6676. }
  6677. //..................................................................
  6678. // If we're newly-confirmed, add myself to the Players list, and
  6679. // immediately send out a player query
  6680. //..................................................................
  6681. else if (joinstate==JOIN_CONFIRMED) {
  6682. //...............................................................
  6683. // Clear the player list, then add myself to the list.
  6684. //...............................................................
  6685. Clear_Listbox(&playerlist);
  6686. Clear_Vector (&Session.Players);
  6687. item = new char [MPLAYER_NAME_MAX + 12];
  6688. #ifdef OLDWAY
  6689. if (Session.House==HOUSE_GOOD) {
  6690. sprintf(item,"%s\t%s",namebuf, Text_String(TXT_ALLIES));
  6691. } else {
  6692. sprintf(item,"%s\t%s",namebuf, Text_String(TXT_SOVIET));
  6693. }
  6694. #else //OLDWAY
  6695. sprintf (item, "%s\t%s", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name()));
  6696. #endif //OLDWAY
  6697. playerlist.Add_Item(item,
  6698. (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]);
  6699. who = new NodeNameType;
  6700. strcpy(who->Name, namebuf);
  6701. who->Player.House = Session.House;
  6702. who->Player.Color = Session.ColorIdx;
  6703. Session.Players.Add (who);
  6704. Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);
  6705. #if (0)
  6706. //...............................................................
  6707. // Re-init the message system to its new smaller size
  6708. //...............................................................
  6709. Session.Messages.Init (0,0, 8,
  6710. MAX_MESSAGE_LENGTH, d_txt6_h, 0, 0, 1,
  6711. 20, MAX_MESSAGE_LENGTH - 5);
  6712. Session.Messages.Add_Edit(Session.ColorIdx, TPF_TEXT | TPF_BRIGHT_COLOR, NULL, '_');
  6713. #endif //(0)
  6714. }
  6715. //..................................................................
  6716. // If we've been rejected, clear any messages we may have been
  6717. // typing, add a message stating why we were rejected, and send a
  6718. // chat announcement.
  6719. //..................................................................
  6720. else if (joinstate==JOIN_REJECTED) {
  6721. Sound_Effect(VOC_SYS_ERROR);
  6722. Send_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf);
  6723. }
  6724. } // end of state change
  6725. //.....................................................................
  6726. // If the game options have changed, print them.
  6727. //.....................................................................
  6728. else if (event == EV_GAME_OPTIONS) {
  6729. Sound_Effect(VOC_OPTIONS_CHANGED);
  6730. parms_received = 1;
  6731. display = REDRAW_PARMS;
  6732. }
  6733. //.....................................................................
  6734. // EV_GAME_SIGNOFF:
  6735. // A game before the one I've selected is gone, so we have a new index
  6736. // now. 'game_index' must be kept set to the currently-selected list
  6737. // item, so we send out queries for the currently-selected game. It's
  6738. // therefore imperative that we detect any changes to the game list.
  6739. // If we're joined in a game, we must decrement our game_index to keep
  6740. // it aligned with the game we're joined to.
  6741. //.....................................................................
  6742. else if (event == EV_GAME_SIGNOFF) {
  6743. if (joinstate==JOIN_CONFIRMED) {
  6744. game_index--;
  6745. join_index--;
  6746. gamelist.Set_Selected_Index(join_index);
  6747. }
  6748. else {
  6749. gamelist.Flag_To_Redraw();
  6750. Clear_Listbox(&playerlist);
  6751. Clear_Vector (&Session.Players);
  6752. game_index = gamelist.Current_Index();
  6753. Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);
  6754. }
  6755. }
  6756. //.....................................................................
  6757. // Service the Ipx connections
  6758. //.....................................................................
  6759. Ipx.Service();
  6760. if (process) {
  6761. //.....................................................................
  6762. // Clean out the Game List; if an old entry is found:
  6763. // - Remove it
  6764. // - Clear the player list
  6765. // - Send queries for the new selected game, if there is one
  6766. //.....................................................................
  6767. for (i = 1; i < Session.Games.Count(); i++) {
  6768. if (TickCount - Session.Games[i]->Game.LastTime > 400) {
  6769. delete Session.Games[i];
  6770. Session.Games.Delete(Session.Games[i]);
  6771. item = (char *)(gamelist.Get_Item (i));
  6772. gamelist.Remove_Item (item);
  6773. delete [] item;
  6774. if (i <= game_index) {
  6775. if (joinstate==JOIN_CONFIRMED) {
  6776. game_index--;
  6777. join_index--;
  6778. gamelist.Set_Selected_Index(join_index);
  6779. }
  6780. else {
  6781. gamelist.Flag_To_Redraw();
  6782. Clear_Listbox(&playerlist);
  6783. Clear_Vector (&Session.Players);
  6784. game_index = gamelist.Current_Index();
  6785. Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf);
  6786. }
  6787. }
  6788. }
  6789. }
  6790. }
  6791. #if (0)
  6792. /*
  6793. ** If we were flagged to start the game and we recognise both players then quit the loop
  6794. */
  6795. if (ready_to_go && Session.Players.Count() == 2) {
  6796. rc = 0;
  6797. process = false;
  6798. }
  6799. #endif //(0)
  6800. //.....................................................................
  6801. // Service the sounds & score; GameActive must be false at this point,
  6802. // so Call_Back() doesn't intercept global messages from me!
  6803. //.....................................................................
  6804. Call_Back();
  6805. } // end of while
  6806. //------------------------------------------------------------------------
  6807. // Establish connections with all other players.
  6808. //------------------------------------------------------------------------
  6809. if (rc == 0) {
  6810. //.....................................................................
  6811. // If the other guys are playing a scenario I don't have (sniff), I can't
  6812. // play. Try to bail gracefully.
  6813. //.....................................................................
  6814. if (Session.Options.ScenarioIndex==-1) {
  6815. WWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
  6816. memset (&Session.GPacket, 0, sizeof(GlobalPacketType));
  6817. Session.GPacket.Command = NET_SIGN_OFF;
  6818. strcpy (Session.GPacket.Name, namebuf);
  6819. //..................................................................
  6820. // Don't send myself the message.
  6821. //..................................................................
  6822. for (i = 1; i < Session.Players.Count(); i++) {
  6823. Ipx.Send_Global_Message (&Session.GPacket,
  6824. sizeof(GlobalPacketType), 1,
  6825. &(Session.Players[i]->Address));
  6826. Ipx.Service();
  6827. }
  6828. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  6829. 0, NULL);
  6830. Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType),
  6831. 0, NULL);
  6832. if (Session.IsBridge) {
  6833. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),
  6834. 0, &Session.BridgeNet);
  6835. Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType),
  6836. 0, &Session.BridgeNet);
  6837. }
  6838. while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
  6839. rc = -1;
  6840. }
  6841. //---------------------------------------------------------------------
  6842. // Prepare to load the scenario.
  6843. //---------------------------------------------------------------------
  6844. else {
  6845. //..................................................................
  6846. // Set the number of players in this game, and the scenario number.
  6847. //..................................................................
  6848. Session.NumPlayers = Session.Players.Count();
  6849. ///*
  6850. //** Hack to fake a scenario name as if it had been sent over the connection.
  6851. //*/
  6852. //sprintf(Scen.ScenarioName, "SCM%02dEA.INI", Session.Options.ScenarioIndex+1);
  6853. // Scen.Scenario = Session.Options.ScenarioIndex;
  6854. }
  6855. //.....................................................................
  6856. // Wait a while, polling the IPX service routines, to give our ACK
  6857. // a chance to get to the other system. If he doesn't get our ACK,
  6858. // he'll be waiting the whole time we load MIX files.
  6859. //.....................................................................
  6860. i = MAX(Ipx.Global_Response_Time() * 2, 60*2);
  6861. starttime = TickCount;
  6862. while (TickCount - starttime < i) {
  6863. Ipx.Service();
  6864. }
  6865. }
  6866. //------------------------------------------------------------------------
  6867. // Init network timing values, using previous response times as a measure
  6868. // of what our retry delta & timeout should be.
  6869. //------------------------------------------------------------------------
  6870. //Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
  6871. // Ipx.Global_Response_Time() * 4);
  6872. Ipx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8));
  6873. //------------------------------------------------------------------------
  6874. // Clear all lists, but NOT the Games & Players vectors.
  6875. //------------------------------------------------------------------------
  6876. Clear_Listbox(&gamelist);
  6877. Clear_Listbox(&playerlist);
  6878. //------------------------------------------------------------------------
  6879. // Restore screen
  6880. //------------------------------------------------------------------------
  6881. Hide_Mouse();
  6882. Load_Title_Page(true);
  6883. Show_Mouse();
  6884. //------------------------------------------------------------------------
  6885. // Load a game if the game owner told us to
  6886. //------------------------------------------------------------------------
  6887. if (load_game) {
  6888. if (!Load_Game (-1)) {
  6889. WWMessageBox().Process (TXT_ERROR_LOADING_GAME);
  6890. rc = -1;
  6891. }
  6892. Frame++;
  6893. }
  6894. //------------------------------------------------------------------------
  6895. // Clear the Players & Games vectors if we're not joined to a game.
  6896. // Clear the Chat vector regardless.
  6897. //------------------------------------------------------------------------
  6898. if (rc != 0) {
  6899. Clear_Vector(&Session.Games);
  6900. Clear_Vector(&Session.Players);
  6901. }
  6902. Clear_Vector(&Session.Chat);
  6903. return(rc);
  6904. #else //WIN32
  6905. return (0);
  6906. #endif //WIN32
  6907. } /* end of Net_Join_Dialog */
  6908. bool Server_Remote_Connect(void)
  6909. {
  6910. int stealth; // original state of Session.NetStealth flag
  6911. //------------------------------------------------------------------------
  6912. // Init network timing parameters; these values should work for both a
  6913. // "real" network, and a simulated modem network (ie Kali)
  6914. //------------------------------------------------------------------------
  6915. Ipx.Set_Timing ( 30, // retry 2 times per second
  6916. -1, // ignore max retries
  6917. 600); // give up after 10 seconds
  6918. //------------------------------------------------------------------------
  6919. // Save the original value of the NetStealth flag, so we can turn stealth
  6920. // off for now (during this portion of the dialogs, we must show ourselves)
  6921. //------------------------------------------------------------------------
  6922. stealth = Session.NetStealth;
  6923. Session.NetStealth = 0;
  6924. //------------------------------------------------------------------------
  6925. // The game is now "open" for joining. Close it as soon as we exit this
  6926. // routine.
  6927. //------------------------------------------------------------------------
  6928. Session.NetOpen = 1;
  6929. //------------------------------------------------------------------------
  6930. // Read in last multiplayer game settings from the .INI file
  6931. //------------------------------------------------------------------------
  6932. if (!Net_Fake_New_Dialog()) {
  6933. Session.Write_MultiPlayer_Settings ();
  6934. return (false);
  6935. }
  6936. Session.NetOpen = 0;
  6937. Session.NetStealth = stealth;
  6938. Session.Write_MultiPlayer_Settings ();
  6939. return (true);
  6940. } /* end of Server_Remote_Connect */
  6941. bool Client_Remote_Connect(void)
  6942. {
  6943. int rc;
  6944. int stealth; // original state of Session.NetStealth flag
  6945. //------------------------------------------------------------------------
  6946. // Init network timing parameters; these values should work for both a
  6947. // "real" network, and a simulated modem network (ie Kali)
  6948. //------------------------------------------------------------------------
  6949. Ipx.Set_Timing ( 30, // retry 2 times per second
  6950. -1, // ignore max retries
  6951. 600); // give up after 10 seconds
  6952. //------------------------------------------------------------------------
  6953. // Save the original value of the NetStealth flag, so we can turn stealth
  6954. // off for now (during this portion of the dialogs, we must show ourselves)
  6955. //------------------------------------------------------------------------
  6956. stealth = Session.NetStealth;
  6957. Session.NetStealth = 0;
  6958. //------------------------------------------------------------------------
  6959. // The game is now "open" for joining. Close it as soon as we exit this
  6960. // routine.
  6961. //------------------------------------------------------------------------
  6962. Session.NetOpen = 1;
  6963. //------------------------------------------------------------------------
  6964. // Read in last multiplayer game settings from the .INI file
  6965. //------------------------------------------------------------------------
  6966. rc = Net_Fake_Join_Dialog();
  6967. Session.Write_MultiPlayer_Settings ();
  6968. Session.NetStealth = stealth;
  6969. Session.NetOpen = 0;
  6970. if (rc == -1) {
  6971. return(false);
  6972. } else {
  6973. return(true);
  6974. }
  6975. } /* end of Client_Remote_Connect */
  6976. /*************************** end of netdlg.cpp *****************************/
  6977. #endif //#ifndef WOLAPI_INTEGRATION