CnC_Remastered_Collection/TIBERIANDAWN/MPLAYER.CPP

1417 lines
51 KiB
C++

//
// Copyright 2020 Electronic Arts Inc.
//
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
// software: you can redistribute it and/or modify it under the terms of
// the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
// in the hope that it will be useful, but with permitted additional restrictions
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
// distributed with this program. You should have received a copy of the
// GNU General Public License along with permitted additional restrictions
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
/* $Header: F:\projects\c&c\vcs\code\mplayer.cpv 1.9 16 Oct 1995 16:51:08 JOE_BOSTIC $ */
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Command & Conquer *
* *
* File Name : MPLAYER.CPP *
* *
* Programmer : Bill Randolph *
* *
* Start Date : April 14, 1995 *
* *
* Last Update : July 5, 1995 [BRR] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* Select_MPlayer_Game -- prompts user for NULL-Modem, Modem, or Network game *
* Read_MultiPlayer_Settings -- reads multi-player settings from conquer.ini *
* Write_MultiPlayer_Settings -- writes multi-player settings to conquer.ini *
* Read_Scenario_Descriptions -- reads multi-player scenario #'s # descriptions *
* Free_Scenario_Descriptions -- frees memory for the scenario descriptions *
* Computer_Message -- "sends" a message from the computer *
* Garble_Message -- "garbles" a message *
* Surrender_Dialog -- Prompts user for surrendering *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "function.h"
#include "tcpip.h"
static void Garble_Message(char *buf);
int Choose_Internet_Game(void);
int Get_Internet_Host_Or_Join(void);
int Get_IP_Address(void);
void Show_Internet_Connection_Progress(void);
/***********************************************************************************************
* Select_MPlayer_Game -- prompts user for NULL-Modem, Modem, or Network game *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* GAME_NORMAL, GAME_MODEM, etc. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 02/14/1995 BR : Created. *
*=============================================================================================*/
GameType Select_MPlayer_Game (void)
{
//PG_TO_FIX
return GAME_NORMAL;
#if (0)
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
bool ipx_avail = FALSE;
int number_of_buttons;
/*........................................................................
Dialog & button dimensions
........................................................................*/
int d_dialog_w = 190*factor;
int d_dialog_h = 26*4*factor;
int d_dialog_x = ((320*factor - d_dialog_w) / 2);
// d_dialog_y = ((200 - d_dialog_h) / 2),
int d_dialog_y = ((136*factor - d_dialog_h) / 2);
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);
int d_txt6_h = 11 * factor;
int d_margin = 7 *factor;
int d_modemserial_w = 80*factor;
int d_modemserial_h = 9*factor;
int d_modemserial_x = d_dialog_cx - d_modemserial_w / 2;
int d_modemserial_y = d_dialog_y + d_margin + d_txt6_h + d_margin;
#if (0)
int d_internet_w = 80*factor;
int d_internet_h = 9*factor;
int d_internet_x = d_dialog_cx - d_internet_w / 2;
int d_internet_y = d_modemserial_y + d_modemserial_h + 2*factor;
#endif //(0)
int d_ipx_w = 80*factor;
int d_ipx_h = 9*factor;
int d_ipx_x = d_dialog_cx - d_ipx_w / 2;
int d_ipx_y = d_modemserial_y + d_modemserial_h + 2*factor;
// int d_ipx_y = d_internet_y + d_internet_h + 2*factor;
int d_cancel_w = 60*factor;
int d_cancel_h = 9*factor;
int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
int d_cancel_y = d_ipx_y + d_ipx_h + d_margin;
CountDownTimerClass delay;
/*........................................................................
Button enumerations:
........................................................................*/
enum {
BUTTON_MODEMSERIAL = 100,
#if (0)
BUTTON_INTERNET,
#endif //(0)
BUTTON_IPX,
BUTTON_CANCEL,
NUM_OF_BUTTONS = 3,
};
number_of_buttons = NUM_OF_BUTTONS;
/*........................................................................
Redraw values: in order from "top" to "bottom" layer of the dialog
........................................................................*/
typedef enum {
REDRAW_NONE = 0,
REDRAW_BUTTONS, // includes map interior & coord values
REDRAW_BACKGROUND, // includes box, map bord, key, coord labels, btns
REDRAW_ALL = REDRAW_BACKGROUND
} RedrawType;
/*........................................................................
Dialog variables:
........................................................................*/
KeyNumType input; // input from user
bool process; // loop while true
RedrawType display; // true = re-draw everything
GameType retval; // return value
int selection;
bool pressed;
int curbutton;
TextButtonClass *buttons[NUM_OF_BUTTONS];
/*........................................................................
Buttons
........................................................................*/
ControlClass *commands = NULL; // the button list
//
// If neither IPX or winsock are active then do only the modem serial dialog
//
if (Ipx.Is_IPX()){
ipx_avail = TRUE;
}
TextButtonClass modemserialbtn (BUTTON_MODEMSERIAL, TXT_MODEM_SERIAL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_modemserial_x, d_modemserial_y, d_modemserial_w, d_modemserial_h);
#if (0)
TextButtonClass internetbtn (BUTTON_INTERNET, TXT_INTERNET,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_internet_x, d_internet_y, d_internet_w, d_internet_h);
#endif //(0)
TextButtonClass ipxbtn (BUTTON_IPX, TXT_NETWORK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_ipx_x, d_ipx_y, d_ipx_w, d_ipx_h);
TextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
/*
------------------------------- Initialize -------------------------------
*/
Set_Logic_Page(SeenBuff);
/*
............................ Create the list .............................
*/
commands = &modemserialbtn;
#if (0)
internetbtn.Add_Tail(*commands);
#endif //(0)
if (ipx_avail){
ipxbtn.Add_Tail(*commands);
}
cancelbtn.Add_Tail(*commands);
/*
......................... Fill array of button ptrs ......................
*/
curbutton = 0;
buttons[0] = &modemserialbtn;
#if (0)
buttons[1] = &internetbtn;
#endif //(0)
if (ipx_avail){
buttons[1] = &ipxbtn;
buttons[2] = &cancelbtn;
}else{
buttons[1] = &cancelbtn;
number_of_buttons--;
}
buttons[curbutton]->Turn_On();
Keyboard::Clear();
Fancy_Text_Print(TXT_NONE, 0, 0, CC_GREEN, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
/*
-------------------------- Main Processing Loop --------------------------
*/
display = REDRAW_ALL;
process = true;
pressed = false;
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=REDRAW_ALL;
}
/*
........................ Invoke game callback .........................
*/
Call_Back();
/*
...................... Refresh display if needed ......................
*/
if (display) {
Hide_Mouse();
if (display >= REDRAW_BACKGROUND) {
/*
..................... Refresh the backdrop ......................
*/
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
Blit_Hid_Page_To_Seen_Buff();
/*
..................... Draw the background .......................
*/
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
Draw_Caption (TXT_SELECT_MPLAYER_GAME, d_dialog_x, d_dialog_y, d_dialog_w);
}
/*
.......................... Redraw buttons ..........................
*/
if (display >= REDRAW_BUTTONS) {
commands->Flag_List_To_Redraw();
}
Show_Mouse();
display = REDRAW_NONE;
}
/*
........................... Get user input ............................
*/
input = commands->Input();
/*
............................ Process input ............................
*/
switch (input) {
case (BUTTON_MODEMSERIAL | KN_BUTTON):
selection = BUTTON_MODEMSERIAL;
pressed = true;
break;
#if (0)
case (BUTTON_INTERNET | KN_BUTTON):
selection = BUTTON_INTERNET;
pressed = true;
break;
#endif //(0)
case (BUTTON_IPX | KN_BUTTON):
selection = BUTTON_IPX;
pressed = true;
break;
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
selection = BUTTON_CANCEL;
pressed = true;
break;
case KN_UP:
buttons[curbutton]->Turn_Off();
buttons[curbutton]->Flag_To_Redraw();
curbutton--;
if (curbutton < 0)
curbutton = (number_of_buttons - 1);
buttons[curbutton]->Turn_On();
buttons[curbutton]->Flag_To_Redraw();
break;
case KN_DOWN:
buttons[curbutton]->Turn_Off();
buttons[curbutton]->Flag_To_Redraw();
curbutton++;
if (curbutton > (number_of_buttons - 1) )
curbutton = 0;
buttons[curbutton]->Turn_On();
buttons[curbutton]->Flag_To_Redraw();
break;
case KN_RETURN:
selection = curbutton + BUTTON_MODEMSERIAL;
if (!ipx_avail) selection--;
pressed = true;
break;
default:
break;
}
if (pressed) {
//
// to make sure the selection is correct in case they used the mouse
//
buttons[curbutton]->Turn_Off();
buttons[curbutton]->Flag_To_Redraw();
curbutton = selection - BUTTON_MODEMSERIAL;
buttons[curbutton]->Turn_On();
// buttons[curbutton]->Flag_To_Redraw();
buttons[curbutton]->IsPressed = true;
buttons[curbutton]->Draw_Me(true);
switch (selection) {
case (BUTTON_MODEMSERIAL):
//
// Pop up the modem/serial/com port dialog
//
retval = Select_Serial_Dialog();
if (retval != GAME_NORMAL) {
process = false;
} else {
buttons[curbutton]->IsPressed = false;
display = REDRAW_ALL;
}
break;
#if (0)
case (BUTTON_INTERNET):
//#define ONLY_FOR_E3
#ifdef ONLY_FOR_E3
Call_Back();
Show_Internet_Connection_Progress(); //changed to do nothing
Hide_Mouse();
Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
Blit_Hid_Page_To_Seen_Buff();
Show_Mouse();
Call_Back();
CCMessageBox().Process("Error! - Unable to ping KANE.WESTWOOD.COM");
buttons[curbutton]->IsPressed = false;
display = REDRAW_ALL;
#endif //ONLY_FOR_E3
#ifdef FORCE_WINSOCK
if (Winsock.Init()){
Read_MultiPlayer_Settings ();
int result = Choose_Internet_Game();
if (!result){
Winsock.Close();
buttons[curbutton]->IsPressed = false;
display = REDRAW_ALL;
break;
}
result = Get_Internet_Host_Or_Join();
if (result == 1){
Winsock.Close();
buttons[curbutton]->IsPressed = false;
display = REDRAW_ALL;
break;
}
Server = !result;
if (Server){
#if (0)
ModemGameToPlay = INTERNET_HOST;
Winsock.Start_Server();
#else
result = Get_IP_Address();
if (!result){
Winsock.Close();
buttons[curbutton]->IsPressed = false;
display = REDRAW_ALL;
break;
}
Winsock.Set_Host_Address(PlanetWestwoodIPAddress);
Winsock.Start_Server();
#endif
}else{
ModemGameToPlay = INTERNET_JOIN;
result = Get_IP_Address();
if (!result){
Winsock.Close();
buttons[curbutton]->IsPressed = false;
display = REDRAW_ALL;
break;
}
Winsock.Set_Host_Address(PlanetWestwoodIPAddress);
Winsock.Start_Client();
}
//CountDownTimerClass connect_timeout;
//connect_timeout.Set(15*60);
////Show_Internet_Connection_Progress();
if (!Winsock.Get_Connected()){
Winsock.Close();
return(GAME_NORMAL);
}
SerialSettingsType *settings;
settings = &SerialDefaults;
Init_Null_Modem(settings);
if (Server){
if (Com_Scenario_Dialog()){
return (GAME_INTERNET);
}else{
Winsock.Close();
return (GAME_NORMAL);
}
}else{
if (Com_Show_Scenario_Dialog()){
return (GAME_INTERNET);
}else{
Winsock.Close();
return (GAME_NORMAL);
}
}
}
#endif //FORCE_WINSOCK
break;
#endif //(0)
case (BUTTON_IPX):
retval = GAME_IPX;
process = false;
break;
case (BUTTON_CANCEL):
retval = GAME_NORMAL;
process = false;
break;
}
pressed = false;
}
}
return(retval);
#endif
}
/***********************************************************************************************
* Read_MultiPlayer_Settings -- reads multi-player settings from conquer.ini *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 02/14/1995 BR : Created. *
*=============================================================================================*/
void Read_MultiPlayer_Settings (void)
{
//PG_TO_FIX
#if (0)
char *buffer; // INI staging buffer pointer.
char *tbuffer; // Accumulation buffer of trigger IDs.
int len; // Length of data in buffer.
char *tokenptr; // ptr to token
PhoneEntryClass *phone; // a phone book entry
char *entry; // a phone book entry
char buf[128]; // buffer for parsing INI entry
int i;
CELL cell;
/*------------------------------------------------------------------------
Fetch working pointer to the INI staging buffer. Make sure that the buffer
is cleared out before proceeding. (Don't use the HidPage for this, since
the HidPage may be needed for various uncompressions during the INI
parsing.)
------------------------------------------------------------------------*/
buffer = (char *)_ShapeBuffer;
memset(buffer, '\0', _ShapeBufferSize);
/*------------------------------------------------------------------------
Clear the initstring entries
------------------------------------------------------------------------*/
for (i = 0; i < InitStrings.Count(); i++) {
delete[] InitStrings[i];
}
InitStrings.Clear();
/*------------------------------------------------------------------------
Clear the dialing entries
------------------------------------------------------------------------*/
for (i = 0; i < PhoneBook.Count(); i++) {
delete PhoneBook[i];
}
PhoneBook.Clear();
/*------------------------------------------------------------------------
Create filename and read the file.
------------------------------------------------------------------------*/
CCFileClass file ("CONQUER.INI");
if (!file.Is_Available()) {
return;
} else {
file.Read(buffer, _ShapeBufferSize-1);
}
file.Close();
if (!Special.IsFromWChat){
/*------------------------------------------------------------------------
Get the player's last-used Handle
------------------------------------------------------------------------*/
WWGetPrivateProfileString("MultiPlayer", "Handle", "Noname", MPlayerName,
sizeof(MPlayerName), buffer);
/*------------------------------------------------------------------------
Get the player's last-used Color
------------------------------------------------------------------------*/
MPlayerPrefColor = WWGetPrivateProfileInt("MultiPlayer", "Color", 0, buffer);
MPlayerHouse = (HousesType)WWGetPrivateProfileInt("MultiPlayer", "Side",
HOUSE_GOOD, buffer);
CurPhoneIdx = WWGetPrivateProfileInt("MultiPlayer", "PhoneIndex", -1, buffer);
}else{
CurPhoneIdx = -1;
}
#if 1
TrapCheckHeap = WWGetPrivateProfileInt( "MultiPlayer", "CheckHeap", 0, buffer);
#endif
/*------------------------------------------------------------------------
Read in default serial settings
------------------------------------------------------------------------*/
WWGetPrivateProfileString ("SerialDefaults", "ModemName", "NoName", SerialDefaults.ModemName, MODEM_NAME_MAX, buffer);
if (!strcmp ( SerialDefaults.ModemName, "NoName")) {
SerialDefaults.ModemName[0] = 0;
}
WWGetPrivateProfileString ("SerialDefaults", "Port", "0", buf, 5, buffer);
sscanf (buf, "%x", &SerialDefaults.Port);
SerialDefaults.IRQ = WWGetPrivateProfileInt("SerialDefaults", "IRQ", -1, buffer);
SerialDefaults.Baud = WWGetPrivateProfileInt("SerialDefaults", "Baud", -1, buffer);
SerialDefaults.Init = WWGetPrivateProfileInt("SerialDefaults", "Init", 0, buffer);
SerialDefaults.Compression = WWGetPrivateProfileInt ("SerialDefaults", "Compression", 0, buffer);
SerialDefaults.ErrorCorrection = WWGetPrivateProfileInt ("SerialDefaults", "ErrorCorrection", 0, buffer);
SerialDefaults.HardwareFlowControl = WWGetPrivateProfileInt ("SerialDefaults", "HardwareFlowControl", 1, buffer);
WWGetPrivateProfileString ("SerialDefaults", "DialMethod", "T",
buf, 2, buffer);
// find dial method
for (i = 0; i < DIAL_METHODS; i++) {
if ( !strcmpi( buf, DialMethodCheck[ i ]) ) {
SerialDefaults.DialMethod = (DialMethodType)i;
break;
}
}
// if method not found set to touch tone
if (i == DIAL_METHODS) {
SerialDefaults.DialMethod = DIAL_TOUCH_TONE;
}
SerialDefaults.InitStringIndex =
WWGetPrivateProfileInt("SerialDefaults",
"InitStringIndex", 0, buffer);
SerialDefaults.CallWaitStringIndex =
WWGetPrivateProfileInt("SerialDefaults",
"CallWaitStringIndex", CALL_WAIT_CUSTOM,
buffer);
WWGetPrivateProfileString ("SerialDefaults", "CallWaitString", "",
SerialDefaults.CallWaitString, CWAITSTRBUF_MAX, buffer);
if (SerialDefaults.IRQ == 0 ||
SerialDefaults.Baud == 0) {
SerialDefaults.Port = 0;
SerialDefaults.IRQ = -1;
SerialDefaults.Baud = -1;
}
/*------------------------------------------------------------------------
Set 'tbuffer' to point past the actual INI data
------------------------------------------------------------------------*/
len = strlen(buffer) + 2;
tbuffer = buffer + len;
/*------------------------------------------------------------------------
Read all Base-Scenario names into 'tbuffer'
------------------------------------------------------------------------*/
WWGetPrivateProfileString("InitStrings", NULL, NULL, tbuffer,
ShapeBufferSize-len, buffer);
/*------------------------------------------------------------------------
Read in & store each entry
------------------------------------------------------------------------*/
while (*tbuffer != '\0') {
entry = new char[ INITSTRBUF_MAX ];
entry[0] = 0;
WWGetPrivateProfileString("InitStrings", tbuffer, NULL, entry,
INITSTRBUF_MAX, buffer);
strupr( entry );
InitStrings.Add( entry );
tbuffer += strlen(tbuffer) + 1;
}
// if no entries then have at least one
if ( tbuffer == (buffer + len) ) {
entry = new char[ INITSTRBUF_MAX ];
strcpy( entry, "ATZ" );
InitStrings.Add( entry );
SerialDefaults.InitStringIndex = 0;
} else {
len = strlen(buffer) + 2;
}
/*------------------------------------------------------------------------
Repeat the process for the phonebook
------------------------------------------------------------------------*/
tbuffer = buffer + len;
/*------------------------------------------------------------------------
Read in all phone book listings.
Format: Name=PhoneNum,Port,IRQ,Baud,InitString
------------------------------------------------------------------------*/
/*........................................................................
Read the entry names in
........................................................................*/
WWGetPrivateProfileString("PhoneBook", NULL, NULL, tbuffer,
ShapeBufferSize-len, buffer);
while (*tbuffer != '\0') {
/*.....................................................................
Create a new phone book entry
.....................................................................*/
phone = new PhoneEntryClass();
/*.....................................................................
Read the entire entry in
.....................................................................*/
WWGetPrivateProfileString("PhoneBook", tbuffer, NULL, buf, 128, buffer);
/*.....................................................................
Extract name, phone # & serial port settings
.....................................................................*/
tokenptr = strtok( buf, "|" );
if (tokenptr) {
strcpy( phone->Name, tokenptr );
strupr( phone->Name );
} else {
phone->Name[0] = 0;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
strcpy( phone->Number, tokenptr );
strupr( phone->Number );
} else {
phone->Number[0] = 0;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
sscanf( tokenptr, "%x", &phone->Settings.Port );
} else {
phone->Settings.Port = 0;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
phone->Settings.IRQ = atoi( tokenptr );
} else {
phone->Settings.IRQ = -1;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
phone->Settings.Baud = atoi( tokenptr );
} else {
phone->Settings.Baud = -1;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
phone->Settings.Compression = atoi( tokenptr );
} else {
phone->Settings.Compression = 0;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
phone->Settings.ErrorCorrection = atoi( tokenptr );
} else {
phone->Settings.ErrorCorrection = 0;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
phone->Settings.HardwareFlowControl = atoi( tokenptr );
} else {
phone->Settings.HardwareFlowControl = 1;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
strcpy( buf, tokenptr );
// find dial method
for (i = 0; i < DIAL_METHODS; i++) {
if ( !strcmpi( buf, DialMethodCheck[ i ]) ) {
phone->Settings.DialMethod = (DialMethodType)i;
break;
}
}
// if method not found set to touch tone
if (i == DIAL_METHODS) {
phone->Settings.DialMethod = DIAL_TOUCH_TONE;
}
} else {
phone->Settings.DialMethod = DIAL_TOUCH_TONE;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
phone->Settings.InitStringIndex = atoi( tokenptr );
} else {
phone->Settings.InitStringIndex = 0;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
phone->Settings.CallWaitStringIndex = atoi( tokenptr );
} else {
phone->Settings.CallWaitStringIndex = CALL_WAIT_CUSTOM;
}
tokenptr = strtok( NULL, "|" );
if (tokenptr) {
strcpy (phone->Settings.CallWaitString, tokenptr);
} else {
phone->Settings.CallWaitString[0] = 0;
}
/*.....................................................................
Add it to our list
.....................................................................*/
PhoneBook.Add(phone);
tbuffer += strlen(tbuffer) + 1;
}
/*------------------------------------------------------------------------
Read special recording playback values, to help find sync bugs
------------------------------------------------------------------------*/
if (PlaybackGame) {
TrapFrame = WWGetPrivateProfileInt ("SyncBug","Frame",0x7fffffff, buffer);
TrapObjType = (RTTIType)WWGetPrivateProfileInt ("SyncBug","Type",RTTI_NONE, buffer);
WWGetPrivateProfileString ("SyncBug","Type","NONE",buf,80,buffer);
if (!stricmp(buf,"AIRCRAFT"))
TrapObjType = RTTI_AIRCRAFT;
else if (!stricmp(buf,"ANIM"))
TrapObjType = RTTI_ANIM;
else if (!stricmp(buf,"BUILDING"))
TrapObjType = RTTI_BUILDING;
else if (!stricmp(buf,"BULLET"))
TrapObjType = RTTI_BULLET;
else if (!stricmp(buf,"INFANTRY"))
TrapObjType = RTTI_INFANTRY;
else if (!stricmp(buf,"UNIT"))
TrapObjType = RTTI_UNIT;
else {
TrapObjType = RTTI_NONE;
}
WWGetPrivateProfileString ("SyncBug","Coord","0",buf,80,buffer);
sscanf(buf,"%x",&TrapCoord);
WWGetPrivateProfileString ("SyncBug","this","0",buf,80,buffer);
sscanf(buf,"%x",&TrapThis);
WWGetPrivateProfileString ("SyncBug","Cell","0",buf,80,buffer);
cell = atoi(buf);
if (cell) {
TrapCell = &(Map[cell]);
}
}
#endif
}
/***********************************************************************************************
* Write_MultiPlayer_Settings -- writes multi-player settings to conquer.ini *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 02/14/1995 BR : Created. *
*=============================================================================================*/
void Write_MultiPlayer_Settings (void)
{
//PG_TO_FIX
#if(0)
char * buffer; // INI staging buffer pointer.
CCFileClass file;
int i;
char entrytext[4];
char buf[128]; // buffer for parsing INI entry
/*------------------------------------------------------------------------
Get a working pointer to the INI staging buffer. Make sure that the buffer
starts cleared out of any data.
------------------------------------------------------------------------*/
buffer = (char *)_ShapeBuffer;
memset(buffer, '\0', _ShapeBufferSize);
file.Set_Name("CONQUER.INI");
if (file.Is_Available()) {
file.Open(READ);
file.Read(buffer, _ShapeBufferSize-1);
file.Close();
}
/*------------------------------------------------------------------------
Save the player's last-used Handle & Color
------------------------------------------------------------------------*/
WWWritePrivateProfileInt("MultiPlayer", "PhoneIndex", CurPhoneIdx, buffer);
WWWritePrivateProfileInt ("MultiPlayer", "Color", MPlayerPrefColor, buffer);
WWWritePrivateProfileInt ("MultiPlayer", "Side", MPlayerHouse, buffer);
WWWritePrivateProfileString("MultiPlayer", "Handle", MPlayerName, buffer);
/*------------------------------------------------------------------------
Clear all existing SerialDefault entries.
------------------------------------------------------------------------*/
WWWritePrivateProfileString ("SerialDefaults", NULL, NULL, buffer);
/*------------------------------------------------------------------------
Save default serial settings in opposite order you want to see them
------------------------------------------------------------------------*/
WWWritePrivateProfileString("SerialDefaults", "CallWaitString",
SerialDefaults.CallWaitString, buffer);
WWWritePrivateProfileInt ("SerialDefaults", "CallWaitStringIndex", SerialDefaults.CallWaitStringIndex, buffer);
WWWritePrivateProfileInt ("SerialDefaults", "InitStringIndex", SerialDefaults.InitStringIndex, buffer);
WWWritePrivateProfileInt ("SerialDefaults", "Init", SerialDefaults.Init, buffer);
WWWritePrivateProfileString("SerialDefaults", "DialMethod",
DialMethodCheck[ SerialDefaults.DialMethod ], buffer);
WWWritePrivateProfileInt ("SerialDefaults", "Baud", SerialDefaults.Baud, buffer);
WWWritePrivateProfileInt ("SerialDefaults", "IRQ", SerialDefaults.IRQ, buffer);
sprintf(buf, "%x", SerialDefaults.Port);
WWWritePrivateProfileString("SerialDefaults", "Port", buf, buffer);
WWWritePrivateProfileString("SerialDefaults", "ModemName", SerialDefaults.ModemName, buffer);
WWWritePrivateProfileInt ("SerialDefaults", "Compression", SerialDefaults.Compression , buffer);
WWWritePrivateProfileInt ("SerialDefaults", "ErrorCorrection", SerialDefaults.ErrorCorrection, buffer);
WWWritePrivateProfileInt ("SerialDefaults", "HardwareFlowControl", SerialDefaults.HardwareFlowControl, buffer);
/*------------------------------------------------------------------------
Clear all existing InitString entries.
------------------------------------------------------------------------*/
WWWritePrivateProfileString ("InitStrings", NULL, NULL, buffer);
/*------------------------------------------------------------------------
Save all InitString entries. In descending order so they come out in
ascending order.
------------------------------------------------------------------------*/
for (i = (InitStrings.Count() - 1); i >= 0; i--) {
sprintf( buf, "%03d", i);
WWWritePrivateProfileString ("InitStrings", buf, InitStrings[i], buffer);
}
/*------------------------------------------------------------------------
Clear all existing Phone Book entries.
------------------------------------------------------------------------*/
WWWritePrivateProfileString ("PhoneBook", NULL, NULL, buffer);
/*------------------------------------------------------------------------
Save all Phone Book entries.
Format: Entry=Name,PhoneNum,Port,IRQ,Baud,InitString
------------------------------------------------------------------------*/
for (i = (PhoneBook.Count() - 1); i >= 0; i--) {
sprintf(buf,"%s|%s|%x|%d|%d|%d|%d|%d|%s|%d|%d|%s",
PhoneBook[i]->Name,
PhoneBook[i]->Number,
PhoneBook[i]->Settings.Port,
PhoneBook[i]->Settings.IRQ,
PhoneBook[i]->Settings.Baud,
PhoneBook[i]->Settings.Compression,
PhoneBook[i]->Settings.ErrorCorrection,
PhoneBook[i]->Settings.HardwareFlowControl,
DialMethodCheck[ PhoneBook[i]->Settings.DialMethod ],
PhoneBook[i]->Settings.InitStringIndex,
PhoneBook[i]->Settings.CallWaitStringIndex,
PhoneBook[i]->Settings.CallWaitString);
sprintf( entrytext, "%03d", i );
WWWritePrivateProfileString ("PhoneBook", entrytext, buf, buffer);
}
/*------------------------------------------------------------------------
Write the INI data out to a file.
------------------------------------------------------------------------*/
file.Open(WRITE);
file.Write(buffer,strlen(buffer));
file.Close();
#endif
}
/***********************************************************************************************
* Read_Scenario_Descriptions -- reads multi-player scenario #'s # descriptions *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 02/14/1995 BR : Created. *
*=============================================================================================*/
void Read_Scenario_Descriptions (void)
{
char *buffer; // INI staging buffer pointer.
CCFileClass file;
int i;
char fname[20];
/*------------------------------------------------------------------------
Clear the scenario description lists
------------------------------------------------------------------------*/
MPlayerScenarios.Clear();
MPlayerFilenum.Clear();
/*------------------------------------------------------------------------
Loop through all possible scenario numbers; if a file is available, add
its number to the FileNum list.
------------------------------------------------------------------------*/
for (i = 0; i < 100; i++) {
Set_Scenario_Name(ScenarioName, i, SCEN_PLAYER_MPLAYER,
SCEN_DIR_EAST, SCEN_VAR_A);
sprintf(fname,"%s.INI",ScenarioName);
file.Set_Name (fname);
if (file.Is_Available()) {
MPlayerFilenum.Add(i);
}
}
/*------------------------------------------------------------------------
Now, for every file in the FileNum list, read in the INI file, and extract
its description.
------------------------------------------------------------------------*/
for (i = 0; i < MPlayerFilenum.Count(); i++) {
/*.....................................................................
Fetch working pointer to the INI staging buffer. Make sure that the
buffer is cleared out before proceeding.
.....................................................................*/
buffer = (char *)_ShapeBuffer;
memset(buffer, '\0', _ShapeBufferSize);
/*.....................................................................
Create filename and read the file.
.....................................................................*/
Set_Scenario_Name(ScenarioName, MPlayerFilenum[i], SCEN_PLAYER_MPLAYER,
SCEN_DIR_EAST, SCEN_VAR_A);
sprintf(fname,"%s.INI",ScenarioName);
file.Set_Name (fname);
file.Read(buffer, _ShapeBufferSize-1);
file.Close();
/*.....................................................................
Extract description & add it to the list.
.....................................................................*/
WWGetPrivateProfileString("Basic", "Name", "Nulls-Ville",
MPlayerDescriptions[i], 40, buffer);
MPlayerScenarios.Add(MPlayerDescriptions[i]);
}
}
/***********************************************************************************************
* Free_Scenario_Descriptions -- frees memory for the scenario descriptions *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 06/05/1995 BRR : Created. *
*=============================================================================================*/
void Free_Scenario_Descriptions(void)
{
/*------------------------------------------------------------------------
Clear the scenario descriptions & filenames
------------------------------------------------------------------------*/
MPlayerScenarios.Clear();
MPlayerFilenum.Clear();
//PG_TO_FIX
#if (0)
int i;
/*------------------------------------------------------------------------
Clear the initstring entries
------------------------------------------------------------------------*/
for (i = 0; i < InitStrings.Count(); i++) {
delete InitStrings[i];
}
InitStrings.Clear();
/*------------------------------------------------------------------------
Clear the dialing entries
------------------------------------------------------------------------*/
for (i = 0; i < PhoneBook.Count(); i++) {
delete PhoneBook[i];
}
PhoneBook.Clear();
#endif
}
/***************************************************************************
* Computer_Message -- "sends" a message from the computer *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 06/06/1995 BRR : Created. *
*=========================================================================*/
void Computer_Message(void)
{
int color;
char txt[160];
HousesType house;
HouseClass *ptr;
/*------------------------------------------------------------------------
Find the computer house that the message will be from
------------------------------------------------------------------------*/
for (house = HOUSE_MULTI1; house < (HOUSE_MULTI1 + MPlayerMax); house++) {
ptr = HouseClass::As_Pointer(house);
if (!ptr || ptr->IsHuman || ptr->IsDefeated) {
continue;
}
/*.....................................................................
Decode this house's color
.....................................................................*/
color = MPlayerTColors[ptr->RemapColor];
/*.....................................................................
We now have a 1/4 chance of echoing one of the human players' messages
back.
.....................................................................*/
if (IRandom(0,3) == 2) {
/*..................................................................
Now we have a 1/3 chance of garbling the human message.
..................................................................*/
if (IRandom(0,2) == 1) {
Garble_Message(LastMessage);
}
/*..................................................................
Only add the message if there is one to add.
..................................................................*/
if (strlen(LastMessage)) {
sprintf(txt,"%s %s",Text_String(TXT_FROM_COMPUTER),LastMessage);
Messages.Add_Message(txt, color,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
}
} else {
sprintf(txt,"%s %s",Text_String(TXT_FROM_COMPUTER),
Text_String(TXT_COMP_MSG1 + IRandom(0,12)));
Messages.Add_Message(txt, color,
TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, 600, 0, 0);
}
return;
}
}
/***************************************************************************
* Garble_Message -- "garbles" a message *
* *
* INPUT: *
* buf buffer to garble; stores output message *
* *
* OUTPUT: *
* none. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 06/06/1995 BRR : Created. *
*=========================================================================*/
static void Garble_Message(char *buf)
{
char txt[80];
char punct[20]; // for punctuation
char *p; // working ptr
int numwords; // # words in the phrase
char *words[40]; // ptrs to various words in the phrase
int i,j;
/*------------------------------------------------------------------------
Pull off any trailing punctuation
------------------------------------------------------------------------*/
p = buf + strlen(buf) - 1;
while (1) {
if (p < buf)
break;
if (p[0]=='!' || p[0]=='.' || p[0]=='?') {
p--;
} else {
p++;
break;
}
if (strlen(p) >= (sizeof(punct) - 1) ) {
break;
}
}
strcpy (punct, p);
p[0] = 0;
for (i = 0; i < 40; i++) {
words[i] = NULL;
}
/*------------------------------------------------------------------------
Copy the original buffer
------------------------------------------------------------------------*/
strcpy(txt,buf);
/*------------------------------------------------------------------------
Split it up into words
------------------------------------------------------------------------*/
p = strtok (txt, " ");
numwords = 0;
while (p) {
words[numwords] = p;
numwords++;
p = strtok (NULL, " ");
}
/*------------------------------------------------------------------------
Now randomly put the words back. Don't use the real random-number
generator, since different machines will have different LastMessage's,
and will go out of sync.
------------------------------------------------------------------------*/
buf[0] = 0;
for (i = 0; i < numwords; i++) {
j = Sim_IRandom(0,numwords);
if (words[j] == NULL) { // this word has been used already
i--;
continue;
}
strcat(buf,words[j]);
words[j] = NULL;
if (i < numwords-1)
strcat(buf," ");
}
strcat(buf,punct);
}
/***************************************************************************
* Surrender_Dialog -- Prompts user for surrendering *
* *
* INPUT: *
* none. *
* *
* OUTPUT: *
* 0 = user cancels, 1 = user wants to surrender. *
* *
* WARNINGS: *
* none. *
* *
* HISTORY: *
* 07/05/1995 BRR : Created. *
*=========================================================================*/
int Surrender_Dialog(void)
{
int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
/*........................................................................
Dialog & button dimensions
........................................................................*/
int d_dialog_w = 170*factor; // dialog width
int d_dialog_h = 53*factor; // dialog height
int d_dialog_x = ((320*factor - d_dialog_w) / 2); // centered x-coord
int d_dialog_y = ((200*factor - d_dialog_h) / 2); // centered y-coord
int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // coord of x-center
int d_txt6_h = 6*factor+1; // ht of 6-pt text
int d_margin = 5*factor; // margin width/height
int d_topmargin = 20*factor; // top margin
int d_ok_w = 45*factor; // ok width
int d_ok_h = 9*factor; // ok height
int d_ok_x = d_dialog_cx - d_ok_w - 5*factor; // ok x
int d_ok_y = d_dialog_y + d_dialog_h - d_ok_h - d_margin; // ok y
int d_cancel_w = 45*factor; // cancel width
int d_cancel_h = 9*factor; // cancel height
int d_cancel_x = d_dialog_cx + 5*factor; // cancel x
int d_cancel_y = d_dialog_y + d_dialog_h - d_cancel_h - d_margin; // cancel y
/*........................................................................
Button enumerations
........................................................................*/
enum {
BUTTON_OK = 100,
BUTTON_CANCEL,
};
/*........................................................................
Redraw values: in order from "top" to "bottom" layer of the dialog
........................................................................*/
typedef enum {
REDRAW_NONE = 0,
REDRAW_BUTTONS,
REDRAW_BACKGROUND,
REDRAW_ALL = REDRAW_BACKGROUND
} RedrawType;
/*........................................................................
Dialog variables
........................................................................*/
RedrawType display; // requested redraw level
bool process; // loop while true
KeyNumType input;
int retcode;
/*........................................................................
Buttons
........................................................................*/
ControlClass *commands = NULL; // the button list
TextButtonClass okbtn (BUTTON_OK, TXT_OK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_ok_x, d_ok_y, d_ok_w, d_ok_h);
TextButtonClass cancelbtn (BUTTON_CANCEL, TXT_CANCEL,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
/*
------------------------------- Initialize -------------------------------
*/
Set_Logic_Page(SeenBuff);
/*
......................... Create the button list .........................
*/
commands = &okbtn;
cancelbtn.Add_Tail(*commands);
/*
-------------------------- Main Processing Loop --------------------------
*/
display = REDRAW_ALL;
process = true;
while (process) {
/*
** If we have just received input focus again after running in the background then
** we need to redraw.
*/
if (AllSurfaces.SurfacesRestored){
AllSurfaces.SurfacesRestored=FALSE;
display=REDRAW_ALL;
}
/*
........................ Invoke game callback .........................
*/
if (Main_Loop()) {
retcode = 0;
process = false;
}
/*
...................... Refresh display if needed ......................
*/
if (display) {
/*
...................... Display the dialog box ......................
*/
Hide_Mouse();
if (display >= REDRAW_BACKGROUND) {
Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
Draw_Caption(TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
/*
....................... Draw the captions .......................
*/
Fancy_Text_Print(Text_String(TXT_SURRENDER),
d_dialog_cx, d_dialog_y + d_topmargin,
CC_GREEN, TBLACK,
TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
}
/*
........................ Redraw the buttons ........................
*/
if (display >= REDRAW_BUTTONS) {
commands->Flag_List_To_Redraw();
}
Show_Mouse();
display = REDRAW_NONE;
}
/*
........................... Get user input ............................
*/
input = commands->Input();
/*
............................ Process input ............................
*/
switch (input) {
case (KN_RETURN):
case (BUTTON_OK | KN_BUTTON):
retcode = 1;
process = false;
break;
case (KN_ESC):
case (BUTTON_CANCEL | KN_BUTTON):
retcode = 0;
process = false;
break;
default:
break;
}
}
/*
--------------------------- Redraw the display ---------------------------
*/
HiddenPage.Clear();
Map.Flag_To_Redraw(true);
Map.Render();
return (retcode);
}