NETDLG.CPP (337753B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/NETDLG.CPP 13 10/13/97 2:20p Steve_t $ */ 17 /*********************************************************************************************** 18 *** 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 *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : NETDLG.CPP * 24 * * 25 * Programmer : Bill Randolph * 26 * * 27 * Start Date : January 23, 1995 * 28 * * 29 * Last Update : December 12, 1995 [BRR] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * * 33 * These routines establish & maintain peer-to-peer connections between this system * 34 * and all others in the game. Each system finds out the IPX address of the others, * 35 * and forms a direct connection (IPXConnectionClass) to that system. Systems are * 36 * found out via broadcast queries. Every system broadcasts its queries, and every * 37 * system replies to queries it receives. At the point when the game owner signals * 38 * 'OK', every system must know about all the other systems in the game. * 39 * * 40 * How Bridges are handled: * 41 * Currently, bridges are handled by specifying the destination IPX address of the * 42 * "server" (game owner's system) on the command-line. This address is used to * 43 * derive a broadcast address to that destination network, and this system's queries * 44 * are broadcast over its network & the server's network; replies to the queries come * 45 * with each system's IPX address attached, so once we have the address, we can form * 46 * a connection with any system on the bridged net. * 47 * * 48 * The flaw in this plan is that we can only cross one bridge. If there are 3 nets * 49 * bridged (A, B, & C), and the server is on net B, and we're on net A, our broadcasts * 50 * will reach nets A & B, but not C. The way to circumvent this (if it becomes a problem) * 51 * would be to have the server tell us what other systems are in its game, not each * 52 * individual player's system. Thus, each system would find out about all the other systems * 53 * by interacting with the game's owner system (this would be more involved than what * 54 * I'm doing here). * 55 * * 56 * Here's a list of all the different packets sent over the Global Channel: * 57 * * 58 * NET_QUERY_GAME * 59 * (no other data) * 60 * NET_ANSWER_GAME * 61 * Name: game owner's name * 62 * GameInfo: game's version & open state * 63 * NET_QUERY_PLAYER * 64 * Name: name of game we want players to respond for * 65 * NET_ANSWER_PLAYER * 66 * Name: player's name * 67 * PlayerInfo: info about player * 68 * NET_CHAT_ANNOUNCE * 69 * Chat: unique id of the local node, so I can tell * 70 * if this chat announcement is from myself * 71 * NET_QUERY_JOIN * 72 * Name: name of player wanting to join * 73 * PlayerInfo: player's requested house, color, & version range * 74 * NET_CONFIRM_JOIN * 75 * PlayerInfo: approves player's house & color * 76 * NET_REJECT_JOIN * 77 * Reject.Why: tells why we got rejected * 78 * NET_GAME_OPTIONS * 79 * ScenarioInfo: info about scenario * 80 * NET_SIGN_OFF * 81 * Name: name of player signing off * 82 * NET_PING * 83 * (no other data) * 84 * NET_GO * 85 * Delay: value of one-way response time, in frames * 86 * * 87 *---------------------------------------------------------------------------------------------* 88 * Functions: * 89 * Init_Network -- initializes network stuff * 90 * Shutdown_Network -- shuts down network stuff * 91 * Process_Global_Packet -- responds to remote queries * 92 * Destroy_Connection -- destroys the given connection * 93 * Remote_Connect -- handles connecting this user to others * 94 * Net_Join_Dialog -- lets user join an existing game, or start a new one * 95 * Request_To_Join -- Sends a JOIN request packet to game owner * 96 * Unjoin_Game -- Cancels joining a game * 97 * Send_Join_Queries -- sends queries for the Join Dialog * 98 * Get_Join_Responses -- sends queries for the Join Dialog * 99 * Net_New_Dialog -- lets user start a new game * 100 * Get_NewGame_Responses -- processes packets for New Game dialog * 101 * Compute_Name_CRC -- computes CRC from char string * 102 * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog * 103 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 104 // Warning - Most disgusting cpp file of all time. ajw 105 106 #include "function.h" 107 108 //PG Stubs 109 void Destroy_Connection(int, int) {} 110 bool Process_Global_Packet(GlobalPacketType *, IPXAddressClass *) { return false; } 111 bool Client_Remote_Connect(void) { return false; } 112 bool Server_Remote_Connect(void) { return false; } 113 bool Init_Network(void) { return false; } 114 bool Remote_Connect(void) { return false; } 115 116 #if (0) //PG 117 118 119 #ifdef WIN32 120 #ifdef WINSOCK_IPX 121 #include "WSProto.h" 122 #else //WINSOCK_IPX 123 #include "tcpip.h" 124 #endif //WINSOCK_IPX 125 #include "ccdde.h" 126 #else //WIN32 127 #include "fakesock.h" 128 #endif //WIN32 129 130 #include <time.h> 131 //#include <dos.h> 132 133 //#include "WolDebug.h" 134 135 #define SHOW_MONO 0 136 //#define OLDWAY 1 137 138 #ifdef FRENCH 139 #define TXT_HACKHACK "Connexion En Cours..." 140 #endif 141 #if defined(ENGLISH) || defined(GERMAN) 142 #define TXT_HACKHACK Text_String(TXT_CONNECTING) 143 #endif 144 145 #ifdef FIXIT_CSII // checked - ajw 9/28/98 146 bool Is_Mission_126x126 (char *file_name); 147 bool Is_Mission_Aftermath (char *file_name); 148 bool Is_Mission_Counterstrike (char *file_name); 149 bool bSpecialAftermathScenario( const char* szScenarioDescription ); 150 #endif 151 152 #ifdef FIXIT_VERSION_3 153 bool Force_Scenario_Available( const char* szName ); 154 #endif 155 #ifdef WOLAPI_INTEGRATION 156 #include "WolStrng.h" 157 #include "WolapiOb.h" 158 extern WolapiObject* pWolapi; 159 #endif 160 161 #include "COORDA.h" 162 163 //--------------------------------------------------------------------------- 164 // The possible states of the join-game dialog 165 //--------------------------------------------------------------------------- 166 typedef enum { 167 JOIN_REJECTED = -1, // we've been rejected 168 JOIN_NOTHING, // we're not trying to join a game 169 JOIN_WAIT_CONFIRM, // we're asking to join, & waiting for confirmation 170 JOIN_CONFIRMED, // we've been confirmed 171 JOIN_GAME_START, // the game we've joined is starting 172 JOIN_GAME_START_LOAD, // the game we've joined is starting; load saved game 173 } JoinStateType; 174 175 //--------------------------------------------------------------------------- 176 // The possible return codes from Get_Join_Responses() 177 //--------------------------------------------------------------------------- 178 typedef enum { 179 EV_NONE, // nothing happened 180 EV_STATE_CHANGE, // Join dialog is in a new state 181 EV_NEW_GAME, // a new game formed, or is now open 182 EV_NEW_PLAYER, // a new player was detected 183 EV_PLAYER_SIGNOFF, // a player has signed off 184 EV_GAME_SIGNOFF, // a gamed owner has signed off 185 EV_GAME_OPTIONS, // a game options packet was received 186 EV_MESSAGE, // a message was received 187 } JoinEventType; 188 189 190 //--------------------------------------------------------------------------- 191 // The possible reasons we're rejected from joining a game 192 //--------------------------------------------------------------------------- 193 typedef enum { 194 REJECT_DUPLICATE_NAME, // player's name is a duplicate 195 REJECT_GAME_FULL, // game is full 196 REJECT_VERSION_TOO_OLD, // joiner's version is too old 197 REJECT_VERSION_TOO_NEW, // joiner's version is too new 198 REJECT_BY_OWNER, // game owner clicked "reject" 199 REJECT_DISBANDED, // game was disbanded 200 REJECT_MISMATCH, // "rules.ini" file mismatch. 201 } RejectType; 202 203 #ifdef ENGLISH 204 char const *EngMisStr[] = { 205 "Coastal Influence (Med)", 206 "Middle Mayhem (Sm)", 207 "Equal Opportunity (Sm)", 208 "Marooned II (Med)", 209 "Keep off the Grass (Sm)", 210 "Isle of Fury (Lg)", 211 "Ivory Wastelands (Sm)", 212 "Shallow Grave (Med)", 213 "North By Northwest (Lg)", 214 "First Come, First Serve (Sm)", 215 "Island Hoppers (Sm)", 216 "Raraku (Lg)", 217 "Central Conflict (Lg)", 218 "Combat Alley (Med)", 219 "Island Wars (Lg)", 220 "Desolation (Lg)", 221 "No Escape (Med)", 222 "No Man's Land (Med)", 223 "Normandy (Med)", 224 "Pond Skirmish (Med)", 225 "Ridge War (Med)", 226 "A Path Beyond (Lg)", 227 "Dugout Isle (Med)", 228 "Treasure Isle (Med)", 229 230 "Africa (Lg)", 231 "Alaska Anarchy (Lg)", 232 "All that Glitters... (Lg)", 233 "Apre's Peace (Lg)", 234 "Antartica (Lg)", 235 "Armourgarden (Lg)", 236 "Austraila (Med)", 237 "Barrier to Entry (Lg)", 238 "Bavarian Blast (Med)", 239 "Be Shore (Med)", 240 "Bearing Straits (Med)", 241 "Blow Holes (Lg)", 242 "Bonsai (Sm)", 243 "Brother Stalin (Lg)", 244 "Bullseye (Lg)", 245 "C&C (Med)", 246 "Camos Canyon (Med)", 247 "Camos Coves (Lg)", 248 "Camos Cross (Lg)", 249 "Camos Crossing (Sm)", 250 "Central Arena (Lg)", 251 "Canyon River (Med)", 252 "Crossroads (Sm)", 253 "Czech Mate (Lg)", 254 "Dday (Med)", 255 "Disaster Central (Lg)", 256 "Docklands (Med)", 257 "East Coast (Med)", 258 "Eastern Seaboard (Lg)", 259 "Finger Lake (Lg)", 260 "Fjords (Med)", 261 "Floodlands (Lg)", 262 "Forest under fire (Lg)", 263 "Four Corners (Lg)", 264 "Frostbit Fjords (Lg)", 265 "Glenboig (Sm)", 266 "Hell Frozen Over (Lg)", 267 "India (Lg)", 268 "Indirect Fire (Lg)", 269 "Island Wars II (Lg)", 270 "Italy (Lg)", 271 "Kabalo (Lg)", 272 "King of the Hills (Lg)", 273 "Lake Divide (Med)", 274 "Lakelands (Lg)", 275 "Land Ladder (Lg)", 276 "Lotsa Lakes (Lg)", 277 "Lunar Battlefield (Lg Special)", 278 "Malibu Fields (Med)", 279 "Marshland (Med)", 280 "MyLai Delta (Med)", 281 "Natural Harbor (Med)", 282 "No Way Out (Lg)", 283 "Normandy Landing (Lg)", 284 "Ore Wars (Med)", 285 "Oz (Lg)", 286 "Pilgrim Fathers II (Lg)", 287 "Pip's Ice Tea (Med)", 288 "Polar Panic (Lg)", 289 "Ponds (Med)", 290 "Putney (Lg)", 291 "Return to Zion (Lg)", 292 "Ring of Land (Lg)", 293 "River Basin (Lg)", 294 "River Delta (Med)", 295 "River Islands (Med)", 296 "River Maze (Sm)", 297 "Rivers (Sm)", 298 "Run the Gauntlet (Med)", 299 "Scappa Flow (Lg)", 300 "Siberian Slaughter (Lg)", 301 "Sleepy Valley (Sm)", 302 "Snake River (Lg)", 303 "Snow Wars (Lg)", 304 "Snowball fight (Lg)", 305 "Snowy Island (Lg)", 306 "So Near So Far (Sm)", 307 "South America (Lg)", 308 "Spring Line (Lg)", 309 "Star (Lg)", 310 "Straighter & Narrower (Sm)", 311 "TerrainSpotting (Sm)", 312 "The Bay (Lg)", 313 "The Garden (Lg)", 314 "The Great Lakes (Med)", 315 "The Ice Arena (Lg)", 316 "The Lake District (Lg)", 317 "The Linked lands (Lg)", 318 "The Mississippi (Med)", 319 "The Sticky Bit (Lg)", 320 "The Valley (Med)", 321 "The Woods Today (Lg)", 322 "Things to Come (Lg)", 323 "Tiger Core (Sm)", 324 "To the Core (Sm)", 325 "Tournament Hills (Lg)", 326 "Tropical Storm (Med)", 327 "Tundra Trouble (Lg)", 328 "Uk (Med)", 329 "Undiscovered Country (Sm)", 330 "United States (Med)", 331 "Volcano (Sm)", 332 "Wastelands (Lg)", 333 "Water Works (Sm)", 334 "World Map (Med)", 335 "Zambezi (Lg)", 336 337 "A Pattern of Islands (Lg 8 players)", 338 "Arena Valley Extreme (Mega 8 players)", 339 "Around the Rim (Sm 4 players)", 340 "Ashes to Ashes (Lg 6 players)", 341 "Artic Wasteland (Mega 8 players)", 342 "Badajoz (Med 4 players)", 343 "Baptism of Fire (Lg 6 players)", 344 "Big Fish, Small Pond (Lg 6 players)", 345 "Blue Lakes (Lg 8 players)", 346 "Booby Traps (Mega 8 players)", 347 "Bridgehead (Lg 6 players)", 348 "Butterfly Bay (Lg 6 players)", 349 "Central Conflict Extreme (Mega 8 players)", 350 "Circles of Death (Mega 8 players)", 351 "Cold Front (Med 6 players)", 352 "Cold Pass (Med 4 players)", 353 "Combat Zones (Mega 8 players)", 354 "Conflict Cove (Sm 4 players)", 355 "Culloden Moor (Med 8 players)", 356 "Damnation Alley (Mega 8 players)", 357 "Death Valley (Mega 8 players)", 358 "Deep Six (Mega 8 players)", 359 "Destruction Derby (Mega 8 players)", 360 "Diamonds Aren't Forever (Mega 8 players)", 361 "Elysium (Sm 4 players)", 362 "Equal Shares (Lg 4 players)", 363 "Frost Bitten (Mega 8 players)", 364 "Frozen Valley (Med 6 players)", 365 "Gettysburg (Sm 4 players)", 366 "Glacial Valley (Sm 4 players)", 367 "Gold Coast (Med 6 players)", 368 "Gold Rush (Lg 4 players)", 369 "Habitat (Lg 4 players)", 370 "Hades Frozen Over (Sm 4 players)", 371 "Hamburger Hill (Mega 8 players)", 372 "Hastings (Sm 4 players)", 373 "Hell's Pass (Med 6 players)", 374 "Holy Grounds (Mega 8 players)", 375 "Ice Bergs (Med 6 players)", 376 "Ice Station (Lg 6 players)", 377 "Ice Queen (Lg 4 players)", 378 "In the Sun (Med 6 players)", 379 "Innocents? (Mega 8 players)", 380 "Islands (Med 8 players)", 381 "Island Plateau (Lg 4 players)", 382 "Island Wars Extreme (Mega 8 players)", 383 "Kananga (Med 6 players)", 384 "King of the Hills Extreme (Mega 8 players)", 385 "Lake Land (Lg 8 players)", 386 "Land Locked (Lg 8 players)", 387 "Lanes (Med 8 players)", 388 "Leipzip (Sm 4 players)", 389 "Meander (Lg 8 players)", 390 "Mekong (Med 8 players)", 391 "Middle Ground (Med 8 players)", 392 "Naval Conquests (Mega 8 players)", 393 "On your Marks (Med 4 players)", 394 "Open Warfare (Mega 8 players)", 395 "Ore Gardens (Lg 8 players)", 396 "Potholes (Mega 8 players)", 397 "Puddles (Med 4 players)", 398 "Random Violence (Mega 8 players)", 399 "Revenge (Med 8 players)", 400 "Rias (Med 8 players)", 401 "River Crossing (Sm 4 players)", 402 "River Rampage (Mega 8 players)", 403 "River Rapids (Lg 6 players)", 404 "Rivers Wild (Mega 8 players)", 405 "Rorkes Drift (Lg 4 players)", 406 "Seaside (Med 4 players)", 407 "Shades (Med 8 players)", 408 "Smuggler's Cove (Lg 6 players)", 409 "Snow Garden (Sm 2 players)", 410 "Stalingrad (Sm 4 players)", 411 "Sticks & Stones (Med 4 players)", 412 "Strathearn Valley (Lg 6 players)", 413 "Super Bridgehead (Mega 8 players)", 414 "Super Mekong (Mega 8 players)", 415 "Super Ore Gardens (Mega 8 players)", 416 "Switch (Med 4 players)", 417 "The Berg (Mega 8 players)", 418 "The Boyne (Med 4 players)", 419 "The Bulge (Sm 4 players)", 420 "The Cauldron (Lg 6 players)", 421 "The Finger (Lg 6 players)", 422 "The Hills Have Eyes (Mega 8 players)", 423 "The Keyes (Med 6 players)", 424 "The Lakes (Med 8 players)", 425 "The Neck (Med 6 players)", 426 "The Web (Lg 6 players)", 427 "To the Core (Lg 4 players)", 428 "Trafalgar (Lg 4 players)", 429 "Twin Rivers (Sm 4 players)", 430 "Umtumbo Gorge (Lg 4 players)", 431 "Watch Your Step Extreme (Mega 8 players)", 432 "Waterfalls (Lg 8 players)", 433 "Waterloo Revisited (Lg 6 players)", 434 "Water Werks (Mega 8 players)", 435 "Warlord's Lake (Sm 4 players)", 436 "Zama (Sm 4 players)", 437 438 NULL 439 }; 440 #endif 441 442 #ifdef GERMAN 443 char const *EngMisStr[] = { 444 445 "A Path Beyond (Lg)", "Weg ins Jenseits (Gr)", 446 "Central Conflict (Lg)", "Der zentrale Konflikt (Gr)", 447 "Coastal Influence (Med)", "Sturm an der Kste (Mit)", 448 "Combat Alley (Med)", "Boulevard der Schlachten (Mit)", 449 "Desolation (Lg)", "Verwstung (Gr)", 450 "Dugout Isle (Med)", "Buddelschiff (Mit)", 451 "Equal Opportunity (Sm)", "Gleiche Chancen (Kl)", 452 "First Come, First Serve (Sm)", "Wer zuerst kommt... (Kl)", 453 "Island Hoppers (Sm)", "Inselspringen (Kl)", 454 "Island Wars (Lg)", "Der Krieg der Eilande (Gr)", 455 "Isle of Fury (Lg)", "Insel des Zorns (Gr)", 456 "Ivory Wastelands (Sm)", "Elfenbeinwste (Kl)", 457 "Keep off the Grass (Sm)", "Rasen betreten verboten (Kl)", 458 "Marooned II (Med)", "Gestrandet (Mit)", 459 "Middle Mayhem (Sm)", "Mittelsmann (Kl)", 460 "No Escape (Med)", "Kein Entrinnen (Mit)", 461 "No Man's Land (Med)", "Niemandsland (Mit)", 462 "Normandy (Med)", "Normandie (Mit)", 463 "North By Northwest (Lg)", "Nord auf Nordwest (Gr)", 464 "Pond Skirmish (Med)", "Teichgepl„nkel (Mit)", 465 "Raraku (Lg)", "Raraku (Gr)", 466 "Ridge War (Med)", "Das Tal der Cyborgs (Mit)", 467 "Shallow Grave (Med)", "Ein enges Grab (Mit)", 468 "Treasure Isle (Med)", "Die Schatzinsel (Mit)", 469 470 "Africa (Lg)", "Afrika (Gr)", 471 "Alaska Anarchy (Lg)", "Anarchie in Alaska (Gr)", 472 "All that Glitters... (Lg)", "Alles was gl„nzt... (Gr)", 473 "Apre's Peace (Lg)", "Apres Frieden (Gr)", 474 "Antartica (Lg)", "Antarktica (Gr)", 475 "Armourgarden (Lg)", "Garten der Panzer (Gr)", 476 "Austraila (Med)", "Koalaland (Mit)", 477 "Barrier to Entry (Lg)", "Zutritt verboten (Gr)", 478 "Bavarian Blast (Med)", "Bayrische Blasmusik (Mit)", 479 "Be Shore (Med)", "Strandl„ufer (Mit)", 480 "Bearing Straits (Med)", "Die Heringstrasse (Mit)", 481 "Blow Holes (Lg)", "L”cheriger K„se (Gr)", 482 "Bonsai (Sm)", "Bonsai (Kl)", 483 "Brother Stalin (Lg)", "Brderchen Stalin (Gr)", 484 "Bullseye (Lg)", "Bullseye (Gr)", 485 "C&C (Med)", "C&C (Mit)", 486 "Camos Canyon (Med)", "Camos-Canyon (Mit)", 487 "Camos Coves (Lg)", "Camos-Grotte (Gr)", 488 "Camos Cross (Lg)", "Camos-Kreuz (Gr)", 489 "Camos Crossing (Sm)", "Camos-Kreuzweg (Kl)", 490 "Central Arena (Lg)", "Spielplatz des Teufels (Gr)", 491 "Canyon River (Med)", "Canyonfluss (Mit)", 492 "Crossroads (Sm)", "Kreuzung (Kl)", 493 "Czech Mate (Lg)", "Tschechische Er”ffnung (Gr)", 494 "Dday (Med)", "D-Day (Mit)", 495 "Disaster Central (Lg)", "Endstation Schweinebucht (Gr)", 496 "Docklands (Med)", "Docklands (Mit)", 497 "East Coast (Med)", "Ostkste (Mit)", 498 "Eastern Seaboard (Lg)", "Die Passage nach Osten (Gr)", 499 "Finger Lake (Lg)", "Fingersee (Gr)", 500 "Fjords (Med)", "Fjorde (Mit)", 501 "Floodlands (Lg)", "Land unter! (Gr)", 502 "Forest under fire (Lg)", "Waldsterben im Feuer (Gr)", 503 "Four Corners (Lg)", "Viereck (Gr)", 504 "Frostbit Fjords (Lg)", "Frostbeulenfjord (Gr)", 505 "Glenboig (Sm)", "Glenboig (Kl)", 506 "Hell Frozen Over (Lg)", "Winter in der H”lle (Gr)", 507 "India (Lg)", "Indien (Gr)", 508 "Indirect Fire (Lg)", "Indirekter Beschuss (Gr)", 509 "Island Wars II (Lg)", "Krieg der Inseln (Gr)", 510 "Italy (Lg)", "Italien (Gr)", 511 "Kabalo (Lg)", "Kabalo (Gr)", 512 "King of the Hills (Lg)", "K”nig des Maulwurfshgels (Gr)", 513 "Lake Divide (Med)", "Wasserscheide (Mit)", 514 "Lakelands (Lg)", "Seenplatte (Gr)", 515 "Land Ladder (Lg)", "Das Leiterspiel (Gr)", 516 "Lotsa Lakes (Lg)", "Mehr Seen (Gr)", 517 "Lunar Battlefield (Lg Special)", "Schlachtfeld Mond (Gr Spezial)", 518 "Malibu Fields (Med)", "Malibu (Mit)", 519 "Marshland (Med)", "Schlammschlacht (Mit)", 520 "MyLai Delta (Med)", "Das Delta von My Lai (Mit)", 521 "Natural Harbor (Med)", "Natrlicher Hafen (Mit)", 522 "No Way Out (Lg)", "Kein Entkommen (Gr)", 523 "Normandy Landing (Lg)", "Landung in der Normandie (Gr)", 524 "Ore Wars (Med)", "Die Erz-Kriege (Mit)", 525 "Oz (Lg)", "Das Land Oz (Gr)", 526 "Pilgrim Fathers II (Lg)", "Die Grnderv„ter (Gr)", 527 "Pip's Ice Tea (Med)", "Pips Eistee (Mit)", 528 "Polar Panic (Lg)", "Panik am Pol (Gr)", 529 "Ponds (Med)", "Tmpelspringer (Mit)", 530 "Putney (Lg)", "Putney (Gr)", 531 "Return to Zion (Lg)", "Rckkehr nach Zion (Gr)", 532 "Ring of Land (Lg)", "Der Landring (Gr)", 533 "River Basin (Lg)", "Flusslauf (Gr)", 534 "River Delta (Med)", "Flussdelta (Mit)", 535 "River Islands (Med)", "Flussinsel (Mit)", 536 "River Maze (Sm)", "Flussgewirr (Kl)", 537 "Rivers (Sm)", "Flsse (Kl)", 538 "Run the Gauntlet (Med)", "Spiessrutenlauf (Mit)", 539 "Scappa Flow (Lg)", "Scapa Flow (Gr)", 540 "Siberian Slaughter (Lg)", "Sibirisches Gemetzel (Gr)", 541 "Sleepy Valley (Sm)", "Tal der Ahnungslosen (Kl)", 542 "Snake River (Lg)", "Am Schlangenfluss (Gr)", 543 "Snow Wars (Lg)", "Krieg der Flocken (Gr)", 544 "Snowball fight (Lg)", "Schneeballschlacht (Gr)", 545 "Snowy Island (Lg)", "Schneeinsel (Gr)", 546 "So Near So Far (Sm)", "So nah und doch so fern (Kl)", 547 "South America (Lg)", "Sdamerika (Gr)", 548 "Spring Line (Lg)", "Frhlingsgefhle (Gr)", 549 "Star (Lg)", "Stern (Gr)", 550 "Straighter & Narrower (Sm)", "Enger & schmaler (Kl)", 551 "TerrainSpotting (Sm)", "TerrainSpotting (Kl)", 552 "The Bay (Lg)", "Die Bucht (Gr)", 553 "The Garden (Lg)", "Der Garten (Gr)", 554 "The Great Lakes (Med)", "Die Grossen Seen (Mit)", 555 "The Ice Arena (Lg)", "Eisarena (Gr)", 556 "The Lake District (Lg)", "Kalte Seenplatte (Gr)", 557 "The Linked lands (Lg)", "Die verbundenen L„nder (Gr)", 558 "The Mississippi (Med)", "Grsse von Tom Sawyer (Mit)", 559 "The Sticky Bit (Lg)", "Der klebrige Teil (Gr)", 560 "The Valley (Med)", "Das Tal (Mit)", 561 "The Woods Today (Lg)", "Waldl„ufer (Gr)", 562 "Things to Come (Lg)", "Was die Zukunft bringt (Gr)", 563 "Tiger Core (Sm)", "Das Herz des Tigers (Kl)", 564 "To the Core (Sm)", "Mitten ins Herz (Kl)", 565 "Tournament Hills (Lg)", "Hgel der Entscheidung (Gr)", 566 "Tropical Storm (Med)", "Tropenstrme (Mit)", 567 "Tundra Trouble (Lg)", "Tauziehen in der Tundra (Gr)", 568 "Uk (Med)", "GB (Mit)", 569 "Undiscovered Country (Sm)", "Unentdecktes Land (Kl)", 570 "United States (Med)", "US (Mit)", 571 "Volcano (Sm)", "Vulkan (Kl)", 572 "Wastelands (Lg)", "Wstenei (Gr)", 573 "Water Works (Sm)", "Wasserwerke (Kl)", 574 "World Map (Med)", "Weltkarte (Kl)", 575 "Zambezi (Lg)", "Sambesi (Gr)", 576 577 //#if 0 578 "A Pattern of Islands (Lg 8 players)", "Inselmuster (gross, 8 Spieler)", 579 "Arena Valley Extreme (Mega 8 players)", "Arenatal (sehr gross, 8 Spieler)", 580 "Around the Rim (Sm 4 players)", "Um die Kante (klein, 4 Spieler)", 581 "Ashes to Ashes (Lg 6 players)", "Asche zu Asche (gross, 6 Spieler)", 582 "Artic Wasteland (Mega 8 players)", "Arktische Wste (sehr gross, 8 Spieler)", 583 "Badajoz (Med 4 players)", "Badjoz (mittelgross, 4 Spieler)", 584 "Baptism of Fire (Lg 6 players)", "Feuertaufe (gross, 6 Spieler)", 585 "Big Fish, Small Pond (Lg 6 players)", "Grosser Fisch im kleinen Teich (gross, 6 Spieler)", 586 "Blue Lakes (Lg 8 players)", "Die blauen Seen (gross, 8 Spieler)", 587 "Booby Traps (Mega 8 players)", "Vorsicht, Falle! (sehr gross, 8 Spieler)", 588 "Bridgehead (Lg 6 players)", "Brckenkopf im Niemandsland (gross, 6 Spieler)", 589 "Butterfly Bay (Lg 6 players)", "Schmetterlingsbucht (gross, 6 Spieler)", 590 "Central Conflict Extreme (Mega 8 players)", "Zentraler Konflikt fr K”nner (sehr gross, 8 Spieler)", 591 "Circles of Death (Mega 8 players)", "Todeskreise (sehr gross, 8 Spieler)", 592 "Cold Front (Med 6 players)", "Kaltfront ( mittelgross, 6 Spieler)", 593 "Cold Pass (Med 4 players)", "Cooler Pass (mittelgross, 4 Spieler)", 594 "Combat Zones (Mega 8 players)", "Kampfgebiete (sehr gross, 8 Spieler)", 595 "Conflict Cove (Sm 4 players)", "H”hlenkonflikt (klein, 4 Spieler)", 596 "Culloden Moor (Med 8 players)", "Culloden-Moor (mittelgross, 8 Spieler)", 597 "Damnation Alley (Mega 8 players)", "Strasse der Verdammten (sehr gross, 8 Spieler)", 598 "Death Valley (Mega 8 players)", "Tal des Todes (sehr gross, 8 Spieler)", 599 "Deep Six (Mega 8 players)", "Tiefe Sechs (sehr gross, 8 Spieler)", 600 "Destruction Derby (Mega 8 players)", "Destruction Derby (sehr gross, 8 Spieler)", 601 "Diamonds Aren't Forever (Mega 8 players)", "Verg„ngliche Diamanten (sehr gross, 8 Spieler)", 602 "Elysium (Sm 4 players)", "Elysium (klein, 4 Spieler)", 603 "Equal Shares (Lg 4 players)", "Gleiche Anteile (gross, 4 Spieler)", 604 "Frost Bitten (Mega 8 players)", "Frostbrand (sehr gross, 8 Spieler)", 605 "Frozen Valley (Med 6 players)", "Eisiges Tal (mittelgross, 6 Spieler)", 606 "Gettysburg (Sm 4 players)", "Gettysburg (klein, 4 Spieler)", 607 "Glacial Valley (Sm 4 players)", "Gletschertal (klein, 4 Spieler)", 608 "Gold Coast (Med 6 players)", "Goldkste (mittelgross, 6 Spieler)", 609 "Gold Rush (Lg 4 players)", "Goldrausch (gross, 4 Spieler)", 610 "Habitat (Lg 4 players)", "Habitat (gross, 4 Spieler)", 611 "Hades Frozen Over (Sm 4 players)", "Frostschutz fr die H”lle (klein, 4 Spieler)", 612 "Hamburger Hill (Mega 8 players)", "Hamburger Hill (sehr gross, 8 Spieler)", 613 "Hastings (Sm 4 players)", "Hastings (klein, 4 Spieler)", 614 "Hell's Pass (Med 6 players)", "H”llenpass (mittelgross, 6 Spieler)", 615 "Holy Grounds (Mega 8 players)", "Heiliger Boden (sehr gross, 8 Spieler)", 616 "Ice Bergs (Med 6 players)", "Eisberge (mittelgross, 6 Spieler)", 617 "Ice Station (Lg 6 players)", "Eisstation (gross, 6 Spieler)", 618 "Ice Queen (Lg 4 players)", "Eisk”nigin (gross, 4 Spieler)", 619 "In the Sun (Med 6 players)", "Unter der Sonne (mittelgross, 6 Spieler)", 620 "Innocents? (Mega 8 players)", "Unschuldig? Wer? (sehr gross, 8 Spieler)", 621 "Islands (Med 8 players)", "Inseln im Nebel (mittelgross, 8 Spieler)", 622 "Island Plateau (Lg 4 players)", "Inselplateau (gross, 4 Spieler)", 623 "Island Wars Extreme (Mega 8 players)", "Extremes Inselspringen (sehr gross, 8 Spieler)", 624 "Kananga (Med 6 players)", "Kananga (mittelgross, 6 Spieler)", 625 "King of the Hills Extreme (Mega 8 players)", "K”nig des Maulwurfshgels (sehr gross, 8 Spieler)", 626 "Lake Land (Lg 8 players)", "Seenland (gross, 8 Spieler)", 627 "Land Locked (Lg 8 players)", "Das Verschlossene Land (gross, 8 Spieler)", 628 "Lanes (Med 8 players)", "Gassenjungen (mittelgross, 8 Spieler)", 629 "Leipzip (Sm 4 players)", "Leipzig (klein, 4 Spieler)", 630 "Meander (Lg 8 players)", "M„ander (gross, 8 Spieler)", 631 "Mekong (Med 8 players)", "Mekong (mittelgross, 8 Spieler)", 632 "Middle Ground (Med 8 players)", "Mittelsmann (mittelgross, 8 Spieler)", 633 "Naval Conquests (Mega 8 players)", "Kommt zur Marine, haben sie gesagt (sehr gross, 8 Spieler)", 634 "On your Marks (Med 4 players)", "Auf die Pl„tze (mittelgross, 4 Spieler)", 635 "Open Warfare (Mega 8 players)", "Offener Schlagabtausch (sehr gross, 8 Spieler)", 636 "Ore Gardens (Lg 8 players)", "Erzparadies (gross, 8 Spieler)", 637 "Potholes (Mega 8 players)", "Schlagl”cher (sehr gross, 8 Spieler)", 638 "Puddles (Med 4 players)", "Pftzen (mittelgross, 4 Spieler)", 639 "Random Violence (Mega 8 players)", "Unberechenbare Gewalt (sehr gross, 8 Spieler)", 640 "Revenge (Med 8 players)", "Rache (mittelgross, 8 Spieler)", 641 "Rias (Med 8 players)", "Kabul (mittelgross, 8 Spieler)", 642 "River Crossing (Sm 4 players)", "Die Furt (klein, 4 Spieler)", 643 "River Rampage (Mega 8 players)", "Flussfahrt (sehr gross, 8 Spieler)", 644 "River Rapids (Lg 6 players)", "Stromschnellen (gross, 6 Spieler)", 645 "Rivers Wild (Mega 8 players)", "Wildwasser (sehr gross, 8 Spieler)", 646 "Rorkes Drift (Lg 4 players)", "Rorkes Drift (gross, 4 Spieler)", 647 "Seaside (Med 4 players)", "Strandleben (mittelgross, 4 Spieler)", 648 "Shades (Med 8 players)", "Schattenreich (mittelgross, 8 Spieler)", 649 "Smuggler's Cove (Lg 6 players)", "Schmugglerh”hle (gross, 6 Spieler)", 650 "Snow Garden (Sm 2 players)", "Schneegest”ber (klein, 2 Spieler)", 651 "Stalingrad (Sm 4 players)", "Stalingrad (klein, 4 Spieler)", 652 "Sticks & Stones (Med 4 players)", "Holz und Steine (mittelgross, 4 Spieler)", 653 "Strathearn Valley (Lg 6 players)", "Das Tal von Strathearn (gross, 6 Spieler)", 654 "Super Bridgehead (Mega 8 players)", "Super-Brckenkopf (sehr gross, 8 Spieler)", 655 "Super Mekong (Mega 8 players)", "Super-Mekong (sehr gross, 8 Spieler)", 656 "Super Ore Gardens (Mega 8 players)", "Super-Erzparadies (sehr gross, 8 Spieler)", 657 "Switch (Med 4 players)", "Schalter (mittelgross, 4 Spieler)", 658 "The Berg (Mega 8 players)", "Der Berg (sehr gross, 8 Spieler)", 659 "The Boyne (Med 4 players)", "Boyne (mittelgross, 4 Spieler)", 660 "The Bulge (Sm 4 players)", "Die W”lbung (klein, 4 Spieler)", 661 "The Cauldron (Lg 6 players)", "Der Kessel (gross, 6 Spieler)", 662 "The Finger (Lg 6 players)", "Der Finger (gross, 6 Spieler)", 663 "The Hills Have Eyes (Mega 8 players)", "Die Hgel haben Augen (sehr gross, 8 Spieler)", 664 "The Keyes (Med 6 players)", "Ein Sumpf (mittelgross, 6 Spieler)", 665 "The Lakes (Med 8 players)", "Die Seen (mittelgross, 8 Spieler)", 666 "The Neck (Med 6 players)", "Der Hals (mittelgross, 6 Spieler)", 667 "The Web (Lg 6 players)", "Das Netz (gross, 6 Spieler)", 668 "To the Core (Lg 4 players)", "Mitten ins Herz (gross, 4 Spieler)", 669 "Trafalgar (Lg 4 players)", "Trafalgar (gross, 4 Spieler)", 670 "Twin Rivers (Sm 4 players)", "Zwillingsstr”me (klein, 4 Spieler)", 671 "Umtumbo Gorge (Lg 4 players)", "Die Umtumbo-Schlucht (gross, 4 Spieler)", 672 "Watch Your Step Extreme (Mega 8 players)", "Vorsicht, Lebensgefahr (sehr gross, 8 Spieler)", 673 "Waterfalls (Lg 8 players)", "Wasserfall (gross, 8 Spieler)", 674 "Waterloo Revisited (Lg 6 players)", "Zu Besuch in Waterloo (gross, 6 Spieler)", 675 "Water Werks (Mega 8 players)", "Wasserwerk (sehr gross, 8 Spieler)", 676 "Warlord's Lake (Sm 4 players)", "Der See des Kriegsgottes (klein, 4 Spieler)", 677 "Zama (Sm 4 players)", "Zama (klein, 4 Spieler)", 678 //#endif 679 NULL 680 }; 681 #endif 682 #ifdef FRENCH 683 char const *EngMisStr[] = { 684 685 "A Path Beyond (Lg)", "Le Passage (Max)", 686 "Central Conflict (Lg)", "Conflit Central (Max)", 687 "Coastal Influence (Med)", "Le Chant des Canons (Moy)", 688 "Combat Alley (Med)", "Aux Armes! (Moy)", 689 "Desolation (Lg)", "D‚solation (Max)", 690 "Dugout Isle (Med)", "L'Ile Maudite (Moy)", 691 "Equal Opportunity (Sm)", "A Chances Egales (Min)", 692 "First Come, First Serve (Sm)", "La Loi du Plus Fort (Min)", 693 "Island Hoppers (Sm)", "D'une Ile … l'autre (Min)", 694 "Island Wars (Lg)", "Guerres Insulaires (Max)", 695 "Isle of Fury (Lg)", "L'Ile de la Furie(Max)", 696 "Ivory Wastelands (Sm)", "Terres d'Ivoire (Min)", 697 "Keep off the Grass (Sm)", "Hors de mon Chemin (Min)", 698 "Marooned II (Med)", "Isolement II (Moy)", 699 "Middle Mayhem (Sm)", "Chaos Interne (Min)", 700 "No Escape (Med)", "Le PiŠge (Moy)", 701 "No Man's Land (Med)", "No Man's Land (Moy)", 702 "Normandy (Med)", "Normandie (Moy)", 703 "North By Northwest (Lg)", "Nord, Nord-Ouest (Max)", 704 "Pond Skirmish (Med)", "Bain de Sang (Moy)", 705 "Raraku (Lg)", "Raraku (Max)", 706 "Ridge War (Med)", "Guerre au Sommet (Moy)", 707 "Shallow Grave (Med)", "La Saveur de la Mort (Moy)", 708 "Treasure Isle (Med)", "L'Ile au Tr‚sor (Moy)", 709 710 "Africa (Lg)", "Afrique (Max)", 711 "Alaska Anarchy (Lg)", "Anarchie en Alaska (Max)", 712 "All that Glitters... (Lg)", "Tout ce qui brille... (Max)", 713 "Apre's Peace (Lg)", "Une Paix Durement N‚goci‚e... (Max)", 714 "Antartica (Lg)", "Antarctique (Max)", 715 "Armourgarden (Lg)", "La Guerre des Blind‚s (Max)", 716 "Austraila (Med)", "Australie (Moy)", 717 "Barrier to Entry (Lg)", "BarriŠre … l'Entr‚e (Max)", 718 "Bavarian Blast (Med)", "Tonnerre Bavarois (Moy)", 719 "Be Shore (Med)", "Plages Menac‚es (Moy)", 720 "Bearing Straits (Med)", "Droit Devant ! (Moy)", 721 "Blow Holes (Lg)", "CratŠres (Max)", 722 "Bonsai (Sm)", "Bonsa‹ (Min)", 723 "Brother Stalin (Lg)", "FrŠre Staline (Max)", 724 "Bullseye (Lg)", "L'oeil du Taureau (Max)", 725 "C&C (Med)", "C&C (Moy)", 726 "Camos Canyon (Med)", "Le Canyon (Moy)", 727 "Camos Coves (Lg)", "Criques (Max)", 728 "Camos Cross (Lg)", "La Croix de Guerre (Max)", 729 "Camos Crossing (Sm)", "La Crois‚e des Chemins (Min)", 730 "Central Arena (Lg)", "L'ArŠne Diabolique (Max)", 731 "Canyon River (Med)", "Au Milieu Coule Une RiviŠre (Moy)", 732 "Crossroads (Sm)", "Carrefours (Min)", 733 "Czech Mate (Lg)", "TchŠque et Mat (Max)", 734 "Dday (Med)", "Le Jour J (Moy)", 735 "Disaster Central (Lg)", "D‚sastre Central (Max)", 736 "Docklands (Med)", "L'Enfer des Docks (Moy)", 737 "East Coast (Med)", "C“te Est (Moy)", 738 "Eastern Seaboard (Lg)", "Rivages de l'Est (Max)", 739 "Finger Lake (Lg)", "Le Lac de tous les Dangers (Max)", 740 "Fjords (Med)", "Fjords (Moy)", 741 "Floodlands (Lg)", "Campagne Lacustre (Max)", 742 "Forest under fire (Lg)", "Forˆt en flammes (Max)", 743 "Four Corners (Lg)", "4 Coins (Max)", 744 "Frostbit Fjords (Lg)", "Fjords Gel‚s (Max)", 745 "Glenboig (Sm)", "Glenboig (Min)", 746 "Hell Frozen Over (Lg)", "Enfer de Glace Max)", 747 "India (Lg)", "Inde (Max)", 748 "Indirect Fire (Lg)", "Attaque Indirecte (Max)", 749 "Island Wars II (Lg)", "Guerres Insulaires II (Max)", 750 "Italy (Lg)", "Italie (Max)", 751 "Kabalo (Lg)", "Kabalo (Max)", 752 "King of the Hills (Lg)", "Le Roi des Montagnes (Max)", 753 "Lake Divide (Med)", "La Guerre du Lac (Moy)", 754 "Lakelands (Lg)", "Terres Submerg‚es (Max)", 755 "Land Ladder (Lg)", "Jusqu'au Sommet (Max)", 756 "Lotsa Lakes (Lg)", "Terres de Lacs (Max)", 757 "Lunar Battlefield (Lg Special)", "Combat Lunaire (Max Sp‚cial)", 758 "Malibu Fields (Med)", "Les Champs de Malibu (Moy)", 759 "Marshland (Med)", "Mar‚cages (Moy)", 760 "MyLai Delta (Med)", "Le Delta Mylai (Moy)", 761 "Natural Harbor (Med)", "Port Naturel (Moy)", 762 "No Way Out (Lg)", "Sans Issue (Max)", 763 "Normandy Landing (Lg)", "Le D‚barquement (Max)", 764 "Ore Wars (Med)", "La Guerre du Minerai (Moy)", 765 "Oz (Lg)", "Oz (Max)", 766 "Pilgrim Fathers II (Lg)", "Les PŠlerins 2 (Max)", 767 "Pip's Ice Tea (Med)", "Les Tranch‚es de Glace (Moy)", 768 "Polar Panic (Lg)", "Panique Polaire (Max)", 769 "Ponds (Med)", "Les Etangs (Moy)", 770 "Putney (Lg)", "La Meilleure D‚fense... (Max)", 771 "Return to Zion (Lg)", "Retour … Sion (Max)", 772 "Ring of Land (Lg)", "Le Cycle Infernal (Max)", 773 "River Basin (Lg)", "Confrontation Navale (Max)", 774 "River Delta (Med)", "Le Delta (Moy)", 775 "River Islands (Med)", "C“tes … Surveiller de PrŠs (Moy)", 776 "River Maze (Sm)", "Labyrinthe Fluvial (Min)", 777 "Rivers (Sm)", "RiviŠres (Min)", 778 "Run the Gauntlet (Med)", "Relevons le D‚fi ! (Moy)", 779 "Scappa Flow (Lg)", "Combats Sanglants (Max)", 780 "Siberian Slaughter (Lg)", "Carnage Sib‚rien (Max)", 781 "Sleepy Valley (Sm)", "La Vall‚e Endormie (Min)", 782 "Snake River (Lg)", "La RiviŠre aux Serpents (Max)", 783 "Snow Wars (Lg)", "Guerres de Neige (Max)", 784 "Snowball fight (Lg)", "Bataille de Boules de Neige (Max)", 785 "Snowy Island (Lg)", "L'Ile sous la Neige (Max)", 786 "So Near So Far (Sm)", "Si Loin, Si Proche (Min)", 787 "South America (Lg)", "Am‚rique du Sud (Max)", 788 "Spring Line (Lg)", "Ligne de Front (Max)", 789 "Star (Lg)", "Etoile (Max)", 790 "Straighter & Narrower (Sm)", "L'Entonnoir (Min)", 791 "TerrainSpotting (Sm)", "TerrainSpotting (Min)", 792 "The Bay (Lg)", "La Baie (Max)", 793 "The Garden (Lg)", "Le Jardin (Max)", 794 "The Great Lakes (Med)", "Les Grands Lacs (Moy)", 795 "The Ice Arena (Lg)", "L'ArŠne de Glace (Max)", 796 "The Lake District (Lg)", "Un Lac Imprenable (Max)", 797 "The Linked lands (Lg)", "Passages … Gu‚ (Max)", 798 "The Mississippi (Med)", "Mississippi (Moy)", 799 "The Sticky Bit (Lg)", "Marasme (Max)", 800 "The Valley (Med)", "La Vall‚e (Moy)", 801 "The Woods Today (Lg)", "Aujoud'hui: la Mort ! (Max)", 802 "Things to Come (Lg)", "D‚nouement Incertain (Max)", 803 "Tiger Core (Sm)", "Le Coeur du Tigre (Min)", 804 "To the Core (Sm)", "Le Coeur du Conflit (Min)", 805 "Tournament Hills (Lg)", "Combat en Altitude (Max)", 806 "Tropical Storm (Med)", "Ouragan Tropical (Moy)", 807 "Tundra Trouble (Lg)", "La Toundra (Max)", 808 "Uk (Med)", "Royaume Uni (Moy)", 809 "Undiscovered Country (Sm)", "Terre Inconnue (Min)", 810 "United States (Med)", "Etats Unis (Moy)", 811 "Volcano (Sm)", "Le Volcan (Min)", 812 "Wastelands (Lg)", "Terres D‚sol‚es (Max)", 813 "Water Works (Sm)", "Jeux d'Eau (Min)", 814 "World Map (Med)", "Carte du Monde (Moy)", 815 "Zambezi (Lg)", "ZambŠze (Max)", 816 //#if 0 817 "A Pattern of Islands (Lg 8 players)", "Archipel (Max. 8 joueurs)", 818 "Arena Valley Extreme (Mega 8 players)", "La Vall‚e de l'arŠne (XL 8 joueurs)", 819 "Around the Rim (Sm 4 players)", "Autour de la crˆte (Min. 4 joueurs)", 820 "Ashes to Ashes (Lg 6 players)", "R‚duit en cendres (Max. 6 joueurs)", 821 "Artic Wasteland (Mega 8 players)", "D‚solation arctique (XL 8 joueurs)", 822 "Badajoz (Med 4 players)", "Badjoz (Moy. 4 joueurs)", 823 "Baptism of Fire (Lg 6 players)", "Baptˆme du feu (Max. 6 joueurs)", 824 "Big Fish, Small Pond (Lg 6 players)", "Gros poisson, Min. Mare (Max. 6 joueurs)", 825 "Blue Lakes (Lg 8 players)", "Lacs bleus (Max. 8 joueurs)", 826 "Booby Traps (Mega 8 players)", "PiŠges (XL 8 joueurs)", 827 "Bridgehead (Lg 6 players)", "Tˆte de pont (Max. 6 joueurs)", 828 "Butterfly Bay (Lg 6 players)", "La baie du papillon (Max. 6 joueurs)", 829 "Central Conflict Extreme (Mega 8 players)", "Conflit central extrˆme (XL 8 joueurs)", 830 "Circles of Death (Mega 8 players)", "Les cercles de la mort (XL 8 joueurs)", 831 "Cold Front (Med 6 players)", "Front froid ( Moy. 6 joueurs)", 832 "Cold Pass (Med 4 players)", "La Passe Glac‚e (Moy. 4 joueurs)", 833 "Combat Zones (Mega 8 players)", "Zones de combat (XL 8 joueurs)", 834 "Conflict Cove (Sm 4 players)", "La Crique du conflit (Min. 4 joueurs)", 835 "Culloden Moor (Med 8 players)", "La Lande de Culloden (Moy. 8 joueurs)", 836 "Damnation Alley (Mega 8 players)", "Le chemin de la damnation (XL 8 joueurs)", 837 "Death Valley (Mega 8 players)", "La vall‚e de la mort (XL 8 joueurs)", 838 "Deep Six (Mega 8 players)", "Six de profondeur (XL 8 joueurs)", 839 "Destruction Derby (Mega 8 players)", "Stock car (XL 8 joueurs)", 840 "Diamonds Aren't Forever (Mega 8 players)", "Les diamants ne sont pas ‚ternels (XL 8 joueurs)", 841 "Elysium (Sm 4 players)", "Elys‚e (Min. 4 joueurs)", 842 "Equal Shares (Lg 4 players)", "Parts ‚gales (Max. 4 joueurs)", 843 "Frost Bitten (Mega 8 players)", "Engelures (XL 8 joueurs)", 844 "Frozen Valley (Med 6 players)", "La Vall‚e glac‚e (Moy. 6 joueurs)", 845 "Gettysburg (Sm 4 players)", "Gettysburg (Min. 4 joueurs)", 846 "Glacial Valley (Sm 4 players)", "Vall‚e de glace (Min. 4 joueurs)", 847 "Gold Coast (Med 6 players)", "La c“te dor‚e (Moy. 6 joueurs)", 848 "Gold Rush (Lg 4 players)", "La ru‚e vers l'or (Max. 4 joueurs)", 849 "Habitat (Lg 4 players)", "Habitat (Max. 4 joueurs)", 850 "Hades Frozen Over (Sm 4 players)", "Les enfers glac‚s (Min. 4 joueurs)", 851 "Hamburger Hill (Mega 8 players)", "Hamburger Hill (XL 8 joueurs)", 852 "Hastings (Sm 4 players)", "Hastings (Min. 4 joueurs)", 853 "Hell's Pass (Med 6 players)", "La route de l'enfer (Moy. 6 joueurs)", 854 "Holy Grounds (Mega 8 players)", "Terres saintes (XL 8 joueurs)", 855 "Ice Bergs (Med 6 players)", "Icebergs (Moy. 6 joueurs)", 856 "Ice Station (Lg 6 players)", "Station glac‚e (Max. 6 joueurs)", 857 "Ice Queen (Lg 4 players)", "Reine des glaces (Max. 4 joueurs)", 858 "In the Sun (Med 6 players)", "Sous le soleil (Moy. 6 joueurs)", 859 "Innocents? (Mega 8 players)", "Innocents ? (XL 8 joueurs)", 860 "Islands (Med 8 players)", "Iles (Moy. 8 joueurs)", 861 "Island Plateau (Lg 4 players)", "Plateau des Œles (Max. 4 joueurs)", 862 "Island Wars Extreme (Mega 8 players)", "Guerres insulaires extrˆme (XL 8 joueurs)", 863 "Kananga (Med 6 players)", "Kananga (Moy. 6 joueurs)", 864 "King of the Hills Extreme (Mega 8 players)", "Roi des collines extrˆme (XL 8 joueurs)", 865 "Lake Land (Lg 8 players)", "Paysage lacustre (Max. 8 joueurs)", 866 "Land Locked (Lg 8 players)", "Enclave (Max. 8 joueurs)", 867 "Lanes (Med 8 players)", "Le parcours du combattant (Moy. 8 joueurs)", 868 "Leipzip (Sm 4 players)", "Leipzig (Min. 4 joueurs)", 869 "Meander (Lg 8 players)", "M‚andre (Max. 8 joueurs)", 870 "Mekong (Med 8 players)", "M‚kong (Moy. 8 joueurs)", 871 "Middle Ground (Med 8 players)", "Plateau m‚dian (Moy. 8 joueurs)", 872 "Naval Conquests (Mega 8 players)", "Conquˆtes navales (XL 8 joueurs)", 873 "On your Marks (Med 4 players)", "A vos marques (Moy. 4 joueurs)", 874 "Open Warfare (Mega 8 players)", "Guerre ouverte (XL 8 joueurs)", 875 "Ore Gardens (Lg 8 players)", "Jardins de minerai (Max. 8 joueurs)", 876 "Potholes (Mega 8 players)", "Nids de poules (XL 8 joueurs)", 877 "Puddles (Med 4 players)", "Flaques (Moy. 4 joueurs)", 878 "Random Violence (Mega 8 players)", "Violence al‚atoire (XL 8 joueurs)", 879 "Revenge (Med 8 players)", "Vengeance (Moy. 8 joueurs)", 880 "Rias (Med 8 players)", "Rias (Moy. 8 joueurs)", 881 "River Crossing (Sm 4 players)", "Passage … gu‚ (Min. 4 joueurs)", 882 "River Rampage (Mega 8 players)", "RiviŠre d‚chaŒn‚e (XL 8 joueurs)", 883 "River Rapids (Lg 6 players)", "Rapides (Max. 6 joueurs)", 884 "Rivers Wild (Mega 8 players)", "RiviŠres sauvages (XL 8 joueurs)", 885 "Rorkes Drift (Lg 4 players)", "L'Exode de Rorkes (Max. 4 joueurs)", 886 "Seaside (Med 4 players)", "C“te (Moy. 4 joueurs)", 887 "Shades (Med 8 players)", "Ombres (Moy. 8 joueurs)", 888 "Smuggler's Cove (Lg 6 players)", "La Crique du contrebandier (Max. 6 joueurs)", 889 "Snow Garden (Sm 2 players)", "Jardin de neige (Min. 2 joueurs)", 890 "Stalingrad (Sm 4 players)", "Stalingrad (Min. 4 joueurs)", 891 "Sticks & Stones (Med 4 players)", "Bƒton & Roches (Moy. 4 joueurs)", 892 "Strathearn Valley (Lg 6 players)", "La Vall‚e de Strathearn (Max. 6 joueurs)", 893 "Super Bridgehead (Mega 8 players)", "Super tˆte de pont (XL 8 joueurs)", 894 "Super Mekong (Mega 8 players)", "Super M‚kong (XL 8 joueurs)", 895 "Super Ore Gardens (Mega 8 players)", "Super jardin de minerai (XL 8 joueurs)", 896 "Switch (Med 4 players)", "Permutation (Moy. 4 joueurs)", 897 "The Berg (Mega 8 players)", "Le Berg (XL 8 joueurs)", 898 "The Boyne (Med 4 players)", "Le Boyne (Moy. 4 joueurs)", 899 "The Bulge (Sm 4 players)", "Le bombement (Min. 4 joueurs)", 900 "The Cauldron (Lg 6 players)", "Le chaudron (Max. 6 joueurs)", 901 "The Finger (Lg 6 players)", "Le doigt (Max. 6 joueurs)", 902 "The Hills Have Eyes (Mega 8 players)", "Les collines ont des yeux (XL 8 joueurs)", 903 "The Keyes (Med 6 players)", "Les Keyes (Moy. 6 joueurs)", 904 "The Lakes (Med 8 players)", "Les lacs (Moy. 8 joueurs)", 905 "The Neck (Med 6 players)", "Le goulot (Moy. 6 joueurs)", 906 "The Web (Lg 6 players)", "La toile (Max. 6 joueurs)", 907 "To the Core (Lg 4 players)", "Jusqu'au cour (Max. 4 joueurs)", 908 "Trafalgar (Lg 4 players)", "Trafalgar (Max. 4 joueurs)", 909 "Twin Rivers (Sm 4 players)", "Les deux riviŠres (Min. 4 joueurs)", 910 "Umtumbo Gorge (Lg 4 players)", "La Gorge de Umtumbo (Max. 4 joueurs)", 911 "Watch Your Step Extreme (Mega 8 players)", "Pas-…-pas extrˆme (XL 8 joueurs)", 912 "Waterfalls (Lg 8 players)", "Chutes d'eau (Max. 8 joueurs)", 913 "Waterloo Revisited (Lg 6 players)", "Waterloo II (Max. 6 joueurs)", 914 "Water Werks (Mega 8 players)", "Jeux d'eau (XL 8 joueurs)", 915 "Warlord's Lake (Sm 4 players)", "Le lac du guerrier (Min. 4 joueurs)", 916 "Zama (Sm 4 players)", "Zama (Min. 4 joueurs)", 917 //#endif 918 NULL 919 }; 920 #endif 921 922 923 /* 924 ******************************** Prototypes ********************************* 925 */ 926 static int Net_Join_Dialog(void); 927 static int Request_To_Join (char *playername, int join_index, 928 HousesType house, PlayerColorType color); 929 static void Unjoin_Game(char *namebuf,JoinStateType joinstate, 930 ListClass *gamelist, ColorListClass *playerlist, int game_index, 931 int goto_lobby, int msg_x, int msg_y, int msg_h, int send_x, int send_y, 932 int msg_len); 933 static void Send_Join_Queries(int curgame, JoinStateType joinstate, 934 int gamenow, int playernow, int chatnow, char *myname, int init = 0); 935 static JoinEventType Get_Join_Responses(JoinStateType *joinstate, 936 ListClass *gamelist, ColorListClass *playerlist, int join_index, 937 char *my_name, RejectType *why); 938 static int Net_New_Dialog(void); 939 static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist, 940 int *color_used); 941 void Start_WWChat(ColorListClass *playerlist); 942 int Update_WWChat(void); 943 944 945 #define PCOLOR_BROWN PCOLOR_GREY 946 947 948 /*********************************************************************************************** 949 * Init_Network -- initializes network stuff * 950 * * 951 * INPUT: * 952 * none. * 953 * * 954 * OUTPUT: * 955 * true = Initialization OK, false = error * 956 * * 957 * WARNINGS: * 958 * none. * 959 * * 960 * HISTORY: * 961 * 02/14/1995 BR : Created. * 962 *=============================================================================================*/ 963 bool Init_Network (void) 964 { 965 NetNumType net; 966 NetNodeType node; 967 #ifdef WINSOCK_IPX 968 assert ( PacketTransport != NULL ); 969 #endif //WINSOCK_IPX 970 971 //------------------------------------------------------------------------ 972 // This call allocates all necessary queue buffers, allocates Real-mode 973 // memory, and commands IPX to start listening on the Global Channel. 974 //------------------------------------------------------------------------ 975 if (!Ipx.Init()) { 976 return(false); 977 } 978 979 //------------------------------------------------------------------------ 980 // Set up the IPX manager to cross a bridge 981 //------------------------------------------------------------------------ 982 if (Session.Type != GAME_INTERNET) { 983 if (Session.IsBridge) { 984 Session.BridgeNet.Get_Address(net,node); 985 Ipx.Set_Bridge(net); 986 } 987 } 988 989 return(true); 990 991 } /* end of Init_Network */ 992 993 994 /*********************************************************************************************** 995 * Shutdown_Network -- shuts down network stuff * 996 * * 997 * INPUT: * 998 * none. * 999 * * 1000 * OUTPUT: * 1001 * none. * 1002 * * 1003 * WARNINGS: * 1004 * none. * 1005 * * 1006 * HISTORY: * 1007 * 02/14/1995 BR : Created. * 1008 *=============================================================================================*/ 1009 void Shutdown_Network (void) 1010 { 1011 // 1012 // Note: The thought behind this section of code was that if the program 1013 // terminates early, without an EventClass::EXIT event, it still needs to 1014 // tell the other systems that it's gone, so it would send a SIGN_OFF packet. 1015 // BUT, this causes a sync bug if the systems are running slow and this system 1016 // is running ahead of the others; it will send the NET_SIGN_OFF >>before<< 1017 // the other system execute their EventClass::EXIT event, and the other systems 1018 // will kill the connection at some random Frame # & turn my stuff over to 1019 // the computer possibly at different times. 1020 // BRR, 10/29/96 1021 // 1022 #if 0 1023 //------------------------------------------------------------------------ 1024 // If the Players vector contains at least one name, send a sign-off 1025 // packet. If 'Players' is empty, I have no name, so there's no point 1026 // in sending a sign-off. 1027 //------------------------------------------------------------------------ 1028 if (Session.Players.Count()) { 1029 //..................................................................... 1030 // Build a sign-off packet & send it 1031 //..................................................................... 1032 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 1033 Session.GPacket.Command = NET_SIGN_OFF; 1034 strcpy (Session.GPacket.Name, Session.Players[0]->Name); 1035 1036 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 1037 0, NULL); 1038 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 1039 0, NULL); 1040 1041 if (Session.IsBridge && !Winsock.Get_Connected()) { 1042 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 0, 1043 &Session.BridgeNet); 1044 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 0, 1045 &Session.BridgeNet); 1046 } 1047 1048 //..................................................................... 1049 // Wait for the packets to finish going out (or the Global Channel 1050 // times out) 1051 //..................................................................... 1052 for (;;) { 1053 if (Ipx.Global_Num_Send()==0) { 1054 break; 1055 } 1056 Ipx.Service(); 1057 } 1058 } 1059 #endif 1060 1061 //------------------------------------------------------------------------ 1062 // If I was in a game, I'm not now, so clear the game name 1063 //------------------------------------------------------------------------ 1064 Session.GameName[0] = 0; 1065 1066 } /* end of Shutdown_Network */ 1067 1068 1069 /*********************************************************************************************** 1070 * Process_Global_Packet -- responds to remote queries * 1071 * * 1072 * The only commands from other systems this routine responds to are NET_QUERY_GAME * 1073 * and NET_QUERY_PLAYER. The other commands are too context-specific to be able * 1074 * to handle here, such as joining the game or signing off; but this routine handles * 1075 * the majority of the program's needs. * 1076 * * 1077 * INPUT: * 1078 * packet ptr to packet to process * 1079 * address source address of sender * 1080 * * 1081 * OUTPUT: * 1082 * true = packet was processed, false = wasn't * 1083 * * 1084 * WARNINGS: * 1085 * Session.GameName must have been filled in before this function can be called. * 1086 * * 1087 * HISTORY: * 1088 * 02/15/1995 BR : Created. * 1089 *=============================================================================================*/ 1090 bool Process_Global_Packet(GlobalPacketType *packet, IPXAddressClass *address) 1091 { 1092 GlobalPacketType mypacket; 1093 1094 //------------------------------------------------------------------------ 1095 // If our Players vector is empty, just return. 1096 //------------------------------------------------------------------------ 1097 if (Session.Players.Count()==0) { 1098 return (true); 1099 } 1100 1101 //------------------------------------------------------------------------ 1102 // Another system asking what game this is 1103 //------------------------------------------------------------------------ 1104 if (packet->Command==NET_QUERY_GAME && Session.NetStealth==0) { 1105 1106 //..................................................................... 1107 // If the game is closed, let every player respond, and let the sender of 1108 // the query sort it all out. This way, if the game's host exits the game, 1109 // the game still shows up on other players' dialogs. 1110 // If the game is open, only the game owner may respond. 1111 //..................................................................... 1112 if (strlen(Session.GameName) > 0 && ((!Session.NetOpen) || 1113 (Session.NetOpen && 1114 !strcmp(Session.Players[0]->Name,Session.GameName)))) { 1115 1116 memset (&mypacket, 0, sizeof(GlobalPacketType)); 1117 1118 mypacket.Command = NET_ANSWER_GAME; 1119 strcpy(mypacket.Name, Session.GameName); 1120 mypacket.GameInfo.IsOpen = Session.NetOpen; 1121 1122 Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1, 1123 address); 1124 } 1125 return(true); 1126 } 1127 1128 //------------------------------------------------------------------------ 1129 // Another system asking what player I am 1130 //------------------------------------------------------------------------ 1131 else if (packet->Command==NET_QUERY_PLAYER && 1132 !strcmp (packet->Name, Session.GameName) && 1133 (strlen(Session.GameName) > 0) && Session.NetStealth==0) { 1134 1135 memset (&mypacket, 0, sizeof(GlobalPacketType)); // changed DRD 9/26 1136 1137 mypacket.Command = NET_ANSWER_PLAYER; 1138 strcpy(mypacket.Name, Session.Players[0]->Name); 1139 mypacket.PlayerInfo.House = Session.House; 1140 mypacket.PlayerInfo.Color = Session.ColorIdx; 1141 mypacket.PlayerInfo.NameCRC = Compute_Name_CRC(Session.GameName); 1142 1143 Ipx.Send_Global_Message (&mypacket, sizeof(GlobalPacketType), 1, address); 1144 return(true); 1145 } 1146 1147 return(false); 1148 1149 } /* end of Process_Global_Packet */ 1150 1151 1152 /*********************************************************************************************** 1153 * Destroy_Connection -- destroys the given connection * 1154 * * 1155 * Call this routine when a connection goes bad, or another player signs off. * 1156 * * 1157 * INPUT: * 1158 * id connection ID to destroy; this should be the HousesType of the player * 1159 * on this connection * 1160 * error 0 = user signed off; 1 = connection error; otherwise, no error is shown. * 1161 * * 1162 * OUTPUT: * 1163 * none. * 1164 * * 1165 * WARNINGS: * 1166 * none. * 1167 * * 1168 * HISTORY: * 1169 * 04/22/1995 BR : Created. * 1170 *=============================================================================================*/ 1171 void Destroy_Connection(int id, int error) 1172 { 1173 int i; 1174 HouseClass *housep; 1175 char txt[80]; 1176 1177 if (Debug_Print_Events) { 1178 printf("Destroying connection for house %d (%s)\n", 1179 id,HouseClass::As_Pointer((HousesType)id)->IniName); 1180 } 1181 1182 //------------------------------------------------------------------------ 1183 // Do nothing if the house isn't human. 1184 //------------------------------------------------------------------------ 1185 housep = HouseClass::As_Pointer((HousesType)id); 1186 if (!housep || !housep->IsHuman) 1187 return; 1188 1189 //------------------------------------------------------------------------ 1190 // Create a message to display to the user 1191 //------------------------------------------------------------------------ 1192 txt[0] = '\0'; 1193 if (error==1) { 1194 sprintf(txt,Text_String(TXT_CONNECTION_LOST), housep->IniName); 1195 } else if (error==0) { 1196 sprintf(txt,Text_String(TXT_LEFT_GAME), housep->IniName); 1197 } 1198 1199 if (strlen(txt)) { 1200 Session.Messages.Add_Message (NULL,0, txt, housep->RemapColor, TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE); 1201 Map.Flag_To_Redraw(false); 1202 } 1203 1204 //------------------------------------------------------------------------ 1205 // Remove this player from the Players vector 1206 //------------------------------------------------------------------------ 1207 for (i = 0; i < Session.Players.Count(); i++) { 1208 if (!stricmp(Session.Players[i]->Name,housep->IniName)) { 1209 delete Session.Players[i]; 1210 Session.Players.Delete(Session.Players[i]); 1211 break; 1212 } 1213 } 1214 1215 //------------------------------------------------------------------------ 1216 // Delete the IPX connection 1217 //------------------------------------------------------------------------ 1218 Ipx.Delete_Connection(id); 1219 1220 //------------------------------------------------------------------------ 1221 // Turn the player's house over to the computer's AI 1222 //------------------------------------------------------------------------ 1223 housep->IsHuman = false; 1224 housep->IQ = Rule.MaxIQ; 1225 strcpy (housep->IniName,Text_String(TXT_COMPUTER)); 1226 1227 Session.NumPlayers--; 1228 1229 //------------------------------------------------------------------------ 1230 // If we're the last player left, tell the user. 1231 //------------------------------------------------------------------------ 1232 if (Session.NumPlayers == 1) { 1233 sprintf(txt,"%s",Text_String(TXT_JUST_YOU_AND_ME)); 1234 Session.Messages.Add_Message (NULL, 0, txt, housep->RemapColor, 1235 TPF_TEXT, Rule.MessageDelay * TICKS_PER_MINUTE); 1236 Map.Flag_To_Redraw(false); 1237 } 1238 1239 } /* end of Destroy_Connection */ 1240 1241 1242 /*********************************************************************************************** 1243 * Remote_Connect -- handles connecting this user to others * 1244 * * 1245 * INPUT: * 1246 * none. * 1247 * * 1248 * OUTPUT: * 1249 * true = connections established; false = not * 1250 * * 1251 * WARNINGS: * 1252 * none. * 1253 * * 1254 * HISTORY: * 1255 * 02/14/1995 BR : Created. * 1256 *=============================================================================================*/ 1257 bool Remote_Connect(void) 1258 { 1259 int rc; 1260 int stealth; // original state of Session.NetStealth flag 1261 1262 //------------------------------------------------------------------------ 1263 // Init network timing parameters; these values should work for both a 1264 // "real" network, and a simulated modem network (ie Kali) 1265 //------------------------------------------------------------------------ 1266 Ipx.Set_Timing ( 30, // retry 2 times per second 1267 -1, // ignore max retries 1268 600); // give up after 10 seconds 1269 1270 //------------------------------------------------------------------------ 1271 // Save the original value of the NetStealth flag, so we can turn stealth 1272 // off for now (during this portion of the dialogs, we must show ourselves) 1273 //------------------------------------------------------------------------ 1274 stealth = Session.NetStealth; 1275 Session.NetStealth = 0; 1276 1277 //------------------------------------------------------------------------ 1278 // Init my game name to 0-length, since I haven't joined any game yet. 1279 //------------------------------------------------------------------------ 1280 Session.GameName[0] = 0; 1281 1282 //------------------------------------------------------------------------ 1283 // The game is now "open" for joining. Close it as soon as we exit this 1284 // routine. 1285 //------------------------------------------------------------------------ 1286 Session.NetOpen = 1; 1287 1288 //------------------------------------------------------------------------ 1289 // Keep looping until something useful happens. 1290 //------------------------------------------------------------------------ 1291 while (1) { 1292 //..................................................................... 1293 // Pop up the network Join/New dialog 1294 //..................................................................... 1295 rc = Net_Join_Dialog(); 1296 1297 //..................................................................... 1298 // -1 = user selected Cancel 1299 //..................................................................... 1300 if (rc==-1) { 1301 Session.NetStealth = stealth; 1302 Session.NetOpen = 0; 1303 return(false); 1304 } 1305 1306 //..................................................................... 1307 // 0 = user has joined an existing game; save values & return 1308 //..................................................................... 1309 else if (rc==0) { 1310 Session.Write_MultiPlayer_Settings (); 1311 Session.NetStealth = stealth; 1312 Session.NetOpen = 0; 1313 1314 return(true); 1315 } 1316 1317 //..................................................................... 1318 // 1 = user requests New Network Game 1319 //..................................................................... 1320 else if (rc==1) { 1321 //.................................................................. 1322 // Pop up the New Network Game dialog; if user selects OK, return 1323 // 'true'; otherwise, return to the Join Dialog. 1324 //.................................................................. 1325 if (Net_New_Dialog()) { 1326 Session.Write_MultiPlayer_Settings (); 1327 Session.NetStealth = stealth; 1328 Session.NetOpen = 0; 1329 1330 return(true); 1331 } else { 1332 continue; 1333 } 1334 } 1335 } 1336 1337 } /* end of Remote_Connect */ 1338 1339 1340 1341 /*********************************************************************************************** 1342 * Net_Join_Dialog -- lets user join an existing game or start a new one * 1343 * * 1344 * This dialog displays an edit field for the player's name, and a list of all non-stealth- * 1345 * mode games. Clicking once on a game name displays a list of who's in that game. Clicking * 1346 * "New" takes the user to the Net_New dialog, where he waits for other users to join his * 1347 * game. All other input is done through this dialog. * 1348 * * 1349 * The dialog has several "states": * 1350 * * 1351 * 1) Initially, it waits for the user to fill in his/her name and then to select Join or * 1352 * New; if New is selected, this dialog is exited. * 1353 * * 1354 * 2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.* 1355 * The join request is transmitted to the game's owner, and the message "Waiting for * 1356 * Confirmation" is displayed, until a confirmation or denial is received from the game's * 1357 * owner. The user may click Cancel at this point to cancel the join request. * 1358 * (Once Join is selected, the name editing field is disabled, and becomes a display-only * 1359 * field. If cancel is selected, it reappears as an edit field.) The user can still click* 1360 * around & see who's in which games. * 1361 * * 1362 * 3) If the join request is denied, the dialog re-initializes to its pre-join state; the * 1363 * Join & New buttons reappear, & the Name field is available again. * 1364 * * 1365 * 4) If join confirmation is obtained, the message changes to show all the current game * 1366 * settings. The user cannot click around & look at other games any more. * 1367 * * 1368 * Any game running in Stealth mode won't show up on this dialog. * 1369 * * 1370 * The 'Players' vector matches one-for-one the contents of the list box. The local system * 1371 * is always listed first; the IPX Address of the local system will NOT be valid in the * 1372 * Players vector. The Games & Players vectors should be left filled in even after this * 1373 * routine is exited; their contents are used to form connections to the other players, * 1374 * after the scenario has been loaded. * 1375 * * 1376 * The 'Chat' vector contains the address of everyone who sends me a chat announcement. * 1377 * The address field is used to send everyone my outgoing messages. The LastTime * 1378 * field is used as a timeout; if enough time goes by & we don't hear from this node, * 1379 * we ping him, requesting a CHAT_ANNOUNCE if he's still in chat. If we don't hear * 1380 * from him after that, we remove him from our list. * 1381 * * 1382 * INPUT: * 1383 * none. * 1384 * * 1385 * OUTPUT: * 1386 * -1 = cancel, 0 = OK, 1 = New net game requested * 1387 * * 1388 * WARNINGS: * 1389 * none. * 1390 * * 1391 * HISTORY: * 1392 * 02/14/1995 BR : Created. * 1393 *=============================================================================================*/ 1394 static int Net_Join_Dialog(void) 1395 { 1396 //------------------------------------------------------------------------ 1397 // Dialog & button dimensions 1398 //------------------------------------------------------------------------ 1399 int d_dialog_w = 320 *RESFACTOR; // dialog width 1400 int d_dialog_h = 200 *RESFACTOR; // dialog height 1401 int d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2); // dialog x-coord 1402 int d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2); // centered y-coord 1403 int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord 1404 1405 int d_txt6_h = 6 *RESFACTOR+1; // ht of 6-pt text 1406 int d_margin1 = 17 *RESFACTOR; // large margin 1407 int d_margin2 = 7 *RESFACTOR; // small margin 1408 1409 int d_name_w = 70 *RESFACTOR; 1410 int d_name_h = 9 *RESFACTOR; 1411 int d_name_x = d_dialog_x + (d_dialog_w / 4) - (d_name_w / 2); 1412 int d_name_y = d_dialog_y + d_margin2 + d_txt6_h + (2*RESFACTOR); 1413 1414 #ifdef OLDWAY 1415 int d_gdi_w = 40 *RESFACTOR; 1416 int d_gdi_h = 9 *RESFACTOR; 1417 int d_gdi_x = d_dialog_cx - d_gdi_w; 1418 int d_gdi_y = d_name_y; 1419 1420 int d_nod_w = 40 *RESFACTOR; 1421 int d_nod_h = 9 *RESFACTOR; 1422 int d_nod_x = d_dialog_cx; 1423 int d_nod_y = d_name_y; 1424 #else 1425 int d_house_w = 60 *RESFACTOR; 1426 int d_house_h = (8 * 5 *RESFACTOR); 1427 int d_house_x = d_dialog_cx - (d_house_w / 2); 1428 int d_house_y = d_name_y; 1429 #endif 1430 1431 int d_color_w = 10 *RESFACTOR; 1432 int d_color_h = 9 *RESFACTOR; 1433 int d_color_y = d_name_y; 1434 int d_color_x = d_dialog_x + ((d_dialog_w / 4) * 3) - (d_color_w * 3); 1435 1436 int d_gamelist_w = 155 *RESFACTOR; 1437 int d_gamelist_h = ((6 * 6) + 3) *RESFACTOR; // 6 rows high 1438 int d_gamelist_x = d_dialog_x + d_margin1 - 2*RESFACTOR; 1439 int d_gamelist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/; 1440 1441 //BG int d_playerlist_w = 113 *RESFACTOR; 1442 int d_playerlist_w = 118 *RESFACTOR; 1443 int d_playerlist_h = ((6 * 6) + 3) *RESFACTOR; // 6 rows high 1444 int d_playerlist_x = d_dialog_x + d_dialog_w - (d_margin1 + d_playerlist_w - 2*RESFACTOR); 1445 int d_playerlist_y = d_color_y + d_color_h + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/; 1446 1447 int d_count_w = 25 *RESFACTOR; 1448 int d_count_h = d_txt6_h; 1449 int d_count_x = d_gamelist_x + (d_gamelist_w / 2); 1450 int d_count_y = d_gamelist_y + d_gamelist_h + d_margin2; 1451 1452 int d_level_w = 25 *RESFACTOR; 1453 int d_level_h = d_txt6_h; 1454 int d_level_x = d_gamelist_x + (d_gamelist_w / 2); 1455 int d_level_y = d_count_y + d_count_h; 1456 1457 int d_credits_w = 25 *RESFACTOR; 1458 int d_credits_h = d_txt6_h; 1459 int d_credits_x = d_gamelist_x + (d_gamelist_w / 2); 1460 int d_credits_y = d_level_y + d_level_h; 1461 1462 int d_aiplayers_w = 25 *RESFACTOR; 1463 int d_aiplayers_h = d_txt6_h; 1464 int d_aiplayers_x = d_gamelist_x + (d_gamelist_w / 2); 1465 int d_aiplayers_y = d_credits_y + d_level_h; 1466 1467 int d_options_w = d_playerlist_w; 1468 int d_options_h = ((5 * 6) + 4) *RESFACTOR; 1469 int d_options_x = d_playerlist_x; 1470 int d_options_y = d_playerlist_y + d_playerlist_h + d_margin2 - (2*RESFACTOR); 1471 1472 int d_message1_w = d_dialog_w - (d_margin1 * 2) + 4*RESFACTOR; 1473 int d_message1_h = (14 * d_txt6_h) +3*RESFACTOR; 1474 int d_message1_x = d_dialog_x + (d_dialog_w-d_message1_w)/2; 1475 int d_message1_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message1_h); 1476 1477 int d_message2_w = d_message1_w; 1478 int d_message2_h = (8 * d_txt6_h) + 3*RESFACTOR; 1479 int d_message2_x = d_message1_x; 1480 int d_message2_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message2_h); 1481 1482 #ifdef FRENCH //VG2 1483 int d_join_w = 60 *RESFACTOR; 1484 #else 1485 int d_join_w = 40 *RESFACTOR; 1486 #endif 1487 int d_join_h = 9 *RESFACTOR; 1488 int d_join_x = d_dialog_x + (d_dialog_w / 6) - (d_join_w / 2); 1489 int d_join_y = d_dialog_y + d_dialog_h - d_join_h - 8*RESFACTOR; 1490 1491 int d_cancel_w = 50 *RESFACTOR; 1492 int d_cancel_h = 9 *RESFACTOR; 1493 int d_cancel_x = d_dialog_cx - d_cancel_w / 2; 1494 int d_cancel_y = d_join_y; 1495 1496 #ifdef FRENCH 1497 int d_new_w = 60 *RESFACTOR; 1498 #else 1499 int d_new_w = 40 *RESFACTOR; 1500 #endif 1501 int d_new_h = 9 *RESFACTOR; 1502 int d_new_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_new_w / 2); 1503 int d_new_y = d_join_y; 1504 1505 int d_send_w = d_message1_w; 1506 int d_send_h = 9 *RESFACTOR; 1507 int d_send_x = d_message1_x; 1508 int d_send_y = d_message1_y + d_message1_h; 1509 1510 1511 //------------------------------------------------------------------------ 1512 // Button Enumerations 1513 //------------------------------------------------------------------------ 1514 enum { 1515 BUTTON_NAME = 100, 1516 #ifdef OLDWAY 1517 BUTTON_GDI, 1518 BUTTON_NOD, 1519 #else 1520 BUTTON_HOUSE, 1521 #endif 1522 BUTTON_GAMELIST, 1523 BUTTON_PLAYERLIST, 1524 BUTTON_JOIN, 1525 BUTTON_CANCEL, 1526 BUTTON_NEW, 1527 BUTTON_COUNT, 1528 BUTTON_LEVEL, 1529 BUTTON_CREDITS, 1530 BUTTON_AI_PLAYERS, 1531 BUTTON_OPTIONS, 1532 }; 1533 1534 //------------------------------------------------------------------------ 1535 // Redraw values: in order from "top" to "bottom" layer of the dialog 1536 //------------------------------------------------------------------------ 1537 typedef enum { 1538 REDRAW_NONE = 0, 1539 REDRAW_PARMS, 1540 REDRAW_MESSAGE, 1541 REDRAW_COLORS, 1542 REDRAW_BUTTONS, 1543 REDRAW_BACKGROUND, 1544 REDRAW_ALL = REDRAW_BACKGROUND 1545 } RedrawType; 1546 1547 //------------------------------------------------------------------------ 1548 // Dialog variables 1549 //------------------------------------------------------------------------ 1550 RedrawType display = REDRAW_ALL; // redraw level 1551 bool process = true; // process while true 1552 KeyNumType input; 1553 int cbox_x[] = { 1554 d_color_x, 1555 d_color_x + d_color_w, 1556 d_color_x + (d_color_w * 2), 1557 d_color_x + (d_color_w * 3), 1558 d_color_x + (d_color_w * 4), 1559 d_color_x + (d_color_w * 5), 1560 d_color_x + (d_color_w * 6), 1561 d_color_x + (d_color_w * 7), 1562 }; 1563 char housetext[25] = ""; // buffer for house droplist 1564 int isdropped = 0; 1565 1566 JoinStateType joinstate = JOIN_NOTHING; // current "state" of this dialog 1567 char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name 1568 int playertabs[] = {71 *RESFACTOR}; // tabs for player list box 1569 int optiontabs[] = {8}; // tabs for player list box 1570 int game_index = -1; // index of currently-selected game 1571 int join_index = -1; // index of game we're joining 1572 int rc = 0; // -1 = user cancelled, 1 = New 1573 JoinEventType event; // event from incoming packet 1574 int i; // loop counter 1575 char txt[128]; 1576 char const *p; 1577 int parms_received = 0; // 1 = game options received 1578 int found; 1579 NodeNameType *who; // node to add to Players 1580 RejectType why; // reason for rejection 1581 TTimerClass<SystemTimerClass> lastclick_timer; // time b/w send periods 1582 int lastclick_idx = 0; // index of item last clicked on 1583 RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); 1584 Session.Options.ScenarioDescription[0] = 0; //Flag that we dont know the scenario name yet 1585 1586 char * item; 1587 unsigned long starttime; 1588 int load_game = 0; // 1 = load saved game 1589 int goto_lobby; 1590 bool messages_have_focus = true; // Gadget focus starts on the message system 1591 1592 //------------------------------------------------------------------------ 1593 // Buttons 1594 //------------------------------------------------------------------------ 1595 GadgetClass *commands; // button list 1596 1597 EditClass name_edt(BUTTON_NAME, namebuf, MPLAYER_NAME_MAX, TPF_TEXT, 1598 d_name_x, d_name_y, d_name_w, d_name_h, EditClass::ALPHANUMERIC); 1599 1600 #ifdef OLDWAY 1601 TextButtonClass gdibtn(BUTTON_GDI, TXT_ALLIES, TPF_BUTTON, d_gdi_x, d_gdi_y, d_gdi_w); 1602 TextButtonClass nodbtn(BUTTON_NOD, TXT_SOVIET, TPF_BUTTON, d_nod_x, d_nod_y, d_nod_w); 1603 #else 1604 Fancy_Text_Print("", 0, 0, 0, 0, TPF_TEXT); 1605 DropListClass housebtn(BUTTON_HOUSE, housetext, sizeof(housetext), 1606 TPF_TEXT, 1607 d_house_x, d_house_y, d_house_w, d_house_h, 1608 MFCD::Retrieve("BTN-UP.SHP"), 1609 MFCD::Retrieve("BTN-DN.SHP")); 1610 #endif 1611 1612 ListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); 1613 ColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); 1614 TextButtonClass joinbtn(BUTTON_JOIN, TXT_JOIN, TPF_BUTTON, d_join_x, d_join_y, d_join_w); 1615 TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, d_cancel_w); 1616 TextButtonClass newbtn(BUTTON_NEW, TXT_NEW, TPF_BUTTON, d_new_x, d_new_y, d_new_w); 1617 GaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h); 1618 GaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h); 1619 GaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h); 1620 GaugeClass aiplayersgauge(BUTTON_AI_PLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h); 1621 CheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); 1622 StaticButtonClass descrip(0, "", TPF_CENTER|TPF_TEXT, d_dialog_x + 16*RESFACTOR, d_name_y, d_dialog_w - 32*RESFACTOR, d_txt6_h+1); 1623 StaticButtonClass staticcount(0, " ", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y); 1624 StaticButtonClass staticlevel(0, " ", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y); 1625 StaticButtonClass staticcredits(0, " ", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y); 1626 StaticButtonClass staticaiplayers(0, " ", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y); 1627 1628 //------------------------------------------------------------------------ 1629 // Init the button states 1630 //------------------------------------------------------------------------ 1631 //........................................................................ 1632 // Name & Color 1633 //........................................................................ 1634 Session.ColorIdx = Session.PrefColor; // init my preferred color 1635 strcpy (namebuf, Session.Handle); // set my name 1636 name_edt.Set_Text(namebuf,MPLAYER_NAME_MAX); 1637 if (Session.ColorIdx == PCOLOR_DIALOG_BLUE) { 1638 name_edt.Set_Color(&ColorRemaps[PCOLOR_REALLY_BLUE]); 1639 } else { 1640 name_edt.Set_Color(&ColorRemaps[Session.ColorIdx]); 1641 } 1642 1643 //........................................................................ 1644 // List boxes 1645 //........................................................................ 1646 playerlist.Set_Tabs(playertabs); 1647 playerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL); 1648 1649 optionlist.Set_Tabs(optiontabs); 1650 optionlist.Set_Read_Only(1); 1651 1652 optionlist.Add_Item(Text_String(TXT_BASES)); 1653 optionlist.Add_Item(Text_String(TXT_ORE_SPREADS)); 1654 optionlist.Add_Item(Text_String(TXT_CRATES)); 1655 optionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG)); 1656 optionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS)); 1657 1658 optionlist.Check_Item(0, Rule.IsMPBasesOn); 1659 optionlist.Check_Item(1, Rule.IsMPTiberiumGrow); 1660 optionlist.Check_Item(2, Rule.IsMPCrates); 1661 optionlist.Check_Item(3, Rule.IsMPCaptureTheFlag); 1662 optionlist.Check_Item(4, Rule.IsMPShadowGrow); 1663 1664 //........................................................................ 1665 // House buttons 1666 //........................................................................ 1667 #ifdef OLDWAY 1668 if (Session.House==HOUSE_GOOD) { 1669 gdibtn.Turn_On(); 1670 } else { 1671 nodbtn.Turn_On(); 1672 } 1673 #else 1674 for (HousesType house = HOUSE_USSR; house <= HOUSE_FRANCE; house++) { 1675 // for (HousesType house = HOUSE_FIRST; house <= HOUSE_TURKEY; house++) { 1676 housebtn.Add_Item(Text_String(HouseTypeClass::As_Reference(house).Full_Name())); 1677 } 1678 housebtn.Set_Selected_Index(Session.House - HOUSE_USSR); 1679 housebtn.Set_Read_Only (true); 1680 #endif 1681 1682 //........................................................................ 1683 // Option gauges 1684 //........................................................................ 1685 countgauge.Use_Thumb(0); 1686 countgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]); 1687 countgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]); 1688 1689 levelgauge.Use_Thumb(0); 1690 levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1); 1691 levelgauge.Set_Value(BuildLevel - 1); 1692 1693 creditsgauge.Use_Thumb(0); 1694 creditsgauge.Set_Maximum(Rule.MPMaxMoney); 1695 creditsgauge.Set_Value(Session.Options.Credits); 1696 1697 aiplayersgauge.Use_Thumb(0); 1698 aiplayersgauge.Set_Maximum(Session.Options.AIPlayers); 1699 aiplayersgauge.Set_Value(Session.Options.AIPlayers); 1700 1701 Fancy_Text_Print("", 0, 0, scheme, TBLACK, TPF_TEXT); 1702 1703 Session.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14, 1704 MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1, 1705 20, MAX_MESSAGE_LENGTH - 5, d_message2_w); 1706 Session.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, 1707 TPF_TEXT, NULL, '_', d_message2_w); 1708 Session.WWChat = 0; 1709 1710 lastclick_timer = 0; 1711 1712 //------------------------------------------------------------------------ 1713 // Clear the list of games, players, and the chat list 1714 //------------------------------------------------------------------------ 1715 Clear_Vector(&Session.Games); 1716 Clear_Vector(&Session.Players); 1717 Clear_Vector(&Session.Chat); 1718 1719 //------------------------------------------------------------------------ 1720 // Add myself to the Chat vector 1721 //------------------------------------------------------------------------ 1722 who = new NodeNameType; 1723 strcpy(who->Name, namebuf); 1724 who->Chat.LastTime = 0; 1725 who->Chat.LastChance = 0; 1726 who->Chat.Color = Session.GPacket.Chat.Color; 1727 Session.Chat.Add (who); 1728 1729 //------------------------------------------------------------------------ 1730 // Create the "Lobby" game name on the games list, and create a bogus 1731 // node for the gamelist, so Games[i] will always match gamelist[i] 1732 //------------------------------------------------------------------------ 1733 who = new NodeNameType; 1734 strcpy(who->Name, ""); 1735 who->Game.IsOpen = 0; 1736 who->Game.LastTime = 0; 1737 Session.Games.Add (who); 1738 item = new char [MPLAYER_NAME_MAX]; 1739 strcpy(item, Text_String(TXT_LOBBY)); 1740 gamelist.Add_Item(item); 1741 gamelist.Set_Selected_Index(0); 1742 game_index = 0; 1743 1744 //------------------------------------------------------------------------ 1745 // Send game-name query & chat announcement; also, initialize timers. 1746 //------------------------------------------------------------------------ 1747 Send_Join_Queries (game_index, joinstate, 1, 0, 1, namebuf, 1); 1748 Load_Title_Page(true); 1749 CCPalette.Set(); //GamePalette.Set(); 1750 1751 //------------------------------------------------------------------------ 1752 // Init Mono Output 1753 //------------------------------------------------------------------------ 1754 #if(SHOW_MONO) 1755 Ipx.Configure_Debug(-1, sizeof (GlobalHeaderType), sizeof(NetCommandType), GlobalPacketNames, 0, 13); 1756 Ipx.Mono_Debug_Print(-1,1); 1757 #endif 1758 #ifdef WIN32 1759 //char *fred; 1760 #endif 1761 //------------------------------------------------------------------------ 1762 // Processing loop 1763 //------------------------------------------------------------------------ 1764 while (process) { 1765 #if(SHOW_MONO) 1766 Ipx.Mono_Debug_Print(-1,0); 1767 #endif 1768 1769 /* 1770 ** Kludge to make sure we redraw the message input line when it loses focus. 1771 ** If we dont do this then the cursor doesnt disappear. 1772 */ 1773 if (messages_have_focus) { 1774 if (name_edt.Has_Focus()) { 1775 if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; 1776 messages_have_focus = false; 1777 } 1778 } else { 1779 if (!name_edt.Has_Focus()) { 1780 messages_have_focus = true; 1781 } 1782 } 1783 1784 /* 1785 ** Collapse the country list if we are going to redraw the game list 1786 */ 1787 if (gamelist.Is_To_Redraw() && housebtn.IsDropped) { 1788 housebtn.Collapse(); 1789 if (display < REDRAW_BACKGROUND) display = REDRAW_BACKGROUND; 1790 } 1791 1792 #ifdef WIN32 1793 /* 1794 ** If we have just received input focus again after running in the background then 1795 ** we need to redraw. 1796 */ 1797 if (AllSurfaces.SurfacesRestored) { 1798 AllSurfaces.SurfacesRestored=FALSE; 1799 display = REDRAW_ALL; 1800 } 1801 #endif 1802 //..................................................................... 1803 // Refresh display if needed 1804 //..................................................................... 1805 if (display) { 1806 Hide_Mouse(); 1807 1808 //.................................................................. 1809 // Redraw backgound & dialog box 1810 //.................................................................. 1811 if (display >= REDRAW_BACKGROUND) { 1812 housebtn.Collapse(); 1813 Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h); 1814 1815 //............................................................... 1816 // Dialog & Field labels 1817 //............................................................... 1818 Fancy_Text_Print(TXT_CHANNEL_GAMES, d_gamelist_x + (d_gamelist_w / 2), d_gamelist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); 1819 Fancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); 1820 1821 //............................................................... 1822 // For game-browsing, label the name, side, & color buttons: 1823 //............................................................... 1824 if (joinstate < JOIN_CONFIRMED) { 1825 Fancy_Text_Print(TXT_YOUR_NAME, d_name_x + (d_name_w / 2), d_name_y - d_txt6_h, scheme, TBLACK, TPF_CENTER | TPF_TEXT); 1826 1827 #ifdef OLDWAY 1828 Fancy_Text_Print(TXT_SIDE_COLON, 1829 d_gdi_x + d_gdi_w, 1830 d_gdi_y - d_txt6_h, 1831 scheme, TBLACK, 1832 TPF_CENTER | TPF_TEXT); 1833 #else 1834 Fancy_Text_Print(TXT_SIDE_COLON, 1835 d_house_x + (d_house_w / 2), 1836 d_house_y - d_txt6_h, 1837 scheme, TBLACK, 1838 TPF_CENTER | TPF_TEXT); 1839 #endif 1840 1841 Fancy_Text_Print(TXT_COLOR_COLON, 1842 d_dialog_x + ((d_dialog_w / 4) * 3), 1843 d_color_y - d_txt6_h, 1844 scheme, TBLACK, 1845 TPF_CENTER | TPF_TEXT); 1846 } else { 1847 //............................................................... 1848 // If we're joined to a game, just print the player's name & side. 1849 //............................................................... 1850 #ifdef OLDWAY 1851 if (Session.House==HOUSE_GOOD) { 1852 sprintf(txt,Text_String(TXT_S_PLAYING_S),namebuf, Text_String(TXT_ALLIES)); 1853 } else { 1854 sprintf(txt,Text_String(TXT_S_PLAYING_S),namebuf, Text_String(TXT_SOVIET)); 1855 } 1856 #else //OLDWAY 1857 sprintf (txt, Text_String(TXT_S_PLAYING_S), namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); 1858 #endif //OLDWAY 1859 Fancy_Text_Print(txt,d_dialog_cx, d_dialog_y + d_margin2 + (1*RESFACTOR), 1860 (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx], 1861 TBLACK, TPF_CENTER | TPF_TEXT); 1862 } 1863 1864 //............................................................... 1865 // Rebuild the button list 1866 //............................................................... 1867 cancelbtn.Zap(); 1868 gamelist.Zap(); 1869 playerlist.Zap(); 1870 #ifdef OLDWAY 1871 gdibtn.Zap(); 1872 nodbtn.Zap(); 1873 #else 1874 housebtn.Zap(); 1875 #endif 1876 name_edt.Zap(); 1877 joinbtn.Zap(); 1878 newbtn.Zap(); 1879 countgauge.Zap(); 1880 levelgauge.Zap(); 1881 creditsgauge.Zap(); 1882 aiplayersgauge.Zap(); 1883 staticcount.Zap(); 1884 staticlevel.Zap(); 1885 staticcredits.Zap(); 1886 staticaiplayers.Zap(); 1887 1888 commands = &cancelbtn; 1889 gamelist.Add_Tail(*commands); 1890 playerlist.Add_Tail(*commands); 1891 1892 //............................................................... 1893 // Only add the name edit field, the House, Join & New buttons if 1894 // we're doing nothing, or we've just been rejected. 1895 //............................................................... 1896 if (joinstate < JOIN_CONFIRMED) { 1897 #ifdef OLDWAY 1898 gdibtn.Add_Tail(*commands); 1899 nodbtn.Add_Tail(*commands); 1900 #else 1901 housebtn.Add_Tail(*commands); 1902 #endif 1903 name_edt.Add_Tail(*commands); 1904 joinbtn.Add_Tail(*commands); 1905 newbtn.Add_Tail(*commands); 1906 } else { 1907 countgauge.Add_Tail(*commands); 1908 levelgauge.Add_Tail(*commands); 1909 creditsgauge.Add_Tail(*commands); 1910 aiplayersgauge.Add_Tail(*commands); 1911 staticcount.Add_Tail(*commands); 1912 staticlevel.Add_Tail(*commands); 1913 staticcredits.Add_Tail(*commands); 1914 staticaiplayers.Add_Tail(*commands); 1915 optionlist.Add_Tail(*commands); 1916 descrip.Add_Tail(*commands); 1917 } 1918 } 1919 1920 //.................................................................. 1921 // Redraw buttons 1922 //.................................................................. 1923 if (display >= REDRAW_BUTTONS) { 1924 aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count()); 1925 if (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) { 1926 aiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count()); 1927 } 1928 commands->Draw_All(); 1929 } 1930 1931 //.................................................................. 1932 // Draw the color boxes 1933 //.................................................................. 1934 if (display >= REDRAW_COLORS && joinstate < JOIN_CONFIRMED) { 1935 for (i = 0; i < MAX_MPLAYER_COLORS; i++) { 1936 LogicPage->Fill_Rect (cbox_x[i] + 1, d_color_y + 1, 1937 cbox_x[i] + 1 + d_color_w - 2 *RESFACTOR, d_color_y + 1 + d_color_h - 2, 1938 ColorRemaps[i].Box); 1939 // (i == PCOLOR_DIALOG_BLUE) ? ColorRemaps[PCOLOR_REALLY_BLUE].Box : ColorRemaps[i].Box); 1940 1941 if (i == Session.ColorIdx) { 1942 Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_DOWN, false); 1943 } else { 1944 Draw_Box(cbox_x[i], d_color_y, d_color_w, d_color_h, BOXSTYLE_RAISED, false); 1945 } 1946 } 1947 } 1948 1949 //.................................................................. 1950 // Draw the message system; erase old messages first 1951 //.................................................................. 1952 if (display >= REDRAW_MESSAGE) { 1953 if (joinstate==JOIN_CONFIRMED) { 1954 Draw_Box(d_message2_x, d_message2_y, d_message2_w, d_message2_h, BOXSTYLE_BOX, true); 1955 } else { 1956 Draw_Box(d_message1_x, d_message1_y, d_message1_w, d_message1_h, BOXSTYLE_BOX, true); 1957 } 1958 Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true); 1959 Session.Messages.Draw(); 1960 } 1961 1962 //.................................................................. 1963 // Redraw the game options 1964 //.................................................................. 1965 if (display >= REDRAW_PARMS && parms_received && joinstate >= JOIN_CONFIRMED) { 1966 1967 //............................................................... 1968 // Scenario title 1969 //............................................................... 1970 // LogicPage->Fill_Rect(d_dialog_x + 16 *RESFACTOR, d_name_y, d_dialog_x + d_dialog_w - 16 *RESFACTOR, d_name_y + d_txt6_h, BLACK); 1971 1972 p = Text_String(TXT_SCENARIO_COLON); 1973 if (Session.Options.ScenarioDescription[0]) { 1974 1975 // EW - Scenario language translation goes here!!!!!!!! VG 1976 int ii; 1977 for (ii = 0; EngMisStr[ii] != NULL; ii++) { 1978 if (!strcmp(Session.Options.ScenarioDescription, EngMisStr[ii])) { 1979 #if defined(GERMAN) || defined(FRENCH) 1980 sprintf(txt, "%s %s", p, EngMisStr[ii+1]); 1981 #else 1982 sprintf(txt, "%s %s", p, Session.Options.ScenarioDescription); 1983 #endif 1984 break; 1985 } 1986 } 1987 if (EngMisStr[ii] == NULL) { 1988 sprintf(txt, "%s %s", p, Session.Options.ScenarioDescription); 1989 } 1990 descrip.Set_Text(txt); 1991 1992 // sprintf(txt, "%s %s", p, Session.Options.ScenarioDescription); 1993 // descrip.Set_Text(txt); 1994 // Fancy_Text_Print("%s %s", d_dialog_cx, d_name_y, scheme, BLACK, TPF_TEXT | TPF_CENTER, p, Session.Options.ScenarioDescription); 1995 } else { 1996 sprintf(txt, "%s %s", p, Text_String(TXT_NOT_FOUND)); 1997 descrip.Set_Text(txt); 1998 // Fancy_Text_Print("%s %s", d_dialog_cx, d_name_y, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_TEXT | TPF_CENTER, p, Text_String(TXT_NOT_FOUND)); 1999 } 2000 //............................................................... 2001 // Unit count, tech level, credits, ai players 2002 //............................................................... 2003 // LogicPage->Fill_Rect(d_count_x + d_count_w + 2 *RESFACTOR, d_count_y, d_count_x + d_count_w + 35 *RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK); 2004 2005 Fancy_Text_Print(TXT_COUNT, d_count_x - 2 *RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); 2006 2007 sprintf(txt,"%d",Session.Options.UnitCount); 2008 staticcount.Set_Text(txt); 2009 staticcount.Draw_Me(); 2010 // Fancy_Text_Print(txt, d_count_x + d_count_w + 2 *RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT); 2011 2012 Fancy_Text_Print(TXT_LEVEL, d_level_x - 2 *RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); 2013 if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) { 2014 sprintf(txt,"%d",BuildLevel); 2015 } else { 2016 sprintf(txt, "**"); 2017 } 2018 staticlevel.Set_Text(txt); 2019 staticlevel.Draw_Me(); 2020 // Fancy_Text_Print(txt, d_level_x + d_level_w + 2 *RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT); 2021 2022 Fancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2 *RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); 2023 sprintf(txt,"%d",Session.Options.Credits); 2024 staticcredits.Set_Text(txt); 2025 staticcredits.Draw_Me(); 2026 // Fancy_Text_Print(txt, d_credits_x + d_credits_w + 2 *RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT); 2027 2028 Fancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2 * RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); 2029 sprintf(txt,"%d",Session.Options.AIPlayers); 2030 staticaiplayers.Set_Text(txt); 2031 staticaiplayers.Draw_Me(); 2032 // Fancy_Text_Print(txt, d_aiplayers_x + d_aiplayers_w + 2 *RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT); 2033 } 2034 2035 Show_Mouse(); 2036 display = REDRAW_NONE; 2037 } 2038 2039 //..................................................................... 2040 // Get user input 2041 //..................................................................... 2042 input = commands->Input(); 2043 2044 if (input & KN_BUTTON) { 2045 housebtn.Collapse(); 2046 display = REDRAW_BACKGROUND; 2047 } 2048 2049 //..................................................................... 2050 // Process input 2051 //..................................................................... 2052 switch (input) { 2053 2054 //.................................................................. 2055 // Mouse Click: 2056 // If we're joined to a game, display an error if the user tries to 2057 // modify a read-only control. 2058 // If user clicks on a color button: 2059 // - If we've joined a game, don't allow a new color selection 2060 // - otherwise, select that color 2061 // - Change the color of the user's name & message field to match 2062 // the newly-selected color. 2063 //.................................................................. 2064 case KN_LMOUSE: 2065 if (joinstate > JOIN_NOTHING) { 2066 if ( (Get_Mouse_X() >= d_count_x && 2067 Get_Mouse_X() <= d_count_x + d_count_w && 2068 Get_Mouse_Y() >= d_count_y && 2069 Get_Mouse_Y() <= d_aiplayers_y + d_aiplayers_h) || 2070 (Get_Mouse_X() >= d_options_x && 2071 Get_Mouse_X() <= d_options_x + d_options_w && 2072 Get_Mouse_Y() >= d_options_y && 2073 Get_Mouse_Y() <= d_options_y + d_options_h) ) { 2074 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_HOST_CAN_MODIFY), PCOLOR_BROWN, TPF_TEXT, 1200); 2075 Sound_Effect(VOC_SYS_ERROR); 2076 display = REDRAW_MESSAGE; 2077 } 2078 break; 2079 } 2080 2081 if (Keyboard->MouseQX > cbox_x[0] && 2082 Keyboard->MouseQX < (cbox_x[MAX_MPLAYER_COLORS - 1] + d_color_w) && 2083 Keyboard->MouseQY > d_color_y && 2084 Keyboard->MouseQY < (d_color_y + d_color_h)) { 2085 Session.PrefColor = (PlayerColorType) 2086 ((Keyboard->MouseQX - cbox_x[0]) / d_color_w); 2087 Session.ColorIdx = Session.PrefColor; 2088 2089 if (Session.ColorIdx == PCOLOR_DIALOG_BLUE) { 2090 name_edt.Set_Color (&ColorRemaps[PCOLOR_REALLY_BLUE]); 2091 } else { 2092 name_edt.Set_Color (&ColorRemaps[(Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? 2093 PCOLOR_REALLY_BLUE : Session.ColorIdx]); 2094 } 2095 name_edt.Flag_To_Redraw(); 2096 2097 Session.Messages.Set_Edit_Color((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? 2098 PCOLOR_REALLY_BLUE : Session.ColorIdx); 2099 2100 display = REDRAW_COLORS; 2101 } 2102 break; 2103 2104 //.................................................................. 2105 // User clicks on the game list: 2106 //.................................................................. 2107 case (BUTTON_GAMELIST | KN_BUTTON): 2108 //............................................................... 2109 // Handle a double-click 2110 //............................................................... 2111 if (lastclick_timer < 30 && gamelist.Current_Index() == lastclick_idx) { 2112 2113 //............................................................ 2114 // If we're in a game, & the item clicked on is a different 2115 // game, un-join the game we're in. 2116 //............................................................ 2117 if ((joinstate==JOIN_CONFIRMED || joinstate==JOIN_WAIT_CONFIRM) && 2118 lastclick_idx != game_index) { 2119 if (gamelist.Current_Index() == 0) { 2120 goto_lobby = 1; 2121 } else { 2122 goto_lobby = 0; 2123 } 2124 Unjoin_Game(namebuf, joinstate, &gamelist, &playerlist, 2125 game_index, goto_lobby, d_message1_x, d_message1_y, d_txt6_h, 2126 d_send_x, d_send_y, MAX_MESSAGE_LENGTH); 2127 joinstate = JOIN_NOTHING; 2128 display = REDRAW_ALL; 2129 2130 //......................................................... 2131 // Clear the Player vector & the player list box, since 2132 // our game_index has changed. 2133 //......................................................... 2134 Clear_Listbox (&playerlist); 2135 Clear_Vector (&Session.Players); 2136 game_index = gamelist.Current_Index(); 2137 } 2138 //............................................................ 2139 // If we clicked on another game, join that game. 2140 //............................................................ 2141 if (joinstate != JOIN_CONFIRMED && 2142 joinstate != JOIN_WAIT_CONFIRM && lastclick_idx > 0) { 2143 gamelist.Set_Selected_Index(lastclick_idx); 2144 game_index = lastclick_idx; 2145 name_edt.Clear_Focus(); 2146 name_edt.Flag_To_Redraw(); 2147 strcpy (Session.Handle,namebuf); 2148 #ifndef OLDWAY 2149 Session.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR); 2150 #endif 2151 join_index = gamelist.Current_Index(); 2152 parms_received = 0; 2153 if (Request_To_Join (namebuf, join_index, Session.House, 2154 Session.ColorIdx)) { 2155 joinstate = JOIN_WAIT_CONFIRM; 2156 } else { 2157 display = REDRAW_ALL; 2158 } 2159 } 2160 //............................................................ 2161 // Otherwise, we must have joined the lobby 2162 //............................................................ 2163 if (game_index == 0) { 2164 Clear_Listbox (&playerlist); 2165 Session.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14, 2166 MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1, 2167 20, MAX_MESSAGE_LENGTH - 5, d_message2_w); 2168 Session.Messages.Add_Edit ((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? 2169 PCOLOR_REALLY_BLUE : Session.ColorIdx, 2170 TPF_TEXT, NULL, '_', d_message2_w); 2171 Session.WWChat = 0; 2172 display = REDRAW_ALL; 2173 } 2174 } else { 2175 //............................................................... 2176 // Handle a single-click 2177 //............................................................... 2178 //............................................................ 2179 // If no double-click occurred, set the last-clicked index 2180 // & double-click timer. 2181 //............................................................ 2182 lastclick_timer = 0; 2183 lastclick_idx = gamelist.Current_Index(); 2184 2185 //............................................................ 2186 // If we've joined a game, don't allow the selected item to 2187 // change 2188 //............................................................ 2189 if (joinstate==JOIN_CONFIRMED || joinstate==JOIN_WAIT_CONFIRM) { 2190 gamelist.Set_Selected_Index(game_index); 2191 } 2192 2193 //............................................................ 2194 // If we're not in a game, and the user clicks on a different 2195 // entry, clear the player list & send a player query; 2196 // init the click timer, to detect a double-click of this item. 2197 //............................................................ 2198 else if (gamelist.Current_Index() != game_index) { 2199 2200 Clear_Listbox (&playerlist); 2201 Clear_Vector (&Session.Players); 2202 game_index = gamelist.Current_Index(); 2203 Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf); 2204 } 2205 } 2206 break; 2207 2208 #ifdef OLDWAY 2209 //.................................................................. 2210 // House Buttons: set the player's desired House 2211 //.................................................................. 2212 case (BUTTON_GDI | KN_BUTTON): 2213 Session.House = HOUSE_GOOD; 2214 gdibtn.Turn_On(); 2215 nodbtn.Turn_Off(); 2216 break; 2217 2218 case (BUTTON_NOD | KN_BUTTON): 2219 Session.House = HOUSE_BAD; 2220 gdibtn.Turn_Off(); 2221 nodbtn.Turn_On(); 2222 break; 2223 #else 2224 #endif 2225 2226 //.................................................................. 2227 // JOIN: send a join request packet & switch to waiting-for- 2228 // confirmation mode. 2229 //.................................................................. 2230 case (BUTTON_JOIN | KN_BUTTON): 2231 name_edt.Clear_Focus(); 2232 name_edt.Flag_To_Redraw(); 2233 strcpy (Session.Handle,namebuf); 2234 #ifndef OLDWAY 2235 Session.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR); 2236 #endif 2237 join_index = gamelist.Current_Index(); 2238 parms_received = 0; 2239 if (Request_To_Join (namebuf, join_index, Session.House, 2240 Session.ColorIdx)) { 2241 joinstate = JOIN_WAIT_CONFIRM; 2242 } else { 2243 display = REDRAW_MESSAGE; 2244 } 2245 break; 2246 2247 //.................................................................. 2248 // ESC / CANCEL: send a SIGN_OFF 2249 // - If we're part of a game, stay in this dialog; otherwise, exit 2250 //.................................................................. 2251 case (KN_ESC): 2252 case (BUTTON_CANCEL | KN_BUTTON): 2253 if (housebtn.IsDropped) { 2254 housebtn.Collapse(); 2255 } 2256 //............................................................... 2257 // If we're joined to a game, make extra sure the other players in 2258 // that game know I'm exiting; send my SIGN_OFF as an ack-required 2259 // packet. Don't send this to myself (index 0). 2260 //............................................................... 2261 if (joinstate == JOIN_CONFIRMED) { 2262 Unjoin_Game(namebuf, joinstate, &gamelist, &playerlist, 2263 game_index, 1, d_message1_x, d_message1_y, d_txt6_h, d_send_x, 2264 d_send_y, MAX_MESSAGE_LENGTH); 2265 joinstate = JOIN_NOTHING; 2266 display = REDRAW_ALL; 2267 } else { 2268 //............................................................... 2269 // If I'm not joined to a game, send a SIGN_OFF to all players 2270 // in my Chat vector (but not to myself, index 0) 2271 //............................................................... 2272 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 2273 Session.GPacket.Command = NET_SIGN_OFF; 2274 strcpy(Session.GPacket.Name,namebuf); 2275 for (i = 1; i < Session.Chat.Count(); i++) { 2276 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1, &(Session.Chat[i]->Address)); 2277 Ipx.Service(); 2278 } 2279 2280 //............................................................ 2281 // Now broadcast a SIGN_OFF just to be thorough 2282 //............................................................ 2283 Ipx.Send_Global_Message (&Session.GPacket, 2284 sizeof (GlobalPacketType), 0, NULL); 2285 if (Session.IsBridge) { 2286 Ipx.Send_Global_Message (&Session.GPacket, 2287 sizeof(GlobalPacketType), 0, &Session.BridgeNet); 2288 } 2289 2290 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 2291 2292 //............................................................ 2293 // exit the dialog 2294 //............................................................ 2295 process = false; 2296 rc = -1; 2297 } 2298 break; 2299 2300 //.................................................................. 2301 // NEW: bail out with return code 1 2302 //.................................................................. 2303 case (BUTTON_NEW | KN_BUTTON): 2304 //............................................................... 2305 // Force user to enter a name 2306 //............................................................... 2307 if (strlen(namebuf)==0) { 2308 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NAME_ERROR), PCOLOR_BROWN, TPF_TEXT, 1200); 2309 Sound_Effect(VOC_SYS_ERROR); 2310 display = REDRAW_MESSAGE; 2311 break; 2312 } 2313 2314 //............................................................... 2315 // Ensure name is unique 2316 //............................................................... 2317 found = 0; 2318 for (i = 1; i < Session.Games.Count(); i++) { 2319 if (!stricmp(Session.Games[i]->Name, namebuf)) { 2320 found = 1; 2321 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_GAMENAME_MUSTBE_UNIQUE), PCOLOR_BROWN, TPF_TEXT, 1200); 2322 Sound_Effect(VOC_SYS_ERROR); 2323 display = REDRAW_MESSAGE; 2324 break; 2325 } 2326 } 2327 2328 if (found) { 2329 break; 2330 } 2331 2332 //............................................................... 2333 // Save player & game name 2334 //............................................................... 2335 strcpy(Session.Handle,namebuf); 2336 strcpy(Session.GameName,namebuf); 2337 #ifndef OLDWAY 2338 Session.House = (HousesType)(housebtn.Current_Index()+HOUSE_USSR); 2339 #endif 2340 2341 name_edt.Clear_Focus(); 2342 name_edt.Flag_To_Redraw(); 2343 2344 rc = 1; 2345 process = false; 2346 break; 2347 2348 //.................................................................. 2349 // Default: manage the inter-player messages 2350 //.................................................................. 2351 default: 2352 if (Session.Messages.Manage()) { 2353 display = REDRAW_MESSAGE; 2354 } 2355 2356 //............................................................... 2357 // Service keyboard input for any message being edited. 2358 //............................................................... 2359 i = Session.Messages.Input(input); 2360 2361 //............................................................... 2362 // If 'Input' returned 1, it means refresh the message display. 2363 // (We have to redraw the edit line, to erase the cursor.) 2364 //............................................................... 2365 if (i==1) { 2366 Hide_Mouse(); 2367 Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, 2368 BOXSTYLE_BOX, true); 2369 Session.Messages.Draw(); 2370 Show_Mouse(); 2371 } else if (i==2) { 2372 //............................................................... 2373 // If 'Input' returned 2, it means redraw the message display. 2374 // Rather than setting 'display', which would redraw all msgs, 2375 // we only need to erase & redraw the edit box here. 2376 //............................................................... 2377 Hide_Mouse(); 2378 Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, 2379 BOXSTYLE_BOX, true); 2380 Session.Messages.Draw(); 2381 Show_Mouse(); 2382 } else if (i==3 || i==4) { 2383 //............................................................... 2384 // If 'Input' returned 3, it means send the current message. 2385 //............................................................... 2386 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 2387 Session.GPacket.Command = NET_MESSAGE; 2388 strcpy (Session.GPacket.Name, namebuf); 2389 if (i==3) { 2390 strcpy (Session.GPacket.Message.Buf, 2391 Session.Messages.Get_Edit_Buf()); 2392 } else { 2393 strcpy (Session.GPacket.Message.Buf, 2394 Session.Messages.Get_Overflow_Buf()); 2395 Session.Messages.Clear_Overflow_Buf(); 2396 } 2397 Session.GPacket.Message.Color = Session.ColorIdx; 2398 Session.GPacket.Message.NameCRC = 2399 Compute_Name_CRC(Session.GameName); 2400 2401 //............................................................ 2402 // If we're joined in a game, send the message to every player 2403 // in our player list. Skip the local system (index 0). 2404 //............................................................ 2405 if (joinstate == JOIN_CONFIRMED) { 2406 for (i = 1; i < Session.Players.Count(); i++) { 2407 Ipx.Send_Global_Message (&Session.GPacket, 2408 sizeof(GlobalPacketType), 2409 1, &(Session.Players[i]->Address)); 2410 Ipx.Service(); 2411 } 2412 } else { 2413 //............................................................ 2414 // Otherwise, send the message to all players in our chat list. 2415 //............................................................ 2416 for (i = 1; i < Session.Chat.Count(); i++) { 2417 Ipx.Send_Global_Message (&Session.GPacket, 2418 sizeof(GlobalPacketType), 2419 1, &(Session.Chat[i]->Address)); 2420 Ipx.Service(); 2421 } 2422 if (Obfuscate(Session.GPacket.Message.Buf) == 0x72A47EF6) { 2423 Session.WWChat = 1; 2424 Clear_Listbox (&playerlist); 2425 Start_WWChat(&playerlist); 2426 } 2427 } 2428 2429 //............................................................ 2430 // Add the message to our own list, since we're not in the 2431 // player list on this dialog. 2432 //............................................................ 2433 Session.Messages.Add_Message (Session.GPacket.Name, 2434 (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ? 2435 PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color, 2436 Session.GPacket.Message.Buf, 2437 (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, 2438 TPF_TEXT, -1); 2439 Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, 2440 TPF_TEXT, NULL, '_', d_message2_w); 2441 display = REDRAW_MESSAGE; 2442 } 2443 2444 #ifdef OBSOLETE 2445 // 2446 // This is for the old drop-down list of houses, not used any more. 2447 // 2448 if (housebtn.IsDropped) { 2449 isdropped = 1; 2450 } else if (isdropped) { 2451 display = REDRAW_ALL; 2452 } 2453 #endif 2454 2455 break; 2456 } 2457 2458 //..................................................................... 2459 // Resend our query packets 2460 //..................................................................... 2461 Send_Join_Queries(game_index, joinstate, 0, 0, 0, namebuf); 2462 2463 //..................................................................... 2464 // Process incoming packets 2465 //..................................................................... 2466 event = Get_Join_Responses(&joinstate, &gamelist, &playerlist, 2467 join_index, namebuf, &why); 2468 2469 //..................................................................... 2470 // If we've changed state, redraw everything; if we're starting the game, 2471 // break out of the loop. If we've just joined, send out a player query 2472 // so I'll get added to the list instantly. 2473 //..................................................................... 2474 if (event == EV_STATE_CHANGE) { 2475 display = REDRAW_ALL; 2476 2477 if (joinstate==JOIN_GAME_START || joinstate == JOIN_GAME_START_LOAD) { 2478 if (joinstate==JOIN_GAME_START_LOAD) { 2479 load_game = 1; 2480 } 2481 2482 /* 2483 ** Special new kludge for counterstrike. 2484 ** 2485 ** Find local scenario will fail to match a counterstrike mission 2486 ** unless the CS CD is in the drive. So.... 2487 ** 2488 ** If Counterstrike is installed and this is an official map and 2489 ** the file name matches a counterstrike map then tell the host 2490 ** that I have the scenario so he can continue while we make 2491 ** sure the local user has the Counterstrike CD in the drive. 2492 ** 2493 */ 2494 // This is duplicated for Aftermath scenarios. ajw 2495 2496 bool ready_packet_was_sent = false; 2497 #ifdef FIXIT_CSII // checked - ajw 9/28/98 2498 if (Session.ScenarioIsOfficial && 2499 ( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) || 2500 (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) { 2501 #else 2502 if ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) { 2503 #endif 2504 2505 CCFileClass check_file ( Session.ScenarioFileName ); 2506 if ( !check_file.Is_Available() ) { 2507 2508 int current_drive = CCFileClass::Get_CD_Drive(); 2509 #ifdef FIXIT_CSII // checked - ajw 9/28/98 2510 int index = Get_CD_Index(current_drive, 1*60); 2511 bool needcd = false; 2512 if (Is_Mission_Counterstrike(Session.ScenarioFileName)) { 2513 if (index != 2 && index != 3) { 2514 RequiredCD = 2; 2515 needcd = true; 2516 } 2517 } 2518 if (Is_Mission_Aftermath(Session.ScenarioFileName)) { 2519 if (index != 3) { 2520 RequiredCD = 3; 2521 needcd = true; 2522 } 2523 } 2524 if (needcd) { 2525 #else 2526 if ( Get_CD_Index(current_drive, 1*60) != 2 ){ 2527 RequiredCD = 2; 2528 #endif 2529 2530 /* 2531 ** We should have the scenario but the wrong disk is in. 2532 ** Tell the host that I am ready to go anyway. 2533 */ 2534 memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket)); 2535 Session.GPacket.Command = NET_READY_TO_GO; 2536 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 2537 1, &Session.HostAddress); 2538 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0); 2539 ready_packet_was_sent = true; 2540 2541 if (!Force_CD_Available (RequiredCD)){ 2542 Emergency_Exit(EXIT_FAILURE); 2543 } 2544 2545 /* 2546 ** Update the internal list of scenarios to include the counterstrike 2547 ** list. 2548 */ 2549 Session.Read_Scenario_Descriptions(); 2550 2551 } 2552 } 2553 } 2554 2555 2556 /* 2557 ** If the scenario that the host wants to play doesn't exist locally then we 2558 ** need to request that it is sent. If we can identify the scenario locally then 2559 ** we need to fix up the file name so we load the right one. 2560 */ 2561 Ipx.Set_Timing (25, (unsigned long) -1, 1000); 2562 if (Find_Local_Scenario (Session.Options.ScenarioDescription, 2563 Session.ScenarioFileName, 2564 Session.ScenarioFileLength, 2565 Session.ScenarioDigest, 2566 Session.ScenarioIsOfficial)) { 2567 2568 Session.Options.ScenarioIndex = 1; //We dont care what it 2569 //is as long as it isnt -1 2570 2571 /* 2572 ** We have the scenario. Tell the host that I am ready to go. 2573 */ 2574 if ( !ready_packet_was_sent ){ 2575 memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket)); 2576 Session.GPacket.Command = NET_READY_TO_GO; 2577 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 2578 1, &Session.HostAddress); 2579 2580 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0); 2581 } 2582 } else { 2583 #ifndef FIXIT_VERSION_3 // Removed restriction on downloading official maps. 2584 /* 2585 ** Oh dear. Thats a scenario I don't have. Request that the host sends the 2586 ** scenario to me provided it's not an official scenario. 2587 ** 2588 ** If the file is received OK then we will get a true return value and the 2589 ** actual file name to load will be in Session.ScenarioFileName 2590 */ 2591 if (Session.ScenarioIsOfficial) { 2592 Session.Options.ScenarioIndex = -1; 2593 } else { 2594 #endif 2595 Session.Options.ScenarioIndex = 1; //We dont care what it 2596 //is as long as it isnt -1 2597 #ifdef FIXIT_VERSION_3 2598 if( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) ) 2599 break; 2600 #endif 2601 2602 if (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 1)) { 2603 break; 2604 } else { 2605 /* 2606 ** Make sure we dont time-out because of the download 2607 */ 2608 } 2609 #ifndef FIXIT_VERSION_3 2610 } 2611 #endif 2612 } 2613 2614 Ipx.Set_Timing (30, (unsigned long) -1, 600); 2615 strcpy (Scen.ScenarioName, Session.ScenarioFileName); 2616 rc = 0; 2617 process = false; 2618 2619 } else if (joinstate==JOIN_CONFIRMED) { 2620 2621 //.................................................................. 2622 // If we're newly-confirmed, add myself to the Players list, and 2623 // immediately send out a player query 2624 //.................................................................. 2625 //............................................................... 2626 // Clear the player list, then add myself to the list. 2627 //............................................................... 2628 2629 Clear_Listbox(&playerlist); 2630 Clear_Vector (&Session.Players); 2631 2632 item = new char [MPLAYER_NAME_MAX + 64]; 2633 #ifdef OLDWAY 2634 if (Session.House==HOUSE_GOOD) { 2635 sprintf(item,"%s\t%s",namebuf, Text_String(TXT_ALLIES)); 2636 } else { 2637 sprintf(item,"%s\t%s",namebuf, Text_String(TXT_SOVIET)); 2638 } 2639 #else //OLDWAY 2640 sprintf (item, "%s\t%s", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); 2641 #endif //OLDWAY 2642 playerlist.Add_Item(item, 2643 (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]); 2644 2645 who = new NodeNameType; 2646 strcpy(who->Name, namebuf); 2647 who->Player.House = Session.House; 2648 who->Player.Color = Session.ColorIdx; 2649 Session.Players.Add (who); 2650 2651 2652 Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf); 2653 2654 //............................................................... 2655 // Re-init the message system to its new smaller size 2656 //............................................................... 2657 Session.Messages.Init (d_message2_x + 1 *RESFACTOR, d_message2_y + 1 *RESFACTOR, 8, 2658 MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1, 2659 20, MAX_MESSAGE_LENGTH - 5, d_message2_w); 2660 Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? 2661 PCOLOR_REALLY_BLUE : Session.ColorIdx, 2662 TPF_TEXT, NULL, '_', d_message2_w); 2663 } else if (joinstate==JOIN_REJECTED) { 2664 //.................................................................. 2665 // If we've been rejected, clear any messages we may have been 2666 // typing, add a message stating why we were rejected, and send a 2667 // chat announcement. 2668 //.................................................................. 2669 Session.Messages.Init (d_message1_x + 1 *RESFACTOR, d_message1_y + 1 *RESFACTOR, 14, 2670 MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1 *RESFACTOR, d_send_y + 1 *RESFACTOR, 1, 2671 20, MAX_MESSAGE_LENGTH - 5, d_message2_w); 2672 Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? 2673 PCOLOR_REALLY_BLUE : Session.ColorIdx, 2674 TPF_TEXT, NULL, '_', d_message2_w); 2675 2676 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_REQUEST_DENIED), PCOLOR_BROWN, TPF_TEXT, 1200); 2677 Sound_Effect(VOC_SYS_ERROR); 2678 2679 item = NULL; 2680 if (why==REJECT_DUPLICATE_NAME) { 2681 item = (char *)Text_String(TXT_NAME_MUSTBE_UNIQUE); 2682 } 2683 else if (why==REJECT_GAME_FULL) { 2684 item = (char *)Text_String(TXT_GAME_FULL); 2685 } 2686 else if (why==REJECT_VERSION_TOO_OLD) { 2687 item = (char *)Text_String(TXT_YOURGAME_OUTDATED); 2688 } 2689 else if (why==REJECT_VERSION_TOO_NEW) { 2690 item = (char *)Text_String(TXT_DESTGAME_OUTDATED); 2691 } 2692 else if (why==REJECT_MISMATCH) { 2693 item = (char *)Text_String(TXT_MISMATCH); 2694 } 2695 else if (why==REJECT_DISBANDED) { 2696 item = (char *)Text_String(TXT_GAME_CANCELLED); 2697 } 2698 if (item) { 2699 Session.Messages.Add_Message(NULL, 0, item, PCOLOR_BROWN, TPF_TEXT, 1200); 2700 } 2701 2702 Send_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf); 2703 display = REDRAW_ALL; 2704 2705 } 2706 } else if (event == EV_GAME_OPTIONS) { 2707 //..................................................................... 2708 // If the game options have changed, print them. 2709 //..................................................................... 2710 countgauge.Set_Maximum( 2711 SessionClass::CountMax[Session.Options.Bases] - 2712 SessionClass::CountMin[Session.Options.Bases]); 2713 countgauge.Set_Value(Session.Options.UnitCount - 2714 SessionClass::CountMin[Session.Options.Bases]); 2715 levelgauge.Set_Value(BuildLevel - 1); 2716 creditsgauge.Set_Value(Session.Options.Credits); 2717 if (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) { 2718 aiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count()); 2719 } else { 2720 aiplayersgauge.Set_Value(Session.Options.AIPlayers); 2721 } 2722 optionlist.Check_Item(0,Session.Options.Bases); 2723 optionlist.Check_Item(1,Session.Options.Tiberium); 2724 optionlist.Check_Item(2,Session.Options.Goodies); 2725 optionlist.Check_Item(3,Special.IsCaptureTheFlag); 2726 optionlist.Check_Item(4,Special.IsShadowGrow); 2727 optionlist.Flag_To_Redraw(); 2728 2729 Sound_Effect(VOC_OPTIONS_CHANGED); 2730 2731 parms_received = 1; 2732 display = REDRAW_PARMS; 2733 } else if (event == EV_MESSAGE) { 2734 //..................................................................... 2735 // Draw an incoming message 2736 //..................................................................... 2737 display = REDRAW_MESSAGE; 2738 Sound_Effect(VOC_INCOMING_MESSAGE); 2739 } else if (event == EV_NEW_GAME) { 2740 //..................................................................... 2741 // If a new game has formed, or an existing game has changed state 2742 // (from open to closed or closed to open), redraw the message system. 2743 //..................................................................... 2744 display = REDRAW_MESSAGE; 2745 } else if (event == EV_NEW_PLAYER || event == EV_PLAYER_SIGNOFF) { 2746 aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count()); 2747 if (Session.Options.AIPlayers > Rule.MaxPlayers-Session.Players.Count()) { 2748 aiplayersgauge.Set_Value(Rule.MaxPlayers-Session.Players.Count()); 2749 } 2750 } else if (event == EV_GAME_SIGNOFF) { 2751 2752 //..................................................................... 2753 // EV_GAME_SIGNOFF: 2754 // A game before the one I've selected is gone, so we have a new index 2755 // now. 'game_index' must be kept set to the currently-selected list 2756 // item, so we send out queries for the currently-selected game. It's 2757 // therefore imperative that we detect any changes to the game list. 2758 // If we're joined in a game, we must decrement our game_index to keep 2759 // it aligned with the game we're joined to. 2760 //..................................................................... 2761 if (joinstate==JOIN_CONFIRMED) { 2762 game_index--; 2763 join_index--; 2764 gamelist.Set_Selected_Index(join_index); 2765 } else { 2766 gamelist.Flag_To_Redraw(); 2767 Clear_Listbox(&playerlist); 2768 Clear_Vector (&Session.Players); 2769 game_index = gamelist.Current_Index(); 2770 Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf); 2771 } 2772 } 2773 2774 //..................................................................... 2775 // Service the Ipx connections 2776 //..................................................................... 2777 Ipx.Service(); 2778 2779 if (process) { 2780 //..................................................................... 2781 // Clean out the Game List; if an old entry is found: 2782 // - Remove it 2783 // - Clear the player list 2784 // - Send queries for the new selected game, if there is one 2785 //..................................................................... 2786 for (i = 1; i < Session.Games.Count(); i++) { 2787 if (TickCount - Session.Games[i]->Game.LastTime > 400) { 2788 2789 delete Session.Games[i]; 2790 Session.Games.Delete(Session.Games[i]); 2791 2792 item = (char *)(gamelist.Get_Item (i)); 2793 gamelist.Remove_Item (item); 2794 delete [] item; 2795 2796 gamelist.Flag_To_Redraw(); 2797 2798 if (i <= game_index) { 2799 if (joinstate==JOIN_CONFIRMED) { 2800 game_index--; 2801 join_index--; 2802 gamelist.Set_Selected_Index(join_index); 2803 } else { 2804 gamelist.Flag_To_Redraw(); 2805 Clear_Listbox(&playerlist); 2806 Clear_Vector (&Session.Players); 2807 game_index = gamelist.Current_Index(); 2808 Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf); 2809 } 2810 } 2811 } 2812 } 2813 2814 //..................................................................... 2815 // If I've changed my name or color, make sure those changes go into 2816 // the Chat vector. 2817 //..................................................................... 2818 strcpy(Session.Chat[0]->Name, namebuf); 2819 Session.Chat[0]->Chat.Color = Session.ColorIdx; 2820 if (Session.Chat[0]->Chat.Color == PCOLOR_DIALOG_BLUE) { 2821 Session.Chat[0]->Chat.Color = PCOLOR_REALLY_BLUE; 2822 } 2823 2824 //..................................................................... 2825 // Clean out the chat vector. If we find a node that we haven't heard 2826 // from in 6 seconds, delete that node. 2827 // If we haven't heard from a node in 5 seconds, send him a request 2828 // for a chat announcement; he then has 1 second to reply. 2829 //..................................................................... 2830 for (i = 1; i < Session.Chat.Count(); i++) { 2831 if (TickCount - Session.Chat[i]->Chat.LastTime > 360) { 2832 delete Session.Chat[i]; 2833 Session.Chat.Delete(Session.Chat[i]); 2834 } else if (TickCount - Session.Chat[i]->Chat.LastTime > 300 && 2835 Session.Chat[i]->Chat.LastChance == 0) { 2836 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 2837 Session.GPacket.Name[0] = 0; 2838 Session.GPacket.Command = NET_CHAT_REQUEST; 2839 Ipx.Send_Global_Message (&Session.GPacket, 2840 sizeof(GlobalPacketType), 0, &(Session.Chat[i]->Address)); 2841 Ipx.Service(); 2842 Session.Chat[i]->Chat.LastChance = 1; 2843 } 2844 } 2845 2846 //..................................................................... 2847 // Manage the Lobby list: 2848 // If the user has selected the 1st Game ("Lobby"), the names of all 2849 // users in the Chat area show up in the Players list box. 2850 // Users can be changing their names and their colors at any time, so 2851 // we scan the Chat list each time to see if anything's changed; if 2852 // so, we redraw the player list. 2853 // (If WWChat is on, the Chat list is ignored, and the playerlist 2854 // contains custom names.) 2855 //..................................................................... 2856 if (game_index == 0) { 2857 if (!Session.WWChat) { 2858 while (Session.Chat.Count() > playerlist.Count()) { 2859 item = new char [MPLAYER_NAME_MAX]; 2860 item[0] = 0; 2861 playerlist.Add_Item(item); 2862 playerlist.Flag_To_Redraw(); 2863 } 2864 while (playerlist.Count() > Session.Chat.Count()) { 2865 item = (char *)playerlist.Get_Item(0); 2866 playerlist.Remove_Item(item); 2867 delete [] item; 2868 playerlist.Flag_To_Redraw(); 2869 } 2870 for (i = 0; i < Session.Chat.Count(); i++) { 2871 if (stricmp(Session.Chat[i]->Name,playerlist.Get_Item(i)) || 2872 &ColorRemaps[ (Session.Chat[i]->Chat.Color == PCOLOR_DIALOG_BLUE) ? 2873 PCOLOR_REALLY_BLUE : Session.Chat[i]->Chat.Color] != 2874 playerlist.Colors[i]) { 2875 2876 playerlist.Colors[i] = 2877 &ColorRemaps[Session.Chat[i]->Chat.Color]; 2878 if (playerlist.Colors[i] == &ColorRemaps[PCOLOR_DIALOG_BLUE]) { 2879 playerlist.Colors[i] = &ColorRemaps[PCOLOR_REALLY_BLUE]; 2880 } 2881 strcpy((char *)playerlist.Get_Item(i), Session.Chat[i]->Name); 2882 playerlist.Flag_To_Redraw(); 2883 } 2884 } 2885 } else { 2886 if (stricmp(Session.Chat[0]->Name,playerlist.Get_Item(0)) || 2887 &ColorRemaps[Session.Chat[0]->Chat.Color] != 2888 playerlist.Colors[0]) { 2889 playerlist.Colors[0] = &ColorRemaps[Session.Chat[0]->Chat.Color]; 2890 strcpy((char *)playerlist.Get_Item(0), Session.Chat[0]->Name); 2891 playerlist.Flag_To_Redraw(); 2892 } 2893 if (Update_WWChat()) { 2894 display = REDRAW_MESSAGE; 2895 } 2896 } 2897 } 2898 2899 } 2900 //..................................................................... 2901 // Service the sounds & score; GameActive must be false at this point, 2902 // so Call_Back() doesn't intercept global messages from me! 2903 //..................................................................... 2904 Call_Back(); 2905 2906 } // end of while 2907 2908 2909 //------------------------------------------------------------------------ 2910 // Establish connections with all other players. 2911 //------------------------------------------------------------------------ 2912 if (rc == 0) { 2913 //..................................................................... 2914 // If the other guys are playing a scenario I don't have (sniff), I can't 2915 // play. Try to bail gracefully. 2916 //..................................................................... 2917 if (Session.Options.ScenarioIndex==-1) { 2918 WWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH); 2919 2920 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 2921 2922 Session.GPacket.Command = NET_SIGN_OFF; 2923 strcpy (Session.GPacket.Name, namebuf); 2924 2925 //.................................................................. 2926 // Don't send myself the message. 2927 //.................................................................. 2928 for (i = 1; i < Session.Players.Count(); i++) { 2929 Ipx.Send_Global_Message (&Session.GPacket, 2930 sizeof(GlobalPacketType), 1, 2931 &(Session.Players[i]->Address)); 2932 Ipx.Service(); 2933 } 2934 2935 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 2936 0, NULL); 2937 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 2938 0, NULL); 2939 2940 if (Session.IsBridge) { 2941 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 2942 0, &Session.BridgeNet); 2943 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 2944 0, &Session.BridgeNet); 2945 } 2946 2947 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 2948 2949 rc = -1; 2950 2951 } else { 2952 2953 //--------------------------------------------------------------------- 2954 // Prepare to load the scenario. 2955 //--------------------------------------------------------------------- 2956 //.................................................................. 2957 // Set the number of players in this game, and the scenario number. 2958 //.................................................................. 2959 Session.NumPlayers = Session.Players.Count(); 2960 } 2961 2962 //..................................................................... 2963 // Wait a while, polling the IPX service routines, to give our ACK 2964 // a chance to get to the other system. If he doesn't get our ACK, 2965 // he'll be waiting the whole time we load MIX files. 2966 //..................................................................... 2967 i = max(Ipx.Global_Response_Time() * 2, 60); 2968 starttime = TickCount; 2969 while (TickCount - starttime < (unsigned)i) { 2970 Ipx.Service(); 2971 } 2972 } 2973 2974 //------------------------------------------------------------------------ 2975 // Init network timing values, using previous response times as a measure 2976 // of what our retry delta & timeout should be. 2977 //------------------------------------------------------------------------ 2978 // Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1, 2979 // Ipx.Global_Response_Time() * 4); 2980 Ipx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8)); 2981 2982 2983 //------------------------------------------------------------------------ 2984 // Clear all lists, but NOT the Games & Players vectors. 2985 //------------------------------------------------------------------------ 2986 Clear_Listbox(&gamelist); 2987 Clear_Listbox(&playerlist); 2988 2989 //------------------------------------------------------------------------ 2990 // Remove the chat edit box 2991 //------------------------------------------------------------------------ 2992 Session.Messages.Remove_Edit(); 2993 2994 //------------------------------------------------------------------------ 2995 // Restore screen 2996 //------------------------------------------------------------------------ 2997 Hide_Mouse(); 2998 Load_Title_Page(true); 2999 Show_Mouse(); 3000 3001 //------------------------------------------------------------------------ 3002 // Load a game if the game owner told us to 3003 //------------------------------------------------------------------------ 3004 if (load_game) { 3005 if (!Load_Game (-1)) { 3006 WWMessageBox().Process (TXT_ERROR_LOADING_GAME); 3007 rc = -1; 3008 } 3009 Frame++; 3010 } 3011 3012 //------------------------------------------------------------------------ 3013 // Clear the Players & Games vectors if we're not joined to a game. 3014 // Clear the Chat vector regardless. 3015 //------------------------------------------------------------------------ 3016 if (rc != 0) { 3017 Clear_Vector(&Session.Games); 3018 Clear_Vector(&Session.Players); 3019 } 3020 Clear_Vector(&Session.Chat); 3021 3022 return(rc); 3023 3024 } /* end of Net_Join_Dialog */ 3025 3026 3027 /*************************************************************************** 3028 * Request_To_Join -- Sends a JOIN request packet to game owner * 3029 * * 3030 * Regardless of the return code, the Join Dialog will need to be redrawn * 3031 * after calling this routine. * 3032 * * 3033 * INPUT: * 3034 * playername player's name * 3035 * join_index index of game we're joining * 3036 * house requested house * 3037 * color requested color * 3038 * * 3039 * OUTPUT: * 3040 * 1 = Packet sent, 0 = wasn't * 3041 * * 3042 * WARNINGS: * 3043 * none. * 3044 * * 3045 * HISTORY: * 3046 *=========================================================================*/ 3047 static int Request_To_Join (char *playername, int join_index, 3048 HousesType house, PlayerColorType color) 3049 { 3050 //------------------------------------------------------------------------ 3051 // Validate join_index 3052 //------------------------------------------------------------------------ 3053 if (join_index < 1) { 3054 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_MUST_SELECT_GAME), PCOLOR_BROWN, TPF_TEXT, 1200); 3055 Sound_Effect(VOC_SYS_ERROR); 3056 return(false); 3057 } 3058 if ( (Session.Games.Count()<=1) || join_index > Session.Games.Count()) { 3059 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NOTHING_TO_JOIN), PCOLOR_BROWN, TPF_TEXT, 1200); 3060 Sound_Effect(VOC_SYS_ERROR); 3061 return(false); 3062 } 3063 3064 //------------------------------------------------------------------------ 3065 // Force user to enter a name 3066 //------------------------------------------------------------------------ 3067 if (strlen(playername)==0) { 3068 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_NAME_ERROR), PCOLOR_BROWN, TPF_TEXT, 1200); 3069 Sound_Effect(VOC_SYS_ERROR); 3070 return(false); 3071 } 3072 3073 //------------------------------------------------------------------------ 3074 // The game must be open 3075 //------------------------------------------------------------------------ 3076 if (!Session.Games[join_index]->Game.IsOpen) { 3077 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_GAME_IS_CLOSED), PCOLOR_BROWN, TPF_TEXT, 1200); 3078 Sound_Effect(VOC_SYS_ERROR); 3079 return (false); 3080 } 3081 3082 //------------------------------------------------------------------------ 3083 // Send packet to game's owner 3084 //------------------------------------------------------------------------ 3085 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 3086 3087 Session.GPacket.Command = NET_QUERY_JOIN; 3088 strcpy (Session.GPacket.Name, playername); 3089 Session.GPacket.PlayerInfo.House = house; 3090 Session.GPacket.PlayerInfo.Color = color; 3091 #ifdef FIXIT_VERSION_3 3092 // Guest sends host his version. 3093 // Added to the transmitted _min_ version number is a bit indicating presence of Aftermath expansion. 3094 if( Is_Aftermath_Installed() ) 3095 { 3096 // debugprint( "Guest tells host 'I have Aftermath'\n" ); 3097 Session.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version() | 0x80000000; 3098 } 3099 else 3100 { 3101 // debugprint( "Guest tells host 'I don't have Aftermath'\n" ); 3102 Session.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version(); 3103 } 3104 #else 3105 Session.GPacket.PlayerInfo.MinVersion = VerNum.Min_Version(); 3106 #endif 3107 Session.GPacket.PlayerInfo.MaxVersion = VerNum.Max_Version(); 3108 Session.GPacket.PlayerInfo.CheatCheck = RuleINI.Get_Unique_ID(); 3109 3110 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1, 3111 &(Session.Games[join_index]->Address)); 3112 3113 return(true); 3114 3115 } /* end of Request_To_Join */ 3116 3117 3118 /*************************************************************************** 3119 * Unjoin_Game -- Cancels joining a game * 3120 * * 3121 * INPUT: * 3122 * namebuf current player name * 3123 * joinstate current join state * 3124 * gamelist ListBox of game names * 3125 * playerlist ListBox of player names * 3126 * game_index index in 'gamelist' of game we're leaving * 3127 * goto_lobby true = we're going to the lobby * 3128 * msg_x message system x-coord * 3129 * msg_y message system y-coord * 3130 * msg_h message system char height * 3131 * send_x message system send x-coord * 3132 * send_y message system send y-coord * 3133 * msg_len message system max msg length * 3134 * * 3135 * OUTPUT: * 3136 * * 3137 * WARNINGS: * 3138 * * 3139 * HISTORY: * 3140 * 12/12/1995 BRR : Created. * 3141 *=========================================================================*/ 3142 static void Unjoin_Game(char *namebuf,JoinStateType joinstate, 3143 ListClass *gamelist, ColorListClass *playerlist, int game_index, 3144 int goto_lobby, int msg_x, int msg_y, int msg_h, int send_x, int send_y, 3145 int msg_len) 3146 { 3147 int i; 3148 char *item; 3149 3150 //------------------------------------------------------------------------ 3151 // Fill in a SIGN_OFF packet 3152 //------------------------------------------------------------------------ 3153 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 3154 Session.GPacket.Command = NET_SIGN_OFF; 3155 strcpy(Session.GPacket.Name,namebuf); 3156 3157 //------------------------------------------------------------------------ 3158 // If we're joined to a game, make extra sure the other players in 3159 // that game know I'm exiting; send my SIGN_OFF as an ack-required 3160 // packet. Don't send this to myself (index 0). 3161 //------------------------------------------------------------------------ 3162 for (i = 1; i < Session.Players.Count(); i++) { 3163 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1, 3164 &(Session.Players[i]->Address)); 3165 Ipx.Service(); 3166 } 3167 3168 if (joinstate == JOIN_WAIT_CONFIRM || joinstate == JOIN_CONFIRMED) { 3169 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 1, 3170 &(Session.Games[game_index]->Address)); 3171 } 3172 3173 //------------------------------------------------------------------------ 3174 // Re-init the message system to its new larger size 3175 //------------------------------------------------------------------------ 3176 Session.Messages.Init (msg_x + 1, msg_y + 1, 14, 3177 msg_len, msg_h, send_x + 1, send_y + 1, 1, 3178 20, msg_len - 5); 3179 Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? 3180 PCOLOR_REALLY_BLUE : Session.ColorIdx, 3181 TPF_TEXT, NULL, '_'); 3182 3183 //------------------------------------------------------------------------ 3184 // Remove myself from the player list, and reset my game name 3185 //------------------------------------------------------------------------ 3186 if (playerlist->Count()) { 3187 item = (char *)(playerlist->Get_Item(0)); 3188 playerlist->Remove_Item(item); 3189 delete [] item; 3190 playerlist->Flag_To_Redraw(); 3191 } 3192 3193 if (Session.Players.Count() > 0) { 3194 delete Session.Players[0]; 3195 Session.Players.Delete(Session.Players[0]); 3196 } 3197 3198 Session.GameName[0] = 0; 3199 3200 //------------------------------------------------------------------------ 3201 // Highlight "Lobby" on the Game list, Announce I'm ready to chat 3202 //------------------------------------------------------------------------ 3203 if (goto_lobby) { 3204 gamelist->Set_Selected_Index(0); 3205 Send_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf); 3206 } 3207 3208 } // end of Unjoin_Game 3209 3210 3211 /*********************************************************************************************** 3212 * Send_Join_Queries -- sends queries for the Join Dialog * 3213 * * 3214 * This routine [re]sends the queries related to the Join Dialog: * 3215 * - NET_QUERY_GAME * 3216 * - NET_QUERY_PLAYER for the game currently selected (if there is one) * 3217 * * 3218 * The queries are "staggered" in time so they aren't all sent at once; otherwise, we'd * 3219 * be inundated with reply packets & we'd miss some (even though the replies will require * 3220 * ACK's). * 3221 * * 3222 * INPUT: * 3223 * curgame index of currently-selected game; -1 = none * 3224 * joinstate our current joinstate * 3225 * gamenow if 1, will immediately send the game query * 3226 * playernow if 1, will immediately send the player query for currently-selected game * 3227 * chatnow if 1, will immediately send the chat announcement * 3228 * myname user's name * 3229 * init initialize the timers * 3230 * * 3231 * OUTPUT: * 3232 * none. * 3233 * * 3234 * WARNINGS: * 3235 * none. * 3236 * * 3237 * HISTORY: * 3238 * 02/14/1995 BR : Created. * 3239 * 04/15/1995 BRR : Created. * 3240 *=============================================================================================*/ 3241 static void Send_Join_Queries(int curgame, JoinStateType joinstate, 3242 int gamenow, int playernow, int chatnow, char *myname, int init) 3243 { 3244 //........................................................................ 3245 // These values control the timeouts for sending various types of packets; 3246 // they're designed such that they'll rarely occur simultaneously. 3247 //........................................................................ 3248 enum { 3249 GAME_QUERY_TIME = 120, 3250 PLAYER_QUERY_TIME = 35, 3251 CHAT_ANNOUNCE_TIME = 83, 3252 }; 3253 static CDTimerClass<SystemTimerClass> game_timer; // time between NET_QUERY_GAME's 3254 static CDTimerClass<SystemTimerClass> player_timer; // time between NET_QUERY_PLAYERS's 3255 static CDTimerClass<SystemTimerClass> chat_timer; // time between NET_CHAT_ANNOUNCE's 3256 3257 3258 //------------------------------------------------------------------------ 3259 // Initialize timers 3260 //------------------------------------------------------------------------ 3261 if (init) { 3262 game_timer = GAME_QUERY_TIME; 3263 player_timer = PLAYER_QUERY_TIME; 3264 chat_timer = CHAT_ANNOUNCE_TIME; 3265 } 3266 3267 //------------------------------------------------------------------------ 3268 // Send the game-name query if the time has expired, or we're told to do 3269 // it right now 3270 //------------------------------------------------------------------------ 3271 if (!game_timer || gamenow) { 3272 3273 game_timer = GAME_QUERY_TIME; 3274 3275 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 3276 3277 Session.GPacket.Command = NET_QUERY_GAME; 3278 3279 Ipx.Send_Global_Message (&Session.GPacket, 3280 sizeof(GlobalPacketType), 0, NULL); 3281 3282 //..................................................................... 3283 // If the user specified a remote server address, broadcast over that 3284 // network, too. 3285 //..................................................................... 3286 if (Session.IsBridge) { 3287 Ipx.Send_Global_Message (&Session.GPacket, 3288 sizeof(GlobalPacketType), 0, &Session.BridgeNet); 3289 } 3290 } 3291 3292 //------------------------------------------------------------------------ 3293 // Send the player query for the game currently clicked on, if the time has 3294 // expired and there is a currently-selected game, or we're told to do it 3295 // right now 3296 //------------------------------------------------------------------------ 3297 if ( ((curgame > 0) && (curgame < Session.Games.Count()) && 3298 !player_timer) || playernow) { 3299 3300 player_timer = PLAYER_QUERY_TIME; 3301 3302 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 3303 3304 Session.GPacket.Command = NET_QUERY_PLAYER; 3305 strcpy (Session.GPacket.Name, Session.Games[curgame]->Name); 3306 3307 Ipx.Send_Global_Message (&Session.GPacket, 3308 sizeof(GlobalPacketType), 0, NULL); 3309 3310 //..................................................................... 3311 // If the user specified a remote server address, broadcast over that 3312 // network, too. 3313 //..................................................................... 3314 if (Session.IsBridge) { 3315 Ipx.Send_Global_Message (&Session.GPacket, 3316 sizeof(GlobalPacketType), 0, &Session.BridgeNet); 3317 } 3318 } 3319 3320 //------------------------------------------------------------------------ 3321 // Send the chat announcement 3322 //------------------------------------------------------------------------ 3323 if ((!chat_timer && joinstate!=JOIN_CONFIRMED) || chatnow) { 3324 3325 chat_timer = CHAT_ANNOUNCE_TIME; 3326 3327 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 3328 3329 Session.GPacket.Command = NET_CHAT_ANNOUNCE; 3330 strcpy (Session.GPacket.Name, myname); 3331 Session.GPacket.Chat.ID = Session.UniqueID; 3332 Session.GPacket.Chat.Color = Session.ColorIdx; 3333 3334 Ipx.Send_Global_Message (&Session.GPacket, 3335 sizeof(GlobalPacketType), 0, NULL); 3336 3337 if (Session.IsBridge) { 3338 Ipx.Send_Global_Message (&Session.GPacket, 3339 sizeof(GlobalPacketType), 0, &Session.BridgeNet); 3340 } 3341 } 3342 3343 } /* end of Send_Join_Queries */ 3344 3345 3346 /*********************************************************************************************** 3347 * Get_Join_Responses -- sends queries for the Join Dialog * 3348 * * 3349 * This routine polls the Global Channel to see if there are any incoming packets; * 3350 * if so, it processes them. This routine can change the state of the Join Dialog, or * 3351 * the contents of the list boxes, based on what the packet is. * 3352 * * 3353 * The list boxes are passed in as pointers; they can't be made globals, because they * 3354 * can't be constructed, because they require shape pointers to the arrow buttons, and * 3355 * the mix files won't have been initialized when the global variables' constructors are * 3356 * called. * 3357 * * 3358 * This routine sets the globals * 3359 * Session.House (from NET_CONFIRM_JOIN) * 3360 * Session.ColorIdx (from NET_CONFIRM_JOIN) * 3361 * Session.Options.Bases (from NET_GAME_OPTIONS) * 3362 * Session.Options.Tiberium (from NET_GAME_OPTIONS) * 3363 * Session.Options.Goodies (from NET_GAME_OPTIONS) * 3364 * Session.Options.Ghosts (from NET_GAME_OPTIONS) * 3365 * ScenarioIdx (from NET_GAME_OPTIONS; -1 = scenario not found) * 3366 * * 3367 * INPUT: * 3368 * joinstate current state of Join Dialog * 3369 * gamelist list box containing game names * 3370 * playerlist list box containing player names for the currently-selected game * 3371 * join_index index of the game we've joined or are asking to join * 3372 * my_name name of local system * 3373 * why ptr: filled in with reason for rejection from a game * 3374 * * 3375 * OUTPUT: * 3376 * Event that occurred * 3377 * * 3378 * WARNINGS: * 3379 * none. * 3380 * * 3381 * HISTORY: * 3382 * 02/14/1995 BR : Created. * 3383 * 04/15/1995 BRR : Created. * 3384 *=============================================================================================*/ 3385 static JoinEventType Get_Join_Responses(JoinStateType *joinstate, ListClass *gamelist, 3386 ColorListClass *playerlist, int join_index, char *my_name, RejectType *why) 3387 { 3388 int rc; 3389 char * item; // general-purpose string 3390 NodeNameType *who; // node to add to Games or Players 3391 int i; 3392 int found; 3393 JoinEventType retcode = EV_NONE; 3394 char txt[80]; 3395 3396 //------------------------------------------------------------------------ 3397 // If there is no incoming packet, just return 3398 //------------------------------------------------------------------------ 3399 rc = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen, 3400 &Session.GAddress, &Session.GProductID); 3401 if (!rc || Session.GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER0) 3402 return(EV_NONE); 3403 3404 //------------------------------------------------------------------------ 3405 // If we're joined in a game, handle the packet in a standard way; otherwise, 3406 // don't answer standard queries. 3407 //------------------------------------------------------------------------ 3408 if ( (*joinstate)==JOIN_CONFIRMED && 3409 Process_Global_Packet(&Session.GPacket,&Session.GAddress)!=0) { 3410 return(EV_NONE); 3411 } 3412 3413 //------------------------------------------------------------------------ 3414 // NET_ANSWER_GAME: Another system is answering our GAME query, so add that 3415 // system to our list box if it's new. 3416 //------------------------------------------------------------------------ 3417 if (Session.GPacket.Command==NET_ANSWER_GAME) { 3418 3419 //..................................................................... 3420 // See if this name is unique 3421 //..................................................................... 3422 retcode = EV_NONE; 3423 found = 0; 3424 for (i = 1; i < Session.Games.Count(); i++) { 3425 if (!strcmp(Session.Games[i]->Name, Session.GPacket.Name)) { 3426 found = 1; 3427 3428 //............................................................... 3429 // If name was found, update the node's time stamp & IsOpen flag. 3430 //............................................................... 3431 Session.Games[i]->Game.LastTime = TickCount; 3432 if (Session.Games[i]->Game.IsOpen != Session.GPacket.GameInfo.IsOpen) { 3433 item = (char *)gamelist->Get_Item(i); 3434 if (Session.GPacket.GameInfo.IsOpen) { 3435 sprintf(item,Text_String(TXT_THATGUYS_GAME), 3436 Session.GPacket.Name); 3437 } 3438 else { 3439 sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET), 3440 Session.GPacket.Name); 3441 } 3442 Session.Games[i]->Game.IsOpen = Session.GPacket.GameInfo.IsOpen; 3443 gamelist->Flag_To_Redraw(); 3444 3445 //............................................................ 3446 // If this game has gone from closed to open, copy the 3447 // responder's address into our Game slot, since the guy 3448 // responding to this must be game owner. 3449 //............................................................ 3450 if (Session.Games[i]->Game.IsOpen) { 3451 Session.Games[i]->Address = Session.GAddress; 3452 } 3453 3454 //............................................................ 3455 // If we're in chat mode, print a message that the state of 3456 // this game has changed. 3457 //............................................................ 3458 if (*joinstate < JOIN_CONFIRMED) { 3459 if (Session.Games[i]->Game.IsOpen) { 3460 sprintf(txt,Text_String(TXT_S_FORMED_NEW_GAME), 3461 Session.Games[Session.Games.Count()-1]->Name); 3462 Sound_Effect(VOC_GAME_FORMING); 3463 } 3464 else { 3465 sprintf(txt,Text_String(TXT_GAME_NOW_IN_PROGRESS), 3466 Session.Games[Session.Games.Count()-1]->Name); 3467 Sound_Effect(VOC_GAME_CLOSED); 3468 } 3469 Session.Messages.Add_Message(NULL, 0, txt, PCOLOR_BROWN, TPF_TEXT, 1200); 3470 retcode = EV_NEW_GAME; 3471 } 3472 } 3473 break; 3474 } 3475 } 3476 3477 //..................................................................... 3478 // name not found (or addresses are different); add it to 'Games' 3479 //..................................................................... 3480 if (found==0) { 3481 3482 //.................................................................. 3483 // Create a new node structure, fill it in, add it to 'Games' 3484 //.................................................................. 3485 who = new NodeNameType; 3486 strcpy(who->Name, Session.GPacket.Name); 3487 who->Address = Session.GAddress; 3488 who->Game.IsOpen = Session.GPacket.GameInfo.IsOpen; 3489 who->Game.LastTime = TickCount; 3490 Session.Games.Add (who); 3491 3492 //.................................................................. 3493 // Create a string for "xxx's Game", leaving room for brackets around 3494 // the string if it's a closed game 3495 //.................................................................. 3496 item = new char [MPLAYER_NAME_MAX + 64]; 3497 if (Session.GPacket.GameInfo.IsOpen) { 3498 sprintf(item,Text_String(TXT_THATGUYS_GAME),Session.GPacket.Name); 3499 } 3500 else { 3501 sprintf(item,Text_String(TXT_THATGUYS_GAME_BRACKET), 3502 Session.GPacket.Name); 3503 } 3504 gamelist->Add_Item(item); 3505 3506 //.................................................................. 3507 // If this player's in the Chat vector, remove him from there 3508 //.................................................................. 3509 for (i = 1; i < Session.Chat.Count(); i++) { 3510 if (Session.Chat[i]->Address==Session.GAddress) { 3511 delete Session.Chat[i]; 3512 Session.Chat.Delete(Session.Chat[i]); 3513 break; 3514 } 3515 } 3516 3517 //.................................................................. 3518 // If this game is open, display a message stating that it's 3519 // now available. 3520 //.................................................................. 3521 if (Session.GPacket.GameInfo.IsOpen && (*joinstate) < JOIN_CONFIRMED) { 3522 sprintf(txt,Text_String(TXT_S_FORMED_NEW_GAME), 3523 Session.GPacket.Name); 3524 Session.Messages.Add_Message(NULL, 0, txt, PCOLOR_BROWN, TPF_TEXT, 1200); 3525 Sound_Effect(VOC_GAME_FORMING); 3526 } 3527 3528 retcode = EV_NEW_GAME; 3529 } 3530 } 3531 3532 //------------------------------------------------------------------------ 3533 // NET_ANSWER_PLAYER: Another system is answering our PLAYER query, so add 3534 // it to our player list box & the Player Vector if it's new 3535 //------------------------------------------------------------------------ 3536 else if (Session.GPacket.Command==NET_ANSWER_PLAYER) { 3537 //..................................................................... 3538 // See if this name is unique 3539 //..................................................................... 3540 retcode = EV_NONE; 3541 found = 0; 3542 for (i = 0; i < Session.Players.Count(); i++) { 3543 3544 //.................................................................. 3545 // If the address is already present, re-copy their name, color & 3546 // house into the existing entry, in case they've changed it without 3547 // our knowledge; set the 'found' flag so we won't create a new entry. 3548 //.................................................................. 3549 if (Session.Players[i]->Address==Session.GAddress) { 3550 strcpy(Session.Players[i]->Name, Session.GPacket.Name); 3551 Session.Players[i]->Player.House = Session.GPacket.PlayerInfo.House; 3552 Session.Players[i]->Player.Color = Session.GPacket.PlayerInfo.Color; 3553 3554 playerlist->Colors[i] = 3555 &ColorRemaps[Session.GPacket.PlayerInfo.Color]; 3556 3557 if (playerlist->Colors[i] == &ColorRemaps[PCOLOR_DIALOG_BLUE]) { 3558 playerlist->Colors[i] = &ColorRemaps[PCOLOR_REALLY_BLUE]; 3559 } 3560 3561 found = 1; 3562 break; 3563 } 3564 } 3565 3566 //..................................................................... 3567 // Don't add this player if he's not part of the game that's selected. 3568 //..................................................................... 3569 i = gamelist->Current_Index(); 3570 if (Session.Games.Count() && Session.GPacket.PlayerInfo.NameCRC != 3571 Compute_Name_CRC(Session.Games[i]->Name)) { 3572 found = 1; 3573 } 3574 3575 //..................................................................... 3576 // Don't add this player if it's myself. (We must check the name 3577 // since the address of myself in 'Players' won't be valid.) 3578 //..................................................................... 3579 if (!strcmp (my_name,Session.GPacket.Name)) { 3580 found = 1; 3581 } 3582 3583 //..................................................................... 3584 // name not found, or address didn't match; add to player list box 3585 // & Players Vector 3586 //..................................................................... 3587 if (found==0) { 3588 //.................................................................. 3589 // Create & add a node to the Vector 3590 //.................................................................. 3591 who = new NodeNameType; 3592 strcpy(who->Name, Session.GPacket.Name); 3593 who->Address = Session.GAddress; 3594 who->Player.House = Session.GPacket.PlayerInfo.House; 3595 who->Player.Color = Session.GPacket.PlayerInfo.Color; 3596 Session.Players.Add (who); 3597 3598 //.................................................................. 3599 // Create & add a string to the list box 3600 //.................................................................. 3601 item = new char [MPLAYER_NAME_MAX + 64]; 3602 #ifdef OLDWAY 3603 if (Session.GPacket.PlayerInfo.House==HOUSE_GOOD) { 3604 sprintf(item,"%s\t%s",Session.GPacket.Name, Text_String(TXT_ALLIES)); 3605 } else { 3606 sprintf(item,"%s\t%s",Session.GPacket.Name, Text_String(TXT_SOVIET)); 3607 } 3608 #else //OLDWAY 3609 sprintf (item, "%s\t%s", Session.GPacket.Name, Text_String(HouseTypeClass::As_Reference(Session.GPacket.PlayerInfo.House).Full_Name())); 3610 #endif //OLDWAY 3611 playerlist->Add_Item(item, 3612 (who->Player.Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[who->Player.Color]); 3613 3614 //.................................................................. 3615 // If this player's in the Chat vector, remove him from there 3616 //.................................................................. 3617 for (i = 1; i < Session.Chat.Count(); i++) { 3618 if (Session.Chat[i]->Address==Session.GAddress) { 3619 delete Session.Chat[i]; 3620 Session.Chat.Delete(Session.Chat[i]); 3621 break; 3622 } 3623 } 3624 3625 //.................................................................. 3626 // If this player has joined our game, play a special sound. 3627 //.................................................................. 3628 if ((*joinstate)>=JOIN_CONFIRMED) { 3629 Sound_Effect(VOC_PLAYER_JOINED); 3630 } 3631 3632 retcode = EV_NEW_PLAYER; 3633 } 3634 } 3635 3636 //------------------------------------------------------------------------ 3637 // NET_CONFIRM_JOIN: The game owner has confirmed our JOIN query; mark us 3638 // as being confirmed, and start answering queries from other systems 3639 //------------------------------------------------------------------------ 3640 else if (Session.GPacket.Command==NET_CONFIRM_JOIN) { 3641 if ( (*joinstate) != JOIN_CONFIRMED) { 3642 strcpy (Session.GameName, Session.GPacket.Name); 3643 Session.House = Session.GPacket.PlayerInfo.House; 3644 Session.ColorIdx = Session.GPacket.PlayerInfo.Color; 3645 3646 (*joinstate) = JOIN_CONFIRMED; 3647 retcode = EV_STATE_CHANGE; 3648 } 3649 } 3650 3651 //------------------------------------------------------------------------ 3652 // NET_REJECT_JOIN: The game owner has turned down our JOIN query; restore 3653 // the dialog state to its first pop-up state. 3654 //------------------------------------------------------------------------ 3655 else if (Session.GPacket.Command==NET_REJECT_JOIN) { 3656 //..................................................................... 3657 // If we're confirmed in a game, broadcast a sign-off to tell all other 3658 // systems that I'm no longer a part of any game; this way, I'll be 3659 // properly removed from their dialogs. 3660 //..................................................................... 3661 if ( (*joinstate) == JOIN_CONFIRMED) { 3662 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 3663 Session.GPacket.Command = NET_SIGN_OFF; 3664 strcpy (Session.GPacket.Name,my_name); 3665 3666 for (i = 1; i < Session.Players.Count(); i++) { 3667 Ipx.Send_Global_Message (&Session.GPacket, 3668 sizeof(GlobalPacketType), 1, 3669 &(Session.Players[i]->Address)); 3670 Ipx.Service(); 3671 } 3672 3673 Ipx.Send_Global_Message (&Session.GPacket, 3674 sizeof (GlobalPacketType), 0, NULL); 3675 if (Session.IsBridge) { 3676 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 3677 0, &Session.BridgeNet); 3678 } 3679 3680 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 3681 3682 Session.GameName[0] = 0; 3683 3684 //.................................................................. 3685 // remove myself from the player list 3686 //.................................................................. 3687 item = (char *)(playerlist->Get_Item(0)); 3688 playerlist->Remove_Item(item); 3689 delete [] item; 3690 playerlist->Flag_To_Redraw(); 3691 3692 delete Session.Players[0]; 3693 Session.Players.Delete(Session.Players[0]); 3694 3695 (*joinstate) = JOIN_REJECTED; 3696 (*why) = REJECT_BY_OWNER; 3697 retcode = EV_STATE_CHANGE; 3698 } 3699 //..................................................................... 3700 // If we're waiting for confirmation & got rejected, tell the user why 3701 //..................................................................... 3702 else if ((*joinstate) == JOIN_WAIT_CONFIRM) { 3703 (*why) = (RejectType)Session.GPacket.Reject.Why; 3704 (*joinstate) = JOIN_REJECTED; 3705 retcode = EV_STATE_CHANGE; 3706 } 3707 } 3708 3709 //------------------------------------------------------------------------ 3710 // NET_GAME_OPTIONS: The game owner has changed the game options & is 3711 // sending us the new values. 3712 //------------------------------------------------------------------------ 3713 else if (Session.GPacket.Command==NET_GAME_OPTIONS) { 3714 if ( (*joinstate)==JOIN_CONFIRMED || (*joinstate)==JOIN_WAIT_CONFIRM) { 3715 Session.Options.Credits = Session.GPacket.ScenarioInfo.Credits; 3716 Session.Options.Bases = Session.GPacket.ScenarioInfo.IsBases; 3717 Session.Options.Tiberium = Session.GPacket.ScenarioInfo.IsTiberium; 3718 Session.Options.Goodies = Session.GPacket.ScenarioInfo.IsGoodies; 3719 // Session.Options.Ghosts = Session.GPacket.ScenarioInfo.IsGhosties; 3720 Session.Options.AIPlayers = Session.GPacket.ScenarioInfo.AIPlayers; 3721 BuildLevel = Session.GPacket.ScenarioInfo.BuildLevel; 3722 Session.Options.UnitCount = Session.GPacket.ScenarioInfo.UnitCount; 3723 Seed = Session.GPacket.ScenarioInfo.Seed; 3724 Special = Session.GPacket.ScenarioInfo.Special; 3725 Options.GameSpeed = Session.GPacket.ScenarioInfo.GameSpeed; 3726 3727 #ifdef FIXIT_VERSION_3 3728 // Guest receives game version number from host. 3729 // Added to the transmitted version number is a bit indicating presence of Aftermath expansion. 3730 unsigned long lVersion = Session.GPacket.ScenarioInfo.Version & ~0x80000000; // Actual version number. 3731 Session.CommProtocol = VerNum.Version_Protocol( lVersion ); 3732 bAftermathMultiplayer = Session.GPacket.ScenarioInfo.Version & 0x80000000; 3733 // if( bAftermathMultiplayer ) 3734 // debugprint( "Guest hears host say 'This is an Aftermath game'\n" ); 3735 // else 3736 // debugprint( "Guest hears host say 'This is NOT an Aftermath game'\n" ); 3737 #else 3738 Session.CommProtocol = VerNum.Version_Protocol(Session.GPacket.ScenarioInfo.Version); 3739 PlayingAgainstVersion = Session.GPacket.ScenarioInfo.Version; 3740 #endif 3741 3742 if (Session.Options.Tiberium) { 3743 Special.IsTGrowth = 1; 3744 Rule.IsTGrowth = 1; 3745 Special.IsTSpread = 1; 3746 Rule.IsTSpread = 1; 3747 } else { 3748 Special.IsTGrowth = 0; 3749 Rule.IsTGrowth = 0; 3750 Special.IsTSpread = 0; 3751 Rule.IsTSpread = 0; 3752 } 3753 3754 /*............................................................... 3755 Copy the information about the scenario that the host wants to 3756 play so ee can request this scenario from the host if we don't 3757 have it locally. 3758 ...............................................................*/ 3759 strcpy (Session.Options.ScenarioDescription, Session.GPacket.ScenarioInfo.Scenario); 3760 strcpy (Session.ScenarioFileName, Session.GPacket.ScenarioInfo.ShortFileName); 3761 #ifdef WOLAPI_INTEGRATION 3762 strncpy (Session.ScenarioDigest, (char*)Session.GPacket.ScenarioInfo.FileDigest, sizeof (Session.GPacket.ScenarioInfo.FileDigest)); 3763 #else 3764 strcpy (Session.ScenarioDigest, (char*)Session.GPacket.ScenarioInfo.FileDigest); 3765 #endif 3766 Session.ScenarioIsOfficial = Session.GPacket.ScenarioInfo.OfficialScenario; 3767 Session.ScenarioFileLength = Session.GPacket.ScenarioInfo.FileLength; 3768 3769 retcode = EV_GAME_OPTIONS; 3770 } 3771 } 3772 3773 //------------------------------------------------------------------------ 3774 // NET_SIGN_OFF: Another system is signing off: search for that system in 3775 // both the game list & player list, & remove it if found 3776 //------------------------------------------------------------------------ 3777 else if (Session.GPacket.Command==NET_SIGN_OFF) { 3778 //..................................................................... 3779 // Remove this name from the list of games 3780 //..................................................................... 3781 for (i = 1; i < Session.Games.Count(); i++) { 3782 if (!strcmp(Session.Games[i]->Name, Session.GPacket.Name) && 3783 Session.Games[i]->Address==Session.GAddress) { 3784 3785 //............................................................... 3786 // If the system signing off is the currently-selected list 3787 // item, clear the player list since that game is no longer 3788 // forming. 3789 //............................................................... 3790 if (i==gamelist->Current_Index()) { 3791 Clear_Listbox (playerlist); 3792 Clear_Vector (&Session.Players); 3793 } 3794 3795 //............................................................... 3796 // If the system signing off was the owner of our game, mark 3797 // ourselves as rejected 3798 //............................................................... 3799 if ( (*joinstate) > JOIN_NOTHING && i==join_index) { 3800 (*joinstate) = JOIN_REJECTED; 3801 retcode = EV_STATE_CHANGE; 3802 (*why) = REJECT_DISBANDED; 3803 } 3804 3805 //............................................................... 3806 // Set my return code 3807 //............................................................... 3808 if (retcode == EV_NONE) { 3809 if (i <= gamelist->Current_Index()) { 3810 retcode = EV_GAME_SIGNOFF; 3811 } 3812 else { 3813 retcode = EV_PLAYER_SIGNOFF; 3814 } 3815 } 3816 3817 //............................................................... 3818 // Remove game name from game list 3819 //............................................................... 3820 delete Session.Games[i]; 3821 Session.Games.Delete(Session.Games[i]); 3822 item = (char *)(gamelist->Get_Item (i)); 3823 gamelist->Remove_Item (item); 3824 delete [] item; 3825 gamelist->Flag_To_Redraw(); 3826 3827 } 3828 } 3829 3830 //..................................................................... 3831 // Remove this name from the list of players 3832 //..................................................................... 3833 for (i = 0; i < Session.Players.Count(); i++) { 3834 3835 //.................................................................. 3836 // Name found; remove it 3837 //.................................................................. 3838 if (Session.Players[i]->Address==Session.GAddress) { 3839 item = (char *)(playerlist->Get_Item(i)); 3840 playerlist->Remove_Item(item); 3841 delete [] item; 3842 3843 delete Session.Players[i]; 3844 Session.Players.Delete(Session.Players[i]); 3845 3846 playerlist->Flag_To_Redraw(); 3847 3848 //............................................................... 3849 // If this player has left our game, play a special sound. 3850 //............................................................... 3851 if ((*joinstate)>=JOIN_CONFIRMED) { 3852 Sound_Effect(VOC_PLAYER_LEFT); 3853 } 3854 3855 if (retcode == EV_NONE) { 3856 retcode = EV_PLAYER_SIGNOFF; 3857 } 3858 } 3859 } 3860 3861 //..................................................................... 3862 // Remove this name from the chat list 3863 //..................................................................... 3864 for (i = 1; i < Session.Chat.Count(); i++) { 3865 3866 //.................................................................. 3867 // Name found; remove it 3868 //.................................................................. 3869 if (Session.Chat[i]->Address==Session.GAddress) { 3870 3871 delete Session.Chat[i]; 3872 Session.Chat.Delete(Session.Chat[i]); 3873 3874 if (retcode == EV_NONE) { 3875 retcode = EV_PLAYER_SIGNOFF; 3876 } 3877 } 3878 } 3879 } 3880 3881 //------------------------------------------------------------------------ 3882 // NET_GO: The game's owner is signalling us to start playing. 3883 //------------------------------------------------------------------------ 3884 else if (Session.GPacket.Command==NET_GO) { 3885 if ( (*joinstate)==JOIN_CONFIRMED) { 3886 Session.MaxAhead = Session.GPacket.ResponseTime.OneWay; 3887 (*joinstate) = JOIN_GAME_START; 3888 retcode = EV_STATE_CHANGE; 3889 Session.HostAddress = Session.GAddress; 3890 } 3891 } 3892 3893 //------------------------------------------------------------------------ 3894 // NET_LOADGAME: The game's owner is signalling us to start playing. 3895 //------------------------------------------------------------------------ 3896 else if (Session.GPacket.Command==NET_LOADGAME) { 3897 if ( (*joinstate)==JOIN_CONFIRMED) { 3898 Session.MaxAhead = Session.GPacket.ResponseTime.OneWay; 3899 (*joinstate) = JOIN_GAME_START_LOAD; 3900 retcode = EV_STATE_CHANGE; 3901 } 3902 } 3903 3904 //------------------------------------------------------------------------ 3905 // NET_CHAT_ANNOUNCE: Someone is ready to chat; add them to our list, if 3906 // they aren't already on it, and it's not myself. 3907 //------------------------------------------------------------------------ 3908 else if (Session.GPacket.Command==NET_CHAT_ANNOUNCE) { 3909 found = 0; 3910 //..................................................................... 3911 // If this packet is from myself, don't add it to the list 3912 //..................................................................... 3913 if (Session.GPacket.Chat.ID == Session.UniqueID) { 3914 found = 1; 3915 } 3916 //..................................................................... 3917 // Otherwise, see if we already have this address stored in our list 3918 // If so, update that node's time values & name (in case the user 3919 // changed it), and return. 3920 //..................................................................... 3921 else { 3922 for (i = 0; i < Session.Chat.Count(); i++) { 3923 if (Session.Chat[i]->Address==Session.GAddress) { 3924 strcpy (Session.Chat[i]->Name, Session.GPacket.Name); 3925 Session.Chat[i]->Chat.LastTime = TickCount; 3926 Session.Chat[i]->Chat.LastChance = 0; 3927 Session.Chat[i]->Chat.Color = Session.GPacket.Chat.Color; 3928 found = 1; 3929 break; 3930 } 3931 } 3932 } 3933 //..................................................................... 3934 // Add a new node to the list 3935 //..................................................................... 3936 if (!found) { 3937 who = new NodeNameType; 3938 strcpy (who->Name, Session.GPacket.Name); 3939 who->Address = Session.GAddress; 3940 who->Chat.LastTime = TickCount; 3941 who->Chat.LastChance = 0; 3942 who->Chat.Color = Session.GPacket.Chat.Color; 3943 Session.Chat.Add (who); 3944 } 3945 } 3946 3947 //------------------------------------------------------------------------ 3948 // NET_CHAT_REQUEST: Someone is requesting a CHAT_ANNOUNCE from us; send 3949 // one to him directly. 3950 //------------------------------------------------------------------------ 3951 else if (Session.GPacket.Command==NET_CHAT_REQUEST) { 3952 if ((*joinstate) != JOIN_WAIT_CONFIRM && (*joinstate) != JOIN_CONFIRMED) { 3953 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 3954 3955 Session.GPacket.Command = NET_CHAT_ANNOUNCE; 3956 strcpy(Session.GPacket.Name, my_name); 3957 Session.GPacket.Chat.ID = Session.UniqueID; 3958 Session.GPacket.Chat.Color = Session.ColorIdx; 3959 3960 Ipx.Send_Global_Message (&Session.GPacket, 3961 sizeof(GlobalPacketType), 1, &Session.GAddress); 3962 3963 Ipx.Service(); 3964 } 3965 } 3966 3967 //------------------------------------------------------------------------ 3968 // NET_MESSAGE: Someone is sending us a message 3969 //------------------------------------------------------------------------ 3970 else if (Session.GPacket.Command==NET_MESSAGE) { 3971 //..................................................................... 3972 // If we're in a game, the sender must be in our game. 3973 //..................................................................... 3974 if ( (*joinstate)==JOIN_CONFIRMED) { 3975 if (Session.GPacket.Message.NameCRC == 3976 Compute_Name_CRC(Session.GameName)) { 3977 Session.Messages.Add_Message (Session.GPacket.Name, 3978 (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ? 3979 PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color, 3980 Session.GPacket.Message.Buf, 3981 (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ? 3982 PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color, 3983 TPF_TEXT, -1); 3984 } 3985 } 3986 //..................................................................... 3987 // Otherwise, we're in the chat room; display any old message. 3988 //..................................................................... 3989 else { 3990 Session.Messages.Add_Message (Session.GPacket.Name, 3991 Session.GPacket.Message.Color, 3992 Session.GPacket.Message.Buf, 3993 (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ? 3994 PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color, 3995 TPF_TEXT, -1); 3996 } 3997 3998 retcode = EV_MESSAGE; 3999 } 4000 4001 //------------------------------------------------------------------------ 4002 // NET_PING: Someone is pinging me to get a response time measure (will only 4003 // happen after I've joined a game). Do nothing; the IPX Manager will handle 4004 // sending an ACK, and updating the response time measurements. 4005 //------------------------------------------------------------------------ 4006 else if (Session.GPacket.Command==NET_PING) { 4007 retcode = EV_NONE; 4008 } 4009 4010 //------------------------------------------------------------------------ 4011 // Default case: nothing happened. (This case will be hit every time I 4012 // receive my own NET_QUERY_GAME or NET_QUERY_PLAYER packets.) 4013 //------------------------------------------------------------------------ 4014 else { 4015 retcode = EV_NONE; 4016 } 4017 4018 return(retcode); 4019 4020 } /* end of Get_Join_Responses */ 4021 4022 4023 /*********************************************************************************************** 4024 * Net_New_Dialog -- lets user start a new game * 4025 * * 4026 * This dialog shows a list of who's requesting to join this game, and lets * 4027 * the game initiator selectively approve each user. * 4028 * * 4029 * The 'Players' vector matches one-for-one the contents of the list box. The local system * 4030 * is always listed first; the IPX Address of the local system will NOT be valid in the * 4031 * Players vector. The Games & Players vectors should be left filled in even after this * 4032 * routine is exited; their contents are used to form connections to the other players, * 4033 * after the scenario has been loaded. * 4034 * * 4035 * INPUT: * 4036 * none. * 4037 * * 4038 * OUTPUT: * 4039 * true = success, false = cancel * 4040 * * 4041 * WARNINGS: * 4042 * Session.GameName must contain this player's name. * 4043 * * 4044 * HISTORY: * 4045 * 02/14/1995 BR : Created. * 4046 *=============================================================================================*/ 4047 static int Net_New_Dialog(void) 4048 { 4049 return 0; //PG 4050 #if (0) 4051 typedef enum { 4052 NUM_MESSAGES = 10 4053 } NumMessagesType; 4054 4055 //------------------------------------------------------------------------ 4056 // Dialog & button dimensions 4057 //------------------------------------------------------------------------ 4058 int d_dialog_w = 320 *RESFACTOR; // dialog width 4059 int d_dialog_h = 200 *RESFACTOR; // dialog height 4060 int d_dialog_x = ((320 *RESFACTOR- d_dialog_w) / 2); // dialog x-coord 4061 int d_dialog_y = ((200 *RESFACTOR- d_dialog_h) / 2); // centered y-coord 4062 int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord 4063 4064 int d_txt6_h = 6*RESFACTOR+1; // ht of 6-pt text 4065 int d_margin1 = 5*RESFACTOR; // margin width/height 4066 int d_margin2 = 2*RESFACTOR; // margin width/height 4067 4068 //BG int d_playerlist_w = 118*RESFACTOR; 4069 int d_playerlist_w = 124*RESFACTOR; 4070 int d_playerlist_h = (6 * d_txt6_h) + 3*RESFACTOR; // 6 rows high 4071 int d_playerlist_x = d_dialog_x + d_margin1 + d_margin1 + 5*RESFACTOR; 4072 int d_playerlist_y = d_dialog_y + d_margin1 + d_txt6_h + 3*RESFACTOR; 4073 4074 int d_scenariolist_w = 162*RESFACTOR; 4075 int d_scenariolist_h = (6 * d_txt6_h) + 3*RESFACTOR; // 6 rows high 4076 int d_scenariolist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_scenariolist_w - (5*RESFACTOR); 4077 int d_scenariolist_y = d_playerlist_y; 4078 4079 int d_reject_w = 55*RESFACTOR; 4080 int d_reject_h = 9*RESFACTOR; 4081 int d_reject_x = d_playerlist_x + (d_playerlist_w / 2) - (d_reject_w / 2); 4082 int d_reject_y = d_playerlist_y + d_playerlist_h + d_margin2; 4083 4084 int d_count_w = 25*RESFACTOR; 4085 int d_count_h = d_txt6_h; 4086 int d_count_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged) 4087 int d_count_y = d_reject_y + d_reject_h /*KO+ d_margin2*/; 4088 4089 int d_level_w = 25*RESFACTOR; 4090 int d_level_h = d_txt6_h; 4091 int d_level_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged) 4092 int d_level_y = d_count_y + d_count_h; 4093 4094 int d_credits_w = 25*RESFACTOR; 4095 int d_credits_h = d_txt6_h; 4096 int d_credits_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged) 4097 int d_credits_y = d_level_y + d_level_h; 4098 4099 int d_aiplayers_w = 25*RESFACTOR; 4100 int d_aiplayers_h = d_txt6_h; 4101 int d_aiplayers_x = d_playerlist_x + (d_playerlist_w / 2) + 20*RESFACTOR; // (fudged) 4102 int d_aiplayers_y = d_credits_y + d_credits_h; 4103 4104 int d_options_w = 106*RESFACTOR; 4105 int d_options_h = ((5 * 6) + 4)*RESFACTOR; 4106 int d_options_x = d_scenariolist_x + ((d_scenariolist_w - d_options_w) / 2); 4107 int d_options_y = d_scenariolist_y + d_scenariolist_h + d_margin1; 4108 4109 int d_message_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR; 4110 int d_message_h = (NUM_MESSAGES * d_txt6_h) + 3*RESFACTOR; // 10 rows high 4111 int d_message_x = d_dialog_x + d_margin1 + 10*RESFACTOR; 4112 int d_message_y = d_dialog_y + d_dialog_h - (27*RESFACTOR + d_message_h); 4113 // int d_message_y = d_options_y + d_options_h + d_margin1; 4114 4115 int d_send_w = d_dialog_w - (d_margin1 * 2) - 20*RESFACTOR; 4116 int d_send_h = 9*RESFACTOR; 4117 int d_send_x = d_dialog_x + d_margin1 + 10*RESFACTOR; 4118 int d_send_y = d_message_y + d_message_h; 4119 4120 int d_ok_w = 50*RESFACTOR; 4121 int d_ok_h = 9*RESFACTOR; 4122 int d_ok_x = d_dialog_x + (d_dialog_w / 6) - (d_ok_w / 2); 4123 int d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin1 - 3*RESFACTOR; 4124 4125 int d_cancel_w = 50*RESFACTOR; 4126 int d_cancel_h = 9*RESFACTOR; 4127 int d_cancel_x = d_dialog_cx - (d_cancel_w / 2); 4128 int d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin1 - 3*RESFACTOR; 4129 4130 int d_load_w = 50*RESFACTOR; 4131 int d_load_h = 9*RESFACTOR; 4132 int d_load_x = d_dialog_x + ((d_dialog_w * 5) / 6) - (d_load_w / 2); 4133 int d_load_y = d_dialog_y + d_dialog_h - d_load_h - d_margin1 - 3*RESFACTOR; 4134 4135 //------------------------------------------------------------------------ 4136 // Button Enumerations 4137 //------------------------------------------------------------------------ 4138 enum { 4139 BUTTON_PLAYERLIST = 100, 4140 BUTTON_SCENARIOLIST, 4141 BUTTON_REJECT, 4142 BUTTON_COUNT, 4143 BUTTON_LEVEL, 4144 BUTTON_CREDITS, 4145 BUTTON_AIPLAYERS, 4146 BUTTON_OPTIONS, 4147 BUTTON_OK, 4148 BUTTON_LOAD, 4149 BUTTON_CANCEL, 4150 }; 4151 4152 //------------------------------------------------------------------------ 4153 // Redraw values: in order from "top" to "bottom" layer of the dialog 4154 //------------------------------------------------------------------------ 4155 typedef enum { 4156 REDRAW_NONE = 0, 4157 REDRAW_PARMS, 4158 REDRAW_MESSAGE, 4159 REDRAW_BUTTONS, 4160 REDRAW_BACKGROUND, 4161 REDRAW_ALL = REDRAW_BACKGROUND 4162 } RedrawType; 4163 4164 //------------------------------------------------------------------------ 4165 // Dialog variables 4166 //------------------------------------------------------------------------ 4167 RedrawType display = REDRAW_ALL; // redraw level 4168 bool process = true; // process while true 4169 KeyNumType input; 4170 4171 int transmit; // 1 = re-transmit new game options 4172 4173 long ok_timer = 0; // for timing OK button 4174 int index; // index for rejecting a player 4175 int rc; 4176 int i,j; 4177 char *item; 4178 int tabs[] = {77*RESFACTOR}; // tabs for player list box 4179 int optiontabs[] = {8*RESFACTOR}; // tabs for option list box 4180 4181 NodeNameType *who; // node to add to Players 4182 long ping_timer = 0; // for sending Ping packets 4183 4184 int color_used[MAX_MPLAYER_COLORS]; // 1 = color has been used 4185 char txt[80]; 4186 JoinEventType whahoppa; // event generated by received packets 4187 static int first_time = 1; // 1 = 1st time this dialog is run 4188 CCFileClass loadfile ("SAVEGAME.NET"); 4189 int load_game = 0; // 1 = load a saved game 4190 RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); 4191 4192 //------------------------------------------------------------------------ 4193 // Buttons 4194 //------------------------------------------------------------------------ 4195 GadgetClass *commands; // button list 4196 4197 ColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); 4198 ListClass scenariolist(BUTTON_SCENARIOLIST, d_scenariolist_x, d_scenariolist_y, d_scenariolist_w, d_scenariolist_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); 4199 TextButtonClass rejectbtn(BUTTON_REJECT, TXT_REJECT, TPF_BUTTON, d_reject_x, d_reject_y); 4200 GaugeClass countgauge(BUTTON_COUNT, d_count_x, d_count_y, d_count_w, d_count_h); 4201 GaugeClass levelgauge(BUTTON_LEVEL, d_level_x, d_level_y, d_level_w, d_level_h); 4202 GaugeClass creditsgauge(BUTTON_CREDITS, d_credits_x, d_credits_y, d_credits_w, d_credits_h); 4203 GaugeClass aiplayersgauge(BUTTON_AIPLAYERS, d_aiplayers_x, d_aiplayers_y, d_aiplayers_w, d_aiplayers_h); 4204 CheckListClass optionlist(BUTTON_OPTIONS, d_options_x, d_options_y, d_options_w, d_options_h, TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); 4205 TextButtonClass okbtn(BUTTON_OK, TXT_OK, TPF_BUTTON, d_ok_x, d_ok_y, 60*RESFACTOR); 4206 TextButtonClass loadbtn(BUTTON_LOAD, TXT_LOAD_BUTTON, TPF_BUTTON, d_load_x, d_load_y, 60*RESFACTOR); 4207 TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, d_cancel_x, d_cancel_y, 60*RESFACTOR); 4208 4209 StaticButtonClass staticunit(0, " ", TPF_TEXT, d_count_x + d_count_w + 2*RESFACTOR, d_count_y); 4210 StaticButtonClass staticlevel(0, " ", TPF_TEXT, d_level_x + d_level_w + 2*RESFACTOR, d_level_y); 4211 StaticButtonClass staticcredits(0, " ", TPF_TEXT, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y); 4212 StaticButtonClass staticaiplayers(0, " ", TPF_TEXT, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y); 4213 4214 //------------------------------------------------------------------------ 4215 // Build the button list 4216 //------------------------------------------------------------------------ 4217 commands = &playerlist; 4218 scenariolist.Add_Tail(*commands); 4219 rejectbtn.Add_Tail(*commands); 4220 staticunit.Add_Tail(*commands); 4221 staticlevel.Add_Tail(*commands); 4222 staticcredits.Add_Tail(*commands); 4223 staticaiplayers.Add_Tail(*commands); 4224 countgauge.Add_Tail(*commands); 4225 creditsgauge.Add_Tail(*commands); 4226 aiplayersgauge.Add_Tail(*commands); 4227 levelgauge.Add_Tail(*commands); 4228 optionlist.Add_Tail(*commands); 4229 okbtn.Add_Tail(*commands); 4230 cancelbtn.Add_Tail(*commands); 4231 if (loadfile.Is_Available()) { 4232 #ifdef FIXIT_MULTI_SAVE 4233 // loadbtn.Add_Tail(*commands); 4234 #endif 4235 } else { 4236 cancelbtn.X = loadbtn.X; 4237 } 4238 playerlist.Set_Tabs(tabs); 4239 4240 //------------------------------------------------------------------------ 4241 // Init dialog values, only the first time through 4242 //------------------------------------------------------------------------ 4243 Special.IsCaptureTheFlag = Rule.IsMPCaptureTheFlag; 4244 if (first_time) { 4245 Session.Options.Credits = Rule.MPDefaultMoney; // init credits & credit buffer 4246 Session.Options.Bases = Rule.IsMPBasesOn; // init scenario parameters 4247 Session.Options.Tiberium = Rule.IsMPTiberiumGrow; 4248 Session.Options.Goodies = Rule.IsMPCrates; 4249 Session.Options.AIPlayers = 0; 4250 Session.Options.UnitCount = 4251 (SessionClass::CountMax[Session.Options.Bases] + 4252 SessionClass::CountMin[Session.Options.Bases]) / 2; 4253 first_time = 0; 4254 } 4255 4256 //------------------------------------------------------------------------ 4257 // Init button states 4258 //------------------------------------------------------------------------ 4259 optionlist.Set_Tabs(optiontabs); 4260 optionlist.Set_Read_Only(0); 4261 4262 optionlist.Add_Item(Text_String(TXT_BASES)); 4263 optionlist.Add_Item(Text_String(TXT_ORE_SPREADS)); 4264 optionlist.Add_Item(Text_String(TXT_CRATES)); 4265 optionlist.Add_Item(Text_String(TXT_CAPTURE_THE_FLAG)); 4266 optionlist.Add_Item(Text_String(TXT_SHADOW_REGROWS)); 4267 4268 optionlist.Check_Item(0, Session.Options.Bases); 4269 optionlist.Check_Item(1, Session.Options.Tiberium); 4270 optionlist.Check_Item(2, Session.Options.Goodies); 4271 optionlist.Check_Item(3, Special.IsCaptureTheFlag); 4272 optionlist.Check_Item(4, Special.IsShadowGrow); 4273 4274 countgauge.Set_Maximum(SessionClass::CountMax[Session.Options.Bases] - SessionClass::CountMin[Session.Options.Bases]); 4275 countgauge.Set_Value(Session.Options.UnitCount - SessionClass::CountMin[Session.Options.Bases]); 4276 4277 levelgauge.Set_Maximum(MPLAYER_BUILD_LEVEL_MAX - 1); 4278 levelgauge.Set_Value(BuildLevel - 1); 4279 4280 creditsgauge.Set_Maximum(Rule.MPMaxMoney); 4281 creditsgauge.Set_Value(Session.Options.Credits); 4282 4283 //------------------------------------------------------------------------ 4284 // Init other scenario parameters 4285 //------------------------------------------------------------------------ 4286 Special.IsTGrowth = Session.Options.Tiberium; 4287 Rule.IsTGrowth = Session.Options.Tiberium; 4288 Special.IsTSpread = Session.Options.Tiberium; 4289 Rule.IsTSpread = Session.Options.Tiberium; 4290 transmit = 0; 4291 4292 //------------------------------------------------------------------------ 4293 // Init scenario description list box 4294 //------------------------------------------------------------------------ 4295 for (i = 0; i < Session.Scenarios.Count(); i++) { 4296 for (j = 0; EngMisStr[j] != NULL; j++) { 4297 if (!strcmp(Session.Scenarios[i]->Description(), EngMisStr[j])) { 4298 #ifdef FIXIT_CSII // ajw Added Aftermath installed checks (before, it was assumed). 4299 // Add mission if it's available to us. 4300 if( !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) || 4301 ( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) ) 4302 #endif 4303 #if defined(GERMAN) || defined(FRENCH) 4304 scenariolist.Add_Item(EngMisStr[j+1]); 4305 #else 4306 scenariolist.Add_Item(EngMisStr[j]); 4307 #endif 4308 4309 break; 4310 } 4311 } 4312 if ( EngMisStr[j] == NULL) { 4313 #ifdef FIXIT_CSII // ajw Added Aftermath installed checks (before, it was assumed). Added officialness check. 4314 // Add mission if it's available to us. 4315 if( !Session.Scenarios[i]->Get_Official() || 4316 !( ( Is_Mission_Counterstrike((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Counterstrike_Installed() ) || 4317 ( Is_Mission_Aftermath((char *)(Session.Scenarios[i]->Get_Filename())) && !Is_Aftermath_Installed() ) ) ) 4318 #endif 4319 { 4320 scenariolist.Add_Item(Session.Scenarios[i]->Description()); 4321 } 4322 } 4323 } 4324 4325 Session.Options.ScenarioIndex = 0; // 1st scenario is selected 4326 #ifdef FIXIT_VERSION_3 4327 bAftermathMultiplayer = Is_Aftermath_Installed(); 4328 // debugprint( "Host decides that, initially, bAftermathMultiplayer is %i\n", bAftermathMultiplayer ); 4329 #else 4330 PlayingAgainstVersion = VerNum.Version_Number(); 4331 #endif 4332 4333 //------------------------------------------------------------------------ 4334 // Init player color-used flags 4335 //------------------------------------------------------------------------ 4336 for (i = 0; i < MAX_MPLAYER_COLORS; i++) { 4337 color_used[i] = 0; // init all colors to available 4338 } 4339 color_used[Session.ColorIdx] = 1; // set my color to used 4340 playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, scheme); 4341 4342 //------------------------------------------------------------------------ 4343 // Init random-number generator, & create a seed to be used for all random 4344 // numbers from here on out 4345 //------------------------------------------------------------------------ 4346 srand(time(NULL)); 4347 Seed = rand(); 4348 4349 //------------------------------------------------------------------------ 4350 // Init the message display system 4351 //------------------------------------------------------------------------ 4352 Session.Messages.Init(d_message_x + 1*RESFACTOR, d_message_y + 1*RESFACTOR, NUM_MESSAGES, 4353 MAX_MESSAGE_LENGTH, d_txt6_h, d_send_x + 1*RESFACTOR, d_send_y + 1*RESFACTOR, 1, 4354 20, MAX_MESSAGE_LENGTH - 5, d_message_w); 4355 Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? 4356 PCOLOR_REALLY_BLUE : Session.ColorIdx, 4357 TPF_TEXT, NULL, '_', d_message_w); 4358 4359 //------------------------------------------------------------------------ 4360 // Init the version-clipping system 4361 //------------------------------------------------------------------------ 4362 VerNum.Init_Clipping(); 4363 4364 //------------------------------------------------------------------------ 4365 // Clear the list of players 4366 //------------------------------------------------------------------------ 4367 Clear_Vector(&Session.Players); 4368 4369 //------------------------------------------------------------------------ 4370 // Add myself to the list, and to the Players vector. 4371 //------------------------------------------------------------------------ 4372 item = new char [MPLAYER_NAME_MAX + 64]; 4373 #ifdef OLDWAY 4374 if (Session.House==HOUSE_GOOD) { 4375 sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_ALLIES)); 4376 } else { 4377 sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_SOVIET)); 4378 } 4379 #else //OLDWAY 4380 sprintf (item, "%s\t%s", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); 4381 #endif //OLDWAY 4382 playerlist.Add_Item(item, 4383 (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]); 4384 4385 who = new NodeNameType; 4386 strcpy(who->Name, Session.Handle); 4387 who->Player.House = Session.House; 4388 who->Player.Color = Session.ColorIdx; 4389 Session.Players.Add (who); 4390 Load_Title_Page(true); 4391 CCPalette.Set(); //GamePalette.Set(); 4392 4393 // 4394 // Now init the max range of the AI players slider. 4395 // 4396 aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count()); 4397 aiplayersgauge.Set_Value(Session.Options.AIPlayers); 4398 4399 //------------------------------------------------------------------------ 4400 // Processing loop 4401 //------------------------------------------------------------------------ 4402 while (process) { 4403 #if(SHOW_MONO) 4404 Ipx.Mono_Debug_Print(-1,0); 4405 #endif 4406 4407 #ifdef WIN32 4408 /* 4409 ** If we have just received input focus again after running in the background then 4410 ** we need to redraw. 4411 */ 4412 if (AllSurfaces.SurfacesRestored) { 4413 AllSurfaces.SurfacesRestored=FALSE; 4414 display = REDRAW_ALL; 4415 } 4416 #endif 4417 //..................................................................... 4418 // Refresh display if needed 4419 //..................................................................... 4420 if (display) { 4421 Hide_Mouse(); 4422 4423 //.................................................................. 4424 // Redraw backgound & dialog box 4425 //.................................................................. 4426 if (display >= REDRAW_BACKGROUND) { 4427 Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h); 4428 4429 //............................................................... 4430 // Dialog & Field labels 4431 //............................................................... 4432 Fancy_Text_Print(TXT_PLAYERS, d_playerlist_x + (d_playerlist_w / 2), d_playerlist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER); 4433 Fancy_Text_Print(TXT_SCENARIOS, d_scenariolist_x + (d_scenariolist_w / 2), d_scenariolist_y - d_txt6_h, scheme, TBLACK, TPF_TEXT | TPF_CENTER); 4434 Fancy_Text_Print(TXT_COUNT, d_count_x - 2*RESFACTOR, d_count_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); 4435 Fancy_Text_Print(TXT_LEVEL, d_level_x - 2*RESFACTOR, d_level_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); 4436 Fancy_Text_Print(TXT_CREDITS_COLON, d_credits_x - 2*RESFACTOR, d_credits_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); 4437 Fancy_Text_Print(TXT_AI_PLAYERS_COLON, d_aiplayers_x - 2*RESFACTOR, d_aiplayers_y, scheme, TBLACK, TPF_TEXT | TPF_RIGHT); 4438 } 4439 4440 //.................................................................. 4441 // Redraw buttons 4442 //.................................................................. 4443 if (display >= REDRAW_BUTTONS) { 4444 4445 /* 4446 ** Zap, Zap, Zap 4447 */ 4448 playerlist.Zap(); 4449 scenariolist.Zap(); 4450 rejectbtn.Zap(); 4451 staticunit.Zap(); 4452 staticlevel.Zap(); 4453 staticcredits.Zap(); 4454 staticaiplayers.Zap(); 4455 countgauge.Zap(); 4456 creditsgauge.Zap(); 4457 aiplayersgauge.Zap(); 4458 levelgauge.Zap(); 4459 optionlist.Zap(); 4460 okbtn.Zap(); 4461 cancelbtn.Zap(); 4462 loadbtn.Zap(); 4463 4464 4465 /* 4466 ** Hack hack, hack 4467 */ 4468 commands = &playerlist; 4469 scenariolist.Add_Tail(*commands); 4470 rejectbtn.Add_Tail(*commands); 4471 staticunit.Add_Tail(*commands); 4472 staticlevel.Add_Tail(*commands); 4473 staticcredits.Add_Tail(*commands); 4474 staticaiplayers.Add_Tail(*commands); 4475 countgauge.Add_Tail(*commands); 4476 creditsgauge.Add_Tail(*commands); 4477 aiplayersgauge.Add_Tail(*commands); 4478 levelgauge.Add_Tail(*commands); 4479 optionlist.Add_Tail(*commands); 4480 okbtn.Add_Tail(*commands); 4481 cancelbtn.Add_Tail(*commands); 4482 #ifdef FIXIT_VERSION_3 4483 if( loadfile.Is_Available() ) { 4484 #else 4485 if (loadfile.Is_Available() && PlayingAgainstVersion > VERSION_RED_ALERT_104 ) { 4486 #endif 4487 #ifdef FIXIT_MULTI_SAVE 4488 loadbtn.Add_Tail(*commands); 4489 #endif 4490 } 4491 commands->Draw_All(); 4492 } 4493 4494 //.................................................................. 4495 // Draw the messages: 4496 // - Erase an old message first 4497 // - If we're in a game, print the game options (if they've been 4498 // received) 4499 // - If we've been rejected from a game, print that message 4500 //.................................................................. 4501 if (display >= REDRAW_MESSAGE) { 4502 Draw_Box(d_message_x, d_message_y, d_message_w, d_message_h, BOXSTYLE_BOX, true); 4503 Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, BOXSTYLE_BOX, true); 4504 Session.Messages.Draw(); 4505 } 4506 4507 //.................................................................. 4508 // Update game parameter labels 4509 //.................................................................. 4510 if (display >= REDRAW_PARMS) { 4511 // LogicPage->Fill_Rect(d_count_x + d_count_w + 2*RESFACTOR, d_count_y, d_count_x + d_count_w + 35*RESFACTOR, d_aiplayers_y + d_aiplayers_h+RESFACTOR, BLACK); 4512 4513 sprintf(txt,"%d",Session.Options.UnitCount); 4514 staticunit.Set_Text(txt); 4515 staticunit.Draw_Me(); 4516 // Fancy_Text_Print(txt, d_count_x + d_count_w + 2*RESFACTOR, d_count_y, scheme, BLACK, TPF_TEXT); 4517 4518 if (BuildLevel <= MPLAYER_BUILD_LEVEL_MAX) { 4519 sprintf(txt,"%d",BuildLevel); 4520 } else { 4521 sprintf(txt, "**"); 4522 } 4523 staticlevel.Set_Text(txt); 4524 staticlevel.Draw_Me(); 4525 // Fancy_Text_Print(txt, d_level_x + d_level_w + 2*RESFACTOR, d_level_y, scheme, BLACK, TPF_TEXT); 4526 4527 sprintf(txt,"%d",Session.Options.Credits); 4528 staticcredits.Set_Text(txt); 4529 staticcredits.Draw_Me(); 4530 // Fancy_Text_Print(txt, d_credits_x + d_credits_w + 2*RESFACTOR, d_credits_y, scheme, BLACK, TPF_TEXT); 4531 4532 sprintf(txt,"%d",Session.Options.AIPlayers); 4533 staticaiplayers.Set_Text(txt); 4534 staticaiplayers.Draw_Me(); 4535 // Fancy_Text_Print(txt, d_aiplayers_x + d_aiplayers_w + 2*RESFACTOR, d_aiplayers_y, scheme, BLACK, TPF_TEXT); 4536 } 4537 4538 Show_Mouse(); 4539 display = REDRAW_NONE; 4540 } 4541 4542 //..................................................................... 4543 // Get user input 4544 //..................................................................... 4545 input = commands->Input(); 4546 4547 //..................................................................... 4548 // Process input 4549 //..................................................................... 4550 switch (input) { 4551 4552 //.................................................................. 4553 // New Scenario selected. 4554 //.................................................................. 4555 #ifdef FIXIT_VERSION_3 // All scenarios now allowable as downloads. ajw 4556 case (BUTTON_SCENARIOLIST | KN_BUTTON): 4557 if (scenariolist.Current_Index() != Session.Options.ScenarioIndex) 4558 { 4559 Session.Options.ScenarioIndex = scenariolist.Current_Index(); 4560 transmit = 1; 4561 } 4562 break; 4563 4564 #else // FIXIT_VERSION_3 4565 case (BUTTON_SCENARIOLIST | KN_BUTTON): 4566 if (scenariolist.Current_Index() != Session.Options.ScenarioIndex) { 4567 #ifdef FIXIT_CSII // checked - ajw 4568 if ((PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) && 4569 #else 4570 if (PlayingAgainstVersion < VERSION_RED_ALERT_107 && 4571 #endif 4572 Session.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){ 4573 scenariolist.Set_Selected_Index (Session.Options.ScenarioIndex); 4574 Session.Messages.Add_Message(NULL, 0, 4575 (char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200); 4576 Sound_Effect(VOC_SYS_ERROR); 4577 if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; 4578 #ifdef FIXIT_CSII // checked - ajw 4579 }else 4580 if (PlayingAgainstVersion < VERSION_AFTERMATH_CS && 4581 Is_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){ 4582 scenariolist.Set_Selected_Index (Session.Options.ScenarioIndex); 4583 Session.Messages.Add_Message(NULL, 0, 4584 (char *)Text_String(TXT_NO_CS_SCENARIOS), PCOLOR_BROWN, TPF_TEXT, 1200); 4585 Sound_Effect(VOC_SYS_ERROR); 4586 if (display < REDRAW_MESSAGE) display = REDRAW_MESSAGE; 4587 #endif 4588 } else { 4589 Session.Options.ScenarioIndex = scenariolist.Current_Index(); 4590 transmit = 1; 4591 } 4592 } 4593 break; 4594 #endif // FIXIT_VERSION_3 4595 4596 //.................................................................. 4597 // Reject the currently-selected player (don't allow rejecting myself, 4598 // who will be the first entry in the list) 4599 //.................................................................. 4600 case (BUTTON_REJECT | KN_BUTTON): 4601 index = playerlist.Current_Index(); 4602 4603 if (index == 0) { 4604 Session.Messages.Add_Message(NULL, 0, 4605 (char *)Text_String(TXT_CANT_REJECT_SELF), PCOLOR_BROWN, TPF_TEXT, 1200); 4606 Sound_Effect(VOC_SYS_ERROR); 4607 display = REDRAW_MESSAGE; 4608 break; 4609 4610 } else if (index < 0 || index >= playerlist.Count()) { 4611 Session.Messages.Add_Message(NULL, 0, 4612 (char *)Text_String(TXT_SELECT_PLAYER_REJECT), 4613 PCOLOR_BROWN, TPF_TEXT, 1200); 4614 Sound_Effect(VOC_SYS_ERROR); 4615 display = REDRAW_MESSAGE; 4616 break; 4617 } 4618 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 4619 4620 Session.GPacket.Command = NET_REJECT_JOIN; 4621 4622 Ipx.Send_Global_Message (&Session.GPacket, 4623 sizeof (GlobalPacketType), 1, 4624 &(Session.Players[index]->Address)); 4625 break; 4626 4627 //.................................................................. 4628 // User adjusts max # units 4629 //.................................................................. 4630 case (BUTTON_COUNT | KN_BUTTON): 4631 Session.Options.UnitCount = countgauge.Get_Value() + 4632 SessionClass::CountMin[Session.Options.Bases]; 4633 transmit = 1; 4634 display = REDRAW_PARMS; 4635 break; 4636 4637 //.................................................................. 4638 // User adjusts build level 4639 //.................................................................. 4640 case (BUTTON_LEVEL | KN_BUTTON): 4641 BuildLevel = levelgauge.Get_Value() + 1; 4642 if (BuildLevel > MPLAYER_BUILD_LEVEL_MAX) // if it's pegged, max it out 4643 BuildLevel = MPLAYER_BUILD_LEVEL_MAX; 4644 transmit = 1; 4645 display = REDRAW_PARMS; 4646 break; 4647 4648 //.................................................................. 4649 // User edits the credits value; retransmit new game options 4650 // Round the credits to the nearest 500. 4651 //.................................................................. 4652 case (BUTTON_CREDITS | KN_BUTTON): 4653 Session.Options.Credits = creditsgauge.Get_Value(); 4654 Session.Options.Credits = 4655 ((Session.Options.Credits + 250) / 500) * 500; 4656 transmit = 1; 4657 display = REDRAW_PARMS; 4658 break; 4659 4660 //.................................................................. 4661 // User adjusts # of AI players 4662 //.................................................................. 4663 case (BUTTON_AIPLAYERS | KN_BUTTON): 4664 Session.Options.AIPlayers = aiplayersgauge.Get_Value(); 4665 if (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) { // if it's pegged, max it out 4666 Session.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count(); 4667 aiplayersgauge.Set_Value(Session.Options.AIPlayers); 4668 } 4669 transmit = 1; 4670 display = REDRAW_PARMS; 4671 break; 4672 4673 //.................................................................. 4674 // Toggle-able options: 4675 // If 'Bases' gets toggled, we have to change the range of the 4676 // UnitCount slider. 4677 // Also, if Tiberium gets toggled, we have to set the flags 4678 // in SpecialClass. 4679 //.................................................................. 4680 case (BUTTON_OPTIONS | KN_BUTTON): 4681 if (Special.IsCaptureTheFlag != optionlist.Is_Checked(3) && !Special.IsCaptureTheFlag) { 4682 optionlist.Check_Item(0, true); 4683 } 4684 if (Session.Options.Bases != (optionlist.Is_Checked(0) ? 1 : 0)) { 4685 Session.Options.Bases = (optionlist.Is_Checked(0) ? 1 : 0); 4686 if (Session.Options.Bases) { 4687 Session.Options.UnitCount = Fixed_To_Cardinal ( 4688 SessionClass::CountMax[1] - 4689 SessionClass::CountMin[1], 4690 Cardinal_To_Fixed( 4691 SessionClass::CountMax[0]-SessionClass::CountMin[0], 4692 Session.Options.UnitCount-SessionClass::CountMin[0])) + 4693 SessionClass::CountMin[1]; 4694 } else { 4695 optionlist.Check_Item(3, false); 4696 Session.Options.UnitCount = Fixed_To_Cardinal ( 4697 SessionClass::CountMax[0] - 4698 SessionClass::CountMin[0], 4699 Cardinal_To_Fixed( 4700 SessionClass::CountMax[1]-SessionClass::CountMin[1], 4701 Session.Options.UnitCount - SessionClass::CountMin[1])) + 4702 SessionClass::CountMin[0]; 4703 } 4704 countgauge.Set_Maximum( 4705 SessionClass::CountMax[Session.Options.Bases] - 4706 SessionClass::CountMin[Session.Options.Bases]); 4707 countgauge.Set_Value(Session.Options.UnitCount - 4708 SessionClass::CountMin[Session.Options.Bases]); 4709 } 4710 Session.Options.Tiberium = optionlist.Is_Checked(1); 4711 Special.IsTGrowth = Session.Options.Tiberium; 4712 Rule.IsTGrowth = Session.Options.Tiberium; 4713 Special.IsTSpread = Session.Options.Tiberium; 4714 Rule.IsTSpread = Session.Options.Tiberium; 4715 4716 Session.Options.Goodies = optionlist.Is_Checked(2); 4717 Special.IsCaptureTheFlag = optionlist.Is_Checked(3); 4718 Special.IsShadowGrow = optionlist.Is_Checked(4); 4719 4720 transmit = 1; 4721 display = REDRAW_PARMS; 4722 break; 4723 4724 //.................................................................. 4725 // OK: exit loop with TRUE status 4726 //.................................................................. 4727 case (BUTTON_LOAD | KN_BUTTON): 4728 case (BUTTON_OK | KN_BUTTON): 4729 //............................................................... 4730 // If a new player has joined in the last second, don't allow 4731 // an OK; force a wait longer than 1 second (to give all players 4732 // a chance to know about this new guy) 4733 //............................................................... 4734 i = max(Ipx.Global_Response_Time() * 2, 60); 4735 while ((int)TickCount - ok_timer < i) { 4736 Ipx.Service(); 4737 } 4738 4739 //............................................................... 4740 // If there are at least 2 players, go ahead & play; error otherwise 4741 //............................................................... 4742 if (Session.Players.Count() > 1 ) { 4743 // if (Session.Players.Count() + Session.Options.AIPlayers > 1 ) { 4744 rc = TRUE; 4745 process = FALSE; 4746 } else { 4747 Session.Messages.Add_Message(NULL, 0, (char *)Text_String(TXT_ONLY_ONE), PCOLOR_BROWN, TPF_TEXT, 1200); 4748 Sound_Effect(VOC_SYS_ERROR); 4749 display = REDRAW_MESSAGE; 4750 } 4751 if (input==(BUTTON_LOAD | KN_BUTTON)) { 4752 load_game = 1; 4753 } else { 4754 load_game = 0; 4755 } 4756 break; 4757 4758 //.................................................................. 4759 // CANCEL: send a SIGN_OFF, bail out with error code 4760 //.................................................................. 4761 case (KN_ESC): 4762 case (BUTTON_CANCEL | KN_BUTTON): 4763 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 4764 4765 Session.GPacket.Command = NET_SIGN_OFF; 4766 strcpy (Session.GPacket.Name, Session.Handle); 4767 4768 //............................................................... 4769 // Broadcast my sign-off over my network 4770 //............................................................... 4771 Ipx.Send_Global_Message (&Session.GPacket, 4772 sizeof (GlobalPacketType), 0, NULL); 4773 Ipx.Send_Global_Message (&Session.GPacket, 4774 sizeof (GlobalPacketType), 0, NULL); 4775 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 4776 4777 //............................................................... 4778 // Broadcast my sign-off over a bridged network if there is one 4779 //............................................................... 4780 if (Session.IsBridge) { 4781 Ipx.Send_Global_Message (&Session.GPacket, 4782 sizeof(GlobalPacketType), 0, &Session.BridgeNet); 4783 Ipx.Send_Global_Message (&Session.GPacket, 4784 sizeof(GlobalPacketType), 0, &Session.BridgeNet); 4785 } 4786 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 4787 4788 //............................................................... 4789 // And now, just be absolutely sure, send my sign-off to each 4790 // player in my game. (If there's a bridge between us, the other 4791 // player will have specified my address, so he can cross the 4792 // bridge; but I may not have specified a bridge address, so the 4793 // only way I have of crossing the bridge is to send a packet 4794 // directly to him.) 4795 // Don't send this message to myself. 4796 //............................................................... 4797 for (i = 1; i < Session.Players.Count(); i++) { 4798 Ipx.Send_Global_Message (&Session.GPacket, 4799 sizeof(GlobalPacketType), 1, &(Session.Players[i]->Address)); 4800 Ipx.Service(); 4801 } 4802 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 4803 Session.GameName[0] = 0; 4804 process = false; 4805 rc = false; 4806 break; 4807 4808 //.................................................................. 4809 // Default: manage the inter-player messages 4810 //.................................................................. 4811 default: 4812 if (Session.Messages.Manage()) { 4813 display = REDRAW_MESSAGE; 4814 } 4815 4816 //............................................................... 4817 // Re-draw the messages & service keyboard input for any message 4818 // being edited. 4819 //............................................................... 4820 i = Session.Messages.Input(input); 4821 4822 //............................................................... 4823 // If 'Input' returned 1, it means refresh the message display. 4824 //............................................................... 4825 if (i==1) { 4826 Hide_Mouse(); 4827 Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, 4828 BOXSTYLE_BOX, true); // (erase the cursor) 4829 Session.Messages.Draw(); 4830 Show_Mouse(); 4831 } else if (i==2) { 4832 //............................................................... 4833 // If 'Input' returned 2, it means redraw the message display. 4834 //............................................................... 4835 Hide_Mouse(); 4836 Draw_Box(d_send_x, d_send_y, d_send_w, d_send_h, 4837 BOXSTYLE_BOX, true); // (erase the cursor) 4838 Session.Messages.Draw(); 4839 Show_Mouse(); 4840 } else if (i==3 || i==4) { 4841 //............................................................... 4842 // If 'input' returned 3, it means send the current message. 4843 //............................................................... 4844 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 4845 Session.GPacket.Command = NET_MESSAGE; 4846 strcpy (Session.GPacket.Name, Session.Handle); 4847 if (i==3) { 4848 strcpy (Session.GPacket.Message.Buf, 4849 Session.Messages.Get_Edit_Buf()); 4850 } else { 4851 strcpy (Session.GPacket.Message.Buf, 4852 Session.Messages.Get_Overflow_Buf()); 4853 Session.Messages.Clear_Overflow_Buf(); 4854 } 4855 Session.GPacket.Message.Color = Session.ColorIdx; 4856 Session.GPacket.Message.NameCRC = 4857 Compute_Name_CRC(Session.GameName); 4858 4859 //............................................................ 4860 // Send the message to every player in our player list, except 4861 // myself. 4862 //............................................................ 4863 for (i = 1; i < Session.Players.Count(); i++) { 4864 Ipx.Send_Global_Message (&Session.GPacket, 4865 sizeof(GlobalPacketType), 1, 4866 &(Session.Players[i]->Address)); 4867 Ipx.Service(); 4868 } 4869 4870 //............................................................ 4871 // Add the message to our own list, since we're not in the 4872 // player list on this dialog. 4873 // If there's no message with this ID already displayed, just 4874 // add a new message; if there is one, concatenate it. 4875 //............................................................ 4876 Session.Messages.Add_Message (Session.GPacket.Name, 4877 (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ? 4878 PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color, 4879 Session.GPacket.Message.Buf, 4880 (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? PCOLOR_REALLY_BLUE : Session.ColorIdx, 4881 TPF_TEXT, -1); 4882 4883 Session.Messages.Add_Edit((Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? 4884 PCOLOR_REALLY_BLUE : Session.ColorIdx, 4885 TPF_TEXT, NULL, '_', d_message_w); 4886 4887 display = REDRAW_MESSAGE; 4888 } 4889 break; 4890 } 4891 4892 //..................................................................... 4893 // Process incoming packets 4894 //..................................................................... 4895 #ifndef FIXIT_VERSION_3 4896 int oldversion = PlayingAgainstVersion; 4897 #endif 4898 whahoppa = Get_NewGame_Responses(&playerlist, color_used); 4899 if (whahoppa == EV_NEW_PLAYER) { 4900 ok_timer = TickCount; 4901 aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count()); 4902 Session.Options.AIPlayers = aiplayersgauge.Get_Value(); 4903 if (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) { // if it's pegged, max it out 4904 Session.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count(); 4905 aiplayersgauge.Set_Value(Session.Options.AIPlayers); 4906 } 4907 #ifdef FIXIT_VERSION_3 // All scenarios now allowable for download, regardless of if CS scen. or 126x126 scen. 4908 if (display < REDRAW_PARMS) display = REDRAW_PARMS; 4909 #else // FIXIT_VERSION_3 4910 if (oldversion == PlayingAgainstVersion){ 4911 if (display < REDRAW_PARMS) display = REDRAW_PARMS; 4912 }else{ 4913 4914 /* 4915 ** If a CS scenario was selected and we now have a red alert only player 4916 ** in the mix then deselect the cs scenario. 4917 */ 4918 #ifdef FIXIT_CSII // checked - ajw 4919 if ((PlayingAgainstVersion != VERSION_RED_ALERT_107 && PlayingAgainstVersion != VERSION_RED_ALERT_108 && PlayingAgainstVersion < VERSION_AFTERMATH_CS) && 4920 #else 4921 if (PlayingAgainstVersion < VERSION_RED_ALERT_107 && 4922 #endif 4923 Session.Scenarios[scenariolist.Current_Index()]->Get_Expansion()){ 4924 scenariolist.Set_Selected_Index (0); 4925 Session.Options.ScenarioIndex = scenariolist.Current_Index(); 4926 } 4927 #ifdef FIXIT_CSII // checked - ajw 4928 /* 4929 ** If an AM mega scenario was selected and we now have a non-AM 4930 ** player in the mix then deselect the mega scenario. 4931 */ 4932 if (PlayingAgainstVersion < VERSION_AFTERMATH_CS && 4933 Is_Mission_126x126((char *)Session.Scenarios[scenariolist.Current_Index()]->Get_Filename() ) ){ 4934 scenariolist.Set_Selected_Index (0); 4935 Session.Options.ScenarioIndex = scenariolist.Current_Index(); 4936 } 4937 #endif 4938 display = REDRAW_BACKGROUND; 4939 } 4940 #endif // FIXIT_VERSION_3 4941 4942 transmit = 1; 4943 } else if (whahoppa == EV_MESSAGE) { 4944 display = REDRAW_MESSAGE; 4945 } else if (whahoppa == EV_PLAYER_SIGNOFF) { 4946 aiplayersgauge.Set_Maximum(Rule.MaxPlayers-Session.Players.Count()); 4947 Session.Options.AIPlayers = aiplayersgauge.Get_Value(); 4948 if (Session.Options.AIPlayers+Session.Players.Count() > Rule.MaxPlayers) { // if it's pegged, max it out 4949 Session.Options.AIPlayers = Rule.MaxPlayers - Session.Players.Count(); 4950 aiplayersgauge.Set_Value(Session.Options.AIPlayers); 4951 display = REDRAW_PARMS; 4952 } 4953 transmit = 1; 4954 } 4955 4956 //..................................................................... 4957 // If our Transmit flag is set, we need to send out a game option packet 4958 // Don't send it to myself. 4959 //..................................................................... 4960 if (transmit) { 4961 for (i = 1; i < Session.Players.Count(); i++) { 4962 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 4963 4964 Session.GPacket.Command = NET_GAME_OPTIONS; 4965 4966 /* 4967 ** Set up the scenario info so the remote player can match the scenario on his machine 4968 ** or request a download if it doesnt exist 4969 */ 4970 strcpy (Session.GPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description()); 4971 CCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename()); 4972 Session.GPacket.ScenarioInfo.FileLength = file.Size(); 4973 #ifdef WOLAPI_INTEGRATION 4974 strcpy( Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() ); 4975 #else 4976 strncpy (Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(Session.GPacket.ScenarioInfo.ShortFileName)); 4977 #endif 4978 strncpy ((char*)Session.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof (Session.GPacket.ScenarioInfo.FileDigest)); 4979 Session.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official(); 4980 4981 Session.GPacket.ScenarioInfo.Credits = Session.Options.Credits; 4982 Session.GPacket.ScenarioInfo.IsBases = Session.Options.Bases; 4983 Session.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium; 4984 Session.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies; 4985 Session.GPacket.ScenarioInfo.BuildLevel = BuildLevel; 4986 Session.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount; 4987 Session.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers; 4988 Session.GPacket.ScenarioInfo.Seed = Seed; 4989 Session.GPacket.ScenarioInfo.Special = Special; 4990 Session.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed; 4991 #ifdef FIXIT_VERSION_3 4992 Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version(); 4993 // Host encodes whether or not this is an Aftermath game in the highest bit. 4994 if( bAftermathMultiplayer ) 4995 { 4996 // debugprint( "Host tells guests 'This is an Aftermath game'\n" ); 4997 Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version() | 0x80000000; 4998 } 4999 else 5000 { 5001 // debugprint( "Host tells guests 'This is NOT an Aftermath game'\n" ); 5002 Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version(); 5003 } 5004 #else 5005 Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version(); 5006 #endif 5007 5008 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 5009 1, &(Session.Players[i]->Address) ); 5010 } 5011 Sound_Effect(VOC_OPTIONS_CHANGED); 5012 transmit = 0; 5013 } 5014 5015 //..................................................................... 5016 // Ping every player in my game, to force the Global Channel to measure 5017 // the connection response time. Don't ping myself (index 0). 5018 //..................................................................... 5019 if (TickCount - ping_timer > 15) { 5020 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 5021 Session.GPacket.Command = NET_PING; 5022 for (i = 1; i < Session.Players.Count(); i++) { 5023 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 5024 1, &(Session.Players[i]->Address) ); 5025 } 5026 ping_timer = TickCount; 5027 } 5028 5029 //..................................................................... 5030 // Service the Ipx connections 5031 //..................................................................... 5032 Ipx.Service(); 5033 5034 //..................................................................... 5035 // Service the sounds & score; GameActive must be false at this point, 5036 // so Call_Back() doesn't intercept global messages from me! 5037 //..................................................................... 5038 Call_Back(); 5039 } 5040 5041 //------------------------------------------------------------------------ 5042 // Prepare to load the scenario 5043 //------------------------------------------------------------------------ 5044 if (rc) { 5045 //..................................................................... 5046 // Set the player count & scenario number 5047 //..................................................................... 5048 Session.NumPlayers = Session.Players.Count(); 5049 5050 Scen.Scenario = Session.Options.ScenarioIndex; 5051 strcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename()); 5052 5053 //..................................................................... 5054 // Compute frame delay value for packet transmissions: 5055 // - Divide global channel's response time by 8 (2 to convert to 1-way 5056 // value, 4 more to convert from ticks to frames) 5057 //..................................................................... 5058 if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) { 5059 Session.MaxAhead = max( ((((Ipx.Global_Response_Time() / 8) + 5060 (Session.FrameSendRate - 1)) / Session.FrameSendRate) * 5061 Session.FrameSendRate), (Session.FrameSendRate * 2) ); 5062 } 5063 else { 5064 Session.MaxAhead = max( (Ipx.Global_Response_Time() / 8), 5065 NETWORK_MIN_MAX_AHEAD ); 5066 } 5067 5068 Ipx.Set_Timing (25, (unsigned long) -1, 1000); 5069 5070 //..................................................................... 5071 // Send all players the NET_GO packet. Wait until all ACK's have been 5072 // received. 5073 //..................................................................... 5074 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 5075 if (load_game) 5076 Session.GPacket.Command = NET_LOADGAME; 5077 else 5078 Session.GPacket.Command = NET_GO; 5079 Session.GPacket.ResponseTime.OneWay = Session.MaxAhead; 5080 for (i = 1; i < Session.Players.Count(); i++) { 5081 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 5082 1, &(Session.Players[i]->Address) ); 5083 } 5084 //..................................................................... 5085 // Wait for all the ACK's to come in. 5086 //..................................................................... 5087 while (Ipx.Global_Num_Send() > 0) { 5088 Ipx.Service(); 5089 } 5090 5091 /* 5092 ** Wait for the go responses from each player in case someone needs the scenario 5093 ** file to be sent. 5094 */ 5095 int responses[20]; //In big trub if more than 20 players 5096 memset (responses, 0, sizeof (responses)); 5097 int num_responses = 0; 5098 bool send_scenario = false; 5099 #ifdef WIN32 5100 WWDebugString ("RA95 - About to wait for 'GO' response."); 5101 #endif 5102 CDTimerClass<SystemTimerClass> response_timer; // timeout timer for waiting for responses 5103 response_timer = 60*10; // Wait for 10 seconds. If we dont hear by then assume someone crashed 5104 5105 do { 5106 Ipx.Service(); 5107 int retcode = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen, 5108 &Session.GAddress, &Session.GProductID); 5109 if (retcode && Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) { 5110 5111 for ( i=1 ; i<Session.Players.Count() ; i++ ) { 5112 if (Session.Players[i]->Address == Session.GAddress) { 5113 if (!responses[i]) { 5114 if (Session.GPacket.Command == NET_REQ_SCENARIO) { 5115 responses[i] = Session.GPacket.Command; 5116 send_scenario = true; 5117 num_responses++; 5118 } 5119 if (Session.GPacket.Command == NET_READY_TO_GO) { 5120 responses[i] = Session.GPacket.Command; 5121 num_responses++; 5122 } 5123 } 5124 } 5125 } 5126 } 5127 } while ( num_responses < Session.Players.Count()-1 && response_timer ); 5128 5129 #ifdef FIXIT_VERSION_3 5130 if( Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official() ) 5131 { 5132 if( !Force_Scenario_Available( Scen.ScenarioName ) ) 5133 Emergency_Exit(EXIT_FAILURE); 5134 } 5135 #endif 5136 5137 /* 5138 ** If one of the machines requested that the scenario be sent then send it. 5139 */ 5140 if (send_scenario) { 5141 memset (Session.ScenarioRequests, 0, sizeof (Session.ScenarioRequests)); 5142 Session.RequestCount = 0; 5143 for ( i=1 ; i<Session.Players.Count() ; i++ ) { 5144 if (responses[i] == NET_REQ_SCENARIO) { 5145 Session.ScenarioRequests[Session.RequestCount++] = i; 5146 } 5147 } 5148 Send_Remote_File (Scen.ScenarioName, 1); 5149 } 5150 } 5151 5152 //------------------------------------------------------------------------ 5153 // Init network timing values, using previous response times as a measure 5154 // of what our retry delta & timeout should be. 5155 //------------------------------------------------------------------------ 5156 //Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1, Ipx.Global_Response_Time() * 4); 5157 Ipx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8)); 5158 5159 //------------------------------------------------------------------------ 5160 // Clear all lists, but NOT the Games or Players vectors. 5161 //------------------------------------------------------------------------ 5162 while (scenariolist.Count()) { 5163 scenariolist.Remove_Item(scenariolist.Get_Item(0)); 5164 } 5165 Clear_Listbox(&playerlist); 5166 5167 //------------------------------------------------------------------------ 5168 // Remove the chat edit box 5169 //------------------------------------------------------------------------ 5170 Session.Messages.Remove_Edit(); 5171 5172 //------------------------------------------------------------------------ 5173 // Restore screen 5174 //------------------------------------------------------------------------ 5175 Hide_Mouse(); 5176 Load_Title_Page(true); 5177 //#ifdef WIN32 5178 // Load_Uncompress(CCFileClass("TITLE.CPS"), SysMemPage, SysMemPage, CCPalette); 5179 // SysMemPage.Scale(SeenPage); 5180 //#else 5181 // Load_Uncompress(CCFileClass("TITLE.CPS"), HidPage, HidPage, CCPalette); 5182 // HidPage.Blit(SeenPage); 5183 //#endif //WIN32 5184 Show_Mouse(); 5185 5186 if (load_game) { 5187 if (!Load_Game (-1)) { 5188 WWMessageBox().Process (TXT_ERROR_LOADING_GAME); 5189 rc = false; 5190 } 5191 Frame++; 5192 } 5193 5194 //------------------------------------------------------------------------ 5195 // Clear the Players vector if we're not starting a game. 5196 //------------------------------------------------------------------------ 5197 if (!rc) { 5198 Clear_Vector(&Session.Players); 5199 } 5200 5201 // while (optionlist.Count()>0) { 5202 // item = (char *)optionlist.Get_Item(0); 5203 // delete [] item; 5204 // optionlist.Remove_Item(item); 5205 // } 5206 5207 return(rc); 5208 #endif 5209 } /* end of Net_New_Dialog */ 5210 5211 5212 /*************************************************************************** 5213 * Get_NewGame_Responses -- processes packets for New Game dialog * 5214 * * 5215 * This routine can modify the contents of the given list box, as well * 5216 * as the contents of the Players Vector global. * 5217 * * 5218 * INPUT: * 5219 * playerlist list of players in this game * 5220 * color_used array of color-used flags * 5221 * * 5222 * OUTPUT: * 5223 * EV_NONE = nothing happened * 5224 * EV_NEW_PLAYER = a new player has joined; false otherwise * 5225 * EV_PLAYER_SIGNOFF = a player has left * 5226 * EV_MESSAGE = a message was received * 5227 * * 5228 * WARNINGS: * 5229 * none. * 5230 * * 5231 * HISTORY: * 5232 * 04/18/1995 BRR : Created. * 5233 *=========================================================================*/ 5234 static JoinEventType Get_NewGame_Responses(ColorListClass *playerlist, 5235 int *color_used) 5236 { 5237 int rc; 5238 char * item; // general-purpose string 5239 NodeNameType *who; // node to add to Players Vector 5240 int i; 5241 int found; 5242 JoinEventType retval = EV_NONE; 5243 int resend; 5244 unsigned long version; // version # to use 5245 5246 //------------------------------------------------------------------------ 5247 // If there is no incoming packet, just return 5248 //------------------------------------------------------------------------ 5249 rc = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen, 5250 &Session.GAddress, &Session.GProductID); 5251 if (!rc || Session.GProductID != IPXGlobalConnClass::COMMAND_AND_CONQUER0) { 5252 return(EV_NONE); 5253 } 5254 5255 //------------------------------------------------------------------------ 5256 // Try to handle the packet in a standard way 5257 //------------------------------------------------------------------------ 5258 if (Process_Global_Packet(&Session.GPacket,&Session.GAddress) != 0) { 5259 return(EV_NONE); 5260 } else if (Session.GPacket.Command==NET_QUERY_JOIN) { 5261 //------------------------------------------------------------------------ 5262 // NET_QUERY_JOIN: 5263 //------------------------------------------------------------------------ 5264 //..................................................................... 5265 // See if this name is unique: 5266 // - If the name matches, but the address is different, reject this player 5267 // - If the name & address match, this packet must be a re-send of a 5268 // previous request; in this case, do nothing. The other player must have 5269 // received my CONFIRM_JOIN packet (since it was sent with an ACK 5270 // required), so we can ignore this resend. 5271 //..................................................................... 5272 found = 0; 5273 resend = 0; 5274 for (i = 1; i < Session.Players.Count(); i++) { 5275 if (!strcmp(Session.Players[i]->Name,Session.GPacket.Name)) { 5276 if (Session.Players[i]->Address != Session.GAddress) { 5277 found = 1; 5278 } 5279 else { 5280 resend = 1; 5281 } 5282 break; 5283 } 5284 } 5285 //..................................................................... 5286 // If his name is the same as mine, treat it like a duplicate name 5287 //..................................................................... 5288 if (!strcmp (Session.Players[0]->Name, Session.GPacket.Name)) { 5289 found = 1; 5290 } 5291 5292 //..................................................................... 5293 // Reject if name is a duplicate 5294 //..................................................................... 5295 if (found) { 5296 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 5297 Session.GPacket.Command = NET_REJECT_JOIN; 5298 Session.GPacket.Reject.Why = (int)REJECT_DUPLICATE_NAME; 5299 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 5300 1, &Session.GAddress); 5301 return(EV_NONE); 5302 } 5303 5304 //..................................................................... 5305 // Reject if there are too many players 5306 //..................................................................... 5307 else if ( (Session.Players.Count() >= Session.MaxPlayers) && !resend) { 5308 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 5309 Session.GPacket.Command = NET_REJECT_JOIN; 5310 Session.GPacket.Reject.Why = (int)REJECT_GAME_FULL; 5311 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 5312 1, &Session.GAddress); 5313 return(EV_NONE); 5314 } 5315 5316 /* 5317 ** Don't allow joining if the rules.ini file doesn't appear to match. 5318 */ 5319 else if (Session.GPacket.PlayerInfo.CheatCheck != RuleINI.Get_Unique_ID() && !resend) { 5320 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 5321 Session.GPacket.Command = NET_REJECT_JOIN; 5322 Session.GPacket.Reject.Why = (int)REJECT_MISMATCH; 5323 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 1, &Session.GAddress); 5324 return(EV_NONE); 5325 } 5326 5327 //..................................................................... 5328 // If this packet is NOT a resend, accept the player. Grant him the 5329 // requested color if possible. 5330 //..................................................................... 5331 else if (!resend) { 5332 //.................................................................. 5333 // Check the player's version range against our own, to see if 5334 // there's an overlap region 5335 //.................................................................. 5336 #ifdef FIXIT_VERSION_3 5337 // Added to the transmitted _min_ version number is a bit indicating presence of Aftermath expansion. 5338 bool bGuestHasAftermath = Session.GPacket.PlayerInfo.MinVersion & 0x80000000; 5339 if( bGuestHasAftermath ) 5340 // debugprint( "Host hears guest say 'I have Aftermath'\n" ); 5341 ; 5342 else 5343 { 5344 // debugprint( "Host hears guest say 'I don't have Aftermath'\n" ); 5345 if( bAftermathMultiplayer ) 5346 { 5347 // debugprint( "Host decides this is no longer an Aftermath game!\n" ); 5348 bAftermathMultiplayer = false; 5349 } 5350 } 5351 5352 Session.GPacket.PlayerInfo.MinVersion &= ~0x80000000; // Strip special bit. 5353 #endif 5354 version = VerNum.Clip_Version (Session.GPacket.PlayerInfo.MinVersion, 5355 Session.GPacket.PlayerInfo.MaxVersion); 5356 5357 #ifndef FIXIT_VERSION_3 5358 PlayingAgainstVersion = version; 5359 #endif 5360 5361 // TCTCTC save off version number 5362 5363 //.................................................................. 5364 // Reject player if his version is too old 5365 //.................................................................. 5366 if (version == 0) { 5367 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 5368 Session.GPacket.Command = NET_REJECT_JOIN; 5369 Session.GPacket.Reject.Why = (int)REJECT_VERSION_TOO_OLD; 5370 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 5371 1, &Session.GAddress); 5372 return(EV_NONE); 5373 } 5374 5375 //.................................................................. 5376 // Reject player if his version is too new 5377 //.................................................................. 5378 else if (version == 0xffffffff) { 5379 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 5380 Session.GPacket.Command = NET_REJECT_JOIN; 5381 Session.GPacket.Reject.Why = (int)REJECT_VERSION_TOO_NEW; 5382 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 5383 1, &Session.GAddress); 5384 return(EV_NONE); 5385 } 5386 //.................................................................. 5387 // If the player is accepted, our mutually-accepted version may be 5388 // different; set the CommProtocol accordingly. 5389 //.................................................................. 5390 else { 5391 Session.CommProtocol = VerNum.Version_Protocol(version); 5392 } 5393 5394 //.................................................................. 5395 // Add node to the Vector list 5396 //.................................................................. 5397 who = new NodeNameType; 5398 strcpy(who->Name, Session.GPacket.Name); 5399 who->Address = Session.GAddress; 5400 who->Player.House = Session.GPacket.PlayerInfo.House; 5401 Session.Players.Add (who); 5402 5403 //.................................................................. 5404 // Set player's color; if requested color isn't used, give it to him; 5405 // otherwise, give him the 1st available color. Mark the color we 5406 // give him as used. 5407 //.................................................................. 5408 if (color_used[Session.GPacket.PlayerInfo.Color] == 0) { 5409 who->Player.Color = Session.GPacket.PlayerInfo.Color; 5410 } 5411 else { 5412 for (i = 0; i < MAX_MPLAYER_COLORS; i++) { 5413 if (color_used[i]==0) { 5414 who->Player.Color = (PlayerColorType)i; 5415 break; 5416 } 5417 } 5418 } 5419 color_used[who->Player.Color] = 1; 5420 5421 //.................................................................. 5422 // Add player name to the list box 5423 //.................................................................. 5424 item = new char [MPLAYER_NAME_MAX + 64]; 5425 #ifdef OLDWAY 5426 if (Session.GPacket.PlayerInfo.House==HOUSE_GOOD) { 5427 sprintf(item,"%s\t%s",Session.GPacket.Name, Text_String(TXT_ALLIES)); 5428 } 5429 else { 5430 sprintf(item,"%s\t%s",Session.GPacket.Name, Text_String(TXT_SOVIET)); 5431 } 5432 #else //OLDWAY 5433 sprintf (item, "%s\t%s", Session.GPacket.Name, 5434 Text_String(HouseTypeClass::As_Reference(Session.GPacket.PlayerInfo.House).Full_Name())); 5435 #endif //OLDWAY 5436 playerlist->Add_Item(item, 5437 (who->Player.Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[who->Player.Color]); 5438 5439 //.................................................................. 5440 // Send a confirmation packet 5441 //.................................................................. 5442 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 5443 5444 Session.GPacket.Command = NET_CONFIRM_JOIN; 5445 strcpy(Session.GPacket.Name,Session.Handle); 5446 Session.GPacket.PlayerInfo.House = who->Player.House; 5447 Session.GPacket.PlayerInfo.Color = who->Player.Color; 5448 5449 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 5450 1, &Session.GAddress); 5451 5452 //.................................................................. 5453 // Play a special sound. 5454 //.................................................................. 5455 Sound_Effect(VOC_PLAYER_JOINED); 5456 5457 retval = EV_NEW_PLAYER; 5458 } 5459 } 5460 5461 //------------------------------------------------------------------------ 5462 // NET_SIGN_OFF: Another system is signing off: search for that system in 5463 // the player list, & remove it if found 5464 //------------------------------------------------------------------------ 5465 else if (Session.GPacket.Command==NET_SIGN_OFF) { 5466 for (i = 0; i < Session.Players.Count(); i++) { 5467 5468 //.................................................................. 5469 // Name found; remove it 5470 //.................................................................. 5471 if (!strcmp (Session.Players[i]->Name, Session.GPacket.Name) && 5472 Session.Players[i]->Address==Session.GAddress) { 5473 5474 //............................................................... 5475 // Remove from the list box 5476 //............................................................... 5477 item = (char *)(playerlist->Get_Item(i)); 5478 playerlist->Remove_Item(item); 5479 playerlist->Flag_To_Redraw(); 5480 delete [] item; 5481 5482 //............................................................... 5483 // Mark his color as available 5484 //............................................................... 5485 color_used[Session.Players[i]->Player.Color] = 0; 5486 5487 //............................................................... 5488 // Delete from the Vector list 5489 //............................................................... 5490 delete Session.Players[i]; 5491 Session.Players.Delete(Session.Players[i]); 5492 5493 //............................................................... 5494 // Play a special sound. 5495 //............................................................... 5496 Sound_Effect(VOC_PLAYER_LEFT); 5497 5498 retval = EV_PLAYER_SIGNOFF; 5499 5500 break; 5501 } 5502 } 5503 } 5504 5505 //------------------------------------------------------------------------ 5506 // NET_MESSAGE: Someone is sending us a message 5507 //------------------------------------------------------------------------ 5508 else if (Session.GPacket.Command==NET_MESSAGE) { 5509 Session.Messages.Add_Message (Session.GPacket.Name, 5510 (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ? 5511 PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color, 5512 Session.GPacket.Message.Buf, 5513 (Session.GPacket.Message.Color == PCOLOR_DIALOG_BLUE) ? 5514 PCOLOR_REALLY_BLUE : Session.GPacket.Message.Color, 5515 TPF_TEXT, -1); 5516 5517 Sound_Effect(VOC_INCOMING_MESSAGE); 5518 5519 retval = EV_MESSAGE; 5520 } 5521 5522 return(retval); 5523 5524 } /* end of Get_NewGame_Responses */ 5525 5526 5527 /*************************************************************************** 5528 * Compute_Name_CRC -- computes CRC from char string * 5529 * * 5530 * INPUT: * 5531 * name string to create CRC for * 5532 * * 5533 * OUTPUT: * 5534 * CRC * 5535 * * 5536 * WARNINGS: * 5537 * none. * 5538 * * 5539 * HISTORY: * 5540 * 06/29/1995 BRR : Created. * 5541 *=========================================================================*/ 5542 unsigned long Compute_Name_CRC(char *name) 5543 { 5544 char buf[80]; 5545 unsigned long crc = 0L; 5546 int i; 5547 5548 strcpy (buf, name); 5549 strupr (buf); 5550 5551 for (i = 0; i < (int)strlen(buf); i++) { 5552 Add_CRC (&crc, (unsigned long)buf[i]); 5553 } 5554 5555 return (crc); 5556 5557 } /* end of Compute_Name_CRC */ 5558 5559 5560 /*************************************************************************** 5561 * Net_Reconnect_Dialog -- Draws/updates the network reconnect dialog * 5562 * * 5563 * INPUT: * 5564 * reconn 1 = reconnect, 0 = waiting for first-time connection * 5565 * fresh 1 = draw from scratch, 0 = only update time counter * 5566 * oldest_index IPX connection index of oldest connection * 5567 * (only used for reconnection) * 5568 * timeval value to print in the countdown field * 5569 * * 5570 * OUTPUT: * 5571 * none. * 5572 * * 5573 * WARNINGS: * 5574 * none. * 5575 * * 5576 * HISTORY: * 5577 * 07/08/1995 BRR : Created. * 5578 *=========================================================================*/ 5579 void Net_Reconnect_Dialog(int reconn, int fresh, int oldest_index, 5580 unsigned long timeval) 5581 { 5582 reconn; fresh; oldest_index; timeval; 5583 #if (0)//PG 5584 static int x,y,w,h; 5585 int id; 5586 char buf1[40] = {0}; 5587 char buf2[40] = {0}; 5588 char const *buf3 = ""; 5589 5590 int d_txt6_h = 6 * RESFACTOR+1; 5591 int d_margin = 5 * RESFACTOR; 5592 5593 RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); 5594 5595 #ifdef WIN32 5596 /* 5597 ** If we have just received input focus again after running in the background then 5598 ** we need to redraw. 5599 */ 5600 if (AllSurfaces.SurfacesRestored) { 5601 AllSurfaces.SurfacesRestored=FALSE; 5602 fresh = true; 5603 } 5604 #endif 5605 5606 //------------------------------------------------------------------------ 5607 // Draw the dialog from scratch 5608 //------------------------------------------------------------------------ 5609 if (fresh) { 5610 Fancy_Text_Print("", 0, 0, scheme, TBLACK, TPF_CENTER | TPF_TEXT); 5611 5612 switch ( Session.Type) { 5613 case GAME_IPX: 5614 case GAME_INTERNET: 5615 case GAME_MODEM: 5616 case GAME_NULL_MODEM: 5617 5618 if (reconn) { 5619 id = Ipx.Connection_ID(oldest_index); 5620 sprintf(buf1,Text_String(TXT_RECONNECTING_TO), 5621 Ipx.Connection_Name(id)); 5622 } else { 5623 sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS)); 5624 } 5625 break; 5626 5627 #if(TEN) 5628 case GAME_TEN: 5629 if (reconn) { 5630 id = Ten->Connection_ID(oldest_index); 5631 sprintf(buf1,Text_String(TXT_RECONNECTING_TO), 5632 Ten->Connection_Name(id)); 5633 } 5634 else { 5635 sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS)); 5636 } 5637 #endif // TEN 5638 5639 #if(MPATH) 5640 case GAME_MPATH: 5641 if (reconn) { 5642 id = MPath->Connection_ID(oldest_index); 5643 sprintf(buf1,Text_String(TXT_RECONNECTING_TO), 5644 MPath->Connection_Name(id)); 5645 } 5646 else { 5647 sprintf(buf1,Text_String(TXT_WAITING_FOR_CONNECTIONS)); 5648 } 5649 #endif // MPATH 5650 } 5651 5652 sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1); 5653 buf3 = Text_String(TXT_PRESS_ESC); 5654 5655 w = max(String_Pixel_Width(buf1),String_Pixel_Width(buf2)); 5656 5657 #ifdef FIXIT_VERSION_3 5658 char szNewCancelMessage[ 300 ]; 5659 sprintf( szNewCancelMessage, "%s%s", buf3, TXT_WOL_CANCELMEANSFORFEIT ); 5660 5661 if( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament ) 5662 { 5663 w = max(String_Pixel_Width(szNewCancelMessage), w); // * RESFACTOR; why was it ever multiplied by this!!!? 5664 w += (d_margin * 12); 5665 } 5666 else 5667 { 5668 w = max(String_Pixel_Width(buf3), w) * RESFACTOR; 5669 w += (d_margin * 5); 5670 } 5671 #else 5672 w = max(String_Pixel_Width(buf3), w) * RESFACTOR; 5673 w += (d_margin * 5); 5674 #endif 5675 5676 h = (d_txt6_h * 3) + (d_margin * 6); 5677 x = 160*RESFACTOR - (w / 2); 5678 y = 100*RESFACTOR - (h / 2); 5679 5680 Hide_Mouse(); 5681 Set_Logic_Page(SeenBuff); 5682 Dialog_Box(x, y, w, h); 5683 5684 Fancy_Text_Print (buf1, 160*RESFACTOR, y + (d_margin * 2), scheme, TBLACK, TPF_CENTER | TPF_TEXT); 5685 5686 Fancy_Text_Print (buf2, 160*RESFACTOR, y + (d_margin * 2) + d_txt6_h + d_margin, scheme, TBLACK, TPF_CENTER | TPF_TEXT); 5687 5688 #ifdef FIXIT_VERSION_3 5689 if( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament ) 5690 Fancy_Text_Print (szNewCancelMessage, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT); 5691 else 5692 Fancy_Text_Print (buf3, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT); 5693 #else 5694 Fancy_Text_Print (buf3, 160*RESFACTOR, y + (d_margin * 2) + (d_txt6_h + d_margin) * 2, scheme, TBLACK, TPF_CENTER | TPF_TEXT); 5695 #endif 5696 5697 Show_Mouse(); 5698 } 5699 //------------------------------------------------------------------------ 5700 // Just update the timeout value on the dialog 5701 //------------------------------------------------------------------------ 5702 else { 5703 Hide_Mouse(); 5704 Set_Logic_Page(SeenBuff); 5705 5706 sprintf(buf2,Text_String(TXT_TIME_ALLOWED), timeval + 1); 5707 5708 int fillx = 160*RESFACTOR - (String_Pixel_Width (buf2) / 2) -6; 5709 LogicPage->Fill_Rect (fillx, y + (d_margin * 2) + d_txt6_h + d_margin, 5710 fillx + String_Pixel_Width (buf2) + 12, 5711 y + (d_margin * 2) + d_txt6_h + d_margin + d_txt6_h +1*RESFACTOR, 5712 BLACK); 5713 5714 Fancy_Text_Print (buf2, 160*RESFACTOR, y + (d_margin * 2) + d_txt6_h + d_margin, scheme, BLACK, TPF_CENTER | TPF_TEXT); 5715 5716 Show_Mouse(); 5717 } 5718 #endif 5719 } /* end of Net_Reconnect_Dialog */ 5720 5721 #define MAX_CHAT_NAME 12 5722 #define MAX_CHAT_PHRASE 45 5723 5724 struct WWPerson { 5725 char Name[MAX_CHAT_NAME]; 5726 char Phrase[MAX_CHAT_PHRASE]; 5727 PlayerColorType Color; 5728 unsigned long LastTime; 5729 }; 5730 5731 struct WWPerson WWPersons[] = { 5732 { {66,105,108,108,32,82,0,0,0,0,0,0,}, 5733 {72,101,121,44,32,105,115,110,39,116,32,116,104,105,115,32,99,111,111,108,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5734 { {66,105,108,108,32,82,0,0,0,0,0,0,}, 5735 {72,101,121,44,32,119,97,110,116,32,115,111,109,101,32,115,101,97,102,111,111,100,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5736 { {66,97,114,114,121,32,71,0,0,0,0,0,}, 5737 {71,114,101,97,116,46,32,74,117,115,116,32,103,114,101,97,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5738 { {66,97,114,114,121,32,71,0,0,0,0,0,}, 5739 {87,111,110,100,101,114,102,117,108,46,32,80,101,114,102,101,99,116,44,32,105,110,32,102,97,99,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5740 { {66,105,108,108,32,80,0,0,0,0,0,0,}, 5741 {89,111,117,32,99,97,108,108,32,116,104,105,115,32,65,73,63,32,32,83,104,101,101,115,104,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5742 { {66,105,108,108,32,80,0,0,0,0,0,0,}, 5743 {66,105,108,108,115,32,114,117,108,101,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5744 { {66,114,101,116,116,32,83,0,0,0,0,0,}, 5745 {84,97,107,101,32,116,104,105,115,32,111,117,116,44,32,110,111,119,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5746 { {66,114,101,116,116,32,83,0,0,0,0,0,}, 5747 {87,104,121,32,99,97,110,39,116,32,121,111,117,32,102,105,116,32,97,110,121,32,109,111,114,101,32,108,101,116,116,101,114,115,32,111,110,32,116,104,101,32,108,0,0,},PCOLOR_GREEN,0}, 5748 { {66,114,101,116,116,32,83,0,0,0,0,0,}, 5749 {69,100,44,32,73,32,119,97,110,116,32,116,111,32,116,97,108,107,32,116,111,32,121,111,117,32,97,98,111,117,116,32,116,104,105,115,46,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5750 { {66,114,101,116,116,32,83,0,0,0,0,0,}, 5751 {69,100,44,32,99,111,109,101,32,116,111,32,109,121,32,111,102,102,105,99,101,44,32,110,111,119,33,32,32,91,99,114,97,99,107,33,93,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5752 { {80,101,110,105,110,97,32,70,0,0,0,0,}, 5753 {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,115,116,97,112,108,101,114,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5754 { {80,101,110,105,110,97,32,70,0,0,0,0,}, 5755 {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,116,104,101,115,97,117,114,117,115,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5756 { {80,101,110,105,110,97,32,70,0,0,0,0,}, 5757 {72,97,115,32,97,110,121,111,110,101,32,115,101,101,110,32,109,121,32,112,101,110,99,105,108,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5758 { {77,105,108,111,32,66,0,0,0,0,0,0,}, 5759 {72,101,121,32,83,116,101,118,101,44,32,99,97,110,32,119,101,32,109,101,101,116,32,105,110,32,121,111,117,114,32,111,102,102,105,99,101,63,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5760 { {77,105,108,111,32,66,0,0,0,0,0,0,}, 5761 {83,116,101,118,101,44,32,105,116,39,108,108,32,111,110,108,121,32,116,97,107,101,32,97,32,109,105,110,117,116,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5762 { {82,111,98,32,83,0,0,0,0,0,0,0,}, 5763 {77,105,108,111,44,32,100,105,97,108,32,50,52,57,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5764 { {69,108,115,98,101,116,104,32,87,0,0,0,}, 5765 {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,119,105,116,104,32,97,110,32,69,45,76,45,83,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5766 { {69,108,115,98,101,116,104,32,87,0,0,0,}, 5767 {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,110,111,116,32,39,69,108,115,98,97,114,102,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5768 { {69,108,115,98,101,116,104,32,87,0,0,0,}, 5769 {84,104,97,116,39,115,32,39,69,108,115,98,101,116,104,39,44,32,110,111,116,32,39,69,108,102,98,117,116,116,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5770 { {75,97,114,101,110,32,71,0,0,0,0,0,}, 5771 {84,104,105,115,32,105,115,32,115,111,111,111,32,119,101,105,114,100,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5772 { {75,97,114,101,110,32,71,0,0,0,0,0,}, 5773 {68,117,104,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5774 { {80,104,105,108,32,71,0,0,0,0,0,0,}, 5775 {72,101,121,44,32,105,116,32,119,111,114,107,101,100,32,111,110,32,109,121,32,99,111,109,112,117,116,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5776 { {80,104,105,108,32,71,0,0,0,0,0,0,}, 5777 {84,104,105,115,32,116,104,105,110,103,32,105,115,32,99,108,101,97,114,108,121,32,97,32,119,97,115,116,101,32,111,102,32,109,101,109,111,114,121,46,0,0,0,0,0,},PCOLOR_GREEN,0}, 5778 { {74,111,101,32,66,0,0,0,0,0,0,0,}, 5779 {72,109,109,44,32,73,32,115,101,101,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5780 { {74,111,101,32,66,0,0,0,0,0,0,0,}, 5781 {65,104,104,44,32,121,101,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5782 { {77,97,114,105,97,32,68,77,77,76,0,0,}, 5783 {78,111,116,32,97,110,111,116,104,101,114,32,105,110,115,116,97,108,108,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5784 { {77,97,114,105,97,32,68,77,77,76,0,0,}, 5785 {72,65,32,72,65,32,72,65,32,72,65,32,72,65,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5786 { {77,105,107,101,32,76,0,0,0,0,0,0,}, 5787 {84,104,105,115,32,105,115,32,114,101,97,108,108,121,32,99,111,111,108,33,32,32,71,111,115,104,32,103,117,121,115,33,32,32,87,111,119,33,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5788 { {77,105,107,101,32,76,0,0,0,0,0,0,}, 5789 {87,111,119,33,32,32,89,111,117,32,103,117,121,115,32,97,114,101,32,116,104,101,32,103,114,101,97,116,101,115,116,33,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5790 { {77,105,107,101,32,71,0,0,0,0,0,0,}, 5791 {71,114,97,121,102,105,115,104,32,102,111,114,32,108,117,110,99,104,32,97,103,97,105,110,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5792 { {77,105,107,101,32,71,0,0,0,0,0,0,}, 5793 {84,104,105,115,32,105,115,32,108,97,109,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5794 { {71,108,101,110,110,32,83,0,0,0,0,0,}, 5795 {84,104,105,115,32,116,104,105,110,103,39,115,32,98,117,103,103,101,100,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5796 { {71,108,101,110,110,32,83,0,0,0,0,0,}, 5797 {83,104,105,112,32,105,116,33,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5798 { {83,116,101,118,101,32,87,0,0,0,0,0,}, 5799 {79,75,32,101,118,101,114,121,111,110,101,44,32,111,117,116,32,111,102,32,109,121,32,111,102,102,105,99,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5800 { {69,100,32,68,0,0,0,0,0,0,0,0,}, 5801 {65,32,103,111,111,100,32,99,104,97,116,32,112,114,111,103,114,97,109,32,105,115,32,108,105,107,101,32,97,32,110,105,110,106,97,46,46,46,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5802 { {69,100,32,68,0,0,0,0,0,0,0,0,}, 5803 {65,32,103,111,111,100,32,110,105,110,106,97,32,105,115,32,108,105,107,101,32,97,32,110,105,110,106,97,46,46,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5804 { {69,114,105,107,32,89,0,0,0,0,0,0,}, 5805 {73,32,119,101,97,114,32,100,101,115,105,103,110,101,114,32,106,101,97,110,115,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5806 { {69,114,105,107,32,89,0,0,0,0,0,0,}, 5807 {72,101,121,32,66,105,108,108,44,32,116,104,105,115,32,116,104,105,110,103,32,107,101,101,112,115,32,99,114,97,25,26,24,104,105,110,103,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5808 { {74,101,102,102,32,70,0,0,0,0,0,0,}, 5809 {84,104,105,115,32,105,115,32,97,98,115,111,108,117,116,101,108,121,32,116,104,101,32,98,101,115,116,32,101,118,101,114,33,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5810 { {74,101,102,102,32,70,0,0,0,0,0,0,}, 5811 {84,104,105,115,32,105,115,32,97,98,115,111,108,117,116,101,108,121,32,116,104,101,32,119,111,114,115,116,32,101,118,101,114,33,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5812 { {82,105,99,107,32,78,0,0,0,0,0,0,}, 5813 {83,111,117,110,100,115,32,108,105,107,101,32,97,32,100,114,105,118,101,114,32,112,114,111,98,108,101,109,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5814 { {83,99,111,116,116,32,66,0,0,0,0,0,}, 5815 {73,32,110,101,101,100,32,116,104,105,115,32,102,111,114,32,76,79,76,50,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5816 { {83,116,101,118,101,32,84,0,0,0,0,0,}, 5817 {84,104,105,115,32,115,101,101,109,115,32,114,97,116,104,101,114,32,115,105,108,108,121,44,32,97,99,116,117,97,108,108,121,46,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5818 { {80,97,117,108,32,77,0,0,0,0,0,0,}, 5819 {78,111,32,46,46,46,46,32,32,87,32,65,32,89,33,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5820 { {82,105,99,107,32,80,0,0,0,0,0,0,}, 5821 {65,72,32,72,65,32,72,65,32,72,65,33,33,32,32,72,65,72,65,33,33,32,32,65,72,72,32,72,65,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5822 { {74,111,101,32,75,0,0,0,0,0,0,0,}, 5823 {83,116,97,108,105,110,32,107,105,108,108,101,100,32,109,121,32,102,97,116,104,101,114,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5824 { {74,111,101,32,75,0,0,0,0,0,0,0,}, 5825 {73,32,104,111,112,101,32,121,111,117,39,114,101,32,112,114,111,117,100,32,111,102,32,121,111,117,114,115,101,108,102,44,32,66,105,108,108,46,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5826 { {66,105,103,32,87,105,108,108,121,0,0,0,}, 5827 {65,110,121,98,111,100,121,32,102,101,114,32,97,32,115,112,105,116,116,105,110,39,32,99,111,110,116,101,115,116,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5828 { {69,114,105,99,32,87,0,0,0,0,0,0,}, 5829 {75,97,114,97,116,101,32,105,115,32,103,111,111,100,32,98,117,116,32,121,111,117,32,117,115,101,32,105,116,32,102,111,114,32,101,118,105,108,33,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5830 { {84,101,100,32,77,0,0,0,0,0,0,0,}, 5831 {72,97,46,32,32,70,117,110,110,121,46,32,32,84,104,105,115,32,105,115,32,102,117,110,110,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5832 { {68,97,109,111,110,32,82,0,0,0,0,0,}, 5833 {73,32,98,108,97,109,101,32,116,104,101,32,70,114,101,110,99,104,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5834 { {68,119,105,103,104,116,32,79,0,0,0,0,}, 5835 {79,104,44,32,109,97,110,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5836 { {75,105,97,32,72,0,0,0,0,0,0,0,}, 5837 {73,111,110,32,99,97,110,110,111,110,32,114,101,97,100,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5838 { {75,105,97,32,72,0,0,0,0,0,0,0,}, 5839 {83,101,108,101,99,116,32,116,97,114,103,101,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5840 { {66,114,117,99,101,32,74,0,0,0,0,0,}, 5841 {73,32,97,109,32,116,104,101,32,71,101,110,105,101,32,111,102,32,116,104,101,32,108,97,109,112,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5842 { {76,97,117,114,97,32,87,0,0,0,0,0,}, 5843 {71,111,32,97,119,97,121,44,32,66,105,108,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5844 { {68,97,118,105,100,32,68,0,0,0,0,0,}, 5845 {72,109,109,109,46,46,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5846 { {77,105,107,101,32,76,105,0,0,0,0,0,}, 5847 {67,97,108,108,32,109,101,32,78,97,116,101,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5848 { {68,101,110,122,105,108,32,76,0,0,0,0,}, 5849 {84,104,105,115,32,119,111,117,108,100,32,98,101,32,98,101,116,116,101,114,32,111,110,32,116,104,101,32,77,97,99,46,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5850 { {71,114,101,103,32,72,0,0,0,0,0,0,}, 5851 {66,117,116,32,100,111,101,115,32,105,116,32,102,105,116,32,105,110,116,111,32,50,32,77,66,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5852 { {74,111,110,97,116,104,97,110,32,76,0,0,}, 5853 {73,32,116,104,105,110,107,32,73,32,110,101,101,100,32,97,32,104,97,105,114,99,117,116,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5854 { {65,100,97,109,32,73,0,0,0,0,0,0,}, 5855 {87,104,97,116,101,118,101,114,46,32,32,66,101,101,102,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5856 { {75,117,114,116,32,79,0,0,0,0,0,0,}, 5857 {70,105,120,32,105,116,32,121,111,117,114,115,101,108,102,46,32,32,73,39,109,32,98,117,115,121,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5858 { {74,111,115,101,112,104,32,72,0,0,0,0,}, 5859 {60,73,99,121,32,103,108,97,114,101,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5860 { {77,97,116,116,32,72,0,0,0,0,0,0,}, 5861 {73,39,109,32,110,101,118,101,114,32,103,111,111,100,32,119,105,116,104,32,99,108,101,118,101,114,32,111,110,32,116,104,101,32,115,112,111,116,46,46,46,0,0,0,0,},PCOLOR_GREEN,0}, 5862 { {67,104,114,105,115,32,82,0,0,0,0,0,}, 5863 {73,32,108,111,118,101,32,109,121,32,106,111,98,46,32,32,89,101,97,104,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5864 { {80,97,116,32,67,0,0,0,0,0,0,0,}, 5865 {73,39,109,32,97,32,112,114,111,102,101,115,115,105,111,110,97,108,32,121,111,100,101,108,108,101,114,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5866 { {73,97,110,32,76,0,0,0,0,0,0,0,}, 5867 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5868 { {74,97,99,107,32,77,0,0,0,0,0,0,}, 5869 {73,32,108,105,118,101,32,97,98,111,117,116,32,97,32,98,108,111,99,107,32,102,114,111,109,32,116,104,101,32,112,114,111,112,111,115,101,100,32,115,105,116,101,46,0,},PCOLOR_GREEN,0}, 5870 { {74,101,102,102,32,66,0,0,0,0,0,0,}, 5871 {84,104,101,121,32,97,108,108,32,108,111,111,107,32,108,105,107,101,32,97,110,116,115,32,102,114,111,109,32,117,112,32,104,101,114,101,46,0,0,0,0,0,0,0,0,},PCOLOR_GREEN,0}, 5872 }; 5873 5874 CDTimerClass<SystemTimerClass> wwperson_timer; 5875 5876 void Start_WWChat(ColorListClass *playerlist) 5877 { 5878 char *item; 5879 int i; 5880 HousesType house; 5881 5882 //------------------------------------------------------------------------ 5883 // Ensure a different sequence each time 5884 //------------------------------------------------------------------------ 5885 Scen.RandomNumber = rand(); 5886 5887 //------------------------------------------------------------------------ 5888 // Add myself to the player list 5889 //------------------------------------------------------------------------ 5890 item = new char [MPLAYER_NAME_MAX + 64]; 5891 #ifdef OLDWAY 5892 if (Session.House==HOUSE_GOOD) { 5893 sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_ALLIES)); 5894 } 5895 else { 5896 sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_SOVIET)); 5897 } 5898 #else //OLDWAY 5899 sprintf (item, "%s\t%s", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); 5900 #endif //OLDWAY 5901 playerlist->Add_Item(item, 5902 (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]); 5903 5904 //------------------------------------------------------------------------ 5905 // Add everyone else to the list 5906 //------------------------------------------------------------------------ 5907 for (i = 0; i < sizeof(WWPersons) / sizeof(struct WWPerson); i++) { 5908 //..................................................................... 5909 // Add the 1st entry to the list no matter what; for entries after the 5910 // 1st, only add the name if it's different from the previous name. 5911 //..................................................................... 5912 if (i==0 || strcmp(WWPersons[i].Name, WWPersons[i-1].Name)) { 5913 WWPersons[i].Color = (PlayerColorType)(Random_Pick(0,(int)(PCOLOR_LAST - 1))); 5914 if (Percent_Chance(50)) { 5915 house = HOUSE_GREECE; 5916 } else { 5917 house = HOUSE_USSR; 5918 } 5919 // house = (HousesType)Random_Pick((int)HOUSE_GOOD,(int)HOUSE_BAD); 5920 item = new char [MPLAYER_NAME_MAX + 64]; 5921 if (house != HOUSE_USSR && house != HOUSE_UKRAINE) { 5922 sprintf(item,"%s\t%s", WWPersons[i].Name, Text_String(TXT_ALLIES)); 5923 } else { 5924 sprintf(item,"%s\t%s", WWPersons[i].Name, Text_String(TXT_SOVIET)); 5925 } 5926 playerlist->Add_Item(item, 5927 (WWPersons[i].Color == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[WWPersons[i].Color]); 5928 } 5929 //..................................................................... 5930 // If this entry's name is the same as the previous, copy the color 5931 // value from the previous entry. 5932 //..................................................................... 5933 else if (i > 0) { 5934 WWPersons[i].Color = WWPersons[i-1].Color; 5935 } 5936 5937 } 5938 5939 //wwperson_timer = 240; 5940 wwperson_timer = Random_Pick(90,360); 5941 5942 } // end of Start_WWChat 5943 5944 5945 int Update_WWChat(void) 5946 { 5947 int i; 5948 int j; 5949 5950 //------------------------------------------------------------------------ 5951 // Do nothing if it's too soon. 5952 //------------------------------------------------------------------------ 5953 if (wwperson_timer > 0) { 5954 return(0); 5955 } 5956 5957 //wwperson_timer = 240; 5958 wwperson_timer = Random_Pick(90,360); 5959 5960 //------------------------------------------------------------------------ 5961 // Even after the timer's gone off, there's only a 1/8 chance we'll 5962 // print a message. 5963 //------------------------------------------------------------------------ 5964 if (Percent_Chance(12)) { 5965 return(0); 5966 } 5967 5968 //------------------------------------------------------------------------ 5969 // Randomly select a message to "send"; ensure we pick a message that 5970 // hasn't been recently displayed. 5971 //------------------------------------------------------------------------ 5972 j = sizeof(WWPersons) / sizeof(struct WWPerson); 5973 i = Random_Pick (0, j - 1); 5974 if ((TickCount - WWPersons[i].LastTime) < 1800 && 5975 WWPersons[i].LastTime != 0) { 5976 return(0); 5977 } 5978 5979 Session.Messages.Add_Message (WWPersons[i].Name, 5980 0, 5981 WWPersons[i].Phrase, WWPersons[i].Color, 5982 TPF_TEXT, -1); 5983 WWPersons[i].LastTime = TickCount; 5984 5985 return (1); 5986 5987 } // end of Update_WWChat 5988 5989 5990 #if(0) 5991 /*****************************************************************************/ 5992 void Start_Logging(void) 5993 { 5994 FILE *fp; 5995 static char *ColorNames[6] = { 5996 "Yellow", 5997 "Red", 5998 "BlueGreen", 5999 "Orange", 6000 "Green", 6001 "Blue", 6002 }; 6003 int i; 6004 int id; 6005 HousesType house; 6006 char *housenames[] = { 6007 "ALLIES", 6008 "SOVIET", 6009 "Neutral", 6010 "Special", 6011 "Multi1", 6012 "Multi2", 6013 "Multi3", 6014 "Multi4", 6015 }; 6016 time_t t; 6017 6018 fp = fopen("NETPLAY.LOG","at"); 6019 if (!fp) 6020 return; 6021 6022 /* 6023 ** Print game header 6024 */ 6025 t = time(NULL); 6026 fprintf (fp,"==============================================================\n"); 6027 fprintf (fp,"Date: %s",ctime(&t)); 6028 fprintf (fp,"Scenario: %s\n", 6029 Session.Scenarios[Session.Options.ScenarioIndex].Description()); 6030 fprintf (fp,"Total # players: %d\n",Session.NumPlayers); 6031 fprintf (fp,"==============================================================\n"); 6032 6033 /* 6034 ** Print connection info 6035 */ 6036 6037 /* 6038 ** Print player data 6039 */ 6040 fprintf(fp,"Local Player:\n"); 6041 fprintf (fp," Name:%s\n", Session.Handle); 6042 fprintf (fp," Color:%s\n", ColorNames[Session.ColorIdx]); 6043 fprintf (fp," House:%s\n", housenames[Session.House]); 6044 fprintf (fp,"\n"); 6045 6046 for (i = 0; i < Ipx.Num_Connections(); i++) { 6047 id = Ipx.Connection_ID(i); 6048 house = (HouseClass)id; 6049 fprintf(fp,"Connection %d:\n",i); 6050 fprintf (fp," Name:%s\n", Ipx.Connection_Name(id)); 6051 fprintf (fp," Color:%s\n", 6052 ColorNames[HouseClass::As_Pointer(house)->RemapColor); 6053 fprintf (fp," House:%s\n", housenames[house]); 6054 fprintf (fp,"\n"); 6055 } 6056 6057 /* 6058 ** Print game options 6059 */ 6060 fprintf(fp,"Game Options:\n"); 6061 fprintf(fp," Bases:%d\n",Session.Options.Bases); 6062 fprintf(fp," Credits:%d\n",Session.Options.Credits); 6063 fprintf(fp," Tiberium:%d\n",Session.Options.Tiberium); 6064 fprintf(fp," Crates:%d\n",Session.Options.Goodies); 6065 fprintf(fp," AI Players:%d\n",Session.Options.AIPlayers); 6066 fprintf(fp," Build Level:%d\n",BuildLevel); 6067 fprintf(fp," Unit Count:%d\n",Session.Options.UnitCount); 6068 fprintf(fp," Seed:%d\n",Seed); 6069 fprintf (fp,"\n"); 6070 6071 fclose(fp); 6072 6073 } /* end of Start_Logging */ 6074 6075 6076 void Log_Message(char *msg) 6077 { 6078 FILE *fp; 6079 6080 fp = fopen("NETPLAY.LOG","at"); 6081 if (!fp) 6082 return; 6083 6084 fprintf(fp,"%s (Frame:%d)\n",msg,Frame); 6085 fclose(fp); 6086 flushall(); 6087 6088 } /* end of Log_Message */ 6089 #endif 6090 6091 6092 6093 6094 6095 #ifndef WOLAPI_INTEGRATION // Rest of file ifdeffed out. 6096 6097 6098 6099 6100 6101 extern bool Spawn_WChat(bool can_launch); 6102 6103 /*********************************************************************************************** 6104 * Net_Fake_New_Dialog -- lets user start a new game * 6105 * * 6106 * This dialog shows a list of who's requesting to join this game, and lets * 6107 * the game initiator selectively approve each user. * 6108 * * 6109 * The 'Players' vector matches one-for-one the contents of the list box. The local system * 6110 * is always listed first; the IPX Address of the local system will NOT be valid in the * 6111 * Players vector. The Games & Players vectors should be left filled in even after this * 6112 * routine is exited; their contents are used to form connections to the other players, * 6113 * after the scenario has been loaded. * 6114 * * 6115 * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ * 6116 * ³ New Network Game ³ * 6117 * ³ ³ * 6118 * ³ Players Scenario ³ * 6119 * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ * 6120 * ³ ³ Boffo ³.³ ³ Green Acres ³.³ ³ * 6121 * ³ ³ Bozo ÃÄ´ ³ Brown Sewers ÃÄ´ ³ * 6122 * ³ ³ Bonzo ³ ³ ³ ... ³ ³ ³ * 6123 * ³ ³ ÃÄ´ ³ ÃÄ´ ³ * 6124 * ³ ³ ³.³ ³ ³.³ ³ * 6125 * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ * 6126 * ³ [Reject] Count:--- ## ³ * 6127 * ³ Level:--- ## ³ * 6128 * ³ ³ * 6129 * ³ Credits: _____ ³ * 6130 * ³ [ Bases ] [ Crates ] ³ * 6131 * ³ [ Tiberium ] [ AI Players ] ³ * 6132 * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ * 6133 * ³ ³ ³ ³ * 6134 * ³ ³ ³ ³ * 6135 * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ * 6136 * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ * 6137 * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ * 6138 * ³ [OK] [Cancel] ³ * 6139 * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ * 6140 * * 6141 * INPUT: * 6142 * none. * 6143 * * 6144 * OUTPUT: * 6145 * true = success, false = cancel * 6146 * * 6147 * WARNINGS: * 6148 * Session.GameName must contain this player's name. * 6149 * * 6150 * HISTORY: * 6151 * 02/14/1995 BR : Created. * 6152 *=============================================================================================*/ 6153 static int Net_Fake_New_Dialog(void) 6154 { 6155 #ifdef WIN32 6156 //------------------------------------------------------------------------ 6157 // Dialog & button dimensions 6158 //------------------------------------------------------------------------ 6159 int d_dialog_w = 120 *RESFACTOR; // dialog width 6160 int d_dialog_h = 80 *RESFACTOR; // dialog height 6161 int d_dialog_x = ((320 *RESFACTOR- d_dialog_w) / 2); // dialog x-coord 6162 int d_dialog_y = ((200 *RESFACTOR- d_dialog_h) / 2); // centered y-coord 6163 int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord 6164 6165 int d_txt6_h = 6*RESFACTOR+1; // ht of 6-pt text 6166 int d_margin1 = 5*RESFACTOR; // margin width/height 6167 int d_margin2 = 2*RESFACTOR; // margin width/height 6168 6169 int d_playerlist_w = 118*RESFACTOR; 6170 int d_playerlist_h = ((6 * 6) + 3)*RESFACTOR; // 6 rows high 6171 //int d_playerlist_x = d_dialog_x + d_margin1 + d_margin1; 6172 int d_playerlist_x = 500*RESFACTOR; 6173 int d_playerlist_y = d_dialog_y + d_margin1 + d_txt6_h; 6174 6175 #if (GERMAN | FRENCH) 6176 int d_cancel_w = 50*RESFACTOR; 6177 #else 6178 int d_cancel_w = 40*RESFACTOR; 6179 #endif 6180 int d_cancel_h = 9*RESFACTOR; 6181 int d_cancel_x = d_dialog_cx - d_cancel_w / 2; 6182 int d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR; 6183 6184 6185 //------------------------------------------------------------------------ 6186 // Button Enumerations 6187 //------------------------------------------------------------------------ 6188 enum { 6189 BUTTON_PLAYERLIST = 100, 6190 BUTTON_CANCEL, 6191 }; 6192 6193 //------------------------------------------------------------------------ 6194 // Redraw values: in order from "top" to "bottom" layer of the dialog 6195 //------------------------------------------------------------------------ 6196 typedef enum { 6197 REDRAW_NONE = 0, 6198 REDRAW_PARMS, 6199 REDRAW_MESSAGE, 6200 REDRAW_BUTTONS, 6201 REDRAW_BACKGROUND, 6202 REDRAW_ALL = REDRAW_BACKGROUND 6203 } RedrawType; 6204 6205 //------------------------------------------------------------------------ 6206 // Dialog variables 6207 //------------------------------------------------------------------------ 6208 RedrawType display = REDRAW_ALL; // redraw level 6209 bool process = true; // process while true 6210 KeyNumType input; 6211 6212 int transmit; // 1 = re-transmit new game options 6213 6214 long ok_timer = 0; // for timing OK button 6215 int rc; 6216 int i; 6217 char *item; 6218 int tabs[] = {77}; // tabs for player list box 6219 int optiontabs[] = {8}; // tabs for option list box 6220 6221 NodeNameType *who; // node to add to Players 6222 long ping_timer = 0; // for sending Ping packets 6223 6224 int color_used[MAX_MPLAYER_COLORS]; // 1 = color has been used 6225 JoinEventType whahoppa; // event generated by received packets 6226 CCFileClass loadfile ("SAVEGAME.NET"); 6227 int load_game = 0; // 1 = load a saved game 6228 RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); 6229 6230 int width; 6231 int height; 6232 6233 bool player_joined = false; 6234 CountDownTimerClass join_timer; 6235 6236 //PG_TO_FIX 6237 //Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW); 6238 Format_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height); 6239 6240 //------------------------------------------------------------------------ 6241 // Buttons 6242 //------------------------------------------------------------------------ 6243 GadgetClass *commands; // button list 6244 6245 ColorListClass playerlist(BUTTON_PLAYERLIST, 6246 d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, 6247 TPF_TEXT, 6248 MFCD::Retrieve("BTN-UP.SHP"), 6249 MFCD::Retrieve("BTN-DN.SHP")); 6250 6251 TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, 6252 //#if (GERMAN | FRENCH) 6253 // d_cancel_x, d_cancel_y); 6254 //#else 6255 d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h); 6256 //#endif 6257 6258 //------------------------------------------------------------------------ 6259 // Build the button list 6260 //------------------------------------------------------------------------ 6261 commands = &playerlist; 6262 cancelbtn.Add_Tail(*commands); 6263 playerlist.Set_Tabs(tabs); 6264 6265 //------------------------------------------------------------------------ 6266 // Init other scenario parameters 6267 //------------------------------------------------------------------------ 6268 Rule.IsTGrowth = Special.IsTGrowth; 6269 Special.IsTSpread = Session.Options.Tiberium; 6270 Rule.IsTSpread = Special.IsTSpread; 6271 transmit = 0; 6272 6273 //------------------------------------------------------------------------ 6274 // Init player color-used flags 6275 //------------------------------------------------------------------------ 6276 for (i = 0; i < MAX_MPLAYER_COLORS; i++) { 6277 color_used[i] = 0; // init all colors to available 6278 } 6279 color_used[Session.ColorIdx] = 1; // set my color to used 6280 playerlist.Set_Selected_Style(ColorListClass::SELECT_BAR, scheme); 6281 6282 //------------------------------------------------------------------------ 6283 // Init random-number generator, & create a seed to be used for all random 6284 // numbers from here on out 6285 //------------------------------------------------------------------------ 6286 // randomize(); 6287 Seed = rand(); 6288 6289 //------------------------------------------------------------------------ 6290 // Init the version-clipping system 6291 //------------------------------------------------------------------------ 6292 VerNum.Init_Clipping(); 6293 6294 //------------------------------------------------------------------------ 6295 // Clear the list of players 6296 //------------------------------------------------------------------------ 6297 Clear_Vector(&Session.Players); 6298 //------------------------------------------------------------------------ 6299 // Add myself to the list, and to the Players vector. 6300 //------------------------------------------------------------------------ 6301 item = new char [MPLAYER_NAME_MAX + 64]; 6302 #ifdef OLDWAY 6303 if (Session.House==HOUSE_GOOD) { 6304 sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_ALLIES)); 6305 } 6306 else { 6307 sprintf(item,"%s\t%s",Session.Handle, Text_String(TXT_SOVIET)); 6308 } 6309 #else //OLDWAY 6310 sprintf (item, "%s\t%s", Session.Handle, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); 6311 #endif //OLDWAY 6312 playerlist.Add_Item(item, 6313 (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]); 6314 6315 6316 /* 6317 ** Process the message loop until we are in focus. 6318 */ 6319 CDTimerClass<SystemTimerClass> focus_timer; // Timer to allow a wait after client joins 6320 focus_timer = 5*60; 6321 6322 WWDebugString ("RA95 - About to enter wait for focus loop.\n"); 6323 SetForegroundWindow ( MainWindow ); 6324 ShowWindow ( MainWindow, SW_SHOWMAXIMIZED ); 6325 6326 if (!GameInFocus) { 6327 do { 6328 Keyboard->Check(); 6329 if (!focus_timer){ 6330 WWDebugString ("RA95 - Calling SetForgroundWindow.\n"); 6331 SetForegroundWindow ( MainWindow ); 6332 WWDebugString ("RA95 - Calling ShowWindow.\n"); 6333 ShowWindow ( MainWindow, SW_SHOWMAXIMIZED ); 6334 focus_timer = 5*60; 6335 } 6336 }while (!GameInFocus); 6337 AllSurfaces.SurfacesRestored=FALSE; 6338 } 6339 6340 who = new NodeNameType; 6341 strcpy(who->Name, Session.Handle); 6342 who->Player.House = Session.House; 6343 who->Player.Color = Session.ColorIdx; 6344 Session.Players.Add (who); 6345 6346 if (LogicPage != &SeenBuff && LogicPage!= &HidPage) { 6347 Set_Logic_Page (SeenBuff); 6348 } 6349 6350 Load_Title_Page(true); 6351 CCPalette.Set(); //GamePalette.Set(); 6352 6353 //------------------------------------------------------------------------ 6354 // Processing loop 6355 //------------------------------------------------------------------------ 6356 while (process) { 6357 #if(SHOW_MONO) 6358 Ipx.Mono_Debug_Print(-1,0); 6359 #endif 6360 6361 #ifdef WIN32 6362 /* 6363 ** If we have just received input focus again after running in the background then 6364 ** we need to redraw. 6365 */ 6366 if (AllSurfaces.SurfacesRestored) { 6367 AllSurfaces.SurfacesRestored=FALSE; 6368 display = REDRAW_ALL; 6369 } 6370 #endif 6371 //..................................................................... 6372 // Refresh display if needed 6373 //..................................................................... 6374 if (display) { 6375 Hide_Mouse(); 6376 6377 //.................................................................. 6378 // Redraw backgound & dialog box 6379 //.................................................................. 6380 if (display >= REDRAW_BACKGROUND) { 6381 Load_Title_Page(true); 6382 CCPalette.Set(); //GamePalette.Set(); 6383 Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h); 6384 6385 //............................................................... 6386 // Dialog & Field labels 6387 //............................................................... 6388 Fancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT); 6389 6390 } 6391 6392 //.................................................................. 6393 // Redraw buttons 6394 //.................................................................. 6395 if (display >= REDRAW_BUTTONS) { 6396 commands->Draw_All(); 6397 } 6398 6399 Show_Mouse(); 6400 display = REDRAW_NONE; 6401 } 6402 6403 //..................................................................... 6404 // Get user input 6405 //..................................................................... 6406 input = commands->Input(); 6407 6408 //..................................................................... 6409 // Process input 6410 //..................................................................... 6411 switch (input) { 6412 6413 case (KN_ESC): 6414 case (BUTTON_CANCEL | KN_BUTTON): 6415 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 6416 6417 Session.GPacket.Command = NET_SIGN_OFF; 6418 strcpy (Session.GPacket.Name, Session.Handle); 6419 6420 //............................................................... 6421 // Broadcast my sign-off over my network 6422 //............................................................... 6423 Ipx.Send_Global_Message (&Session.GPacket, 6424 sizeof (GlobalPacketType), 0, NULL); 6425 Ipx.Send_Global_Message (&Session.GPacket, 6426 sizeof (GlobalPacketType), 0, NULL); 6427 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 6428 6429 //............................................................... 6430 // And now, just be absolutely sure, send my sign-off to each 6431 // player in my game. (If there's a bridge between us, the other 6432 // player will have specified my address, so he can cross the 6433 // bridge; but I may not have specified a bridge address, so the 6434 // only way I have of crossing the bridge is to send a packet 6435 // directly to him.) 6436 // Don't send this message to myself. 6437 //............................................................... 6438 for (i = 1; i < Session.Players.Count(); i++) { 6439 Ipx.Send_Global_Message (&Session.GPacket, 6440 sizeof(GlobalPacketType), 1, &(Session.Players[i]->Address)); 6441 Ipx.Service(); 6442 } 6443 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 6444 Session.GameName[0] = 0; 6445 process = false; 6446 rc = false; 6447 Send_Data_To_DDE_Server ("Hello", strlen("Hello"), DDEServerClass::DDE_CONNECTION_FAILED); 6448 GameStatisticsPacketSent = false; 6449 Spawn_WChat(false); 6450 break; 6451 6452 //.................................................................. 6453 // Default: manage the inter-player messages 6454 //.................................................................. 6455 default: 6456 if (Session.Players.Count() > 1) { 6457 6458 /* 6459 ** Wait for several secs after receiving request to join before sending 6460 ** start game packet 6461 */ 6462 if (!player_joined) { 6463 player_joined = true; 6464 join_timer.Set (3*60, true); 6465 break; 6466 } else { 6467 if (join_timer.Time()) break; 6468 } 6469 6470 //............................................................... 6471 // If a new player has joined in the last second, don't allow 6472 // an OK; force a wait longer than 1 second (to give all players 6473 // a chance to know about this new guy) 6474 //............................................................... 6475 i = MAX((int)Ipx.Global_Response_Time() * 2, 60*2); 6476 while ((int)TickCount - ok_timer < i) { 6477 Ipx.Service(); 6478 } 6479 6480 //............................................................... 6481 // If there are at least 2 players, go ahead & play; error otherwise 6482 //............................................................... 6483 if (Session.Solo || Session.Players.Count() > 1 || Session.Options.Ghosts) { 6484 rc = TRUE; 6485 process = FALSE; 6486 } else { 6487 WWMessageBox().Process (TXT_ONLY_ONE,TXT_OOPS,NULL); 6488 display = REDRAW_ALL; 6489 Sound_Effect(VOC_SYS_ERROR); 6490 } 6491 //if (input==(BUTTON_LOAD | KN_BUTTON)) 6492 // load_game = 1; 6493 break; 6494 } 6495 break; 6496 6497 } 6498 6499 //..................................................................... 6500 // Process incoming packets 6501 //..................................................................... 6502 whahoppa = Get_NewGame_Responses(&playerlist, color_used); 6503 if (whahoppa == EV_NEW_PLAYER) { 6504 ok_timer = TickCount; 6505 transmit = 1; 6506 } 6507 else if (whahoppa == EV_MESSAGE) { 6508 display = REDRAW_MESSAGE; 6509 } 6510 6511 //..................................................................... 6512 // If our Transmit flag is set, we need to send out a game option packet 6513 // Don't send it to myself. 6514 //..................................................................... 6515 if (transmit) { 6516 for (i = 1; i < Session.Players.Count(); i++) { 6517 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 6518 6519 Session.GPacket.Command = NET_GAME_OPTIONS; 6520 /* 6521 ** Set up the scenario info so the remote player can match the scenario on his machine 6522 ** or request a download if it doesnt exist 6523 */ 6524 strcpy (Session.GPacket.ScenarioInfo.Scenario, Session.Scenarios[Session.Options.ScenarioIndex]->Description()); 6525 CCFileClass file (Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename()); 6526 6527 // ajw - I don't understand why this check is done here and not later. 6528 if ( !file.Is_Available() ) { 6529 6530 /* 6531 ** Special new kludge for counterstrike. 6532 ** 6533 ** The only time the file can be unavailable is if its a counterstrike 6534 ** mission and the CS CD is not in the drive so 6535 ** make sure the counterstrike CD is in the drive. 6536 ** 6537 ** If Counterstrike is installed and 6538 ** the file name matches a counterstrike map then force the CD 6539 ** to be there. 6540 ** 6541 */ 6542 #ifdef FIXIT_CSII // checked - ajw 9/28/98 6543 if ( Expansion_CS_Present() || Expansion_AM_Present() ) { 6544 if ( toupper (Session.ScenarioFileName [2]) == 'M' ){ 6545 6546 int current_drive = CCFileClass::Get_CD_Drive(); 6547 int index = Get_CD_Index(current_drive, 1*60); 6548 bool needcd = false; 6549 if (Is_Mission_Counterstrike(Session.ScenarioFileName) && index!=2 && index!=3) { 6550 needcd = true; 6551 RequiredCD = 2; 6552 } 6553 if (Is_Mission_Aftermath(Session.ScenarioFileName) && index!=3) { 6554 needcd = true; 6555 RequiredCD = 3; 6556 } 6557 if (needcd) { 6558 #else 6559 if ( Expansion_CS_Present() ) { 6560 if ( toupper (Session.ScenarioFileName [2]) == 'M' ){ 6561 int scen_num; 6562 sscanf ( Session.ScenarioFileName, "SCM%02d", &scen_num ); 6563 6564 int current_drive = CCFileClass::Get_CD_Drive(); 6565 if ( scen_num>24 && Get_CD_Index(current_drive, 1*60) != 2){ 6566 RequiredCD = 2; 6567 #endif 6568 if (!Force_CD_Available (RequiredCD)){ 6569 Emergency_Exit(EXIT_FAILURE); 6570 } 6571 6572 /* 6573 ** Update the internal list of scenarios to include the counterstrike 6574 ** list. 6575 */ 6576 Session.Read_Scenario_Descriptions(); 6577 6578 } 6579 } 6580 } 6581 6582 /* 6583 ** See if that file is available now. Its fatal if it isnt. 6584 */ 6585 if ( !file.Is_Available() ) { 6586 6587 WWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH); 6588 6589 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 6590 6591 Session.GPacket.Command = NET_SIGN_OFF; 6592 strcpy (Session.GPacket.Name, Session.Handle); 6593 6594 //.................................................................. 6595 // Don't send myself the message. 6596 //.................................................................. 6597 for (i = 1; i < Session.Players.Count(); i++) { 6598 Ipx.Send_Global_Message (&Session.GPacket, 6599 sizeof(GlobalPacketType), 1, 6600 &(Session.Players[i]->Address)); 6601 Ipx.Service(); 6602 } 6603 6604 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 6605 0, NULL); 6606 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 6607 0, NULL); 6608 6609 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 6610 6611 Clear_Listbox(&playerlist); 6612 6613 //------------------------------------------------------------------------ 6614 // Restore screen 6615 //------------------------------------------------------------------------ 6616 Hide_Mouse(); 6617 Load_Title_Page(true); 6618 Show_Mouse(); 6619 6620 //------------------------------------------------------------------------ 6621 // Clear the Players vector if we're not starting a game. 6622 //------------------------------------------------------------------------ 6623 Clear_Vector(&Session.Players); 6624 return (false); 6625 } 6626 } 6627 6628 6629 Session.GPacket.ScenarioInfo.FileLength = file.Size(); 6630 #ifdef WOLAPI_INTEGRATION 6631 strcpy( Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename() ); 6632 #else 6633 strncpy (Session.GPacket.ScenarioInfo.ShortFileName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename(), sizeof(Session.GPacket.ScenarioInfo.ShortFileName)); 6634 #endif 6635 strncpy ((char*)Session.GPacket.ScenarioInfo.FileDigest, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Digest(), sizeof (Session.GPacket.ScenarioInfo.FileDigest)); 6636 Session.GPacket.ScenarioInfo.OfficialScenario = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official(); 6637 6638 Session.GPacket.ScenarioInfo.Credits = Session.Options.Credits; 6639 Session.GPacket.ScenarioInfo.IsBases = Session.Options.Bases; 6640 Session.GPacket.ScenarioInfo.IsTiberium = Session.Options.Tiberium; 6641 Session.GPacket.ScenarioInfo.IsGoodies = Session.Options.Goodies; 6642 //Session.GPacket.ScenarioInfo.IsGhosties = Session.Options.Ghosts; 6643 Session.GPacket.ScenarioInfo.BuildLevel = BuildLevel; 6644 Session.GPacket.ScenarioInfo.UnitCount = Session.Options.UnitCount; 6645 Session.GPacket.ScenarioInfo.AIPlayers = Session.Options.AIPlayers; 6646 Session.GPacket.ScenarioInfo.Seed = Seed; 6647 Session.GPacket.ScenarioInfo.Special = Special; 6648 Session.GPacket.ScenarioInfo.GameSpeed = Options.GameSpeed; 6649 Session.GPacket.ScenarioInfo.Version = VerNum.Get_Clipped_Version(); 6650 6651 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 6652 1, &(Session.Players[i]->Address) ); 6653 } 6654 Sound_Effect(VOC_OPTIONS_CHANGED); 6655 transmit = 0; 6656 } 6657 6658 //..................................................................... 6659 // Ping every player in my game, to force the Global Channel to measure 6660 // the connection response time. Don't ping myself (index 0). 6661 //..................................................................... 6662 if (TickCount - ping_timer > 15) { 6663 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 6664 Session.GPacket.Command = NET_PING; 6665 for (i = 1; i < Session.Players.Count(); i++) { 6666 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 6667 1, &(Session.Players[i]->Address) ); 6668 } 6669 ping_timer = TickCount; 6670 } 6671 6672 //..................................................................... 6673 // Service the Ipx connections 6674 //..................................................................... 6675 Ipx.Service(); 6676 6677 //..................................................................... 6678 // Service the sounds & score; GameActive must be false at this point, 6679 // so Call_Back() doesn't intercept global messages from me! 6680 //..................................................................... 6681 Call_Back(); 6682 } 6683 6684 //------------------------------------------------------------------------ 6685 // Prepare to load the scenario 6686 //------------------------------------------------------------------------ 6687 if (rc) { 6688 //..................................................................... 6689 // Set the player count & scenario number 6690 //..................................................................... 6691 Session.NumPlayers = Session.Players.Count(); 6692 6693 Scen.Scenario = Session.Options.ScenarioIndex; 6694 strcpy (Scen.ScenarioName, Session.Scenarios[Session.Options.ScenarioIndex]->Get_Filename()); 6695 6696 //..................................................................... 6697 // Compute frame delay value for packet transmissions: 6698 // - Divide global channel's response time by 8 (2 to convert to 1-way 6699 // value, 4 more to convert from ticks to frames) 6700 //..................................................................... 6701 if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) { 6702 Session.MaxAhead = MAX( ((((Ipx.Global_Response_Time() / 8) + 6703 (Session.FrameSendRate - 1)) / Session.FrameSendRate) * 6704 Session.FrameSendRate), (Session.FrameSendRate * 2) ); 6705 } 6706 else { 6707 Session.MaxAhead = MAX( ((int)Ipx.Global_Response_Time() / 8), 6708 NETWORK_MIN_MAX_AHEAD ); 6709 } 6710 6711 //..................................................................... 6712 // Send all players the NET_GO packet. Wait until all ACK's have been 6713 // received. 6714 //..................................................................... 6715 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 6716 if (load_game) 6717 Session.GPacket.Command = NET_LOADGAME; 6718 else 6719 Session.GPacket.Command = NET_GO; 6720 Session.GPacket.ResponseTime.OneWay = Session.MaxAhead; 6721 for (i = 1; i < Session.Players.Count(); i++) { 6722 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 6723 1, &(Session.Players[i]->Address) ); 6724 } 6725 //..................................................................... 6726 // Wait for all the ACK's to come in. 6727 //..................................................................... 6728 while (Ipx.Global_Num_Send() > 0) { 6729 Ipx.Service(); 6730 } 6731 6732 6733 /* 6734 ** Wait for the go responses from each player in case someone needs the scenario 6735 ** file to be sent. 6736 */ 6737 int responses[20]; //In big trub if more than 20 players 6738 memset (responses, 0, sizeof (responses)); 6739 int num_responses = 0; 6740 bool send_scenario = false; 6741 WWDebugString ("RA95 - About to wait for 'GO' response.\n"); 6742 6743 CDTimerClass<SystemTimerClass> response_timer; // timeout timer for waiting for responses 6744 response_timer = 60*30; // Wait for 30 seconds. If we dont hear by then assume someone crashed 6745 6746 do { 6747 Ipx.Service(); 6748 int retcode = Ipx.Get_Global_Message (&Session.GPacket, &Session.GPacketlen, 6749 &Session.GAddress, &Session.GProductID); 6750 if (retcode && Session.GProductID == IPXGlobalConnClass::COMMAND_AND_CONQUER0) { 6751 6752 for ( i=1 ; i<Session.Players.Count() ; i++ ) { 6753 if (Session.Players[i]->Address == Session.GAddress) { 6754 if (!responses[i]) { 6755 if (Session.GPacket.Command == NET_REQ_SCENARIO) { 6756 responses[i] = Session.GPacket.Command; 6757 send_scenario = true; 6758 num_responses++; 6759 } 6760 if (Session.GPacket.Command == NET_READY_TO_GO) { 6761 responses[i] = Session.GPacket.Command; 6762 num_responses++; 6763 } 6764 } 6765 } 6766 } 6767 } 6768 } while ( num_responses < Session.Players.Count()-1 && response_timer ); 6769 6770 WWDebugString ("RA95 - Exited response wait loop.\n"); 6771 6772 /* 6773 ** If one of the machines requested that the scenario be sent then send it. 6774 */ 6775 if (send_scenario) { 6776 memset (Session.ScenarioRequests, 0, sizeof (Session.ScenarioRequests)); 6777 Session.RequestCount = 0; 6778 for ( i=1 ; i<Session.Players.Count() ; i++ ) { 6779 if (responses[i] == NET_REQ_SCENARIO) { 6780 Session.ScenarioRequests[Session.RequestCount++] = i; 6781 } 6782 } 6783 Send_Remote_File (Scen.ScenarioName, 1); 6784 } 6785 6786 } 6787 6788 //..................................................................... 6789 // Wait a while, polling the IPX service routines, to give our ACK 6790 // a chance to get to the other system. If he doesn't get our ACK, 6791 // he'll be waiting the whole time we load MIX files. 6792 //..................................................................... 6793 i = MAX((int)Ipx.Global_Response_Time() * 2, 60*2); 6794 int starttime = TickCount; 6795 while ((int)TickCount - starttime < i) { 6796 Ipx.Service(); 6797 } 6798 6799 //------------------------------------------------------------------------ 6800 // Init network timing values, using previous response times as a measure 6801 // of what our retry delta & timeout should be. 6802 //------------------------------------------------------------------------ 6803 //Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1, 6804 // Ipx.Global_Response_Time() * 4); 6805 Ipx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8)); 6806 6807 Clear_Listbox(&playerlist); 6808 6809 //------------------------------------------------------------------------ 6810 // Restore screen 6811 //------------------------------------------------------------------------ 6812 Hide_Mouse(); 6813 Load_Title_Page(true); 6814 Show_Mouse(); 6815 6816 if (load_game) { 6817 if (!Load_Game (-1)) { 6818 WWMessageBox().Process (TXT_ERROR_LOADING_GAME); 6819 rc = false; 6820 } 6821 Frame++; 6822 } 6823 6824 //------------------------------------------------------------------------ 6825 // Clear the Players vector if we're not starting a game. 6826 //------------------------------------------------------------------------ 6827 if (!rc) { 6828 Clear_Vector(&Session.Players); 6829 } 6830 6831 // while (optionlist.Count()>0) { 6832 // item = (char *)optionlist.Get_Item(0); 6833 // delete [] item; 6834 // optionlist.Remove_Item(item); 6835 // } 6836 6837 return(rc); 6838 6839 #else //WIN32 6840 6841 return (0); 6842 6843 #endif //WIN32 6844 } /* end of Net_Fake_New_Dialog */ 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 /*********************************************************************************************** 6856 * Net_Join_Dialog -- lets user join an existing game or start a new one * 6857 * * 6858 * This dialog displays an edit field for the player's name, and a list of all non-stealth- * 6859 * mode games. Clicking once on a game name displays a list of who's in that game. Clicking * 6860 * "New" takes the user to the Net_New dialog, where he waits for other users to join his * 6861 * game. All other input is done through this dialog. * 6862 * * 6863 * The dialog has several "states": * 6864 * * 6865 * 1) Initially, it waits for the user to fill in his/her name and then to select Join or * 6866 * New; if New is selected, this dialog is exited. * 6867 * * 6868 * 2) If Join is selected, the Join & New buttons are removed, but the Cancel button remains.* 6869 * The join request is transmitted to the game's owner, and the message "Waiting for * 6870 * Confirmation" is displayed, until a confirmation or denial is received from the game's * 6871 * owner. The user may click Cancel at this point to cancel the join request. * 6872 * (Once Join is selected, the name editing field is disabled, and becomes a display-only * 6873 * field. If cancel is selected, it reappears as an edit field.) The user can still click* 6874 * around & see who's in which games. * 6875 * * 6876 * 3) If the join request is denied, the dialog re-initializes to its pre-join state; the * 6877 * Join & New buttons reappear, & the Name field is available again. * 6878 * * 6879 * 4) If join confirmation is obtained, the message changes to show all the current game * 6880 * settings. The user cannot click around & look at other games any more. * 6881 * * 6882 * Any game running in Stealth mode won't show up on this dialog. * 6883 * * 6884 * The 'Players' vector matches one-for-one the contents of the list box. The local system * 6885 * is always listed first; the IPX Address of the local system will NOT be valid in the * 6886 * Players vector. The Games & Players vectors should be left filled in even after this * 6887 * routine is exited; their contents are used to form connections to the other players, * 6888 * after the scenario has been loaded. * 6889 * * 6890 * The 'Chat' vector contains the address of everyone who sends me a chat announcement. * 6891 * The address field is used to send everyone my outgoing messages. The LastTime * 6892 * field is used as a timeout; if enough time goes by & we don't hear from this node, * 6893 * we ping him, requesting a CHAT_ANNOUNCE if he's still in chat. If we don't hear * 6894 * from him after that, we remove him from our list. * 6895 * * 6896 * ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ * 6897 * ³ Network Games ³ * 6898 * ³ ³ * 6899 * ³ Your Name: ____________ ³ * 6900 * ³ House: [GDI] [NOD] ³ * 6901 * ³ Desired Color: [ ][ ][ ][ ] ³ * 6902 * ³ ³ * 6903 * ³ Games Players ³ * 6904 * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄ¿ ³ * 6905 * ³ ³(Bill's Game )³.³ ³ Peter Parker GDI ³.³ ³ * 6906 * ³ ³ Peter Parker's Game ÃÄ´ ³ Mary Jane GDI ÃÄ´ ³ * 6907 * ³ ³(Magnum PI's Game )³ ³ ³ JJ Jameson NOD ³ ³ ³ * 6908 * ³ ³ ÃÄ´ ³ ÃÄ´ ³ * 6909 * ³ ³ ³.³ ³ ³.³ ³ * 6910 * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÙ ³ * 6911 * ³ Scenario: Big Long Description ³ * 6912 * ³ Starting Credits: xxxx ³ * 6913 * ³ Count: --- Level: --- ³ * 6914 * ³ Bases: ON Crates: ON ³ * 6915 * ³ Tiberium: ON AI Players: ON ³ * 6916 * ³ ³ * 6917 * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ * 6918 * ³ ³ ³ ³ * 6919 * ³ ³ ³ ³ * 6920 * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ * 6921 * ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ * 6922 * ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ * 6923 * ³ [Join] [Cancel] [New] ³ * 6924 * ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ * 6925 * * 6926 * INPUT: * 6927 * none. * 6928 * * 6929 * OUTPUT: * 6930 * -1 = cancel, 0 = OK, 1 = New net game requested * 6931 * * 6932 * WARNINGS: * 6933 * none. * 6934 * * 6935 * HISTORY: * 6936 * 02/14/1995 BR : Created. * 6937 *=============================================================================================*/ 6938 static int Net_Fake_Join_Dialog(void) 6939 { 6940 6941 #ifdef WIN32 6942 //------------------------------------------------------------------------ 6943 // Dialog & button dimensions 6944 //------------------------------------------------------------------------ 6945 int d_dialog_w = 120 *RESFACTOR; // dialog width 6946 int d_dialog_h = 80 *RESFACTOR; // dialog height 6947 int d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2); // dialog x-coord 6948 int d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2); // centered y-coord 6949 int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // center x-coord 6950 6951 int d_txt6_h = 6 *RESFACTOR+1; // ht of 6-pt text 6952 int d_margin1 = 5 *RESFACTOR; // large margin 6953 int d_margin2 = 7 *RESFACTOR; // small margin 6954 6955 int d_gamelist_w = 160 *RESFACTOR; 6956 int d_gamelist_h = ((6 * 6) + 3) *RESFACTOR; // 6 rows high 6957 // int d_gamelist_x = d_dialog_x + d_margin1 + d_margin1; 6958 int d_gamelist_x = 500*RESFACTOR; //d_dialog_x + d_margin1 + d_margin1; 6959 int d_gamelist_y = 50 + d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/; 6960 6961 int d_playerlist_w = 118 *RESFACTOR; 6962 int d_playerlist_h = ((6 * 6) + 3) *RESFACTOR; // 6 rows high 6963 //int d_playerlist_x = d_dialog_x + d_dialog_w - d_margin1 - d_margin1 - d_playerlist_w; 6964 int d_playerlist_x = 500*RESFACTOR; 6965 int d_playerlist_y = 50+ d_margin2 + 2*RESFACTOR/*KO + d_txt6_h + d_margin2*/; 6966 6967 #if (GERMAN | FRENCH) 6968 int d_cancel_w = 50*RESFACTOR; 6969 #else 6970 int d_cancel_w = 40*RESFACTOR; 6971 #endif 6972 int d_cancel_h = 9*RESFACTOR; 6973 int d_cancel_x = d_dialog_cx - d_cancel_w / 2; 6974 int d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR; 6975 6976 //------------------------------------------------------------------------ 6977 // Button Enumerations 6978 //------------------------------------------------------------------------ 6979 enum { 6980 BUTTON_GAMELIST = 100, 6981 BUTTON_PLAYERLIST, 6982 BUTTON_CANCEL, 6983 }; 6984 6985 //------------------------------------------------------------------------ 6986 // Redraw values: in order from "top" to "bottom" layer of the dialog 6987 //------------------------------------------------------------------------ 6988 typedef enum { 6989 REDRAW_NONE = 0, 6990 REDRAW_PARMS, 6991 REDRAW_MESSAGE, 6992 REDRAW_COLORS, 6993 REDRAW_BUTTONS, 6994 REDRAW_BACKGROUND, 6995 REDRAW_ALL = REDRAW_BACKGROUND 6996 } RedrawType; 6997 6998 //------------------------------------------------------------------------ 6999 // Dialog variables 7000 //------------------------------------------------------------------------ 7001 RedrawType display = REDRAW_ALL; // redraw level 7002 bool process = true; // process while true 7003 KeyNumType input; 7004 char housetext[25] = ""; // buffer for house droplist 7005 int isdropped = 0; 7006 7007 JoinStateType joinstate = JOIN_NOTHING; // current "state" of this dialog 7008 char namebuf[MPLAYER_NAME_MAX] = {0}; // buffer for player's name 7009 int playertabs[] = {77 *RESFACTOR}; // tabs for player list box 7010 int optiontabs[] = {8}; // tabs for player list box 7011 int game_index = -1; // index of currently-selected game 7012 int join_index = -1; // index of game we're joining 7013 int rc = 0; // -1 = user cancelled, 1 = New 7014 JoinEventType event; // event from incoming packet 7015 int i; // loop counter 7016 int parms_received = 0; // 1 = game options received 7017 NodeNameType *who; // node to add to Players 7018 RejectType why; // reason for rejection 7019 TTimerClass<SystemTimerClass> lastclick_timer; // time b/w send periods 7020 int lastclick_idx = 0; // index of item last clicked on 7021 RemapControlType * scheme = GadgetClass::Get_Color_Scheme(); 7022 int ready_to_go = 0; 7023 Session.Options.ScenarioDescription[0] = 0; //Flag that we dont know the scenario name yet 7024 int width; 7025 int height; 7026 7027 //PG_TO_FIX 7028 //Fancy_Text_Print(TXT_NONE,0,0,TBLACK,TBLACK,TPF_6PT_GRAD | TPF_NOSHADOW); 7029 Format_Window_String((char*)TXT_HACKHACK, SeenBuff.Get_Height(), width, height); 7030 char * item; 7031 unsigned long starttime; 7032 int load_game = 0; // 1 = load saved game 7033 7034 //------------------------------------------------------------------------ 7035 // Buttons 7036 //------------------------------------------------------------------------ 7037 GadgetClass *commands; // button list 7038 7039 7040 ListClass gamelist(BUTTON_GAMELIST, d_gamelist_x, d_gamelist_y, d_gamelist_w, d_gamelist_h, 7041 TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); 7042 7043 ColorListClass playerlist(BUTTON_PLAYERLIST, d_playerlist_x, d_playerlist_y, d_playerlist_w, d_playerlist_h, 7044 TPF_TEXT, MFCD::Retrieve("BTN-UP.SHP"), MFCD::Retrieve("BTN-DN.SHP")); 7045 7046 TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL, TPF_BUTTON, 7047 //#if (GERMAN | FRENCH) 7048 // d_cancel_x, d_cancel_y); 7049 //#else 7050 d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h); 7051 //#endif 7052 7053 //------------------------------------------------------------------------ 7054 // Init the button states 7055 //------------------------------------------------------------------------ 7056 //........................................................................ 7057 // Name & Color 7058 //........................................................................ 7059 Session.ColorIdx = Session.PrefColor; // init my preferred color 7060 strcpy (namebuf, Session.Handle); // set my name 7061 7062 //........................................................................ 7063 // List boxes 7064 //........................................................................ 7065 playerlist.Set_Tabs(playertabs); 7066 playerlist.Set_Selected_Style(ColorListClass::SELECT_NORMAL); 7067 7068 Fancy_Text_Print("", 0, 0, scheme, TBLACK, 7069 TPF_CENTER | TPF_TEXT); 7070 7071 lastclick_timer = 0; 7072 7073 //------------------------------------------------------------------------ 7074 // Clear the list of games, players, and the chat list 7075 //------------------------------------------------------------------------ 7076 Clear_Vector(&Session.Games); 7077 Clear_Vector(&Session.Players); 7078 Clear_Vector(&Session.Chat); 7079 7080 //------------------------------------------------------------------------ 7081 // Add myself to the Chat vector 7082 //------------------------------------------------------------------------ 7083 who = new NodeNameType; 7084 strcpy(who->Name, namebuf); 7085 who->Chat.LastTime = 0; 7086 who->Chat.LastChance = 0; 7087 who->Chat.Color = Session.GPacket.Chat.Color; 7088 Session.Chat.Add (who); 7089 7090 //------------------------------------------------------------------------ 7091 // Create the "Lobby" game name on the games list, and create a bogus 7092 // node for the gamelist, so Games[i] will always match gamelist[i] 7093 //------------------------------------------------------------------------ 7094 who = new NodeNameType; 7095 strcpy(who->Name, ""); 7096 who->Game.IsOpen = 0; 7097 who->Game.LastTime = 0; 7098 Session.Games.Add (who); 7099 item = new char [MPLAYER_NAME_MAX]; 7100 strcpy(item, Text_String(TXT_LOBBY)); 7101 gamelist.Add_Item(item); 7102 gamelist.Set_Selected_Index(0); 7103 game_index = 0; 7104 7105 //------------------------------------------------------------------------ 7106 // Send game-name query & chat announcement; also, initialize timers. 7107 //------------------------------------------------------------------------ 7108 Send_Join_Queries (game_index, joinstate, 1, 0, 1, namebuf, 1); 7109 7110 /* 7111 ** Process the message loop until we are in focus. 7112 */ 7113 CDTimerClass<SystemTimerClass> focus_timer; // Timer to allow a wait after client joins 7114 focus_timer = 5*60; 7115 7116 WWDebugString ("RA95 - About to enter wait for focus loop.\n"); 7117 SetForegroundWindow ( MainWindow ); 7118 ShowWindow ( MainWindow, SW_SHOWMAXIMIZED ); 7119 7120 if (!GameInFocus) { 7121 do { 7122 Keyboard->Check(); 7123 if (!focus_timer){ 7124 WWDebugString ("RA95 - Calling SetForgroundWindow.\n"); 7125 SetForegroundWindow ( MainWindow ); 7126 WWDebugString ("RA95 - Calling ShowWindow.\n"); 7127 ShowWindow ( MainWindow, SW_SHOWMAXIMIZED ); 7128 focus_timer = 5*60; 7129 } 7130 }while (!GameInFocus); 7131 AllSurfaces.SurfacesRestored=FALSE; 7132 } 7133 7134 if (LogicPage != &SeenBuff && LogicPage!= &HidPage) { 7135 Set_Logic_Page (SeenBuff); 7136 } 7137 7138 Load_Title_Page(true); 7139 CCPalette.Set(); //GamePalette.Set(); 7140 7141 //------------------------------------------------------------------------ 7142 // Processing loop 7143 //------------------------------------------------------------------------ 7144 while (process) { 7145 7146 #ifdef WIN32 7147 /* 7148 ** If we have just received input focus again after running in the background then 7149 ** we need to redraw. 7150 */ 7151 if (AllSurfaces.SurfacesRestored) { 7152 AllSurfaces.SurfacesRestored=FALSE; 7153 display = REDRAW_ALL; 7154 } 7155 #endif 7156 //..................................................................... 7157 // Refresh display if needed 7158 //..................................................................... 7159 if (display) { 7160 Hide_Mouse(); 7161 7162 //.................................................................. 7163 // Redraw backgound & dialog box 7164 //.................................................................. 7165 if (display >= REDRAW_BACKGROUND) { 7166 Load_Title_Page(true); 7167 CCPalette.Set(); //GamePalette.Set(); 7168 Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h); 7169 7170 //............................................................... 7171 // Dialog & Field labels 7172 //............................................................... 7173 Fancy_Text_Print(TXT_HACKHACK, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR, scheme, TBLACK, TPF_TEXT); 7174 7175 //............................................................... 7176 // Rebuild the button list 7177 //............................................................... 7178 cancelbtn.Zap(); 7179 gamelist.Zap(); 7180 playerlist.Zap(); 7181 7182 commands = &cancelbtn; 7183 gamelist.Add_Tail(*commands); 7184 playerlist.Add_Tail(*commands); 7185 7186 } 7187 7188 //.................................................................. 7189 // Redraw buttons 7190 //.................................................................. 7191 if (display >= REDRAW_BUTTONS) { 7192 commands->Draw_All(); 7193 } 7194 7195 Show_Mouse(); 7196 display = REDRAW_NONE; 7197 } 7198 7199 //..................................................................... 7200 // Get user input 7201 //..................................................................... 7202 input = commands->Input(); 7203 7204 //..................................................................... 7205 // Process input 7206 //..................................................................... 7207 switch (input) { 7208 7209 //.................................................................. 7210 // ESC / CANCEL: send a SIGN_OFF 7211 // - If we're part of a game, stay in this dialog; otherwise, exit 7212 //.................................................................. 7213 case (KN_ESC): 7214 case (BUTTON_CANCEL | KN_BUTTON): 7215 //............................................................... 7216 // If we're joined to a game, make extra sure the other players in 7217 // that game know I'm exiting; send my SIGN_OFF as an ack-required 7218 // packet. Don't send this to myself (index 0). 7219 //............................................................... 7220 if (joinstate == JOIN_CONFIRMED) { 7221 Unjoin_Game(namebuf, joinstate, &gamelist, &playerlist, 7222 game_index, 1, 0, 0, d_txt6_h, 0, 7223 0, MAX_MESSAGE_LENGTH); 7224 joinstate = JOIN_NOTHING; 7225 display = REDRAW_ALL; 7226 } 7227 //............................................................... 7228 // If I'm not joined to a game, send a SIGN_OFF to all players 7229 // in my Chat vector (but not to myself, index 0) 7230 //............................................................... 7231 else { 7232 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 7233 Session.GPacket.Command = NET_SIGN_OFF; 7234 strcpy(Session.GPacket.Name,namebuf); 7235 for (i = 1; i < Session.Chat.Count(); i++) { 7236 Ipx.Send_Global_Message (&Session.GPacket, 7237 sizeof(GlobalPacketType), 7238 1, &(Session.Chat[i]->Address)); 7239 Ipx.Service(); 7240 } 7241 7242 //............................................................ 7243 // Now broadcast a SIGN_OFF just to be thorough 7244 //............................................................ 7245 Ipx.Send_Global_Message (&Session.GPacket, 7246 sizeof (GlobalPacketType), 0, NULL); 7247 if (Session.IsBridge) { 7248 Ipx.Send_Global_Message (&Session.GPacket, 7249 sizeof(GlobalPacketType), 0, &Session.BridgeNet); 7250 } 7251 7252 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 7253 7254 //............................................................ 7255 // exit the dialog 7256 //............................................................ 7257 Send_Data_To_DDE_Server ("Hello", strlen("Hello"), DDEServerClass::DDE_CONNECTION_FAILED); 7258 GameStatisticsPacketSent = false; 7259 Spawn_WChat(false); 7260 process = false; 7261 rc = -1; 7262 } 7263 break; 7264 7265 7266 //.................................................................. 7267 // JOIN: send a join request packet & switch to waiting-for- 7268 // confirmation mode. 7269 //.................................................................. 7270 default: 7271 if (joinstate == JOIN_NOTHING && gamelist.Count() >1 ) { 7272 gamelist.Set_Selected_Index(1); //lastclick_idx); 7273 game_index = 1; 7274 strcpy (Session.Handle,namebuf); 7275 //Session.House = (HousesType)housebtn.Current_Index(); 7276 join_index = gamelist.Current_Index(); 7277 parms_received = 0; 7278 if (Request_To_Join (namebuf, join_index, Session.House, 7279 Session.ColorIdx)) { 7280 joinstate = JOIN_WAIT_CONFIRM; 7281 } else { 7282 display = REDRAW_ALL; 7283 } 7284 } 7285 break; 7286 7287 } 7288 7289 //..................................................................... 7290 // Resend our query packets 7291 //..................................................................... 7292 Send_Join_Queries(game_index, joinstate, 0, 0, 0, namebuf); 7293 7294 //..................................................................... 7295 // Process incoming packets 7296 //..................................................................... 7297 event = Get_Join_Responses(&joinstate, &gamelist, &playerlist, 7298 join_index, namebuf, &why); 7299 7300 //..................................................................... 7301 // If we've changed state, redraw everything; if we're starting the game, 7302 // break out of the loop. If we've just joined, send out a player query 7303 // so I'll get added to the list instantly. 7304 //..................................................................... 7305 if (event == EV_STATE_CHANGE) { 7306 display = REDRAW_ALL; 7307 if (joinstate==JOIN_GAME_START || joinstate == JOIN_GAME_START_LOAD) { 7308 if (joinstate==JOIN_GAME_START_LOAD) load_game = 1; 7309 7310 bool ready_packet_was_sent = false; 7311 7312 if (!load_game){ 7313 /* 7314 ** Special new kludge for counterstrike. 7315 ** 7316 ** Find local scenario will fail to match a counterstrike mission 7317 ** unless the CS CD is in the drive. So.... 7318 ** 7319 ** If Counterstrike is installed and this is an official map and 7320 ** the file name matches a counterstrike map then tell the host 7321 ** that I have the scenario so he can continue while we make 7322 ** sure the local user has the Counterstrike CD in the drive. 7323 ** 7324 */ 7325 // This is duplicated for Aftermath scenarios. ajw 7326 7327 #ifdef FIXIT_CSII // checked - ajw 9/28/98 7328 if (Session.ScenarioIsOfficial && 7329 ( (Expansion_CS_Present() && Is_Mission_Counterstrike(Session.ScenarioFileName)) || 7330 (Expansion_AM_Present() && Is_Mission_Aftermath(Session.ScenarioFileName)) ) ) { 7331 #else 7332 if ( Expansion_CS_Present() && Session.ScenarioIsOfficial ) { 7333 #endif 7334 7335 CCFileClass check_file ( Session.ScenarioFileName ); 7336 if ( !check_file.Is_Available() ) { 7337 7338 int current_drive = CCFileClass::Get_CD_Drive(); 7339 #ifdef FIXIT_CSII // checked - ajw 9/28/98 7340 int index = Get_CD_Index(current_drive, 1*60); 7341 bool needcd = false; 7342 if (Is_Mission_Counterstrike(Session.ScenarioFileName)) { 7343 if (index != 2 && index != 3) { 7344 RequiredCD = 2; 7345 needcd = true; 7346 } 7347 } 7348 if (Is_Mission_Aftermath(Session.ScenarioFileName)) { 7349 if (index != 3) { 7350 RequiredCD = 3; 7351 needcd = true; 7352 } 7353 } 7354 if (needcd) { 7355 #else 7356 if ( Get_CD_Index(current_drive, 1*60) != 2 ){ 7357 RequiredCD = 2; 7358 #endif 7359 7360 /* 7361 ** We should have the scenario but the wrong disk is in. 7362 ** Tell the host that I am ready to go anyway. 7363 */ 7364 memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket)); 7365 Session.GPacket.Command = NET_READY_TO_GO; 7366 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 7367 1, &Session.HostAddress); 7368 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0); 7369 ready_packet_was_sent = true; 7370 7371 if (!Force_CD_Available (RequiredCD)){ 7372 Emergency_Exit(EXIT_FAILURE); 7373 } 7374 7375 CCFileClass testfile ( Session.ScenarioFileName ); 7376 7377 /* 7378 ** Update the internal list of scenarios to include the counterstrike 7379 ** list. 7380 */ 7381 Session.Read_Scenario_Descriptions(); 7382 7383 /* 7384 ** See if that scenario is available now. Its pretty fatal if it isnt. 7385 */ 7386 Session.Options.ScenarioIndex = -1; 7387 for (i = 0; i < Session.Scenarios.Count(); i++) { 7388 if (!strcmp (Session.Scenarios[i]->Description(), Session.Options.ScenarioDescription) ){ 7389 Session.Options.ScenarioIndex = i; 7390 break; 7391 } 7392 } 7393 } 7394 } 7395 } 7396 7397 7398 /* 7399 ** If the scenario that the host wants to play doesnt exist locally then we 7400 ** need to request that it is sent. If we can identify the scenario locally then 7401 ** we need to fix up the file name so we load the right one. 7402 */ 7403 if (Find_Local_Scenario (Session.Options.ScenarioDescription, 7404 Session.ScenarioFileName, 7405 Session.ScenarioFileLength, 7406 Session.ScenarioDigest, 7407 Session.ScenarioIsOfficial)) { 7408 7409 Session.Options.ScenarioIndex = 1; //We dont care what it 7410 //is as long as it isnt -1 7411 7412 /* 7413 ** We have the scenario. Tell the host that I am ready to go. 7414 */ 7415 if ( !ready_packet_was_sent ){ 7416 memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket)); 7417 Session.GPacket.Command = NET_READY_TO_GO; 7418 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 7419 1, &Session.HostAddress); 7420 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0); 7421 } 7422 } else { 7423 #ifndef FIXIT_VERSION_3 // Removed restriction on downloading official maps. 7424 /* 7425 ** Oh dear. Thats a scenario I dont have. Request that the host sends the 7426 ** scenario to me provided its not an official Westwood scenario. 7427 ** 7428 ** If the file is received OK then we will get a true return value and the 7429 ** actual file name to load will be in Session.ScenarioFileName 7430 */ 7431 if (Session.ScenarioIsOfficial) { 7432 Session.Options.ScenarioIndex = -1; 7433 } else { 7434 #endif 7435 Session.Options.ScenarioIndex = 1; //We dont care what it 7436 //is as long as it isnt -1 7437 #ifdef FIXIT_VERSION_3 7438 if( bSpecialAftermathScenario( Session.Options.ScenarioDescription ) ) 7439 break; 7440 #endif 7441 7442 if (!Get_Scenario_File_From_Host(Session.ScenarioFileName, 1)) { 7443 break; 7444 } else { 7445 /* 7446 ** Make sure we dont time-out because of the download 7447 */ 7448 } 7449 #ifndef FIXIT_VERSION_3 7450 } 7451 #endif 7452 } 7453 }else{ 7454 /* 7455 ** Make sure we respond to the host in a load game 7456 */ 7457 memset ((void*)&(Session.GPacket), 0, sizeof (Session.GPacket)); 7458 Session.GPacket.Command = NET_READY_TO_GO; 7459 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 7460 1, &Session.HostAddress); 7461 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0); 7462 } 7463 7464 strcpy (Scen.ScenarioName, Session.ScenarioFileName); 7465 7466 rc = 0; 7467 process = false; 7468 } 7469 7470 //.................................................................. 7471 // If we're newly-confirmed, add myself to the Players list, and 7472 // immediately send out a player query 7473 //.................................................................. 7474 else if (joinstate==JOIN_CONFIRMED) { 7475 //............................................................... 7476 // Clear the player list, then add myself to the list. 7477 //............................................................... 7478 Clear_Listbox(&playerlist); 7479 Clear_Vector (&Session.Players); 7480 7481 item = new char [MPLAYER_NAME_MAX + 12]; 7482 #ifdef OLDWAY 7483 if (Session.House==HOUSE_GOOD) { 7484 sprintf(item,"%s\t%s",namebuf, Text_String(TXT_ALLIES)); 7485 } else { 7486 sprintf(item,"%s\t%s",namebuf, Text_String(TXT_SOVIET)); 7487 } 7488 #else //OLDWAY 7489 sprintf (item, "%s\t%s", namebuf, Text_String(HouseTypeClass::As_Reference(Session.House).Full_Name())); 7490 #endif //OLDWAY 7491 playerlist.Add_Item(item, 7492 (Session.ColorIdx == PCOLOR_DIALOG_BLUE) ? &ColorRemaps[PCOLOR_REALLY_BLUE] : &ColorRemaps[Session.ColorIdx]); 7493 7494 who = new NodeNameType; 7495 strcpy(who->Name, namebuf); 7496 who->Player.House = Session.House; 7497 who->Player.Color = Session.ColorIdx; 7498 Session.Players.Add (who); 7499 7500 Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf); 7501 #if (0) 7502 //............................................................... 7503 // Re-init the message system to its new smaller size 7504 //............................................................... 7505 Session.Messages.Init (0,0, 8, 7506 MAX_MESSAGE_LENGTH, d_txt6_h, 0, 0, 1, 7507 20, MAX_MESSAGE_LENGTH - 5); 7508 Session.Messages.Add_Edit(Session.ColorIdx, TPF_TEXT | TPF_BRIGHT_COLOR, NULL, '_'); 7509 #endif //(0) 7510 } 7511 7512 //.................................................................. 7513 // If we've been rejected, clear any messages we may have been 7514 // typing, add a message stating why we were rejected, and send a 7515 // chat announcement. 7516 //.................................................................. 7517 else if (joinstate==JOIN_REJECTED) { 7518 Sound_Effect(VOC_SYS_ERROR); 7519 Send_Join_Queries (game_index, joinstate, 0, 0, 1, namebuf); 7520 7521 } 7522 } // end of state change 7523 7524 //..................................................................... 7525 // If the game options have changed, print them. 7526 //..................................................................... 7527 else if (event == EV_GAME_OPTIONS) { 7528 7529 Sound_Effect(VOC_OPTIONS_CHANGED); 7530 7531 parms_received = 1; 7532 display = REDRAW_PARMS; 7533 } 7534 7535 7536 //..................................................................... 7537 // EV_GAME_SIGNOFF: 7538 // A game before the one I've selected is gone, so we have a new index 7539 // now. 'game_index' must be kept set to the currently-selected list 7540 // item, so we send out queries for the currently-selected game. It's 7541 // therefore imperative that we detect any changes to the game list. 7542 // If we're joined in a game, we must decrement our game_index to keep 7543 // it aligned with the game we're joined to. 7544 //..................................................................... 7545 else if (event == EV_GAME_SIGNOFF) { 7546 if (joinstate==JOIN_CONFIRMED) { 7547 game_index--; 7548 join_index--; 7549 gamelist.Set_Selected_Index(join_index); 7550 } 7551 else { 7552 gamelist.Flag_To_Redraw(); 7553 Clear_Listbox(&playerlist); 7554 Clear_Vector (&Session.Players); 7555 game_index = gamelist.Current_Index(); 7556 Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf); 7557 } 7558 } 7559 7560 //..................................................................... 7561 // Service the Ipx connections 7562 //..................................................................... 7563 Ipx.Service(); 7564 7565 if (process) { 7566 //..................................................................... 7567 // Clean out the Game List; if an old entry is found: 7568 // - Remove it 7569 // - Clear the player list 7570 // - Send queries for the new selected game, if there is one 7571 //..................................................................... 7572 for (i = 1; i < Session.Games.Count(); i++) { 7573 if (TickCount - Session.Games[i]->Game.LastTime > 400) { 7574 7575 delete Session.Games[i]; 7576 Session.Games.Delete(Session.Games[i]); 7577 7578 item = (char *)(gamelist.Get_Item (i)); 7579 gamelist.Remove_Item (item); 7580 delete [] item; 7581 7582 if (i <= game_index) { 7583 if (joinstate==JOIN_CONFIRMED) { 7584 game_index--; 7585 join_index--; 7586 gamelist.Set_Selected_Index(join_index); 7587 } 7588 else { 7589 gamelist.Flag_To_Redraw(); 7590 Clear_Listbox(&playerlist); 7591 Clear_Vector (&Session.Players); 7592 game_index = gamelist.Current_Index(); 7593 Send_Join_Queries (game_index, joinstate, 0, 1, 0, namebuf); 7594 } 7595 } 7596 } 7597 } 7598 } 7599 7600 #if (0) 7601 /* 7602 ** If we were flagged to start the game and we recognise both players then quit the loop 7603 */ 7604 if (ready_to_go && Session.Players.Count() == 2) { 7605 rc = 0; 7606 process = false; 7607 } 7608 #endif //(0) 7609 7610 //..................................................................... 7611 // Service the sounds & score; GameActive must be false at this point, 7612 // so Call_Back() doesn't intercept global messages from me! 7613 //..................................................................... 7614 Call_Back(); 7615 7616 } // end of while 7617 7618 7619 //------------------------------------------------------------------------ 7620 // Establish connections with all other players. 7621 //------------------------------------------------------------------------ 7622 if (rc == 0) { 7623 //..................................................................... 7624 // If the other guys are playing a scenario I don't have (sniff), I can't 7625 // play. Try to bail gracefully. 7626 //..................................................................... 7627 if (Session.Options.ScenarioIndex==-1) { 7628 WWMessageBox().Process (TXT_UNABLE_PLAY_WAAUGH); 7629 7630 memset (&Session.GPacket, 0, sizeof(GlobalPacketType)); 7631 7632 Session.GPacket.Command = NET_SIGN_OFF; 7633 strcpy (Session.GPacket.Name, namebuf); 7634 7635 //.................................................................. 7636 // Don't send myself the message. 7637 //.................................................................. 7638 for (i = 1; i < Session.Players.Count(); i++) { 7639 Ipx.Send_Global_Message (&Session.GPacket, 7640 sizeof(GlobalPacketType), 1, 7641 &(Session.Players[i]->Address)); 7642 Ipx.Service(); 7643 } 7644 7645 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 7646 0, NULL); 7647 Ipx.Send_Global_Message (&Session.GPacket, sizeof (GlobalPacketType), 7648 0, NULL); 7649 7650 if (Session.IsBridge) { 7651 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 7652 0, &Session.BridgeNet); 7653 Ipx.Send_Global_Message (&Session.GPacket, sizeof(GlobalPacketType), 7654 0, &Session.BridgeNet); 7655 } 7656 7657 while (Ipx.Global_Num_Send() > 0 && Ipx.Service() != 0) ; 7658 7659 rc = -1; 7660 7661 } 7662 //--------------------------------------------------------------------- 7663 // Prepare to load the scenario. 7664 //--------------------------------------------------------------------- 7665 else { 7666 //.................................................................. 7667 // Set the number of players in this game, and the scenario number. 7668 //.................................................................. 7669 Session.NumPlayers = Session.Players.Count(); 7670 ///* 7671 //** Hack to fake a scenario name as if it had been sent over the connection. 7672 //*/ 7673 //sprintf(Scen.ScenarioName, "SCM%02dEA.INI", Session.Options.ScenarioIndex+1); 7674 7675 // Scen.Scenario = Session.Options.ScenarioIndex; 7676 } 7677 7678 //..................................................................... 7679 // Wait a while, polling the IPX service routines, to give our ACK 7680 // a chance to get to the other system. If he doesn't get our ACK, 7681 // he'll be waiting the whole time we load MIX files. 7682 //..................................................................... 7683 i = MAX((int)Ipx.Global_Response_Time() * 2, 60*2); 7684 starttime = TickCount; 7685 while (TickCount - starttime < (unsigned)i) { 7686 Ipx.Service(); 7687 } 7688 } 7689 7690 //------------------------------------------------------------------------ 7691 // Init network timing values, using previous response times as a measure 7692 // of what our retry delta & timeout should be. 7693 //------------------------------------------------------------------------ 7694 //Ipx.Set_Timing (Ipx.Global_Response_Time() + 2, -1, 7695 // Ipx.Global_Response_Time() * 4); 7696 Ipx.Set_Timing (Ipx.Global_Response_Time () + 2, (unsigned long) -1, max (120, Ipx.Global_Response_Time () * 8)); 7697 7698 //------------------------------------------------------------------------ 7699 // Clear all lists, but NOT the Games & Players vectors. 7700 //------------------------------------------------------------------------ 7701 Clear_Listbox(&gamelist); 7702 Clear_Listbox(&playerlist); 7703 7704 //------------------------------------------------------------------------ 7705 // Restore screen 7706 //------------------------------------------------------------------------ 7707 Hide_Mouse(); 7708 Load_Title_Page(true); 7709 Show_Mouse(); 7710 //------------------------------------------------------------------------ 7711 // Load a game if the game owner told us to 7712 //------------------------------------------------------------------------ 7713 if (load_game) { 7714 if (!Load_Game (-1)) { 7715 WWMessageBox().Process (TXT_ERROR_LOADING_GAME); 7716 rc = -1; 7717 } 7718 Frame++; 7719 } 7720 7721 //------------------------------------------------------------------------ 7722 // Clear the Players & Games vectors if we're not joined to a game. 7723 // Clear the Chat vector regardless. 7724 //------------------------------------------------------------------------ 7725 if (rc != 0) { 7726 Clear_Vector(&Session.Games); 7727 Clear_Vector(&Session.Players); 7728 } 7729 Clear_Vector(&Session.Chat); 7730 7731 return(rc); 7732 7733 #else //WIN32 7734 7735 return (0); 7736 7737 #endif //WIN32 7738 7739 } /* end of Net_Join_Dialog */ 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 bool Server_Remote_Connect(void) 7751 { 7752 int stealth; // original state of Session.NetStealth flag 7753 7754 //------------------------------------------------------------------------ 7755 // Init network timing parameters; these values should work for both a 7756 // "real" network, and a simulated modem network (ie Kali) 7757 //------------------------------------------------------------------------ 7758 Ipx.Set_Timing ( 30, // retry 2 times per second 7759 -1, // ignore max retries 7760 600); // give up after 10 seconds 7761 7762 //------------------------------------------------------------------------ 7763 // Save the original value of the NetStealth flag, so we can turn stealth 7764 // off for now (during this portion of the dialogs, we must show ourselves) 7765 //------------------------------------------------------------------------ 7766 stealth = Session.NetStealth; 7767 Session.NetStealth = 0; 7768 7769 //------------------------------------------------------------------------ 7770 // The game is now "open" for joining. Close it as soon as we exit this 7771 // routine. 7772 //------------------------------------------------------------------------ 7773 Session.NetOpen = 1; 7774 7775 //------------------------------------------------------------------------ 7776 // Read in last multiplayer game settings from the .INI file 7777 //------------------------------------------------------------------------ 7778 if (!Net_Fake_New_Dialog()) { 7779 Session.Write_MultiPlayer_Settings (); 7780 return (false); 7781 } 7782 7783 Session.NetOpen = 0; 7784 Session.NetStealth = stealth; 7785 Session.Write_MultiPlayer_Settings (); 7786 return (true); 7787 7788 } /* end of Server_Remote_Connect */ 7789 7790 7791 7792 7793 7794 7795 7796 bool Client_Remote_Connect(void) 7797 { 7798 int rc; 7799 int stealth; // original state of Session.NetStealth flag 7800 7801 //------------------------------------------------------------------------ 7802 // Init network timing parameters; these values should work for both a 7803 // "real" network, and a simulated modem network (ie Kali) 7804 //------------------------------------------------------------------------ 7805 Ipx.Set_Timing ( 30, // retry 2 times per second 7806 -1, // ignore max retries 7807 600); // give up after 10 seconds 7808 7809 //------------------------------------------------------------------------ 7810 // Save the original value of the NetStealth flag, so we can turn stealth 7811 // off for now (during this portion of the dialogs, we must show ourselves) 7812 //------------------------------------------------------------------------ 7813 stealth = Session.NetStealth; 7814 Session.NetStealth = 0; 7815 7816 //------------------------------------------------------------------------ 7817 // The game is now "open" for joining. Close it as soon as we exit this 7818 // routine. 7819 //------------------------------------------------------------------------ 7820 Session.NetOpen = 1; 7821 7822 //------------------------------------------------------------------------ 7823 // Read in last multiplayer game settings from the .INI file 7824 //------------------------------------------------------------------------ 7825 rc = Net_Fake_Join_Dialog(); 7826 Session.Write_MultiPlayer_Settings (); 7827 7828 Session.NetStealth = stealth; 7829 Session.NetOpen = 0; 7830 7831 if (rc == -1) { 7832 return(false); 7833 } else { 7834 return(true); 7835 } 7836 7837 } /* end of Client_Remote_Connect */ 7838 7839 7840 7841 /*************************** end of netdlg.cpp *****************************/ 7842 7843 #endif //#ifndef WOLAPI_INTEGRATION 7844 #endif