| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295 |
- /*
- ** Command & Conquer(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /* $Header: F:\projects\c&c\vcs\code\netdlg.cpv 2.17 16 Oct 1995 16:52:26 JOE_BOSTIC $ */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : NETDLG.CPP *
- * *
- * Programmer : Bill Randolph *
- * *
- * Start Date : January 23, 1995 *
- * *
- * Last Update : July 8, 1995 [BRR] *
- * *
- *---------------------------------------------------------------------------------------------*
- * *
- * These routines establish & maintain peer-to-peer connections between this system *
- * and all others in the game. Each system finds out the IPX address of the others, *
- * and forms a direct connection (IPXConnectionClass) to that system. Systems are *
- * found out via broadcast queries. Every system broadcasts its queries, and every *
- * system replies to queries it receives. At the point when the game owner signals *
- * 'OK', every system must know about all the other systems in the game. *
- * *
- * How Bridges are handled: *
- * Currently, bridges are handled by specifying the destination IPX address of the *
- * "server" (game owner's system) on the command-line. This address is used to *
- * derive a broadcast address to that destination network, and this system's queries *
- * are broadcast over its network & the server's network; replies to the queries come *
- * with each system's IPX address attached, so once we have the address, we can form *
- * a connection with any system on the bridged net. *
- * *
- * The flaw in this plan is that we can only cross one bridge. If there are 3 nets *
- * bridged (A, B, & C), and the server is on net B, and we're on net A, our broadcasts *
- * will reach nets A & B, but not C. The way to circumvent this (if it becomes a problem) *
- * would be to have the server tell us what other systems are in its game, not each *
- * individual player's system. Thus, each system would find out about all the other systems *
- * by interacting with the game's owner system (this would be more involved than what *
- * I'm doing here). *
- * *
- * Here's a list of all the different packets sent over the Global Channel: *
- * *
- * NET_QUERY_GAME *
- * (no other data) *
- * NET_ANSWER_GAME *
- * Name: game owner's name *
- * GameInfo: game's version & open state *
- * NET_QUERY_PLAYER *
- * Name: name of game we want players to respond for *
- * NET_ANSWER_PLAYER *
- * Name: player's name *
- * PlayerInfo: info about player *
- * NET_QUERY_JOIN *
- * Name: name of player wanting to join *
- * PlayerInfo: player's requested house & color *
- * NET_CONFIRM_JOIN *
- * PlayerInfo: approves player's house & color *
- * NET_REJECT_JOIN *
- * (no other data) *
- * NET_GAME_OPTIONS *
- * ScenarioInfo: info about scenario *
- * NET_SIGN_OFF *
- * Name: name of player signing off *
- * NET_PING *
- * (no other data) *
- * NET_GO *
- * Delay: value of one-way response time, in frames *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * Clear_Game_List -- Clears the game-name listbox & 'Games' Vector *
- * Clear_Player_List -- Clears the player-name listbox & Vector *
- * Destroy_Connection -- destroys the given connection *
- * Get_Join_Responses -- sends queries for the Join Dialog *
- * Get_NewGame_Responses -- processes packets for New Game dialog *
- * Init_Network -- initializes network stuff *
- * Net_Join_Dialog -- lets user join an existing game, or start a new one *
- * Net_New_Dialog -- lets user start a new game *
- * Process_Global_Packet -- responds to remote queries *
- * Remote_Connect -- handles connecting this user to others *
- * Request_To_Join -- Sends a JOIN request packet to game owner *
- * Send_Join_Queries -- sends queries for the Join Dialog *
- * Shutdown_Network -- shuts down network stuff *
- * Compute_Name_CRC -- computes CRC from char string *
- * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include <time.h>
- #include "tcpip.h"
- #define SHOW_MONO 0
- #ifndef DEMO
- /*---------------------------------------------------------------------------
- The possible states of the join-game dialog
- ---------------------------------------------------------------------------*/
- typedef enum {
- JOIN_REJECTED = -1, // we've been rejected
- JOIN_NOTHING, // we're not trying to join a game
- JOIN_WAIT_CONFIRM, // we're asking to join, & waiting for confirmation
- JOIN_CONFIRMED, // we've been confirmed
- JOIN_GAME_START, // the game we've joined is starting
- } JoinStateType;
- /*---------------------------------------------------------------------------
- The possible return codes from Get_Join_Responses()
- ---------------------------------------------------------------------------*/
- typedef enum {
- EV_NONE, // nothing happened
- EV_STATE_CHANGE, // Join dialog is in a new state
- EV_NEW_GAME, // a new game was detected
- EV_NEW_PLAYER, // a new player was detected
- EV_PLAYER_SIGNOFF, // a player has signed off
- EV_GAME_SIGNOFF, // a gamed owner has signed off
- EV_GAME_OPTIONS, // a game options packet was received
- EV_MESSAGE, // a message was received
- } JoinEventType;
- /*
- ******************************** Prototypes *********************************
- */
- static int Net_Join_Dialog(void);
- static void Clear_Game_List (ListClass *gamelist);
- static void Clear_Player_List (ListClass *playerlist);
- static int Request_To_Join (char *playername, int join_index, ListClass *playerlist,
- HousesType house, int color);
- static void Send_Join_Queries(int curgame, int gamenow, int playernow);
- static JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,
- ColorListClass *playerlist, int join_index);
- static int Net_New_Dialog(void);
- static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist);
- static int Net_Fake_New_Dialog(void);
- static int Net_Fake_Join_Dialog(void);
- /***********************************************************************************************
- * Init_Network -- initializes network stuff *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = Initialization OK, false = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- bool Init_Network (void)
- {
- NetNumType net;
- NetNodeType node;
- /*------------------------------------------------------------------------
- This call allocates all necessary queue buffers, allocates Real-mode
- memory, and commands IPX to start listening on the Global Channel.
- ------------------------------------------------------------------------*/
- if (!Ipx.Init())
- return(false);
- /*------------------------------------------------------------------------
- Allocate our "meta-packet" buffer
- ------------------------------------------------------------------------*/
- if (!MetaPacket) {
- MetaPacket = new char [sizeof (EventClass) * MAX_EVENTS];
- }
- /*------------------------------------------------------------------------
- Set up the IPX manager to cross a bridge
- ------------------------------------------------------------------------*/
- if (!(GameToPlay == GAME_INTERNET)){
- if (IsBridge) {
- BridgeNet.Get_Address(net,node);
- Ipx.Set_Bridge(net);
- }
- }
- return(true);
- } /* end of Init_Network */
- /***********************************************************************************************
- * Shutdown_Network -- shuts down network stuff *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- void Shutdown_Network (void)
- {
- /*------------------------------------------------------------------------
- Broadcast a sign-off packet, by sending the packet over the Global Channel,
- telling the IPX Manager that no ACK is required, and specifying a NULL
- destination address.
- ------------------------------------------------------------------------*/
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- if (IsBridge && !Winsock.Get_Connected()) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, &BridgeNet);
- }
- /*------------------------------------------------------------------------
- Wait for the packets to finish going out (or the Global Channel times out)
- ------------------------------------------------------------------------*/
- for (;;) {
- if (Ipx.Global_Num_Send()==0) {
- break;
- }
- Ipx.Service();
- }
- /*------------------------------------------------------------------------
- Delete our "meta-packet"
- ------------------------------------------------------------------------*/
- delete [] MetaPacket;
- MetaPacket = 0;
- /*------------------------------------------------------------------------
- If I was in a game, I'm not now, so clear the game name
- ------------------------------------------------------------------------*/
- MPlayerGameName[0] = 0;
- }
- /***********************************************************************************************
- * Process_Global_Packet -- responds to remote queries *
- * *
- * The only commands from other systems this routine responds to are NET_QUERY_GAME *
- * and NET_QUERY_PLAYER. The other commands are too context-specific to be able *
- * to handle here, such as joining the game or signing off; but this routine handles *
- * the majority of the program's needs. *
- * *
- * INPUT: *
- * packet ptr to packet to process *
- * address source address of sender *
- * *
- * OUTPUT: *
- * true = packet was processed, false = wasn't *
- * *
- * WARNINGS: *
- * MPlayerName & MPlayerGameName must have been filled in before this function *
- * can be called. *
- * *
- * HISTORY: *
- * 02/15/1995 BR : Created. *
- *=============================================================================================*/
- bool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address)
- {
- GlobalPacketType mypacket;
- /*
- ---------------- Another system asking what game this is -----------------
- */
- if (packet->Command==NET_QUERY_GAME && NetStealth==0) {
- /*.....................................................................
- If the game is closed, let every player respond, and let the sender of
- the query sort it all out. This way, if the game's host exits the game,
- the game still shows up on other players' dialogs.
- If the game is open, only the game owner may respond.
- .....................................................................*/
- if (strlen(MPlayerName) > 0 && strlen(MPlayerGameName) > 0 &&
- ((!NetOpen) || (NetOpen && !strcmp(MPlayerName,MPlayerGameName)))) {
- memset (packet, 0, sizeof(GlobalPacketType));
- mypacket.Command = NET_ANSWER_GAME;
- strcpy(mypacket.Name, MPlayerGameName);
- #ifdef PATCH
- if (IsV107) {
- mypacket.GameInfo.Version = 1;
- } else {
- mypacket.GameInfo.Version = 2;
- }
- #else
- mypacket.GameInfo.Version = Version_Number();
- #endif
- mypacket.GameInfo.IsOpen = NetOpen;
- Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1,
- address);
- }
- return(true);
- } else {
- /*
- ----------------- Another system asking what player I am -----------------
- */
- if (packet->Command==NET_QUERY_PLAYER &&
- !strcmp (packet->Name, MPlayerGameName) &&
- (strlen(MPlayerGameName) > 0) && NetStealth==0) {
- memset (packet, 0, sizeof(GlobalPacketType));
- mypacket.Command = NET_ANSWER_PLAYER;
- strcpy(mypacket.Name, MPlayerName);
- mypacket.PlayerInfo.House = MPlayerHouse;
- mypacket.PlayerInfo.Color = MPlayerColorIdx;
- mypacket.PlayerInfo.NameCRC = Compute_Name_CRC(MPlayerGameName);
- Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1, address);
- return(true);
- }
- }
- return(false);
- }
- /***********************************************************************************************
- * Destroy_Connection -- destroys the given connection *
- * *
- * Call this routine when a connection goes bad, or another player signs off. *
- * *
- * INPUT: *
- * id connection ID to destroy *
- * error 0 = user signed off; 1 = connection error; otherwise, no error is shown. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 04/22/1995 BR : Created. *
- *=============================================================================================*/
- void Destroy_Connection(int id, int error)
- {
- int i,j;
- HousesType house;
- HouseClass *housep;
- char txt[80];
- /*------------------------------------------------------------------------
- Create a message to display to the user
- ------------------------------------------------------------------------*/
- txt[0] = '\0';
- if (error==1) {
- sprintf(txt,Text_String(TXT_CONNECTION_LOST),Ipx.Connection_Name(id));
- } else if (error==0) {
- sprintf(txt,Text_String(TXT_LEFT_GAME),Ipx.Connection_Name(id));
- }
- if (strlen(txt)) {
- Messages.Add_Message (txt,
- MPlayerTColors[MPlayerID_To_ColorIndex((unsigned char)id)],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
- Map.Flag_To_Redraw(false);
- }
- /*------------------------------------------------------------------------
- Delete the IPX connection, shift the MPlayerID's & MPlayerHouses' back one.
- ------------------------------------------------------------------------*/
- Ipx.Delete_Connection(id);
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == (unsigned char)id) {
- /*..................................................................
- Turn the player's house over to the computer's AI
- ..................................................................*/
- house = MPlayerHouses[i];
- housep = HouseClass::As_Pointer (house);
- housep->IsHuman = false;
- housep->IsStarted = true;
- /*..................................................................
- Move arrays back by one
- ..................................................................*/
- for (j = i; j < MPlayerCount - 1; j++) {
- MPlayerID[j] = MPlayerID[j + 1];
- MPlayerHouses[j] = MPlayerHouses[j + 1];
- strcpy (MPlayerNames[j], MPlayerNames[j+1]);
- TheirProcessTime[j] = TheirProcessTime[j+1];
- }
- }
- }
- MPlayerCount--;
- /*------------------------------------------------------------------------
- If we're the last player left, tell the user.
- ------------------------------------------------------------------------*/
- if (MPlayerCount == 1) {
- sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME));
- Messages.Add_Message (txt,
- MPlayerTColors[MPlayerID_To_ColorIndex((unsigned char)id)],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
- Map.Flag_To_Redraw(false);
- }
- } /* end of Destroy_Connection */
- /***********************************************************************************************
- * Remote_Connect -- handles connecting this user to others *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = connections established; false = not *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- bool Remote_Connect(void)
- {
- int rc;
- int stealth; // original state of NetStealth flag
- /*------------------------------------------------------------------------
- Init network timing parameters; these values should work for both a "real"
- network, and a simulated modem network (ie Kali)
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing ( 30, // retry 2 times per second
- -1, // ignore max retries
- 600); // give up after 10 seconds
- /*------------------------------------------------------------------------
- Save the original value of the NetStealth flag, so we can turn stealth
- off for now (during this portion of the dialogs, we must show ourselves)
- ------------------------------------------------------------------------*/
- stealth = NetStealth;
- NetStealth = 0;
- /*------------------------------------------------------------------------
- Init my game name to 0-length, since I haven't joined any game yet.
- ------------------------------------------------------------------------*/
- MPlayerGameName[0] = 0;
- /*------------------------------------------------------------------------
- The game is now "open" for joining. Close it as soon as we exit this
- routine.
- ------------------------------------------------------------------------*/
- NetOpen = 1;
- /*------------------------------------------------------------------------
- Read the default values from the INI file
- ------------------------------------------------------------------------*/
- Read_MultiPlayer_Settings ();
- /*------------------------------------------------------------------------
- Keep looping until something useful happens.
- ------------------------------------------------------------------------*/
- while (1) {
- /*---------------------------------------------------------------------
- Pop up the network Join/New dialog
- ---------------------------------------------------------------------*/
- rc = Net_Join_Dialog();
- /*---------------------------------------------------------------------
- -1 = user selected Cancel
- ---------------------------------------------------------------------*/
- if (rc==-1) {
- NetStealth = stealth;
- NetOpen = 0;
- return(false);
- } else {
- /*---------------------------------------------------------------------
- 0 = user has joined an existing game; save values & return
- ---------------------------------------------------------------------*/
- if (rc==0) {
- Write_MultiPlayer_Settings ();
- NetStealth = stealth;
- NetOpen = 0;
- return(true);
- } else {
- /*---------------------------------------------------------------------
- 1 = user requests New Network Game
- ---------------------------------------------------------------------*/
- if (rc==1) {
- /*..................................................................
- Pop up the New Network Game dialog; if user selects OK, return
- 'true'; otherwise, return to the Join Dialog.
- ..................................................................*/
- if (Net_New_Dialog()) {
- Write_MultiPlayer_Settings ();
- NetOpen = 0;
- NetStealth = stealth;
- NetOpen = 0;
- return(true);
- } else {
- continue;
- }
- }
- }
- }
- }
- }
- /***********************************************************************************************
- * Remote_Connect -- handles connecting this host to the server in an internet game *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = connections established; false = not *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- bool Server_Remote_Connect(void)
- {
- int stealth; // original state of NetStealth flag
- /*------------------------------------------------------------------------
- Init network timing parameters; these values should work for both a "real"
- network, and a simulated modem network (ie Kali)
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing ( 30, // retry 2 times per second
- -1, // ignore max retries
- 600); // give up after 10 seconds
- /*------------------------------------------------------------------------
- Save the original value of the NetStealth flag, so we can turn stealth
- off for now (during this portion of the dialogs, we must show ourselves)
- ------------------------------------------------------------------------*/
- stealth = NetStealth;
- NetStealth = 0;
- /*------------------------------------------------------------------------
- The game is now "open" for joining. Close it as soon as we exit this
- routine.
- ------------------------------------------------------------------------*/
- NetOpen = 1;
- /*------------------------------------------------------------------------
- Read the default values from the INI file
- ------------------------------------------------------------------------*/
- Read_MultiPlayer_Settings ();
- if (!Net_Fake_New_Dialog()){
- Write_MultiPlayer_Settings ();
- return (false);
- }
- NetOpen = 0;
- NetStealth = stealth;
- Write_MultiPlayer_Settings ();
- return (true);
- }
- /***********************************************************************************************
- * Client_Remote_Connect -- handles connecting this client to the server in an internet game *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = connections established; false = not *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 ST : Created. *
- *=============================================================================================*/
- bool Client_Remote_Connect(void)
- {
- int rc;
- int stealth; // original state of NetStealth flag
- /*------------------------------------------------------------------------
- Init network timing parameters; these values should work for both a "real"
- network, and a simulated modem network (ie Kali)
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing ( 30, // retry 2 times per second
- -1, // ignore max retries
- 600); // give up after 10 seconds
- /*------------------------------------------------------------------------
- Save the original value of the NetStealth flag, so we can turn stealth
- off for now (during this portion of the dialogs, we must show ourselves)
- ------------------------------------------------------------------------*/
- stealth = NetStealth;
- NetStealth = 0;
- /*------------------------------------------------------------------------
- The game is now "open" for joining. Close it as soon as we exit this
- routine.
- ------------------------------------------------------------------------*/
- NetOpen = 1;
- /*------------------------------------------------------------------------
- Read the default values from the INI file
- ------------------------------------------------------------------------*/
- Read_MultiPlayer_Settings ();
- /*---------------------------------------------------------------------
- Pop up the network Join/New dialog
- ---------------------------------------------------------------------*/
- rc = Net_Fake_Join_Dialog();
- Write_MultiPlayer_Settings ();
- NetStealth = stealth;
- NetOpen = 0;
- if (rc == -1) {
- return(false);
- } else {
- return(true);
- }
- }
- /***********************************************************************************************
- * Net_Join_Dialog -- lets user join an existing game or start a new one *
- * *
- * This dialog displays an edit field for the player's name, and a list of all non-stealth- *
- * mode games. Clicking once on a game name displays a list of who's in that game. Clicking *
- * "New" takes the user to the Net_New dialog, where he waits for other users to join his *
- * game. All other input is done through this dialog. *
- * *
- * The dialog has several "states": *
- * *
- * 1) Initially, it waits for the user to fill in his/her name and then to select Join or New; *
- * if New is selected, this dialog is exited. *
- * *
- * 2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains. *
- * The join request is transmitted to the game's owner, and the message "Waiting for *
- * Confirmation" is displayed, until a confirmation or denial is received from the game's *
- * owner. The user may click Cancel at this point to cancel the join request. *
- * (Once Join is selected, the name editing field is disabled, and becomes a display-only *
- * field. If cancel is selected, it reappears as an edit field.) The user can still click *
- * around & see who's in which games. *
- * *
- * 3) If the join request is denied, the dialog re-initializes to its pre-join state; the *
- * Join & New buttons reappear, & the Name field is available again. *
- * *
- * 4) If join confirmation is obtained, the message just changes to "Confirmed. Waiting for *
- * Entry Signal." or some such nonsense. The user can still click around & see who's *
- * in which games. *
- * *
- * Any game running in Stealth mode won't show up on this dialog. *
- * *
- * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ *
- * ³ Network Games ³ *
- * ³ ³ *
- * ³ Your Name: ____________ ³ *
- * ³ House: [GDI] [NOD] ³ *
- * ³ Desired Color: [ ][ ][ ][ ] ³ *
- * ³ ³ *
- * ³ Games Players ³ *
- * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ *
- * ³ ³(Bill's Game )³³ ³ Peter Parker GDI ³³ ³ *
- * ³ ³ Peter Parker's Game ÃÄ´ ³ Mary Jane GDI ÃÄ´ ³ *
- * ³ ³(Magnum PI's Game )³ ³ ³ JJ Jameson NOD ³ ³ ³ *
- * ³ ³ ÃÄ´ ³ ÃÄ´ ³ *
- * ³ ³ ³³ ³ ³³ ³ *
- * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ *
- * ³ Scenario: Big Long Description ³ *
- * ³ Starting Credits: xxxx ³ *
- * ³ Count: --- Level: --- ³ *
- * ³ Bases: ON Crates: ON ³ *
- * ³ Tiberium: ON AI Players: ON ³ *
- * ³ ³ *
- * ³ [Join] [Cancel] [New] ³ *
- * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ *
- * ³ ³ ³ ³ *
- * ³ ³ ³ ³ *
- * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ *
- * ³ [Send Message] ³ *
- * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * -1 = cancel, 0 = OK, 1 = New net game requested *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- static int Net_Join_Dialog(void)
- {
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- /*........................................................................
- Dialog & button dimensions
- ........................................................................*/
- /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
- int d_dialog_w = 287 *factor; // dialog width
- int d_dialog_h = 198*factor; // dialog height
- int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
- int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- int d_txt6_h = 6*factor+1; // ht of 6-pt text
- int d_margin1 = 5*factor; // large margin
- int d_margin2 = 2*factor; // small margin
- int d_name_w = 70*factor;
- int d_name_h = 9*factor;
- int d_name_x = d_dialog_cx - 10*factor;
- int d_name_y = d_dialog_y + d_margin1 + d_txt6_h + d_txt6_h;
- int d_gdi_w = 30*factor;
- int d_gdi_h = 9*factor;
- int d_gdi_x = d_dialog_cx - 10*factor;
- int d_gdi_y = d_name_y + d_name_h + d_margin2;
- int d_nod_w = 30*factor;
- int d_nod_h = 9*factor;
- int d_nod_x = d_gdi_x + d_gdi_w;
- int d_nod_y = d_name_y + d_name_h + d_margin2;
- int d_color_w = 10*factor;
- int d_color_h = 9*factor;
- int d_color_y = d_nod_y + d_nod_h + d_margin2;
- int d_gamelist_w = 160*factor;
- int d_gamelist_h = 27*factor;
- int d_gamelist_x = d_dialog_x + d_margin1;
- int d_gamelist_y = d_color_y + d_color_h + d_margin1 + d_txt6_h;
- int d_playerlist_w = 106*factor;
- int d_playerlist_h = 27*factor;
- int d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_playerlist_w;
- int d_playerlist_y = d_color_y + d_color_h + d_margin1 + d_txt6_h;
- int d_msg1_y = d_gamelist_y + d_gamelist_h + d_margin1;
- int d_msg2_y = d_msg1_y + d_txt6_h;
- int d_msg3_y = d_msg2_y + d_txt6_h;
- int d_msg4_y = d_msg3_y + d_txt6_h;
- int d_msg5_y = d_msg4_y + d_txt6_h;
- int d_join_w = 40*factor;
- int d_join_h = 9*factor;
- int d_join_x = d_dialog_x + (d_dialog_w / 6) - (d_join_w / 2);
- int d_join_y = d_msg5_y + d_txt6_h + d_margin1;
- #if (GERMAN | FRENCH)
- int d_cancel_w = 50*factor;
- #else
- int d_cancel_w = 40*factor;
- #endif
- int d_cancel_h = 9*factor;
- int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
- int d_cancel_y = d_msg5_y + d_txt6_h + d_margin1;
- int d_new_w = 40*factor;
- int d_new_h = 9*factor;
- int d_new_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_new_w / 2);
- int d_new_y = d_msg5_y + d_txt6_h + d_margin1;
- int d_message_w = d_dialog_w - (d_margin1 * 2);
- int d_message_h = 34*factor;
- int d_message_x = d_dialog_x + d_margin1;
- int d_message_y = d_cancel_y + d_cancel_h + d_margin1;
- int d_send_w = 80*factor;
- int d_send_h = 9*factor;
- int d_send_x = d_dialog_cx - (d_send_w / 2);
- int d_send_y = d_message_y + d_message_h + d_margin2;
- /*........................................................................
- Button Enumerations
- ........................................................................*/
- enum {
- BUTTON_NAME = 100,
- BUTTON_GDI,
- BUTTON_NOD,
- BUTTON_GAMELIST,
- BUTTON_PLAYERLIST,
- BUTTON_JOIN,
- BUTTON_CANCEL,
- BUTTON_NEW,
- BUTTON_SEND,
- };
- /*........................................................................
- Redraw values: in order from "top" to "bottom" layer of the dialog
- ........................................................................*/
- typedef enum {
- REDRAW_NONE = 0,
- REDRAW_MESSAGE,
- REDRAW_COLORS,
- REDRAW_BUTTONS,
- REDRAW_BACKGROUND,
- REDRAW_ALL = REDRAW_BACKGROUND
- } RedrawType;
- /*........................................................................
- Dialog variables
- ........................................................................*/
- RedrawType display = REDRAW_ALL; // redraw level
- bool process = true; // process while true
- KeyNumType input;
- int cbox_x[] = { d_gdi_x,
- d_gdi_x + d_color_w,
- d_gdi_x + (d_color_w * 2),
- d_gdi_x + (d_color_w * 3),
- d_gdi_x + (d_color_w * 4),
- d_gdi_x + (d_color_w * 5)};
- JoinStateType joinstate = JOIN_NOTHING; // current "state" of this dialog
- char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
- int tabs[] = {77*factor}; // tabs for player list box
- int game_index = -1; // index of currently-selected game
- int join_index = -1; // index of game we're joining
- int rc = 0; // -1 = user cancelled, 1 = New
- JoinEventType event; // event from incoming packet
- int i,j; // loop counter
- char txt[80];
- char const *p;
- int parms_received; // 1 = game options received
- int found;
- unsigned char tmp_id[MAX_PLAYERS]; // temp storage for sorting player ID's
- int min_index; // for sorting player ID's
- unsigned char min_id; // for sorting player ID's
- unsigned char id; // connection ID
- char * item;
- unsigned long starttime;
- NodeNameType *who;
- int message_length;
- int sent_so_far;
- unsigned short magic_number;
- unsigned short crc;
- void const *up_button;
- void const *down_button;
- if (InMainLoop){
- up_button = Hires_Retrieve("BTN-UP.SHP");
- down_button = Hires_Retrieve("BTN-DN.SHP");
- }else{
- up_button = Hires_Retrieve("BTN-UP2.SHP");
- down_button = Hires_Retrieve("BTN-DN2.SHP");
- }
- /*........................................................................
- Buttons
- ........................................................................*/
- GadgetClass *commands; // button list
- EditClass name_edt (BUTTON_NAME,
- namebuf, MPLAYER_NAME_MAX, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC);
- TextButtonClass gdibtn(BUTTON_GDI, TXT_G_D_I,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_gdi_x, d_gdi_y, d_gdi_w, d_gdi_h);
- TextButtonClass nodbtn(BUTTON_NOD, TXT_N_O_D,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_nod_x, d_nod_y, d_nod_w, d_nod_h);
- ListClass gamelist(BUTTON_GAMELIST,
- d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- ColorListClass playerlist(BUTTON_PLAYERLIST,
- d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- TextButtonClass joinbtn(BUTTON_JOIN, TXT_JOIN,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #ifdef FRENCH
- d_join_x, d_join_y);
- #else
- d_join_x, d_join_y, d_join_w, d_join_h);
- #endif
- TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #if (GERMAN | FRENCH)
- d_cancel_x, d_cancel_y);
- #else
- d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
- #endif
- TextButtonClass newbtn(BUTTON_NEW, TXT_NEW,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_new_x, d_new_y, d_new_w, d_new_h);
- TextButtonClass sendbtn(BUTTON_SEND, TXT_SEND_MESSAGE,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #if (GERMAN | FRENCH)
- d_send_x, d_send_y);
- #else
- d_send_x, d_send_y, d_send_w, d_send_h);
- #endif
- playerlist.Set_Tabs(tabs);
- /*
- ----------------------------- Various Inits ------------------------------
- */
- MPlayerColorIdx = MPlayerPrefColor; // init my preferred color
- strcpy (namebuf, MPlayerName); // set my name
- name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX);
- name_edt.Set_Color (MPlayerTColors[MPlayerColorIdx]);
- playerlist.Set_Selected_Style(ColorListClass::SELECT_NONE);
- if (MPlayerHouse==HOUSE_GOOD) {
- gdibtn.Turn_On();
- } else {
- nodbtn.Turn_On();
- }
- Fancy_Text_Print("", 0, 0, CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Messages.Init (d_message_x + 2, d_message_y + 2, 4,
- MAX_MESSAGE_LENGTH, d_txt6_h);
- /*
- --------------------------- Send network query ---------------------------
- */
- Send_Join_Queries (game_index, 1, 0);
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Set_Palette(Palette);
- /*
- ---------------------------- Init Mono Output ----------------------------
- */
- #if(SHOW_MONO)
- Ipx.Configure_Debug(-1, sizeof (GlobalHeaderType),
- sizeof(NetCommandType), GlobalPacketNames, 11);
- Ipx.Mono_Debug_Print(-1,1);
- #endif
- while (Get_Mouse_State() > 0) Show_Mouse();
- /*
- ---------------------------- Processing loop -----------------------------
- */
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=REDRAW_ALL;
- }
- #if(SHOW_MONO)
- Ipx.Mono_Debug_Print(-1,0);
- #endif
- /*
- ...................... Refresh display if needed ......................
- */
- if (display) {
- Hide_Mouse();
- /*
- .................. Redraw backgound & dialog box ...................
- */
- if (display >= REDRAW_BACKGROUND) {
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Set_Palette(Palette);
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- /*...............................................................
- Dialog & Field labels
- ...............................................................*/
- Draw_Caption (TXT_JOIN_NETWORK_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
- Fancy_Text_Print(TXT_YOUR_NAME,
- d_name_x - 5, d_name_y + 1, CC_GREEN, TBLACK,
- TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print(TXT_SIDE_COLON,
- d_gdi_x - 5, d_gdi_y + 1, CC_GREEN, TBLACK,
- TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print(TXT_COLOR_COLON,
- cbox_x[0] - 5, d_color_y + 1, CC_GREEN, TBLACK,
- TPF_RIGHT | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print(TXT_GAMES,
- d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h,
- CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print(TXT_PLAYERS,
- d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h,
- CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*...............................................................
- Join-state-specific labels:
- ...............................................................*/
- if (joinstate > JOIN_NOTHING) {
- Fancy_Text_Print(namebuf, d_name_x, d_name_y + 1, CC_GREEN,
- TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- if (MPlayerHouse==HOUSE_GOOD) {
- Fancy_Text_Print(TXT_G_D_I, d_gdi_x, d_gdi_y + 1, CC_GREEN,
- TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- } else {
- Fancy_Text_Print(TXT_N_O_D, d_gdi_x, d_gdi_y + 1, CC_GREEN,
- TBLACK, TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- }
- }
- /*
- .................... Rebuild the button list ....................
- */
- cancelbtn.Zap();
- gamelist.Zap();
- playerlist.Zap();
- gdibtn.Zap();
- nodbtn.Zap();
- name_edt.Zap();
- joinbtn.Zap();
- newbtn.Zap();
- sendbtn.Zap();
- commands = &cancelbtn;
- gamelist.Add_Tail(*commands);
- playerlist.Add_Tail(*commands);
- /*...............................................................
- Only add the name edit field, the House, Join & New buttons if
- we're doing nothing, or we've just been rejected.
- ...............................................................*/
- if (joinstate <= JOIN_NOTHING) {
- gdibtn.Add_Tail(*commands);
- nodbtn.Add_Tail(*commands);
- name_edt.Add_Tail(*commands);
- joinbtn.Add_Tail(*commands);
- newbtn.Add_Tail(*commands);
- }
- if (joinstate == JOIN_CONFIRMED)
- sendbtn.Add_Tail(*commands);
- }
- /*
- .......................... Redraw buttons ..........................
- */
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- /*..................................................................
- Draw the color boxes
- ..................................................................*/
- if (display >= REDRAW_COLORS) {
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- LogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1,
- cbox_x[i] + 1 + d_color_w - 2, d_color_y + 1 + d_color_h - 2,
- MPlayerGColors[i]);
- if (i == MPlayerColorIdx) {
- Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
- BOXSTYLE_GREEN_DOWN, false);
- } else {
- Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h,
- BOXSTYLE_GREEN_RAISED, false);
- }
- }
- }
- /*..................................................................
- Draw the message:
- - Erase an old message first
- - If we're in a game, print the game options (if they've been
- received)
- - If we've been rejected from a game, print that message
- ..................................................................*/
- if (display >= REDRAW_MESSAGE) {
- Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h,
- BOXSTYLE_GREEN_BORDER, true);
- Messages.Draw();
- LogicPage->Fill_Rect( d_dialog_x + 2,
- d_msg1_y,
- d_dialog_x + d_dialog_w - 4,
- d_msg5_y + d_txt6_h,
- BLACK);
- if (joinstate==JOIN_CONFIRMED && parms_received) {
- /*............................................................
- Scenario title
- ............................................................*/
- p = Text_String(TXT_SCENARIO_COLON);
- if (ScenarioIdx != -1) {
- sprintf(txt,"%s %s",p, MPlayerScenarios[ScenarioIdx]);
- Fancy_Text_Print (txt, d_dialog_cx,
- d_msg1_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_NOT_FOUND));
- Fancy_Text_Print (txt, d_dialog_cx,
- d_msg1_y, CC_NOD_COLOR, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
- }
- /*............................................................
- # of credits
- ............................................................*/
- p = Text_String(TXT_START_CREDITS_COLON);
- sprintf(txt, "%s %d", p, MPlayerCredits);
- Fancy_Text_Print (txt, d_dialog_cx,
- d_msg2_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW | TPF_CENTER);
- /*............................................................
- Count & Level values
- ............................................................*/
- p = Text_String(TXT_COUNT);
- sprintf(txt,"%s %d",p,MPlayerUnitCount);
- Fancy_Text_Print (txt,
- d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg3_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- p = Text_String(TXT_LEVEL);
- if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
- sprintf(txt, "%s %d", p, BuildLevel);
- } else {
- sprintf(txt, "%s **", p);
- }
- Fancy_Text_Print (txt,
- d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg3_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*............................................................
- Bases
- ............................................................*/
- p = Text_String(TXT_BASES_COLON);
- if (MPlayerBases) {
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
- }
- Fancy_Text_Print (txt,
- d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg4_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*............................................................
- Tiberium
- ............................................................*/
- p = Text_String(TXT_TIBERIUM_COLON);
- if (MPlayerTiberium) {
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
- }
- Fancy_Text_Print (txt,
- d_dialog_x + (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg5_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*............................................................
- Goody boxes
- ............................................................*/
- p = Text_String(TXT_CRATES_COLON);
- if (MPlayerGoodies) {
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
- }
- Fancy_Text_Print (txt,
- d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg4_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*............................................................
- Computer AI players
- ............................................................*/
- if (Special.IsCaptureTheFlag) {
- p = Text_String(TXT_CAPTURE_THE_FLAG_COLON);
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- p = Text_String(TXT_AI_PLAYERS_COLON);
- if (MPlayerGhosts) {
- sprintf(txt,"%s %s",p,Text_String(TXT_ON));
- } else {
- sprintf(txt,"%s %s",p,Text_String(TXT_OFF));
- }
- }
- Fancy_Text_Print (txt,
- d_dialog_x + d_dialog_w - (d_dialog_w / 4) - String_Pixel_Width(p),
- d_msg5_y, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- } else {
- /*...............................................................
- Rejection notice
- ...............................................................*/
- if (joinstate==JOIN_REJECTED) {
- Fancy_Text_Print(TXT_REQUEST_DENIED,
- d_dialog_cx, d_msg3_y, CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- }
- }
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- /*
- ........................... Get user input ............................
- */
- input = commands->Input();
- /*
- ---------------------------- Process input ----------------------------
- */
- switch (input) {
- /*------------------------------------------------------------------
- User clicks on a color button:
- - If we've joined a game, don't allow a new color selection
- - otherwise, select that color
- ------------------------------------------------------------------*/
- case KN_LMOUSE:
- if (joinstate > JOIN_NOTHING)
- break;
- if (_Kbd->MouseQX > cbox_x[0] &&
- _Kbd->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) &&
- _Kbd->MouseQY > d_color_y &&
- _Kbd->MouseQY < (d_color_y + d_color_h)) {
- MPlayerPrefColor = (_Kbd->MouseQX - cbox_x[0]) / d_color_w;
- MPlayerColorIdx = MPlayerPrefColor;
- name_edt.Set_Color (MPlayerTColors[MPlayerColorIdx]);
- name_edt.Flag_To_Redraw();
- display = REDRAW_COLORS;
- }
- break;
- /*------------------------------------------------------------------
- User clicks on the game list:
- - If we've joined a game, don't allow the selected item to change;
- otherwise:
- - Clear the player list
- - Send an immediate player query
- ------------------------------------------------------------------*/
- case (BUTTON_GAMELIST | KN_BUTTON):
- if (joinstate==JOIN_CONFIRMED) {
- gamelist.Set_Selected_Index(game_index);
- } else {
- if (gamelist.Current_Index() != game_index) {
- Clear_Player_List (&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- break;
- /*------------------------------------------------------------------
- House Buttons: set the player's desired House
- ------------------------------------------------------------------*/
- case (BUTTON_GDI | KN_BUTTON):
- MPlayerHouse = HOUSE_GOOD;
- gdibtn.Turn_On();
- nodbtn.Turn_Off();
- break;
- case (BUTTON_NOD | KN_BUTTON):
- MPlayerHouse = HOUSE_BAD;
- gdibtn.Turn_Off();
- nodbtn.Turn_On();
- break;
- /*------------------------------------------------------------------
- JOIN: send a join request packet & switch to waiting-for-confirmation
- mode. (Request_To_Join fills in MPlayerName with my namebuf.)
- ------------------------------------------------------------------*/
- case (BUTTON_JOIN | KN_BUTTON):
- name_edt.Clear_Focus();
- name_edt.Flag_To_Redraw();
- join_index = gamelist.Current_Index();
- parms_received = 0;
- if (Request_To_Join (namebuf, join_index, &playerlist, MPlayerHouse,
- MPlayerColorIdx)) {
- joinstate = JOIN_WAIT_CONFIRM;
- } else {
- display = REDRAW_ALL;
- }
- break;
- /*------------------------------------------------------------------
- CANCEL: send a SIGN_OFF
- - If we're part of a game, stay in this dialog; otherwise, exit
- ------------------------------------------------------------------*/
- case (KN_ESC):
- if (Messages.Get_Edit_Buf() != NULL) {
- Messages.Input(input);
- display = REDRAW_MESSAGE;
- break;
- }
- case (BUTTON_CANCEL | KN_BUTTON):
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy(GPacket.Name,MPlayerName);
- /*...............................................................
- If we're joined to a game, make extra sure the other players in
- that game know I'm exiting; send my SIGN_OFF as an ack-required
- packet. Do not send this packet to myself (index 0).
- ...............................................................*/
- if (joinstate == JOIN_CONFIRMED) {
- //
- // Remove myself from the player list box
- //
- if (playerlist.Count()) { // added: BRR 6/14/96
- item = (char *)(playerlist.Get_Item(0));
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- }
- //
- // Remove myself from the Players list
- //
- if (Players.Count()) { // added: BRR 6/14/96
- who = Players[0];
- Players.Delete(0);
- delete who;
- }
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- }
- /*...............................................................
- Now broadcast my SIGN_OFF so other players looking at this game
- know I'm leaving.
- ...............................................................*/
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- if (joinstate != JOIN_CONFIRMED) {
- process = false;
- rc = -1;
- } else {
- MPlayerGameName[0] = 0;
- joinstate = JOIN_NOTHING;
- display = REDRAW_ALL;
- }
- break;
- /*------------------------------------------------------------------
- NEW: bail out with return code 1
- ------------------------------------------------------------------*/
- case (BUTTON_NEW | KN_BUTTON):
- /*
- .................. Force user to enter a name ...................
- */
- if (strlen(namebuf)==0) {
- CCMessageBox().Process(TXT_NAME_ERROR);
- display = REDRAW_ALL;
- break;
- }
- /*
- ..................... Ensure name is unique .....................
- */
- found = 0;
- for (i = 0; i < Games.Count(); i++) {
- if (!stricmp(Games[i]->Name, namebuf)) {
- found = 1;
- CCMessageBox().Process (TXT_GAMENAME_MUSTBE_UNIQUE);
- display = REDRAW_ALL;
- break;
- }
- }
- if (found)
- break;
- /*
- .................... Save player & game name ....................
- */
- strcpy(MPlayerName,namebuf);
- strcpy(MPlayerGameName,namebuf);
- name_edt.Clear_Focus();
- name_edt.Flag_To_Redraw();
- rc = 1;
- process = false;
- break;
- /*------------------------------------------------------------------
- Default: manage the inter-player messages
- ------------------------------------------------------------------*/
- default:
- /*...............................................................
- F4/SEND/'M' = edit a message
- ...............................................................*/
- if (Messages.Get_Edit_Buf()==NULL) {
- if ( (input == KN_M && joinstate==JOIN_CONFIRMED) ||
- input==(BUTTON_SEND | KN_BUTTON) || input == KN_F4) {
- memset (txt, 0, 80);
- strcpy(txt,Text_String(TXT_TO_ALL)); // "To All:"
- Messages.Add_Edit (MPlayerTColors[MPlayerColorIdx],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, d_message_w-70*factor);
- if (joinstate <= JOIN_NOTHING) {
- name_edt.Clear_Focus();
- name_edt.Flag_To_Redraw();
- }
- display = REDRAW_MESSAGE;
- break;
- }
- } else
- /*...............................................................
- If we're already editing a message and the user clicks on
- 'Send', translate our input to a Return so Messages.Input() will
- work properly.
- ...............................................................*/
- if (input==(BUTTON_SEND | KN_BUTTON)) {
- input = KN_RETURN;
- }
- /*...............................................................
- Manage the message system (get rid of old messages)
- ...............................................................*/
- if (Messages.Manage()) {
- display = REDRAW_MESSAGE;
- }
- /*...............................................................
- Service keyboard input for any message being edited.
- ...............................................................*/
- i = Messages.Input(input);
- /*...............................................................
- If 'Input' returned 1, it means refresh the message display.
- ...............................................................*/
- if (i==1) {
- Messages.Draw();
- } else {
- /*...............................................................
- If 'Input' returned 2, it means redraw the message display.
- ...............................................................*/
- if (i==2) {
- display = REDRAW_MESSAGE;
- } else {
- /*...............................................................
- If 'input' returned 3, it means send the current message.
- ...............................................................*/
- if (i==3) {
- sent_so_far = 0;
- magic_number = MESSAGE_HEAD_MAGIC_NUMBER;
- message_length = strlen(Messages.Get_Edit_Buf());
- crc = (unsigned short)
- (Calculate_CRC(Messages.Get_Edit_Buf(),message_length) &0xffff);
- while ( sent_so_far < message_length ){
- GPacket.Command = NET_MESSAGE;
- strcpy (GPacket.Name, namebuf);
- memcpy (GPacket.Message.Buf, Messages.Get_Edit_Buf()+sent_so_far, COMPAT_MESSAGE_LENGTH-5);
- *(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-5) = 0;
- *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4)) = magic_number;
- *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2)) = crc;
- GPacket.Message.ID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- GPacket.Message.NameCRC = Compute_Name_CRC(MPlayerGameName);
- /*..................................................................
- Send the message to every player in our player list. The local
- system will also receive this message, since it's in the Player list.
- ..................................................................*/
- if (joinstate == JOIN_CONFIRMED) {
- for (i = 1; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket,
- sizeof(GlobalPacketType), 1, &(Players[i]->Address));
- Ipx.Service();
- }
- sprintf(txt,Text_String (TXT_FROM), MPlayerName, GPacket.Message.Buf);
- Messages.Add_Message (txt,
- MPlayerTColors[MPlayerColorIdx],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, magic_number, crc);
- }
- else {
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket,
- sizeof(GlobalPacketType), 1, &(Players[i]->Address));
- Ipx.Service();
- }
- }
- magic_number++;
- sent_so_far += COMPAT_MESSAGE_LENGTH-5;
- }
- }
- }
- }
- break;
- }
- /*---------------------------------------------------------------------
- Resend our query packets
- ---------------------------------------------------------------------*/
- Send_Join_Queries(game_index, 0, 0);
- /*---------------------------------------------------------------------
- Process incoming packets
- ---------------------------------------------------------------------*/
- event = Get_Join_Responses(&joinstate, &gamelist, &playerlist,
- join_index);
- /*.....................................................................
- If we've changed state, redraw everything; if we're starting the game,
- break out of the loop. If we've just joined, send out a player query
- so I'll get added to the list instantly.
- .....................................................................*/
- if (event == EV_STATE_CHANGE) {
- display = REDRAW_ALL;
- if (joinstate==JOIN_GAME_START) {
- rc = 0;
- process = false;
- } else {
- /*..................................................................
- If we're newly-confirmed, immediately send out a player query
- ..................................................................*/
- if (joinstate==JOIN_CONFIRMED) {
- Clear_Player_List(&playerlist);
- item = new char [MPLAYER_NAME_MAX + 4];
- if (MPlayerHouse==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
- }
- playerlist.Add_Item (item, MPlayerTColors[MPlayerColorIdx]);
- who = new NodeNameType;
- strcpy(who->Name, MPlayerName);
- who->Address = IPXAddressClass();
- who->Player.House = MPlayerHouse;
- who->Player.Color = MPlayerColorIdx;
- Players.Add (who);
- Send_Join_Queries (game_index, 0, 1);
- } else {
- /*..................................................................
- If we've been rejected, clear any messages we may have been typing.
- ..................................................................*/
- if (joinstate==JOIN_REJECTED) {
- //
- // Remove myself from the player list box
- //
- if (playerlist.Count()) { // added: BRR 6/14/96
- item = (char *)(playerlist.Get_Item(0));
- if (item){
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- }
- }
- //
- // Remove myself from the Players list
- //
- if (Players.Count()){
- who = Players[0];
- Players.Delete(0);
- delete who;
- }
- Messages.Init (d_message_x + 2, d_message_y + 2, 4,
- MAX_MESSAGE_LENGTH, d_txt6_h);
- }
- }
- }
- } else
- /*.....................................................................
- If a new game is detected, and it's the first game on our list,
- automatically send out a player query for that game.
- .....................................................................*/
- if (event == EV_NEW_GAME && gamelist.Count()==1) {
- gamelist.Set_Selected_Index(0);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- } else
- /*.....................................................................
- If the game options have changed, print them.
- .....................................................................*/
- if (event == EV_GAME_OPTIONS) {
- parms_received = 1;
- display = REDRAW_MESSAGE;
- } else
- /*.....................................................................
- Draw an incoming message
- .....................................................................*/
- if (event == EV_MESSAGE) {
- display = REDRAW_MESSAGE;
- } else
- /*.....................................................................
- A game before the one I've selected is gone, so we have a new index now.
- 'game_index' must be kept set to the currently-selected list item, so
- we send out queries for the currently-selected game. It's therefore
- imperative that we detect any changes to the game list.
- If we're joined in a game, we must decrement our game_index to keep
- it aligned with the game we're joined to.
- .....................................................................*/
- if (event == EV_GAME_SIGNOFF) {
- if (joinstate==JOIN_CONFIRMED) {
- game_index--;
- join_index--;
- gamelist.Set_Selected_Index(join_index);
- } else {
- gamelist.Flag_To_Redraw();
- Clear_Player_List(&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- /*---------------------------------------------------------------------
- Service the Ipx connections
- ---------------------------------------------------------------------*/
- Ipx.Service();
- /*---------------------------------------------------------------------
- Clean out the Game List; if an old entry is found:
- - Remove it
- - Clear the player list
- - Send queries for the new selected game, if there is one
- ---------------------------------------------------------------------*/
- for (i = 0; i < Games.Count(); i++) {
- if (TickCount.Time() - Games[i]->Game.LastTime > 400) {
- Games.Delete(Games[i]);
- item = (char *)(gamelist.Get_Item (i));
- gamelist.Remove_Item (item);
- delete [] item;
- if (i <= game_index) {
- gamelist.Flag_To_Redraw();
- Clear_Player_List(&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- }
- /*---------------------------------------------------------------------
- Service the sounds & score; GameActive must be false at this point,
- so Call_Back() doesn't intercept global messages from me!
- ---------------------------------------------------------------------*/
- Call_Back();
- }
- /*------------------------------------------------------------------------
- Establish connections with all other players.
- ------------------------------------------------------------------------*/
- if (rc == 0) {
- /*.....................................................................
- If the other guys are playing a scenario I don't have (sniff), I can't
- play. Try to bail gracefully.
- .....................................................................*/
- if (ScenarioIdx==-1) {
- CCMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
- //
- // Remove myself from the player list box
- //
- if (playerlist.Count()) { // added: BRR 6/14/96
- item = (char *)(playerlist.Get_Item(0));
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- }
- //
- // Remove myself from the Players list
- //
- if (Players.Count()) { // added: BRR 6/14/96
- who = Players[0];
- Players.Delete(0);
- delete who;
- }
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- rc = -1;
- } else {
- /*..................................................................
- Set the number of players in this game, and my ID
- ..................................................................*/
- MPlayerCount = Players.Count();
- MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- /*..................................................................
- Get the scenario number
- ..................................................................*/
- Scenario = MPlayerFilenum[ScenarioIdx];
- /*..................................................................
- Form connections with all other players. Form the IPX Connection ID
- from the player's Color and House. This will let us extract any
- player's color & house at any time. Fill in 'tmp_id' while we're
- doing this.
- ..................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- /*...............................................................
- Only create the connection if it's not myself!
- ...............................................................*/
- if (strcmp (MPlayerName, Players[i]->Name)) {
- id = Build_MPlayerID(Players[i]->Player.Color,
- Players[i]->Player.House);
- tmp_id[i] = id;
- Ipx.Create_Connection((int)id, Players[i]->Name, &(Players[i]->Address) );
- } else {
- tmp_id[i] = MPlayerLocalID;
- }
- }
- /*..................................................................
- Store every player's ID in the MPlayerID[] array. This array will
- determine the order of event execution, so the ID's must be stored
- in the same order on all systems.
- ..................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- min_index = 0;
- min_id = 0xff;
- for (j = 0; j < MPlayerCount; j++) {
- if (tmp_id[j] < min_id) {
- min_id = tmp_id[j];
- min_index = j;
- }
- }
- MPlayerID[i] = tmp_id[min_index];
- tmp_id[min_index] = 0xff;
- }
- /*..................................................................
- Fill in the array of player names, including my own.
- ..................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == MPlayerLocalID) {
- strcpy (MPlayerNames[i], MPlayerName);
- } else {
- strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
- }
- }
- }
- /*---------------------------------------------------------------------
- Wait a while, polling the IPX service routines, to give our ACK
- a chance to get to the other system. If he doesn't get our ACK, he'll
- be waiting the whole time we load MIX files.
- ---------------------------------------------------------------------*/
- i = MAX(Ipx.Global_Response_Time() * 2, 60);
- starttime = TickCount.Time();
- while (TickCount.Time() - starttime < i) {
- Ipx.Service();
- }
- }
- /*------------------------------------------------------------------------
- Init network timing values, using previous response times as a measure
- of what our retry delta & timeout should be.
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
- Ipx.Global_Response_Time() * 4);
- /*------------------------------------------------------------------------
- Clear all lists
- ------------------------------------------------------------------------*/
- Clear_Game_List(&gamelist);
- Clear_Player_List(&playerlist);
- /*------------------------------------------------------------------------
- Restore screen
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Show_Mouse();
- return(rc);
- }
- /***************************************************************************
- * Clear_Game_List -- Clears the game-name listbox & 'Games' Vector *
- * *
- * Assumes each entry in 'Games' & the list box have been allocated *
- * separately. *
- * *
- * INPUT: *
- * gamelist ptr to list box *
- * *
- * OUTPUT: *
- * none *
- * *
- * WARNINGS: *
- * none *
- * *
- * HISTORY: *
- *=========================================================================*/
- static void Clear_Game_List (ListClass *gamelist)
- {
- char * item;
- int i;
- /*------------------------------------------------------------------------
- Clear the list box
- ------------------------------------------------------------------------*/
- while (gamelist->Count()) {
- item = (char *)(gamelist->Get_Item (0));
- gamelist->Remove_Item(item);
- delete [] item;
- }
- gamelist->Flag_To_Redraw();
- /*------------------------------------------------------------------------
- Clear the 'Games' Vector
- ------------------------------------------------------------------------*/
- for (i = 0; i < Games.Count(); i++)
- delete Games[i];
- Games.Clear();
- } /* end of Clear_Game_List */
- /***************************************************************************
- * Clear_Player_List -- Clears the player-name listbox & Vector *
- * *
- * Assumes each entry in 'Players' & the list box have been allocated *
- * separately. *
- * *
- * INPUT: *
- * playerlist ptr to list box *
- * *
- * OUTPUT: *
- * none *
- * *
- * WARNINGS: *
- * none *
- * *
- * HISTORY: *
- *=========================================================================*/
- static void Clear_Player_List (ListClass *playerlist)
- {
- char * item;
- int i;
- /*------------------------------------------------------------------------
- Clear the list box
- ------------------------------------------------------------------------*/
- while (playerlist->Count()) {
- item = (char *)(playerlist->Get_Item(0));
- playerlist->Remove_Item(item);
- delete [] item;
- }
- playerlist->Flag_To_Redraw();
- /*------------------------------------------------------------------------
- Clear the 'Players' Vector
- ------------------------------------------------------------------------*/
- for (i = 0; i < Players.Count(); i++)
- delete Players[i];
- Players.Clear();
- } /* end of Clear_Player_List */
- /***************************************************************************
- * Request_To_Join -- Sends a JOIN request packet to game owner *
- * *
- * Regardless of the return code, the Join Dialog will need to be redrawn *
- * after calling this routine. *
- * *
- * INPUT: *
- * playername player's name *
- * join_index index of game we're joining *
- * playerlist listbox containing other players' names *
- * house requested house *
- * color requested color *
- * *
- * OUTPUT: *
- * 1 = Packet sent, 0 = wasn't *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- *=========================================================================*/
- static int Request_To_Join (char *playername, int join_index, ListClass *playerlist,
- HousesType house, int color)
- {
- int i;
- playerlist = playerlist; // shaddup, Mr stupid compiler!
- /*
- --------------------------- Validate join_index --------------------------
- */
- if ( (Games.Count()==0) || join_index > Games.Count() || join_index < 0) {
- CCMessageBox().Process (TXT_NOTHING_TO_JOIN);
- return(false);
- }
- /*
- ----------------------- Force user to enter a name -----------------------
- */
- if (strlen(playername)==0) {
- CCMessageBox().Process (TXT_NAME_ERROR);
- return(false);
- }
- /*
- ------------------------- The game must be open --------------------------
- */
- if (!Games[join_index]->Game.IsOpen) {
- CCMessageBox().Process(TXT_GAME_IS_CLOSED);
- return (false);
- }
- /*
- ------------------------ Make sure name is unique ------------------------
- */
- for (i = 0; i < Players.Count(); i++) {
- if (!stricmp(playername, Players[i]->Name)) {
- CCMessageBox().Process (TXT_NAME_MUSTBE_UNIQUE);
- return(false);
- }
- }
- /*
- ----------------------------- Check version #'s --------------------------
- */
- int v;
- #ifdef PATCH
- if (IsV107) {
- v = 1;
- } else {
- v = 2;
- }
- #else
- v = Version_Number();
- #endif
- if (Games[join_index]->Game.Version > v) {
- CCMessageBox().Process (TXT_YOURGAME_OUTDATED);
- return(false);
- } else {
- if (Games[join_index]->Game.Version < v) {
- CCMessageBox().Process (TXT_DESTGAME_OUTDATED);
- return(false);
- }
- }
- /*
- ----------------------------- Save game name -----------------------------
- */
- strcpy (MPlayerName,playername);
- /*
- ----------------------- Send packet to game's owner ----------------------
- */
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_QUERY_JOIN;
- strcpy (GPacket.Name, MPlayerName);
- GPacket.PlayerInfo.House = house;
- GPacket.PlayerInfo.Color = color;
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Games[join_index]->Address));
- return(true);
- }
- /***********************************************************************************************
- * Send_Join_Queries -- sends queries for the Join Dialog *
- * *
- * This routine [re]sends the queries related to the Join Dialog: *
- * - NET_QUERY_GAME *
- * - NET_QUERY_PLAYER for the game currently selected (if there is one) *
- * *
- * The queries are "staggered" in time so they aren't all sent at once; otherwise, we'd *
- * be inundated with reply packets & we'd miss some (even though the replies will require *
- * ACK's). *
- * *
- * INPUT: *
- * curgame index of currently-selected game; -1 = none *
- * gamenow if 1, will immediately send the game query *
- * playernow if 1, will immediately send the player query for currently-selected game *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- * 04/15/1995 BRR : Created. *
- *=============================================================================================*/
- static void Send_Join_Queries(int curgame, int gamenow, int playernow)
- {
- static int lasttime1 = 0; // time since last Game query sent out
- static int lasttime2 = 0; // time since last Player query sent out
- /*------------------------------------------------------------------------
- Send the game-name query if the time has expired, or we're told to do
- it right now
- ------------------------------------------------------------------------*/
- if ( (TickCount.Time() - lasttime1 > 120) || gamenow) {
- lasttime1 = TickCount.Time();
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_QUERY_GAME;
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, NULL);
- /*.....................................................................
- If the user specified a remote server address, broadcast over that
- network, too.
- .....................................................................*/
- if (IsBridge)
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- /*------------------------------------------------------------------------
- Send the player query for the game currently clicked on, if the time has
- expired and there is a currently-selected game, or we're told to do it
- right now
- ------------------------------------------------------------------------*/
- if ( (curgame != -1) && curgame < Games.Count() &&
- ((TickCount.Time() - lasttime2 > 35) || playernow) ) {
- lasttime2 = TickCount.Time();
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_QUERY_PLAYER;
- strcpy (GPacket.Name, Games[curgame]->Name);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0, NULL);
- /*.....................................................................
- If the user specified a remote server address, broadcast over that
- network, too.
- .....................................................................*/
- if (IsBridge)
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- } /* end of Send_Join_Queries */
- /***********************************************************************************************
- * Get_Join_Responses -- sends queries for the Join Dialog *
- * *
- * This routine polls the Global Channel to see if there are any incoming packets; *
- * if so, it processes them. This routine can change the state of the Join Dialog, or *
- * the contents of the list boxes, based on what the packet is. *
- * *
- * The list boxes are passed in as pointers; they can't be made globals, because they *
- * can't be constructed, because they require shape pointers to the arrow buttons, and *
- * the mix files won't have been initialized when the global variables' constructors are *
- * called. *
- * *
- * This routine sets the globals *
- * MPlayerHouse (from NET_CONFIRM_JOIN) *
- * MPlayerColorIdx (from NET_CONFIRM_JOIN) *
- * MPlayerBases (from NET_GAME_OPTIONS) *
- * MPlayerTiberium (from NET_GAME_OPTIONS) *
- * MPlayerGoodies (from NET_GAME_OPTIONS) *
- * MPlayerGhosts (from NET_GAME_OPTIONS) *
- * ScenarioIdx (from NET_GAME_OPTIONS; -1 = scenario not found) *
- * *
- * INPUT: *
- * joinstate current state of Join Dialog *
- * gamelist list box containing game names *
- * playerlist list box containing player names for the currently-selected game *
- * join_index index of the game we've joined or are asking to join *
- * *
- * OUTPUT: *
- * Event that occurred *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- * 04/15/1995 BRR : Created. *
- *=============================================================================================*/
- static JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist,
- ColorListClass *playerlist, int join_index)
- {
- int rc;
- char * item; // general-purpose string
- NodeNameType *who; // node to add to Games or Players
- int i;
- int found;
- JoinEventType retcode = EV_NONE;
- char txt[80];
- int color;
- unsigned short magic_number;
- unsigned short crc;
- /*------------------------------------------------------------------------
- If there is no incoming packet, just return
- ------------------------------------------------------------------------*/
- rc = Ipx.Get_Global_Message (&GPacket, &GPacketlen, &GAddress, &GProductID);
- if (!rc || GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER)
- return(EV_NONE);
- /*------------------------------------------------------------------------
- If we're joined in a game, handle the packet in a standard way; otherwise,
- don't answer standard queries.
- ------------------------------------------------------------------------*/
- if ( (*joinstate)==JOIN_CONFIRMED &&
- Process_Global_Packet(&GPacket,&GAddress)!=0)
- return(EV_NONE);
- /*------------------------------------------------------------------------
- NET_ANSWER_GAME: Another system is answering our GAME query, so add that
- system to our list box if it's new.
- ------------------------------------------------------------------------*/
- if (GPacket.Command==NET_ANSWER_GAME) {
- /*.....................................................................
- See if this name is unique
- .....................................................................*/
- retcode = EV_NONE;
- found = 0;
- for (i = 0; i < Games.Count(); i++) {
- if (!strcmp(Games[i]->Name, GPacket.Name)) {
- found = 1;
- /*...............................................................
- If name was found, update the node's time stamp & IsOpen flag.
- ...............................................................*/
- Games[i]->Game.LastTime = TickCount.Time();
- if (Games[i]->Game.IsOpen != GPacket.GameInfo.IsOpen) {
- item = (char *)gamelist->Get_Item(i);
- if (GPacket.GameInfo.IsOpen) {
- sprintf(item,Text_String(TXT_THATGUYS_GAME),GPacket.Name);
- } else {
- sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),GPacket.Name);
- }
- Games[i]->Game.IsOpen = GPacket.GameInfo.IsOpen;
- gamelist->Flag_To_Redraw();
- /*............................................................
- If this game has gone from closed to open, copy the responder's
- address into our Game slot, since the guy responding to this
- must be game owner.
- ............................................................*/
- if (Games[i]->Game.IsOpen)
- Games[i]->Address = GAddress;
- }
- break;
- }
- }
- /*.....................................................................
- name not found (or addresses are different); add it to 'Games'
- .....................................................................*/
- if (found==0) {
- /*..................................................................
- Create a new node structure, fill it in, add it to 'Games'
- ..................................................................*/
- who = new NodeNameType;
- strcpy(who->Name, GPacket.Name);
- who->Address = GAddress;
- who->Game.Version = GPacket.GameInfo.Version;
- who->Game.IsOpen = GPacket.GameInfo.IsOpen;
- who->Game.LastTime = TickCount.Time();
- Games.Add (who);
- /*..................................................................
- Create a string for "xxx's Game", leaving room for brackets around
- the string if it's a closed game
- ..................................................................*/
- item = new char [MPLAYER_NAME_MAX + 9];
- if (GPacket.GameInfo.IsOpen) {
- sprintf(item,Text_String(TXT_THATGUYS_GAME),GPacket.Name);
- } else {
- sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET),GPacket.Name);
- }
- gamelist->Add_Item(item);
- retcode = EV_NEW_GAME;
- }
- }
- /*------------------------------------------------------------------------
- NET_ANSWER_PLAYER: Another system is answering our PLAYER query, so add it
- to our player list box & the Player Vector if it's new
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_ANSWER_PLAYER) {
- /*.....................................................................
- See if this name is unique
- .....................................................................*/
- retcode = EV_NONE;
- found = 0;
- for (i = 0; i < Players.Count(); i++) {
- /*..................................................................
- If the address is already present, re-copy their name, color &
- house into the existing entry, in case they've changed it without
- our knowledge; set the 'found' flag so we won't create a new entry.
- ..................................................................*/
- if (Players[i]->Address==GAddress) {
- strcpy(Players[i]->Name, GPacket.Name);
- Players[i]->Player.House = GPacket.PlayerInfo.House;
- Players[i]->Player.Color = GPacket.PlayerInfo.Color;
- playerlist->Colors[i] = MPlayerTColors[GPacket.PlayerInfo.Color];
- found = 1;
- break;
- }
- }
- /*.....................................................................
- Don't add this player if he's not part of the game that's selected.
- .....................................................................*/
- i = gamelist->Current_Index();
- if (Games.Count() && GPacket.PlayerInfo.NameCRC != Compute_Name_CRC(Games[i]->Name))
- found = 1;
- /*
- ** Dont add this player if its really me! (hack, hack)
- */
- if (!strcmp(GPacket.Name, MPlayerName)){
- found = 1;
- }
- /*.....................................................................
- name not found (or address didn't match); add to player list box & Vector
- .....................................................................*/
- if (found==0) {
- /*..................................................................
- Create & add a node to the Vector
- ..................................................................*/
- who = new NodeNameType;
- strcpy(who->Name, GPacket.Name);
- who->Address = GAddress;
- who->Player.House = GPacket.PlayerInfo.House;
- who->Player.Color = GPacket.PlayerInfo.Color;
- Players.Add (who);
- /*..................................................................
- Create & add a string to the list box
- ..................................................................*/
- item = new char [MPLAYER_NAME_MAX + 4];
- if (GPacket.PlayerInfo.House==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_N_O_D));
- }
- playerlist->Add_Item(item, MPlayerTColors[who->Player.Color]);
- retcode = EV_NEW_PLAYER;
- }
- }
- /*------------------------------------------------------------------------
- NET_CONFIRM_JOIN: The game owner has confirmed our JOIN query; mark us as
- being confirmed, and start answering queries from other systems
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_CONFIRM_JOIN) {
- if ( (*joinstate) != JOIN_CONFIRMED) {
- strcpy (MPlayerGameName, GPacket.Name);
- MPlayerHouse = GPacket.PlayerInfo.House;
- MPlayerColorIdx = GPacket.PlayerInfo.Color;
- (*joinstate) = JOIN_CONFIRMED;
- retcode = EV_STATE_CHANGE;
- }
- }
- /*------------------------------------------------------------------------
- NET_REJECT_JOIN: The game owner has turned down our JOIN query; restore
- the dialog state to its first pop-up state. Broadcast a sign-off to
- tell all other systems that I'm no longer a part of any game; this way,
- I'll be properly removed from their dialogs.
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_REJECT_JOIN) {
- if ( (*joinstate) != JOIN_REJECTED) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name,MPlayerName);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- MPlayerGameName[0] = 0;
- (*joinstate) = JOIN_REJECTED;
- retcode = EV_STATE_CHANGE;
- }
- }
- /*------------------------------------------------------------------------
- NET_GAME_OPTIONS: The game owner has changed the game options & is sending
- us the new values.
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_GAME_OPTIONS) {
- if ( (*joinstate)==JOIN_CONFIRMED) {
- MPlayerCredits = GPacket.ScenarioInfo.Credits;
- MPlayerBases = GPacket.ScenarioInfo.IsBases;
- MPlayerTiberium = GPacket.ScenarioInfo.IsTiberium;
- MPlayerGoodies = GPacket.ScenarioInfo.IsGoodies;
- MPlayerGhosts = GPacket.ScenarioInfo.IsGhosties;
- BuildLevel = GPacket.ScenarioInfo.BuildLevel;
- MPlayerUnitCount = GPacket.ScenarioInfo.UnitCount;
- Seed = GPacket.ScenarioInfo.Seed;
- Special = GPacket.ScenarioInfo.Special;
- Options.GameSpeed = GPacket.ScenarioInfo.GameSpeed;
- if (MPlayerTiberium) {
- Special.IsTGrowth = 1;
- Special.IsTSpread = 1;
- } else {
- Special.IsTGrowth = 0;
- Special.IsTSpread = 0;
- }
- if (Winsock.Get_Connected()){
- ScenarioIdx = GPacket.ScenarioInfo.Scenario;
- }else{
- ScenarioIdx = -1;
- for (i = 0; i < MPlayerFilenum.Count(); i++) {
- if (GPacket.ScenarioInfo.Scenario == MPlayerFilenum[i])
- ScenarioIdx = i;
- }
- }
- retcode = EV_GAME_OPTIONS;
- }
- }
- /*------------------------------------------------------------------------
- NET_SIGN_OFF: Another system is signing off: search for that system in
- both the game list & player list, & remove it if found
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_SIGN_OFF) {
- /*.....................................................................
- Remove this name from the list of games
- .....................................................................*/
- for (i = 0; i < Games.Count(); i++) {
- if (!strcmp(Games[i]->Name, GPacket.Name) &&
- Games[i]->Address==GAddress) {
- /*...............................................................
- If the system signing off is the currently-selected list
- item, clear the player list since that game is no longer
- forming.
- ...............................................................*/
- if (i==gamelist->Current_Index()) {
- Clear_Player_List (playerlist);
- }
- /*...............................................................
- If the system signing off was the owner of our game, mark
- ourselves as rejected
- ...............................................................*/
- if ( (*joinstate) > JOIN_NOTHING && i==join_index) {
- (*joinstate) = JOIN_REJECTED;
- retcode = EV_STATE_CHANGE;
- }
- /*
- ....................... Set my return code ......................
- */
- if (retcode == EV_NONE) {
- if (i <= gamelist->Current_Index()) {
- retcode = EV_GAME_SIGNOFF;
- } else {
- retcode = EV_PLAYER_SIGNOFF;
- }
- }
- /*
- ................. Remove game name from game list ...............
- */
- Games.Delete(Games[i]);
- item = (char *)(gamelist->Get_Item (i));
- gamelist->Remove_Item (item);
- delete [] item;
- gamelist->Flag_To_Redraw();
- }
- }
- /*.....................................................................
- Remove this name from the list of players
- .....................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- /*
- ..................... Name found; remove it .....................
- */
- if (Players[i]->Address==GAddress) {
- item = (char *)(playerlist->Get_Item(i));
- playerlist->Remove_Item(item);
- delete [] item;
- Players.Delete(Players[i]);
- playerlist->Flag_To_Redraw();
- if (retcode == EV_NONE)
- retcode = EV_PLAYER_SIGNOFF;
- }
- }
- }
- /*------------------------------------------------------------------------
- NET_GO: The game's owner is signalling us to start playing.
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_GO) {
- if ( (*joinstate)==JOIN_CONFIRMED) {
- MPlayerMaxAhead = GPacket.ResponseTime.OneWay;
- (*joinstate) = JOIN_GAME_START;
- retcode = EV_STATE_CHANGE;
- CCDebugString ("C&C95 - Received the 'GO' packet\n");
- }
- }
- /*------------------------------------------------------------------------
- NET_MESSAGE: Someone is sending us a message
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_MESSAGE) {
- sprintf(txt,Text_String (TXT_FROM), GPacket.Name, GPacket.Message.Buf);
- magic_number = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4));
- crc = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2));
- color = MPlayerID_To_ColorIndex(GPacket.Message.ID);
- Messages.Add_Message (txt, MPlayerTColors[color],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
- retcode = EV_MESSAGE;
- }
- /*------------------------------------------------------------------------
- NET_PING: Someone is pinging me to get a response time measure (will only
- happen after I've joined a game). Do nothing; the IPX Manager will handle
- sending an ACK, and updating the response time measurements.
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_PING) {
- retcode = EV_NONE;
- }
- /*------------------------------------------------------------------------
- Default case: nothing happened. (This case will be hit every time I
- receive my own NET_QUERY_GAME or NET_QUERY_PLAYER packets.)
- ------------------------------------------------------------------------*/
- else {
- retcode = EV_NONE;
- }
- return(retcode);
- }
- /***********************************************************************************************
- * Net_New_Dialog -- lets user start a new game *
- * *
- * This dialog shows a list of who's requesting to join this game, and lets *
- * the game initiator selectively approve each user. *
- * *
- * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ *
- * ³ New Network Game ³ *
- * ³ ³ *
- * ³ Players Scenario ³ *
- * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ *
- * ³ ³ Boffo ³³ ³ Hell's Kitchen ³³ ³ *
- * ³ ³ Bozo ÃÄ´ ³ Heaven's Gate ÃÄ´ ³ *
- * ³ ³ Bonzo ³ ³ ³ ... ³ ³ ³ *
- * ³ ³ ÃÄ´ ³ ÃÄ´ ³ *
- * ³ ³ ³³ ³ ³³ ³ *
- * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ *
- * ³ [Reject] Count:--- ## ³ *
- * ³ Level:--- ## ³ *
- * ³ ³ *
- * ³ Credits: _____ ³ *
- * ³ [ Bases ] [ Crates ] ³ *
- * ³ [ Tiberium ] [ AI Players ] ³ *
- * ³ ³ *
- * ³ [OK] [Cancel] ³ *
- * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ *
- * ³ ³ ³ ³ *
- * ³ ³ ³ ³ *
- * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ *
- * ³ [Send Message] ³ *
- * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * true = success, false = cancel *
- * *
- * WARNINGS: *
- * MPlayerName & MPlayerGameName must contain this player's name. *
- * *
- * HISTORY: *
- * 02/14/1995 BR : Created. *
- *=============================================================================================*/
- static int Net_New_Dialog(void)
- {
- /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- /*........................................................................
- Dialog & button dimensions
- ........................................................................*/
- //D_DIALOG_W = 281; // dialog width
- int d_dialog_w = 287*factor; // dialog width
- int d_dialog_h = 177*factor; // dialog height
- int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
- int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- int d_txt6_h = 6*factor+1; // ht of 6-pt text
- int d_margin1 = 5*factor; // margin width/height
- int d_margin2 = 2*factor; // margin width/height
- //d_playerlist_w = 100;
- int d_playerlist_w = 106*factor;
- int d_playerlist_h = 27*factor;
- int d_playerlist_x = d_dialog_x + d_margin1;
- int d_playerlist_y = d_dialog_y + d_margin1 + (d_txt6_h * 3);
- int d_scenariolist_w = 162*factor;
- int d_scenariolist_h = 27*factor;
- int d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_scenariolist_w;
- int d_scenariolist_y = d_dialog_y + d_margin1 + (d_txt6_h * 3);
- #if (GERMAN | FRENCH)
- int d_reject_w = 55*factor;
- #else
- int d_reject_w = 45*factor;
- #endif
- int d_reject_h = 9*factor;
- int d_reject_x = d_playerlist_x + (d_playerlist_w / 2) - (d_reject_w / 2);
- int d_reject_y = d_playerlist_y + d_playerlist_h + d_margin2;
- int d_count_w = 25*factor;
- int d_count_h = d_txt6_h;
- int d_count_x = d_scenariolist_x + (d_scenariolist_w / 2);
- int d_count_y = d_scenariolist_y + d_scenariolist_h + d_margin2;
- int d_level_w = 25*factor;
- int d_level_h = d_txt6_h;
- int d_level_x = d_scenariolist_x + (d_scenariolist_w / 2);
- int d_level_y = d_count_y + d_count_h;
- int d_credits_w = ((CREDITSBUF_MAX - 1) * 7*factor) + 4*factor;
- //int d_credits_w = ((CREDITSBUF_MAX - 1) * 6*factor) + 3*factor;
- int d_credits_h = 9*factor;
- int d_credits_x = d_dialog_cx + 2*factor;
- int d_credits_y = d_level_y + d_level_h + d_margin1;
- #if (GERMAN | FRENCH)
- int d_bases_w = 120*factor;//bga:100;
- #else
- int d_bases_w = 100*factor;
- #endif
- int d_bases_h = 9*factor;
- int d_bases_x = d_dialog_cx - d_bases_w - d_margin2;
- int d_bases_y = d_credits_y + d_credits_h + d_margin2;
- #if (GERMAN | FRENCH)
- int d_tiberium_w = 120*factor;
- #else
- int d_tiberium_w = 100*factor;
- #endif
- int d_tiberium_h = 9*factor;
- int d_tiberium_x = d_dialog_cx - d_bases_w - d_margin2;
- int d_tiberium_y = d_bases_y + d_bases_h + d_margin2;
- #if (GERMAN | FRENCH)
- int d_goodies_w = 120*factor;
- #else
- int d_goodies_w = 100*factor;
- #endif
- int d_goodies_h = 9*factor;
- int d_goodies_x = d_dialog_cx + d_margin2;
- int d_goodies_y = d_credits_y + d_credits_h + d_margin2;
- #if (GERMAN | FRENCH)
- int d_ghosts_w = 120*factor;
- #else
- int d_ghosts_w = 100*factor;
- #endif
- int d_ghosts_h = 9*factor;
- int d_ghosts_x = d_dialog_cx + d_margin2;
- int d_ghosts_y = d_goodies_y + d_goodies_h + d_margin2;
- int d_ok_w = 45*factor;
- int d_ok_h = 9*factor;
- int d_ok_x = d_dialog_cx - d_margin2 - (d_bases_w / 2) - (d_ok_w / 2);
- int d_ok_y = d_ghosts_y + d_ghosts_h + d_margin1;
- #if (GERMAN | FRENCH)
- int d_cancel_w = 50*factor;
- #else
- int d_cancel_w = 45*factor;
- #endif
- int d_cancel_h = 9*factor;
- int d_cancel_x = d_dialog_cx + d_margin2 + (d_goodies_w / 2) - (d_cancel_w / 2);
- int d_cancel_y = d_ghosts_y + d_ghosts_h + d_margin1;
- int d_message_w = d_dialog_w - (d_margin1 * 2);
- int d_message_h = 34*factor;
- int d_message_x = d_dialog_x + d_margin1;
- int d_message_y = d_cancel_y + d_cancel_h + d_margin1;
- int d_send_w = 80*factor;
- int d_send_h = 9*factor;
- int d_send_x = d_dialog_cx - (d_send_w / 2);
- int d_send_y = d_message_y + d_message_h + d_margin2;
- /*........................................................................
- Button Enumerations
- ........................................................................*/
- enum {
- BUTTON_PLAYERLIST = 100,
- BUTTON_SCENARIOLIST,
- BUTTON_REJECT,
- BUTTON_COUNT,
- BUTTON_LEVEL,
- BUTTON_CREDITS,
- BUTTON_BASES,
- BUTTON_TIBERIUM,
- BUTTON_GOODIES,
- BUTTON_GHOSTS,
- BUTTON_OK,
- BUTTON_CANCEL,
- BUTTON_SEND,
- };
- /*........................................................................
- Redraw values: in order from "top" to "bottom" layer of the dialog
- ........................................................................*/
- typedef enum {
- REDRAW_NONE = 0,
- REDRAW_UNIT_COUNT,
- REDRAW_MESSAGE,
- REDRAW_BUTTONS,
- REDRAW_BACKGROUND,
- REDRAW_ALL = REDRAW_BACKGROUND
- } RedrawType;
- /*........................................................................
- Dialog variables
- ........................................................................*/
- RedrawType display = REDRAW_ALL; // redraw level
- bool process = true; // process while true
- KeyNumType input;
- char credbuf[CREDITSBUF_MAX]; // for credit edit box
- int old_cred; // old value in credits buffer
- int transmit; // 1 = re-transmit new game options
- long ok_timer = 0; // for timing OK button
- int index; // index for rejecting a player
- int rc;
- int i,j;
- char *item;
- int tabs[] = {77*factor}; // tabs for player list box
- long ping_timer = 0; // for sending Ping packets
- unsigned char tmp_id[MAX_PLAYERS]; // temp storage for sorting player ID's
- int min_index; // for sorting player ID's
- unsigned char min_id; // for sorting player ID's
- unsigned char id; // connection ID
- char txt[80];
- JoinEventType whahoppa; // event generated by received packets
- static int first_time = 1; // 1 = 1st time this dialog is run
- int message_length;
- int sent_so_far;
- unsigned short magic_number;
- unsigned short crc;
- /*........................................................................
- Buttons
- ........................................................................*/
- GadgetClass *commands; // button list
- void const *up_button;
- void const *down_button;
- if (InMainLoop){
- up_button = Hires_Retrieve("BTN-UP.SHP");
- down_button = Hires_Retrieve("BTN-DN.SHP");
- }else{
- up_button = Hires_Retrieve("BTN-UP2.SHP");
- down_button = Hires_Retrieve("BTN-DN2.SHP");
- }
- ColorListClass playerlist(BUTTON_PLAYERLIST,
- d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- ListClass scenariolist(BUTTON_SCENARIOLIST,
- d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- EditClass credit_edt (BUTTON_CREDITS,
- credbuf, CREDITSBUF_MAX,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_credits_x, d_credits_y, d_credits_w, d_credits_h, EditClass::ALPHANUMERIC);
- TextButtonClass rejectbtn(BUTTON_REJECT, TXT_REJECT,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #if (GERMAN | FRENCH)
- d_reject_x, d_reject_y);
- #else
- d_reject_x, d_reject_y, d_reject_w, d_reject_h);
- #endif
- GaugeClass countgauge (BUTTON_COUNT,
- d_count_x, d_count_y, d_count_w, d_count_h);
- GaugeClass levelgauge (BUTTON_LEVEL,
- d_level_x, d_level_y, d_level_w, d_level_h);
- TextButtonClass basesbtn(BUTTON_BASES, TXT_BASES_OFF,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_bases_x, d_bases_y, d_bases_w, d_bases_h);
- TextButtonClass tiberiumbtn(BUTTON_TIBERIUM, TXT_TIBERIUM_OFF,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_tiberium_x, d_tiberium_y, d_tiberium_w, d_tiberium_h);
- TextButtonClass goodiesbtn(BUTTON_GOODIES, TXT_CRATES_OFF,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_goodies_x, d_goodies_y, d_goodies_w, d_goodies_h);
- TextButtonClass ghostsbtn(BUTTON_GHOSTS, TXT_AI_PLAYERS_OFF,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_ghosts_x, d_ghosts_y, d_ghosts_w, d_ghosts_h);
- TextButtonClass okbtn(BUTTON_OK, TXT_OK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- d_ok_x, d_ok_y, d_ok_w, d_ok_h);
- TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #if (GERMAN | FRENCH)
- d_cancel_x, d_cancel_y);
- #else
- d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
- #endif
- TextButtonClass sendbtn(BUTTON_SEND, TXT_SEND_MESSAGE,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #if (GERMAN | FRENCH)
- d_send_x, d_send_y);
- #else
- d_send_x, d_send_y, d_send_w, d_send_h);
- #endif
- /*
- ------------------------- Build the button list --------------------------
- */
- commands = &playerlist;
- scenariolist.Add_Tail(*commands);
- credit_edt.Add_Tail(*commands);
- rejectbtn.Add_Tail(*commands);
- countgauge.Add_Tail(*commands);
- levelgauge.Add_Tail(*commands);
- basesbtn.Add_Tail(*commands);
- tiberiumbtn.Add_Tail(*commands);
- goodiesbtn.Add_Tail(*commands);
- ghostsbtn.Add_Tail(*commands);
- okbtn.Add_Tail(*commands);
- cancelbtn.Add_Tail(*commands);
- sendbtn.Add_Tail(*commands);
- playerlist.Set_Tabs(tabs);
- /*
- ----------------------------- Various Inits ------------------------------
- */
- /*........................................................................
- Init dialog values, only the first time through
- ........................................................................*/
- if (first_time) {
- MPlayerCredits = 3000; // init credits & credit buffer
- MPlayerBases = 1; // init scenario parameters
- MPlayerTiberium = 0;
- MPlayerGoodies = 0;
- MPlayerGhosts = 0;
- Special.IsCaptureTheFlag = 0;
- MPlayerUnitCount = (MPlayerCountMax[MPlayerBases] + MPlayerCountMin[MPlayerBases]) / 2;
- first_time = 0;
- }
- /*........................................................................
- Init button states
- ........................................................................*/
- if (MPlayerBases) {
- basesbtn.Turn_On();
- basesbtn.Set_Text(TXT_BASES_ON);
- }
- if (MPlayerTiberium) {
- tiberiumbtn.Turn_On();
- tiberiumbtn.Set_Text(TXT_TIBERIUM_ON);
- }
- if (MPlayerGoodies) {
- goodiesbtn.Turn_On();
- goodiesbtn.Set_Text(TXT_CRATES_ON);
- }
- if (MPlayerGhosts) {
- ghostsbtn.Turn_On();
- ghostsbtn.Set_Text(TXT_AI_PLAYERS_ON);
- }
- if (Special.IsCaptureTheFlag) {
- MPlayerGhosts = 0;
- ghostsbtn.Turn_On();
- ghostsbtn.Set_Text(TXT_CAPTURE_THE_FLAG);
- }
- sprintf(credbuf, "%d", MPlayerCredits);
- credit_edt.Set_Text(credbuf, CREDITSBUF_MAX);
- old_cred = MPlayerCredits;
- levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1);
- levelgauge.Set_Value(BuildLevel - 1);
- countgauge.Set_Maximum(MPlayerCountMax[MPlayerBases] - MPlayerCountMin[MPlayerBases]);
- countgauge.Set_Value(MPlayerUnitCount - MPlayerCountMin[MPlayerBases]);
- /*........................................................................
- Init other scenario parameters
- ........................................................................*/
- Special.IsTGrowth = MPlayerTiberium;
- Special.IsTSpread = MPlayerTiberium;
- transmit = 0;
- /*........................................................................
- Init scenario description list box
- ........................................................................*/
- for (i = 0; i < MPlayerScenarios.Count(); i++) {
- scenariolist.Add_Item (strupr(MPlayerScenarios[i]));
- }
- ScenarioIdx = 0; // 1st scenario is selected
- /*........................................................................
- Init player color-used flags
- ........................................................................*/
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- ColorUsed[i] = 0; // init all colors to available
- }
- ColorUsed[MPlayerColorIdx] = 1; // set my color to used
- playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, CC_GREEN_SHADOW);
- /*........................................................................
- Init random-number generator, & create a seed to be used for all random
- numbers from here on out
- ........................................................................*/
- randomize();
- Seed = rand();
- /*........................................................................
- Init the message display system
- ........................................................................*/
- Messages.Init (d_message_x + 2*factor, d_message_y + 2*factor, 4, MAX_MESSAGE_LENGTH,
- d_txt6_h);
- /*------------------------------------------------------------------------
- Add myself to the list. Note that since I'm not in the Players Vector,
- the Vector & listbox are now 1 out of sync.
- ------------------------------------------------------------------------*/
- item = new char [MPLAYER_NAME_MAX + 4];
- if (MPlayerHouse==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
- }
- playerlist.Add_Item(item, MPlayerTColors[MPlayerColorIdx]);
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Set_Palette(Palette);
- while (Get_Mouse_State() > 0) Show_Mouse();
- /*
- ---------------------------- Processing loop -----------------------------
- */
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=REDRAW_ALL;
- }
- #if(SHOW_MONO)
- Ipx.Mono_Debug_Print(-1,0);
- #endif
- /*
- ...................... Refresh display if needed ......................
- */
- if (display == REDRAW_UNIT_COUNT){
- /*
- ** Wipe the background behind the unit count then reprint it
- */
- LogicPage->Fill_Rect(d_count_x + d_count_w + 2*factor,
- d_count_y,
- d_count_x + d_count_w + 2*factor + 20,
- d_count_y + 12,
- 0 );
- sprintf(txt,"%d",MPlayerUnitCount);
- Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- display = REDRAW_NONE;
- }
- if (display) {
- Hide_Mouse();
- /*
- .................. Redraw backgound & dialog box ...................
- */
- if (display >= REDRAW_BACKGROUND) {
- /*
- ** Reload and draw the title page
- */
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Set_Palette(Palette);
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- /*...............................................................
- Dialog & Field labels
- ...............................................................*/
- Draw_Caption (TXT_NETGAME_SETUP, d_dialog_x, d_dialog_y, d_dialog_w);
- Fancy_Text_Print(TXT_PLAYERS,
- d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_CENTER);
- Fancy_Text_Print(TXT_SCENARIOS,
- d_scenariolist_x + (d_scenariolist_w / 2),
- d_scenariolist_y - d_txt6_h,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_CENTER);
- Fancy_Text_Print (TXT_COUNT, d_count_x - 2*factor, d_count_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
- sprintf(txt,"%d",MPlayerUnitCount);
- Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- Fancy_Text_Print (TXT_LEVEL, d_level_x - 2*factor, d_level_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
- if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
- sprintf(txt,"%d",BuildLevel);
- } else {
- sprintf(txt, "**");
- }
- Fancy_Text_Print (txt, d_level_x + d_level_w + 2*factor, d_level_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- Fancy_Text_Print (TXT_START_CREDITS_COLON, d_credits_x - 5*factor,
- d_credits_y + 1*factor, CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_RIGHT);
- }
- /*
- .......................... Redraw buttons ..........................
- */
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- /*..................................................................
- Draw the messages:
- - Erase an old message first
- - If we're in a game, print the game options (if they've been
- received)
- - If we've been rejected from a game, print that message
- ..................................................................*/
- if (display >= REDRAW_MESSAGE) {
- Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h,
- BOXSTYLE_GREEN_BORDER, true);
- Messages.Draw();
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- /*
- ........................... Get user input ............................
- */
- input = commands->Input();
- /*
- ---------------------------- Process input ----------------------------
- */
- switch (input) {
- /*------------------------------------------------------------------
- New Scenario selected.
- ------------------------------------------------------------------*/
- case (BUTTON_SCENARIOLIST | KN_BUTTON):
- if (scenariolist.Current_Index() != ScenarioIdx) {
- ScenarioIdx = scenariolist.Current_Index();
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- }
- break;
- /*------------------------------------------------------------------
- Reject the currently-selected player (don't allow rejecting myself,
- who will be the first entry in the list)
- ------------------------------------------------------------------*/
- case (BUTTON_REJECT | KN_BUTTON):
- index = playerlist.Current_Index();
- if (index == 0) {
- CCMessageBox().Process (TXT_CANT_REJECT_SELF, TXT_OOPS);
- display = REDRAW_ALL;
- break;
- } else {
- if (index < 0 || index >= playerlist.Count()) {
- CCMessageBox().Process (TXT_SELECT_PLAYER_REJECT,TXT_OOPS);
- display = REDRAW_ALL;
- break;
- }
- }
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_REJECT_JOIN;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 1,
- &(Players[index - 1]->Address));
- break;
- /*------------------------------------------------------------------
- User adjusts max # units
- ------------------------------------------------------------------*/
- case (BUTTON_COUNT | KN_BUTTON):
- MPlayerUnitCount = countgauge.Get_Value() + MPlayerCountMin[MPlayerBases];
- Hide_Mouse();
- LogicPage->Fill_Rect (d_count_x + d_count_w + 2*factor, d_count_y,
- d_count_x + d_count_w + 14*factor, d_count_y + 6*factor, BLACK);
- sprintf(txt,"%d",MPlayerUnitCount);
- Fancy_Text_Print (txt, d_count_x + d_count_w + 2*factor, d_count_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- Show_Mouse();
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- User adjusts build level
- ------------------------------------------------------------------*/
- case (BUTTON_LEVEL | KN_BUTTON):
- BuildLevel = levelgauge.Get_Value() + 1;
- if (BuildLevel > MPLAYER_BUILD_LEVEL_MAX) // if it's pegged, max it out
- BuildLevel = MPLAYER_BUILD_LEVEL_MAX;
- Hide_Mouse();
- LogicPage->Fill_Rect (d_level_x + d_level_w + 2*factor, d_level_y,
- d_level_x + d_level_w + 14*factor, d_level_y + 6*factor, BLACK);
- if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) {
- sprintf(txt,"%d",BuildLevel);
- } else {
- sprintf(txt, "**");
- }
- Fancy_Text_Print (txt, d_level_x + d_level_w + 2*factor, d_level_y,
- CC_GREEN, TBLACK,
- TPF_NOSHADOW | TPF_6PT_GRAD | TPF_USE_GRAD_PAL);
- Show_Mouse();
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- User edits the credits value; retransmit new game options
- ------------------------------------------------------------------*/
- case (BUTTON_CREDITS | KN_BUTTON):
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- Toggle bases:
- - Clear scenario list & rebuild it with new names
- - toggle bases button, change its text
- - adjust the MPlayerUnitCount to reflect the new allowed range,
- using the current gauge setting
- - Change the unit count gauge limit & value
- ------------------------------------------------------------------*/
- case (BUTTON_BASES | KN_BUTTON):
- if (MPlayerBases) {
- MPlayerBases = 0;
- basesbtn.Turn_Off();
- basesbtn.Set_Text(TXT_BASES_OFF);
- MPlayerUnitCount = Fixed_To_Cardinal (MPlayerCountMax[0]-MPlayerCountMin[0],
- Cardinal_To_Fixed(MPlayerCountMax[1]-MPlayerCountMin[1],
- MPlayerUnitCount-MPlayerCountMin[1])) + MPlayerCountMin[0];
- } else {
- MPlayerBases = 1;
- basesbtn.Turn_On();
- basesbtn.Set_Text(TXT_BASES_ON);
- MPlayerUnitCount = Fixed_To_Cardinal (MPlayerCountMax[1]-MPlayerCountMin[1],
- Cardinal_To_Fixed(MPlayerCountMax[0]-MPlayerCountMin[0],
- MPlayerUnitCount-MPlayerCountMin[0])) + MPlayerCountMin[1];
- }
- MPlayerCredits = atoi(credbuf);
- countgauge.Set_Maximum(MPlayerCountMax[MPlayerBases] - MPlayerCountMin[MPlayerBases]);
- countgauge.Set_Value(MPlayerUnitCount - MPlayerCountMin[MPlayerBases]);
- transmit = 1;
- countgauge.Flag_To_Redraw();
- display = REDRAW_UNIT_COUNT;
- break;
- /*------------------------------------------------------------------
- Toggle tiberium
- ------------------------------------------------------------------*/
- case (BUTTON_TIBERIUM | KN_BUTTON):
- if (MPlayerTiberium) {
- MPlayerTiberium = 0;
- Special.IsTGrowth = 0;
- Special.IsTSpread = 0;
- tiberiumbtn.Turn_Off();
- tiberiumbtn.Set_Text(TXT_TIBERIUM_OFF);
- } else {
- MPlayerTiberium = 1;
- Special.IsTGrowth = 1;
- Special.IsTSpread = 1;
- tiberiumbtn.Turn_On();
- tiberiumbtn.Set_Text(TXT_TIBERIUM_ON);
- }
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- Toggle goodies
- ------------------------------------------------------------------*/
- case (BUTTON_GOODIES | KN_BUTTON):
- if (MPlayerGoodies) {
- MPlayerGoodies = 0;
- goodiesbtn.Turn_Off();
- goodiesbtn.Set_Text(TXT_CRATES_OFF);
- } else {
- MPlayerGoodies = 1;
- goodiesbtn.Turn_On();
- goodiesbtn.Set_Text(TXT_CRATES_ON);
- }
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- Toggle ghosts/capture-the-flag
- ------------------------------------------------------------------*/
- case (BUTTON_GHOSTS | KN_BUTTON):
- if (!MPlayerGhosts && !Special.IsCaptureTheFlag) { // ghosts OFF => ghosts ON
- MPlayerGhosts = 1;
- Special.IsCaptureTheFlag = 0;
- ghostsbtn.Turn_On();
- ghostsbtn.Set_Text(TXT_AI_PLAYERS_ON);
- } else {
- if (MPlayerGhosts) { // ghosts ON => capture-flag
- MPlayerGhosts = 0;
- Special.IsCaptureTheFlag = 1;
- ghostsbtn.Turn_On();
- ghostsbtn.Set_Text(TXT_CAPTURE_THE_FLAG);
- } else {
- if (Special.IsCaptureTheFlag) { // capture-flag => AI OFF
- MPlayerGhosts = 0;
- Special.IsCaptureTheFlag = 0;
- ghostsbtn.Turn_Off();
- ghostsbtn.Set_Text(TXT_AI_PLAYERS_OFF);
- }
- }
- }
- MPlayerCredits = atoi(credbuf);
- transmit = 1;
- break;
- /*------------------------------------------------------------------
- OK: exit loop with TRUE status
- ------------------------------------------------------------------*/
- case (BUTTON_OK | KN_BUTTON):
- /*...............................................................
- If a new player has joined in the last second, don't allow
- an OK; force a wait longer than 1 second (to give all players
- a chance to know about this new guy)
- ...............................................................*/
- i = MAX(Ipx.Global_Response_Time() * 2, 60);
- while (TickCount.Time() - ok_timer < i)
- Ipx.Service();
- /*...............................................................
- If there are at least 2 players, go ahead & play; error otherwise
- ...............................................................*/
- if (MPlayerSolo || Players.Count() > 0) {
- rc = TRUE;
- process = FALSE;
- } else {
- CCMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);
- display = REDRAW_ALL;
- }
- break;
- /*------------------------------------------------------------------
- CANCEL: send a SIGN_OFF, bail out with error code
- ------------------------------------------------------------------*/
- case (KN_ESC):
- if (Messages.Get_Edit_Buf() != NULL) {
- Messages.Input(input);
- display = REDRAW_MESSAGE;
- break;
- }
- case (BUTTON_CANCEL | KN_BUTTON):
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- /*...............................................................
- Broadcast my sign-off over my network
- ...............................................................*/
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- /*...............................................................
- Broadcast my sign-off over a bridged network if there is one
- ...............................................................*/
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- /*...............................................................
- And now, just be absolutely sure, send my sign-off to each
- player in my game. (If there's a bridge between us, the other
- player will have specified my address, so he can cross the
- bridge; but I may not have specified a bridge address, so the
- only way I have of crossing the bridge is to send a packet
- directly to him.)
- ...............................................................*/
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- MPlayerGameName[0] = 0;
- process = false;
- rc = false;
- break;
- /*------------------------------------------------------------------
- Default: manage the inter-player messages
- ------------------------------------------------------------------*/
- default:
- /*...............................................................
- F4/SEND/'M' = send a message
- ...............................................................*/
- if (Messages.Get_Edit_Buf()==NULL) {
- if (input == KN_M || input==(BUTTON_SEND | KN_BUTTON) ||
- input == KN_F4) {
- memset (txt, 0, 80);
- strcpy(txt,Text_String(TXT_TO_ALL)); // "To All:"
- Messages.Add_Edit (MPlayerTColors[MPlayerColorIdx],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, txt, d_message_w-70*factor);
- credit_edt.Clear_Focus();
- credit_edt.Flag_To_Redraw();
- display = REDRAW_MESSAGE;
- break;
- }
- } else {
- /*...............................................................
- If we're already editing a message and the user clicks on
- 'Send', translate our input to a Return so Messages.Input() will
- work properly.
- ...............................................................*/
- if (input==(BUTTON_SEND | KN_BUTTON)) {
- input = KN_RETURN;
- }
- }
- /*...............................................................
- Manage the message system (get rid of old messages)
- ...............................................................*/
- if (Messages.Manage()) {
- display = REDRAW_MESSAGE;
- }
- /*...............................................................
- Re-draw the messages & service keyboard input for any message
- being edited.
- ...............................................................*/
- i = Messages.Input(input);
- /*...............................................................
- If 'Input' returned 1, it means refresh the message display.
- ...............................................................*/
- if (i==1) {
- Messages.Draw();
- }
- /*...............................................................
- If 'Input' returned 2, it means redraw the message display.
- ...............................................................*/
- else if (i==2) {
- display = REDRAW_MESSAGE;
- }
- /*...............................................................
- If 'input' returned 3, it means send the current message.
- ...............................................................*/
- else if (i==3) {
- sent_so_far = 0;
- magic_number = MESSAGE_HEAD_MAGIC_NUMBER;
- message_length = strlen(Messages.Get_Edit_Buf());
- crc = (unsigned short)
- (Calculate_CRC(Messages.Get_Edit_Buf(), message_length) &0xffff);
- while ( sent_so_far < message_length ){
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_MESSAGE;
- strcpy (GPacket.Name, MPlayerName);
- memcpy (GPacket.Message.Buf, Messages.Get_Edit_Buf()+sent_so_far, COMPAT_MESSAGE_LENGTH-5);
- *(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-5) = 0;
- *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4)) = magic_number;
- *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2)) = crc;
- GPacket.Message.ID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- GPacket.Message.NameCRC = Compute_Name_CRC(MPlayerGameName);
- /*..................................................................
- Send the message to every player in our player list.
- ..................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- /*..................................................................
- Add the message to our own list, since we're not in the player list
- on this dialog.
- ..................................................................*/
- sprintf(txt,Text_String (TXT_FROM), MPlayerName, GPacket.Message.Buf);
- Messages.Add_Message (txt, MPlayerTColors[MPlayerColorIdx],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
- magic_number++;
- sent_so_far += COMPAT_MESSAGE_LENGTH-5;
- }
- display = REDRAW_MESSAGE;
- }
- }
- /*---------------------------------------------------------------------
- Detect editing of the credits buffer, transmit new values to players
- ---------------------------------------------------------------------*/
- if (atoi(credbuf) != old_cred) {
- old_cred = Bound(atoi(credbuf), 0, 9999);
- MPlayerCredits = old_cred;
- transmit = 1;
- sprintf(credbuf, "%d", MPlayerCredits);
- credit_edt.Set_Text(credbuf, CREDITSBUF_MAX);
- }
- /*---------------------------------------------------------------------
- Process incoming packets
- ---------------------------------------------------------------------*/
- whahoppa = Get_NewGame_Responses(&playerlist);
- if (whahoppa == EV_NEW_PLAYER) {
- ok_timer = TickCount.Time();
- transmit = 1;
- } else {
- if (whahoppa == EV_MESSAGE) {
- display = REDRAW_MESSAGE;
- }
- }
- /*---------------------------------------------------------------------
- If our Transmit flag is set, we need to send out a game option packet
- ---------------------------------------------------------------------*/
- if (transmit) {
- for (i = 0; i < Players.Count(); i++) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_GAME_OPTIONS;
- GPacket.ScenarioInfo.Scenario = MPlayerFilenum[ScenarioIdx];
- GPacket.ScenarioInfo.Credits = MPlayerCredits;
- GPacket.ScenarioInfo.IsBases = MPlayerBases;
- GPacket.ScenarioInfo.IsTiberium = MPlayerTiberium;
- GPacket.ScenarioInfo.IsGoodies = MPlayerGoodies;
- GPacket.ScenarioInfo.IsGhosties = MPlayerGhosts;
- GPacket.ScenarioInfo.BuildLevel = BuildLevel;
- GPacket.ScenarioInfo.UnitCount = MPlayerUnitCount;
- GPacket.ScenarioInfo.Seed = Seed;
- GPacket.ScenarioInfo.Special = Special;
- GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- }
- transmit = 0;
- }
- /*---------------------------------------------------------------------
- Ping every player in my game, to force the Global Channel to measure
- the connection response time.
- ---------------------------------------------------------------------*/
- if (TickCount.Time() - ping_timer > 15) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_PING;
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- }
- ping_timer = TickCount.Time();
- }
- /*---------------------------------------------------------------------
- Service the Ipx connections
- ---------------------------------------------------------------------*/
- Ipx.Service();
- /*---------------------------------------------------------------------
- Service the sounds & score; GameActive must be false at this point,
- so Call_Back() doesn't intercept global messages from me!
- ---------------------------------------------------------------------*/
- Call_Back();
- } /* end of while */
- /*------------------------------------------------------------------------
- Establish connections with all other players.
- ------------------------------------------------------------------------*/
- if (rc) {
- /*.....................................................................
- Set the number of players in this game, and my ID
- .....................................................................*/
- MPlayerCount = Players.Count() + 1;
- MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- /*.....................................................................
- Get the scenario filename
- .....................................................................*/
- Scenario = MPlayerFilenum[ScenarioIdx];
- /*.....................................................................
- Compute frame delay value for packet transmissions:
- - Divide global channel's response time by 8 (2 to convert to 1-way
- value, 4 more to convert from ticks to frames)
- .....................................................................*/
- MPlayerMaxAhead = MAX( (Ipx.Global_Response_Time() / 8), 2);
- /*.....................................................................
- Send all players the NET_GO packet. Wait until all ACK's have been
- received.
- .....................................................................*/
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_GO;
- GPacket.ResponseTime.OneWay = MPlayerMaxAhead;
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- /*..................................................................
- Wait for all the ACK's to come in.
- ..................................................................*/
- while (Ipx.Global_Num_Send() > 0)
- Ipx.Service();
- }
- /*.....................................................................
- Form connections with all other players. Form the IPX Connection ID
- from the player's Color (high byte) and House (low byte). This
- will let us extract any player's color & house at any time.
- Fill in 'tmp_id' while we're doing this.
- .....................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- id = Build_MPlayerID (Players[i]->Player.Color,
- Players[i]->Player.House);
- tmp_id[i] = id;
- Ipx.Create_Connection(id, Players[i]->Name, &(Players[i]->Address) );
- }
- tmp_id[i] = MPlayerLocalID;
- /*.....................................................................
- Store every player's ID in the MPlayerID[] array. This array will
- determine the order of event execution, so the ID's must be stored
- in the same order on all systems.
- .....................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- min_index = 0;
- min_id = 0xff;
- for (j = 0; j < MPlayerCount; j++) {
- if (tmp_id[j] < min_id) {
- min_id = tmp_id[j];
- min_index = j;
- }
- }
- MPlayerID[i] = tmp_id[min_index];
- tmp_id[min_index] = 0xff;
- }
- /*.....................................................................
- Fill in the array of player names, including my own.
- .....................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == MPlayerLocalID) {
- strcpy (MPlayerNames[i], MPlayerName);
- } else {
- strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
- }
- }
- }
- /*------------------------------------------------------------------------
- Init network timing values, using previous response times as a measure
- of what our retry delta & timeout should be.
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
- Ipx.Global_Response_Time() * 4);
- /*------------------------------------------------------------------------
- Clear all lists
- ------------------------------------------------------------------------*/
- while (scenariolist.Count()) {
- scenariolist.Remove_Item(scenariolist.Get_Item(0));
- }
- Clear_Player_List(&playerlist);
- /*------------------------------------------------------------------------
- Restore screen
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Show_Mouse();
- return(rc);
- }
- /***************************************************************************
- * Get_NewGame_Responses -- processes packets for New Game dialog *
- * *
- * This routine can modify the contents of the given list box, as well *
- * as the contents of the Players Vector global. *
- * *
- * INPUT: *
- * playerlist list of players in this game *
- * *
- * OUTPUT: *
- * EV_NONE = nothing happened *
- * EV_NEW_PLAYER = a new player has joined; false otherwise *
- * EV_MESSAGE = a message was received *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 04/18/1995 BRR : Created. *
- *=========================================================================*/
- static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist)
- {
- int rc;
- char * item; // general-purpose string
- NodeNameType *who; // node to add to Players Vector
- int i;
- int found;
- JoinEventType retval = EV_NONE;
- int resend;
- char txt[80];
- int color;
- unsigned short magic_number;
- unsigned short crc;
- /*------------------------------------------------------------------------
- If there is no incoming packet, just return
- ------------------------------------------------------------------------*/
- rc = Ipx.Get_Global_Message (&GPacket, &GPacketlen, &GAddress, &GProductID);
- if (!rc || GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER) {
- return(EV_NONE);
- }
- /*------------------------------------------------------------------------
- Try to handle the packet in a standard way
- ------------------------------------------------------------------------*/
- if (Process_Global_Packet(&GPacket,&GAddress) != 0) {
- return(EV_NONE);
- } else
- /*------------------------------------------------------------------------
- NET_QUERY_JOIN:
- ------------------------------------------------------------------------*/
- if (GPacket.Command==NET_QUERY_JOIN) {
- /*.....................................................................
- See if this name is unique:
- - If the name matches, but the address is different, reject this player
- - If the name & address match, this packet must be a re-send of a
- prevous request; in this case, do nothing. The other player must have
- received my CONFIRM_JOIN packet (since it was sent with an ACK
- required), so we can ignore this resend.
- .....................................................................*/
- found = 0;
- resend = 0;
- for (i = 0; i < Players.Count(); i++) {
- if (!strcmp(Players[i]->Name,GPacket.Name)) {
- if (Players[i]->Address != GAddress) {
- found = 1;
- }
- else {
- resend = 1;
- }
- break;
- }
- }
- if (!strcmp (MPlayerName, GPacket.Name)) {
- found = 1;
- }
- /*.....................................................................
- Reject if name is a duplicate, or if there are too many players:
- .....................................................................*/
- if (found || (Players.Count() >= (MPlayerMax - 1) && !resend) ) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_REJECT_JOIN;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &GAddress);
- }
- /*.....................................................................
- If this packet is NOT a resend, accept the player. Grant him the
- requested color if possible.
- .....................................................................*/
- else if (!resend) {
- /*..................................................................
- Add node to the Vector list
- ..................................................................*/
- who = new NodeNameType;
- strcpy(who->Name, GPacket.Name);
- who->Address = GAddress;
- who->Player.House = GPacket.PlayerInfo.House;
- Players.Add (who);
- /*..................................................................
- Set player's color; if requested color isn't used, give it to him;
- otherwise, give him the 1st available color. Mark the color we
- give him as used.
- ..................................................................*/
- if (ColorUsed[GPacket.PlayerInfo.Color] == 0) {
- who->Player.Color = GPacket.PlayerInfo.Color;
- } else {
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- if (ColorUsed[i]==0) {
- who->Player.Color = i;
- break;
- }
- }
- }
- ColorUsed[who->Player.Color] = 1;
- /*..................................................................
- Add player name to the list box
- ..................................................................*/
- item = new char [MPLAYER_NAME_MAX + 4];
- if (GPacket.PlayerInfo.House==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",GPacket.Name,Text_String(TXT_N_O_D));
- }
- playerlist->Add_Item (item, MPlayerTColors[who->Player.Color]);
- /*..................................................................
- Send a confirmation packet
- ..................................................................*/
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_CONFIRM_JOIN;
- strcpy(GPacket.Name,MPlayerName);
- GPacket.PlayerInfo.House = who->Player.House;
- GPacket.PlayerInfo.Color = who->Player.Color;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &GAddress);
- retval = EV_NEW_PLAYER;
- }
- }
- /*------------------------------------------------------------------------
- NET_SIGN_OFF: Another system is signing off: search for that system in
- the player list, & remove it if found
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_SIGN_OFF) {
- for (i = 0; i < Players.Count(); i++) {
- /*
- ....................... Name found; remove it ......................
- */
- if (!strcmp (Players[i]->Name, GPacket.Name) &&
- Players[i]->Address==GAddress) {
- /*...............................................................
- Remove from the list box
- ...............................................................*/
- item = (char *)(playerlist->Get_Item(i + 1));
- playerlist->Remove_Item(item);
- playerlist->Flag_To_Redraw();
- delete [] item;
- /*...............................................................
- Mark his color as available
- ...............................................................*/
- ColorUsed[Players[i]->Player.Color] = 0;
- /*...............................................................
- Delete from the Vector list
- ...............................................................*/
- Players.Delete(Players[i]);
- break;
- }
- }
- }
- /*------------------------------------------------------------------------
- NET_MESSAGE: Someone is sending us a message
- ------------------------------------------------------------------------*/
- else if (GPacket.Command==NET_MESSAGE) {
- sprintf(txt,Text_String (TXT_FROM), GPacket.Name, GPacket.Message.Buf);
- magic_number = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-4));
- crc = *((unsigned short*)(GPacket.Message.Buf + COMPAT_MESSAGE_LENGTH-2));
- color = MPlayerID_To_ColorIndex(GPacket.Message.ID);
- Messages.Add_Message (txt, MPlayerTColors[color],
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 1200, magic_number, crc);
- retval = EV_MESSAGE;
- }
- return(retval);
- }
- /***************************************************************************
- * Compute_Name_CRC -- computes CRC from char string *
- * *
- * INPUT: *
- * name string to create CRC for *
- * *
- * OUTPUT: *
- * CRC *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 06/29/1995 BRR : Created. *
- *=========================================================================*/
- unsigned long Compute_Name_CRC(char *name)
- {
- char buf[80];
- unsigned long crc = 0L;
- int i;
- strcpy (buf, name);
- strupr (buf);
- for (i = 0; i < strlen(buf); i++) {
- Add_CRC (&crc, (unsigned long)buf[i]);
- }
- return (crc);
- }
- /***************************************************************************
- * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog *
- * *
- * INPUT: *
- * reconn 1 = reconnect, 0 = waiting for first-time connection *
- * fresh 1 = draw from scratch, 0 = only update time counter *
- * oldest_index IPX connection index of oldest connection *
- * (only used for reconnection) *
- * timeval value to print in the countdown field *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 07/08/1995 BRR : Created. *
- *=========================================================================*/
- void Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index,
- unsigned long timeval)
- {
- static int x,y,w,h;
- int id;
- char buf1[40] = {0};
- char buf2[40] = {0};
- char const *buf3 = "";
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- int d_txt6_h = 6*factor+1;
- int d_margin = 5*factor;
- /*------------------------------------------------------------------------
- Draw the dialog from scratch
- ------------------------------------------------------------------------*/
- if (fresh) {
- Fancy_Text_Print ("", 0, 0, CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- if (reconn) {
- id = Ipx.Connection_ID(oldest_index);
- sprintf(buf1,Text_String(TXT_RECONNECTING_TO),
- Ipx.Connection_Name(id));
- } else {
- sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS));
- }
- sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);
- buf3 = Text_String(TXT_PRESS_ESC);
- w = MAX(String_Pixel_Width(buf1),String_Pixel_Width(buf2));
- w = MAX(String_Pixel_Width(buf3), w);
- w += (d_margin * 2);
- h = (d_txt6_h * 3) + (d_margin * 6);
- x = 160*factor - (w / 2);
- y = 100*factor - (h / 2);
- Hide_Mouse();
- Set_Logic_Page(SeenBuff);
- Dialog_Box(x, y, w, h);
- Fancy_Text_Print (buf1, 160*factor, y + (d_margin * 2), CC_GREEN, BLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print (buf2, 160*factor, y + (d_margin * 2) + d_txt6_h + d_margin,
- CC_GREEN, BLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Fancy_Text_Print (buf3, 160*factor, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2,
- CC_GREEN, BLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Show_Mouse();
- } else {
- /*------------------------------------------------------------------------
- Just update the timeout value on the dialog
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Set_Logic_Page(SeenBuff);
- sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1);
- Fancy_Text_Print (buf2, 160*factor, y + (d_margin * 2) + d_txt6_h + d_margin,
- CC_GREEN, BLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- Show_Mouse();
- }
- }
- /***********************************************************************************************
- * Net_Fake_New_Dialog -- Just like Net_New_Dialog but without the Dialog. For internet play *
- * *
- * This 'dialog' does all the non-dialog game set up stuff that is done in the normal *
- * network game set up dialog. The only visible button is 'cancel' *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: true if successfully connected *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 5/24/96 10:34AM ST : Created *
- *=============================================================================================*/
- static int Net_Fake_New_Dialog(void)
- {
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- int d_dialog_w = 120*factor; // dialog width
- int d_dialog_h = 80*factor; // dialog height
- int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
- int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- //d_playerlist_w = 100;
- int d_playerlist_w = 106*factor;
- int d_playerlist_h = 27*factor;
- int d_playerlist_x = 10 * factor; //off screen
- //int d_playerlist_x = 500*factor; //10 * factor; //off screen
- int d_playerlist_y = d_dialog_y + 20;
- #if (GERMAN | FRENCH)
- int d_cancel_w = 50*factor;
- #else
- int d_cancel_w = 45*factor;
- #endif
- int d_cancel_h = 9*factor;
- int d_cancel_x = d_dialog_cx - (d_cancel_w / 2);
- int d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;
- char text_buffer[64];
- int width;
- int height;
- bool player_joined = false;
- CountDownTimerClass join_timer;
- strcpy(text_buffer, "Connecting....");
- Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
- Format_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);
- /*........................................................................
- Button Enumerations
- ........................................................................*/
- enum {
- BUTTON_CANCEL = 100,
- BUTTON_PLAYERLIST,
- };
- /*........................................................................
- Redraw values: in order from "top" to "bottom" layer of the dialog
- ........................................................................*/
- typedef enum {
- REDRAW_NONE = 0,
- REDRAW_MESSAGE,
- REDRAW_BUTTONS,
- REDRAW_BACKGROUND,
- REDRAW_ALL = REDRAW_BACKGROUND
- } RedrawType;
- /*........................................................................
- Dialog variables
- ........................................................................*/
- RedrawType display = REDRAW_ALL; // redraw level
- bool process = true; // process while true
- KeyNumType input;
- char credbuf[CREDITSBUF_MAX]; // for credit edit box
- int old_cred; // old value in credits buffer
- int transmit; // 1 = re-transmit new game options
- long ok_timer = 0; // for timing OK button
- int rc;
- int i,j;
- char *item;
- int tabs[] = {77*factor}; // tabs for player list box
- long ping_timer = 0; // for sending Ping packets
- unsigned char tmp_id[MAX_PLAYERS]; // temp storage for sorting player ID's
- int min_index; // for sorting player ID's
- unsigned char min_id; // for sorting player ID's
- unsigned char id; // connection ID
- JoinEventType whahoppa; // event generated by received packets
- void const *up_button;
- void const *down_button;
- if (InMainLoop){
- up_button = Hires_Retrieve("BTN-UP.SHP");
- down_button = Hires_Retrieve("BTN-DN.SHP");
- }else{
- up_button = Hires_Retrieve("BTN-UP2.SHP");
- down_button = Hires_Retrieve("BTN-DN2.SHP");
- }
- /*........................................................................
- Buttons
- ........................................................................*/
- GadgetClass *commands; // button list
- ColorListClass playerlist(BUTTON_PLAYERLIST,
- d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #if (GERMAN | FRENCH)
- d_cancel_x, d_cancel_y);
- #else
- d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
- #endif
- CCDebugString ("C&C95 - In new game dialog - initialising lists.\n");
- /*
- ------------------------- Build the button list --------------------------
- */
- commands = &playerlist;
- cancelbtn.Add_Tail(*commands);
- playerlist.Set_Tabs(tabs);
- /*
- ----------------------------- Various Inits ------------------------------
- */
- sprintf(credbuf, "%d", MPlayerCredits);
- old_cred = MPlayerCredits;
- /*........................................................................
- Init other scenario parameters
- ........................................................................*/
- Special.IsTGrowth = MPlayerTiberium;
- Special.IsTSpread = MPlayerTiberium;
- transmit = 0;
- /*........................................................................
- Init player color-used flags
- ........................................................................*/
- for (i = 0; i < MAX_MPLAYER_COLORS; i++) {
- ColorUsed[i] = 0; // init all colors to available
- }
- ColorUsed[MPlayerColorIdx] = 1; // set my color to used
- playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, CC_GREEN_SHADOW);
- /*........................................................................
- Init random-number generator, & create a seed to be used for all random
- numbers from here on out
- ........................................................................*/
- randomize();
- Seed = rand();
- /*------------------------------------------------------------------------
- Add myself to the list. Note that since I'm not in the Players Vector,
- the Vector & listbox are now 1 out of sync.
- ------------------------------------------------------------------------*/
- item = new char [MPLAYER_NAME_MAX + 4];
- if (MPlayerHouse==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
- }
- playerlist.Add_Item(item, MPlayerTColors[MPlayerColorIdx]);
- /*
- ** Process the message loop until we are in focus.
- */
- if (!GameInFocus){
- CCDebugString ("C&C95 - Waiting for game to come into focus.");
- do {
- OutputDebugString (".");
- Keyboard::Check();
- }while (!GameInFocus);
- CCDebugString ("\n");
- AllSurfaces.SurfacesRestored=FALSE;
- }
- CCDebugString ("C&C95 - About to uncompress title page.\n");
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- CCDebugString ("C&C95 - About to set the palette.\n");
- Set_Palette(Palette);
- CCDebugString ("C&C95 - Palette was set OK.\n");
- if (LogicPage != &SeenBuff && LogicPage!= &HidPage){
- CCDebugString ("C&C95 - Logic page invalid");
- Set_Logic_Page (SeenBuff);
- }
- char a_buffer [128];
- sprintf (a_buffer, "Number of players:%d", Players.Count());
- CCDebugString (a_buffer);
- /*
- ** Send a bogus packet to wake up the VSS
- */
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = (NetCommandType)50; //Invalid command
- strcpy (GPacket.Name, MPlayerName);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType), 0, NULL);
- CCDebugString ("C&C95 - About to reveal mouse\n");
- while (Get_Mouse_State() > 0) Show_Mouse();
- /*
- ---------------------------- Processing loop -----------------------------
- */
- CCDebugString ("C&C95 - Entering join dialogue loop\n");
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=REDRAW_ALL;
- }
- /*
- ...................... Refresh display if needed ......................
- */
- if (display) {
- Hide_Mouse();
- /*
- .................. Redraw backgound & dialog box ...................
- */
- if (display >= REDRAW_BACKGROUND) {
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Set_Palette(Palette);
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- /*...............................................................
- Dialog & Field labels
- ...............................................................*/
- Draw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
- Fancy_Text_Print(text_buffer, d_dialog_cx-width/2, d_dialog_y + 25*factor, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- }
- /*
- .......................... Redraw buttons ..........................
- */
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- /*
- ........................... Get user input ............................
- */
- input = commands->Input();
- /*
- ---------------------------- Process input ----------------------------
- */
- switch (input) {
- /*------------------------------------------------------------------
- CANCEL: send a SIGN_OFF, bail out with error code
- ------------------------------------------------------------------*/
- case (KN_ESC):
- case (BUTTON_CANCEL | KN_BUTTON):
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- /*...............................................................
- Broadcast my sign-off over my network
- ...............................................................*/
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- /*...............................................................
- Broadcast my sign-off over a bridged network if there is one
- ...............................................................*/
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- /*...............................................................
- And now, just be absolutely sure, send my sign-off to each
- player in my game. (If there's a bridge between us, the other
- player will have specified my address, so he can cross the
- bridge; but I may not have specified a bridge address, so the
- only way I have of crossing the bridge is to send a packet
- directly to him.)
- ...............................................................*/
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- MPlayerGameName[0] = 0;
- process = false;
- rc = false;
- break;
- /*------------------------------------------------------------------
- default: exit loop with TRUE status
- ------------------------------------------------------------------*/
- default:
- char ddkks[128];
- if (Players.Count() == InternetMaxPlayers-1){
- sprintf (ddkks, "C&C95 - Players.Count() = %d\n", Players.Count());
- CCDebugString (ddkks);
- /*
- ** Wait for several secs after receiving request to join before sending
- ** start game packet
- */
- if (!player_joined){
- player_joined = true;
- join_timer.Set (3*60, true);
- break;
- }else{
- if (join_timer.Time()) break;
- }
- CCDebugString ("C&C95 - Join timer expired\n");
- /*...............................................................
- If a new player has joined in the last second, don't allow
- an OK; force a wait longer than 2 seconds (to give all players
- a chance to know about this new guy)
- ...............................................................*/
- i = MAX(Ipx.Global_Response_Time() * 2, 120);
- while (TickCount.Time() - ok_timer < i)
- Ipx.Service();
- /*...............................................................
- If there are at least 2 players, go ahead & play; error otherwise
- ...............................................................*/
- if (MPlayerSolo || Players.Count() > 0) {
- rc = TRUE;
- process = FALSE;
- } else {
- CCMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL);
- display = REDRAW_ALL;
- }
- }
- break;
- }
- /*---------------------------------------------------------------------
- Process incoming packets
- ---------------------------------------------------------------------*/
- whahoppa = Get_NewGame_Responses(&playerlist);
- if (whahoppa == EV_NEW_PLAYER) {
- ok_timer = TickCount.Time();
- transmit = 1;
- } else {
- if (whahoppa == EV_MESSAGE) {
- display = REDRAW_MESSAGE;
- }
- }
- /*---------------------------------------------------------------------
- If our Transmit flag is set, we need to send out a game option packet
- ---------------------------------------------------------------------*/
- if (transmit) {
- for (i = 0; i < Players.Count(); i++) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_GAME_OPTIONS;
- GPacket.ScenarioInfo.Scenario = ScenarioIdx; //MPlayerFilenum[ScenarioIdx];
- GPacket.ScenarioInfo.Credits = MPlayerCredits;
- GPacket.ScenarioInfo.IsBases = MPlayerBases;
- GPacket.ScenarioInfo.IsTiberium = MPlayerTiberium;
- GPacket.ScenarioInfo.IsGoodies = MPlayerGoodies;
- GPacket.ScenarioInfo.IsGhosties = MPlayerGhosts;
- GPacket.ScenarioInfo.BuildLevel = BuildLevel;
- GPacket.ScenarioInfo.UnitCount = MPlayerUnitCount;
- GPacket.ScenarioInfo.Seed = Seed;
- GPacket.ScenarioInfo.Special = Special;
- GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed;
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- }
- transmit = 0;
- }
- /*---------------------------------------------------------------------
- Ping every player in my game, to force the Global Channel to measure
- the connection response time.
- ---------------------------------------------------------------------*/
- if (TickCount.Time() - ping_timer > 15) {
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_PING;
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- }
- ping_timer = TickCount.Time();
- }
- /*---------------------------------------------------------------------
- Service the Ipx connections
- ---------------------------------------------------------------------*/
- Ipx.Service();
- /*---------------------------------------------------------------------
- Service the sounds & score; GameActive must be false at this point,
- so Call_Back() doesn't intercept global messages from me!
- ---------------------------------------------------------------------*/
- Call_Back();
- } /* end of while */
- CCDebugString ("C&C95 - Exited process loop\n");
- /*------------------------------------------------------------------------
- Establish connections with all other players.
- ------------------------------------------------------------------------*/
- if (rc) {
- /*.....................................................................
- Set the number of players in this game, and my ID
- .....................................................................*/
- MPlayerCount = Players.Count() + 1;
- MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- /*.....................................................................
- Get the scenario filename
- .....................................................................*/
- Scenario = ScenarioIdx; //PlayerFilenum[ScenarioIdx]; We are passed actual number now from wchat not index from
- //Scenario = MPlayerFilenum[ScenarioIdx];
- /*.....................................................................
- Compute frame delay value for packet transmissions:
- - Divide global channel's response time by 8 (2 to convert to 1-way
- value, 4 more to convert from ticks to frames)
- .....................................................................*/
- MPlayerMaxAhead = MAX( (Ipx.Global_Response_Time() / 8), 2);
- /*.....................................................................
- Send all players the NET_GO packet. Wait until all ACK's have been
- received.
- .....................................................................*/
- CCDebugString ("C&C95 - Sending the 'GO' packet\n");
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_GO;
- GPacket.ResponseTime.OneWay = MPlayerMaxAhead;
- for (i = 0; i < Players.Count(); i++) {
- char flopbuf [128];
- sprintf (flopbuf, "Sending 'GO' packet to address %d\n", *((unsigned short*)&(Players[i]->Address)));
- CCDebugString (flopbuf);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 1, &(Players[i]->Address) );
- /*..................................................................
- Wait for all the ACK's to come in.
- ..................................................................*/
- while (Ipx.Global_Num_Send() > 0)
- Ipx.Service();
- }
- /*.....................................................................
- Form connections with all other players. Form the IPX Connection ID
- from the player's Color (high byte) and House (low byte). This
- will let us extract any player's color & house at any time.
- Fill in 'tmp_id' while we're doing this.
- .....................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- id = Build_MPlayerID (Players[i]->Player.Color,
- Players[i]->Player.House);
- tmp_id[i] = id;
- Ipx.Create_Connection(id, Players[i]->Name, &(Players[i]->Address) );
- }
- CCDebugString ("C&C95 - Creating connection to the VSS\n");
- /*
- ** Create an additional connection to the VSS
- */
- if (UseVirtualSubnetServer){
- IPXAddressClass vss_global_address;
- NetNodeType vss_node;
- NetNumType vss_net;
- memset (vss_net, 1, sizeof (vss_net));
- memset (vss_node, 0, sizeof (vss_node));
- vss_global_address.Set_Address(vss_net, vss_node);
- Ipx.Create_Connection( VSS_ID, "VSS", &vss_global_address);
- }
- tmp_id[i] = MPlayerLocalID;
- /*.....................................................................
- Store every player's ID in the MPlayerID[] array. This array will
- determine the order of event execution, so the ID's must be stored
- in the same order on all systems.
- .....................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- min_index = 0;
- min_id = 0xff;
- for (j = 0; j < MPlayerCount; j++) {
- if (tmp_id[j] < min_id) {
- min_id = tmp_id[j];
- min_index = j;
- }
- }
- MPlayerID[i] = tmp_id[min_index];
- tmp_id[min_index] = 0xff;
- }
- /*.....................................................................
- Fill in the array of player names, including my own.
- .....................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == MPlayerLocalID) {
- strcpy (MPlayerNames[i], MPlayerName);
- } else {
- strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
- }
- }
- }
- /*------------------------------------------------------------------------
- Init network timing values, using previous response times as a measure
- of what our retry delta & timeout should be.
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
- Ipx.Global_Response_Time() * 4);
- /*------------------------------------------------------------------------
- Clear all lists
- ------------------------------------------------------------------------*/
- Clear_Player_List(&playerlist);
- /*------------------------------------------------------------------------
- Restore screen
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Show_Mouse();
- return(rc);
- }
- /***********************************************************************************************
- * Net_Fake_Join_Dialog -- Like Net_Join_Dialog but with no dialogs. For Internet Play. *
- * *
- * This 'dialog' does all the non-dialog game set up stuff that is done in the normal *
- * network game set up dialog. The only visible button is 'cancel' *
- * *
- * *
- * INPUT: Nothing *
- * *
- * OUTPUT: 0 = good, -1 = bad *
- * *
- * WARNINGS: None *
- * *
- * HISTORY: *
- * 5/24/96 11:07AM ST : Created *
- *=============================================================================================*/
- static int Net_Fake_Join_Dialog(void)
- {
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- /*........................................................................
- Dialog & button dimensions
- ........................................................................*/
- /* ###Change collision detected! C:\PROJECTS\CODE\NETDLG.CPP... */
- int d_dialog_w = 120 *factor; // dialog width
- int d_dialog_h = 80*factor; // dialog height
- int d_dialog_x = ((320*factor - d_dialog_w) / 2); // dialog x-coord
- int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
- int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord
- int d_margin1=10;
- int d_txt6_h=15;
- int d_gamelist_w = 160*factor;
- int d_gamelist_h = 27*factor;
- //int d_gamelist_x = 500*factor; //230*factor; //Off screen
- int d_gamelist_x = 230*factor; //Off screen
- int d_gamelist_y = d_dialog_y + 20;
- int d_playerlist_w = 106*factor;
- int d_playerlist_h = 27*factor;
- int d_playerlist_x = 10 * factor; //Off screen
- //int d_playerlist_x = 500*factor; //10 * factor; //Off screen
- int d_playerlist_y = d_gamelist_y + 20;
- #if (GERMAN | FRENCH)
- int d_cancel_w = 50*factor;
- #else
- int d_cancel_w = 40*factor;
- #endif
- int d_cancel_h = 9*factor;
- int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
- int d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;
- bool ready_to_go = false;
- char text_buffer[64];
- int width;
- int height;
- strcpy(text_buffer, "Connecting....");
- Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW);
- Format_Window_String(text_buffer, SeenBuff.Get_Height(), width, height);
- /*........................................................................
- Button Enumerations
- ........................................................................*/
- enum {
- BUTTON_CANCEL = 100,
- BUTTON_GAMELIST,
- BUTTON_PLAYERLIST,
- };
- /*........................................................................
- Redraw values: in order from "top" to "bottom" layer of the dialog
- ........................................................................*/
- typedef enum {
- REDRAW_NONE = 0,
- REDRAW_MESSAGE,
- REDRAW_COLORS,
- REDRAW_BUTTONS,
- REDRAW_BACKGROUND,
- REDRAW_ALL = REDRAW_BACKGROUND
- } RedrawType;
- /*........................................................................
- Dialog variables
- ........................................................................*/
- RedrawType display = REDRAW_ALL; // redraw level
- bool process = true; // process while true
- KeyNumType input;
- JoinStateType joinstate = JOIN_NOTHING; // current "state" of this dialog
- char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name
- int game_index = -1; // index of currently-selected game
- int join_index = -1; // index of game we're joining
- int rc = 0; // -1 = user cancelled, 1 = New
- JoinEventType event; // event from incoming packet
- int i,j; // loop counter
- int parms_received; // 1 = game options received
- unsigned char tmp_id[MAX_PLAYERS]; // temp storage for sorting player ID's
- int min_index; // for sorting player ID's
- unsigned char min_id; // for sorting player ID's
- unsigned char id; // connection ID
- char * item;
- unsigned long starttime;
- NodeNameType *who;
- void const *up_button;
- void const *down_button;
- if (InMainLoop){
- up_button = Hires_Retrieve("BTN-UP.SHP");
- down_button = Hires_Retrieve("BTN-DN.SHP");
- }else{
- up_button = Hires_Retrieve("BTN-UP2.SHP");
- down_button = Hires_Retrieve("BTN-DN2.SHP");
- }
- /*........................................................................
- Buttons
- ........................................................................*/
- GadgetClass *commands; // button list
- ColorListClass playerlist(BUTTON_PLAYERLIST,
- d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- ListClass gamelist(BUTTON_GAMELIST,
- d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- up_button,
- down_button);
- TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
- #if (GERMAN | FRENCH)
- d_cancel_x, d_cancel_y);
- #else
- d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
- #endif
- /*
- ----------------------------- Various Inits ------------------------------
- */
- //MPlayerColorIdx = MPlayerPrefColor; // init my preferred color
- playerlist.Set_Selected_Style(ColorListClass::SELECT_NONE);
- Fancy_Text_Print("", 0, 0, CC_GREEN, TBLACK,
- TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*
- --------------------------- Send network query ---------------------------
- */
- CCDebugString ("C&C95 - About to call Send_Join_Queries.\n");
- Send_Join_Queries (game_index, 1, 0);
- /*
- ** Process the message loop until we are in focus.
- */
- if (!GameInFocus){
- CCDebugString ("C&C95 - Waiting for game to come into focus.");
- do {
- CCDebugString (".");
- Keyboard::Check();
- }while (!GameInFocus);
- CCDebugString ("\n");
- AllSurfaces.SurfacesRestored=FALSE;
- }
- CCDebugString ("C&C95 - About to uncompress title page.\n");
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- CCDebugString ("C&C95 - About to set the palette.\n");
- Set_Palette(Palette);
- CCDebugString ("C&C95 - Palette was set OK.\n");
- if (LogicPage != &SeenBuff && LogicPage!= &HidPage){
- CCDebugString ("C&C95 - Logic page invalid\n");
- Set_Logic_Page (SeenBuff);
- }
- char a_buffer [128];
- sprintf (a_buffer, "C&C95 - Number of players:%d\n", Players.Count());
- CCDebugString (a_buffer);
- /*
- ---------------------------- Init Mono Output ----------------------------
- */
- CCDebugString ("C&C95 - About to reveal mouse\n");
- while (Get_Mouse_State() > 0) Show_Mouse();
- /*
- ---------------------------- Processing loop -----------------------------
- */
- CCDebugString ("C&C95 - Entering join dialogue loop\n");
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=REDRAW_ALL;
- }
- /*
- ...................... Refresh display if needed ......................
- */
- if (display) {
- Hide_Mouse();
- /*
- .................. Redraw backgound & dialog box ...................
- */
- if (display >= REDRAW_BACKGROUND) {
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Set_Palette(Palette);
- Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
- /*...............................................................
- Dialog & Field labels
- ...............................................................*/
- Draw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
- Fancy_Text_Print(text_buffer, d_dialog_cx-width/2, d_dialog_y + 25*factor, CC_GREEN, TBLACK,
- TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
- /*
- .................... Rebuild the button list ....................
- */
- cancelbtn.Zap();
- gamelist.Zap();
- playerlist.Zap();
- commands = &cancelbtn;
- gamelist.Add_Tail(*commands);
- playerlist.Add_Tail(*commands);
- }
- /*
- .......................... Redraw buttons ..........................
- */
- if (display >= REDRAW_BUTTONS) {
- commands->Draw_All();
- }
- Show_Mouse();
- display = REDRAW_NONE;
- }
- /*
- ........................... Get user input ............................
- */
- input = commands->Input();
- /*
- ---------------------------- Process input ----------------------------
- */
- switch (input) {
- /*------------------------------------------------------------------
- CANCEL: send a SIGN_OFF
- - If we're part of a game, stay in this dialog; otherwise, exit
- ------------------------------------------------------------------*/
- case (KN_ESC):
- case (BUTTON_CANCEL | KN_BUTTON):
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy(GPacket.Name,MPlayerName);
- /*...............................................................
- If we're joined to a game, make extra sure the other players in
- that game know I'm exiting; send my SIGN_OFF as an ack-required
- packet. Do not send this packet to myself (index 0).
- ...............................................................*/
- if (joinstate == JOIN_CONFIRMED) {
- //
- // Remove myself from the player list box
- //
- item = (char *)(playerlist.Get_Item(0));
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- //
- // Remove myself from the Players list
- //
- who = Players[0];
- Players.Delete(0);
- delete who;
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- }
- /*...............................................................
- Now broadcast my SIGN_OFF so other players looking at this game
- know I'm leaving.
- ...............................................................*/
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- if (joinstate != JOIN_CONFIRMED) {
- process = false;
- rc = -1;
- } else {
- MPlayerGameName[0] = 0;
- joinstate = JOIN_NOTHING;
- display = REDRAW_ALL;
- }
- break;
- /*------------------------------------------------------------------
- JOIN: send a join request packet & switch to waiting-for-confirmation
- mode. (Request_To_Join fills in MPlayerName with my namebuf.)
- ------------------------------------------------------------------*/
- default:
- if (joinstate == JOIN_NOTHING && Games.Count()!=0){
- gamelist.Set_Selected_Index(0);
- join_index = gamelist.Current_Index();
- parms_received = 0;
- if (Request_To_Join (MPlayerName, join_index, &playerlist, MPlayerHouse,
- MPlayerColorIdx)) {
- joinstate = JOIN_WAIT_CONFIRM;
- } else {
- display = REDRAW_ALL;
- }
- }
- break;
- }
- /*---------------------------------------------------------------------
- Resend our query packets
- ---------------------------------------------------------------------*/
- Send_Join_Queries(game_index, 0, 0);
- /*---------------------------------------------------------------------
- Process incoming packets
- ---------------------------------------------------------------------*/
- event = Get_Join_Responses(&joinstate, &gamelist, &playerlist,
- join_index);
- /*.....................................................................
- If we've changed state, redraw everything; if we're starting the game,
- break out of the loop. If we've just joined, send out a player query
- so I'll get added to the list instantly.
- .....................................................................*/
- if (event == EV_STATE_CHANGE) {
- display = REDRAW_ALL;
- if (joinstate==JOIN_GAME_START) {
- CCDebugString ("C&C95 - Received 'GO' packet\n");
- ready_to_go = true;
- } else {
- /*..................................................................
- If we're newly-confirmed, immediately send out a player query
- ..................................................................*/
- if (joinstate==JOIN_CONFIRMED) {
- Clear_Player_List(&playerlist);
- item = new char [MPLAYER_NAME_MAX + 4];
- if (MPlayerHouse==HOUSE_GOOD) {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_G_D_I));
- } else {
- sprintf(item,"%s\t%s",MPlayerName,Text_String(TXT_N_O_D));
- }
- playerlist.Add_Item (item, MPlayerTColors[MPlayerColorIdx]);
- who = new NodeNameType;
- strcpy(who->Name, MPlayerName);
- who->Address = IPXAddressClass();
- who->Player.House = MPlayerHouse;
- who->Player.Color = MPlayerColorIdx;
- Players.Add (who);
- Send_Join_Queries (game_index, 0, 1);
- } else {
- /*..................................................................
- If we've been rejected, clear any messages we may have been typing.
- ..................................................................*/
- if (joinstate==JOIN_REJECTED) {
- //
- // Remove myself from the player list box
- //
- item = (char *)(playerlist.Get_Item(0));
- if (item){
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- }
- //
- // Remove myself from the Players list
- //
- if (Players.Count()){
- who = Players[0];
- Players.Delete(0);
- delete who;
- }
- }
- }
- }
- } else
- /*.....................................................................
- If a new game is detected, and it's the first game on our list,
- automatically send out a player query for that game.
- .....................................................................*/
- if (event == EV_NEW_GAME && gamelist.Count()==1) {
- gamelist.Set_Selected_Index(0);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- } else
- /*.....................................................................
- If the game options have changed, print them.
- .....................................................................*/
- if (event == EV_GAME_OPTIONS) {
- parms_received = 1;
- display = REDRAW_MESSAGE;
- } else
- /*.....................................................................
- Draw an incoming message
- .....................................................................*/
- if (event == EV_MESSAGE) {
- display = REDRAW_MESSAGE;
- } else
- /*.....................................................................
- A game before the one I've selected is gone, so we have a new index now.
- 'game_index' must be kept set to the currently-selected list item, so
- we send out queries for the currently-selected game. It's therefore
- imperative that we detect any changes to the game list.
- If we're joined in a game, we must decrement our game_index to keep
- it aligned with the game we're joined to.
- .....................................................................*/
- if (event == EV_GAME_SIGNOFF) {
- if (joinstate==JOIN_CONFIRMED) {
- game_index--;
- join_index--;
- gamelist.Set_Selected_Index(join_index);
- } else {
- gamelist.Flag_To_Redraw();
- Clear_Player_List(&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- /*---------------------------------------------------------------------
- Service the Ipx connections
- ---------------------------------------------------------------------*/
- Ipx.Service();
- /*---------------------------------------------------------------------
- Clean out the Game List; if an old entry is found:
- - Remove it
- - Clear the player list
- - Send queries for the new selected game, if there is one
- ---------------------------------------------------------------------*/
- for (i = 0; i < Games.Count(); i++) {
- if (TickCount.Time() - Games[i]->Game.LastTime > 400) {
- Games.Delete(Games[i]);
- item = (char *)(gamelist.Get_Item (i));
- gamelist.Remove_Item (item);
- delete [] item;
- if (i <= game_index) {
- gamelist.Flag_To_Redraw();
- Clear_Player_List(&playerlist);
- game_index = gamelist.Current_Index();
- Send_Join_Queries (game_index, 0, 1);
- }
- }
- }
- /*
- ** If we were flagged to start the game and we recognise both players then quit the loop
- */
- char ddkks[128];
- sprintf (ddkks, "C&C95 - Players.Count() = %d\n", Players.Count());
- CCDebugString (ddkks);
- if (ready_to_go){ // && Players.Count() == InternetMaxPlayers){
- rc = 0;
- process = false;
- }
- /*---------------------------------------------------------------------
- Service the sounds & score; GameActive must be false at this point,
- so Call_Back() doesn't intercept global messages from me!
- ---------------------------------------------------------------------*/
- Call_Back();
- }
- /*------------------------------------------------------------------------
- Establish connections with all other players.
- ------------------------------------------------------------------------*/
- if (rc == 0) {
- /*.....................................................................
- If the other guys are playing a scenario I don't have (sniff), I can't
- play. Try to bail gracefully.
- .....................................................................*/
- if (ScenarioIdx==-1) {
- CCMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH);
- //
- // Remove myself from the player list box
- //
- item = (char *)(playerlist.Get_Item(0));
- playerlist.Remove_Item(item);
- delete [] item;
- playerlist.Flag_To_Redraw();
- //
- // Remove myself from the Players list
- //
- who = Players[0];
- Players.Delete(0);
- delete who;
- memset (&GPacket, 0, sizeof(GlobalPacketType));
- GPacket.Command = NET_SIGN_OFF;
- strcpy (GPacket.Name, MPlayerName);
- for (i = 0; i < Players.Count(); i++) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 1,
- &(Players[i]->Address));
- Ipx.Service();
- }
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- Ipx.Send_Global_Message (&GPacket, sizeof (GlobalPacketType),
- 0, NULL);
- if (IsBridge) {
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- Ipx.Send_Global_Message (&GPacket, sizeof(GlobalPacketType), 0,
- &BridgeNet);
- }
- while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ;
- rc = -1;
- } else {
- /*..................................................................
- Set the number of players in this game, and my ID
- ..................................................................*/
- MPlayerCount = Players.Count();
- MPlayerLocalID = Build_MPlayerID (MPlayerColorIdx, MPlayerHouse);
- /*..................................................................
- Get the scenario number
- ..................................................................*/
- Scenario = ScenarioIdx; //PlayerFilenum[ScenarioIdx]; We are passed actual number now from wchat not index from
- /*..................................................................
- Form connections with all other players. Form the IPX Connection ID
- from the player's Color and House. This will let us extract any
- player's color & house at any time. Fill in 'tmp_id' while we're
- doing this.
- ..................................................................*/
- for (i = 0; i < Players.Count(); i++) {
- /*...............................................................
- Only create the connection if it's not myself!
- ...............................................................*/
- if (strcmp (MPlayerName, Players[i]->Name)) {
- id = Build_MPlayerID(Players[i]->Player.Color,
- Players[i]->Player.House);
- tmp_id[i] = id;
- Ipx.Create_Connection((int)id, Players[i]->Name, &(Players[i]->Address) );
- } else {
- tmp_id[i] = MPlayerLocalID;
- }
- }
- /*
- ** Create an additional connection to the VSS
- */
- if (UseVirtualSubnetServer){
- IPXAddressClass vss_global_address;
- NetNodeType vss_node;
- NetNumType vss_net;
- memset (vss_net, 1, sizeof (vss_net));
- memset (vss_node, 0, sizeof (vss_node));
- vss_global_address.Set_Address(vss_net, vss_node);
- Ipx.Create_Connection( VSS_ID, "VSS", &vss_global_address);
- }
- /*..................................................................
- Store every player's ID in the MPlayerID[] array. This array will
- determine the order of event execution, so the ID's must be stored
- in the same order on all systems.
- ..................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- min_index = 0;
- min_id = 0xff;
- for (j = 0; j < MPlayerCount; j++) {
- if (tmp_id[j] < min_id) {
- min_id = tmp_id[j];
- min_index = j;
- }
- }
- MPlayerID[i] = tmp_id[min_index];
- tmp_id[min_index] = 0xff;
- }
- /*..................................................................
- Fill in the array of player names, including my own.
- ..................................................................*/
- for (i = 0; i < MPlayerCount; i++) {
- if (MPlayerID[i] == MPlayerLocalID) {
- strcpy (MPlayerNames[i], MPlayerName);
- } else {
- strcpy (MPlayerNames[i], Ipx.Connection_Name(MPlayerID[i]));
- }
- }
- }
- /*---------------------------------------------------------------------
- Wait a while, polling the IPX service routines, to give our ACK
- a chance to get to the other system. If he doesn't get our ACK, he'll
- be waiting the whole time we load MIX files.
- ---------------------------------------------------------------------*/
- i = MAX(Ipx.Global_Response_Time() * 2, 120);
- starttime = TickCount.Time();
- while (TickCount.Time() - starttime < i) {
- Ipx.Service();
- }
- }
- /*------------------------------------------------------------------------
- Init network timing values, using previous response times as a measure
- of what our retry delta & timeout should be.
- ------------------------------------------------------------------------*/
- Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1,
- Ipx.Global_Response_Time() * 4);
- /*------------------------------------------------------------------------
- Clear all lists
- ------------------------------------------------------------------------*/
- Clear_Game_List(&gamelist);
- Clear_Player_List(&playerlist);
- /*------------------------------------------------------------------------
- Restore screen
- ------------------------------------------------------------------------*/
- Hide_Mouse();
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- HidPage.Blit(SeenBuff);
- Show_Mouse();
- return(rc);
- }
- #endif
|