Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.

This commit is contained in:
LFeenanEA 2025-02-27 17:34:39 +00:00
parent 2e338c00cb
commit 3d0ee53a05
No known key found for this signature in database
GPG Key ID: C6EBE8C2EA08F7E0
6072 changed files with 2283311 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ActionManager.h //////////////////////////////////////////////////////////////////////////
// Author: Colin Day
// Desc: TheActionManager is a convenient place for us to wrap up all sorts of logical
// queries about what objects can do in the world and to other objects. The purpose
// of having a central place for this logic assists us in making these logical kind
// of queries in the user interface and allows us to use the same code to validate
// commands as they come in over the network interface in order to do the
// real action.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __ACTIONMANAGER_H_
#define __ACTIONMANAGER_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/SubsystemInterface.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Object;
class Player;
class SpecialPowerTemplate;
enum SpecialPowerType;
enum WeaponSlotType;
enum CommandSourceType;
enum CanAttackResult;
enum CanEnterType
{
CHECK_CAPACITY,
DONT_CHECK_CAPACITY,
COMBATDROP_INTO
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class ActionManager : public SubsystemInterface
{
public:
ActionManager( void );
virtual ~ActionManager( void );
virtual void init( void ) { }; ///< subsystem interface
virtual void reset( void ) { }; ///< subsystem interface
virtual void update( void ) { }; ///< subsystem interface
//Single unit to unit check
Bool canGetRepairedAt( const Object *obj, const Object *repairDest, CommandSourceType commandSource );
Bool canTransferSuppliesAt( const Object *obj, const Object *transferDest );
Bool canDockAt( const Object *obj, const Object *dockDest, CommandSourceType commandSource );
Bool canGetHealedAt( const Object *obj, const Object *healDest, CommandSourceType commandSource );
Bool canRepairObject( const Object *obj, const Object *objectToRepair, CommandSourceType commandSource );
Bool canResumeConstructionOf( const Object *obj, const Object *objectBeingConstructed, CommandSourceType commandSource );
Bool canEnterObject( const Object *obj, const Object *objectToEnter, CommandSourceType commandSource, CanEnterType mode );
CanAttackResult getCanAttackObject( const Object *obj, const Object *objectToAttack, CommandSourceType commandSource, AbleToAttackType attackType );
Bool canConvertObjectToCarBomb( const Object *obj, const Object *objectToConvert, CommandSourceType commandSource );
Bool canHijackVehicle( const Object *obj, const Object *ObjectToHijack, CommandSourceType commandSource ); // LORENZEN
Bool canCaptureBuilding( const Object *obj, const Object *objectToCapture, CommandSourceType commandSource );
Bool canDisableVehicleViaHacking( const Object *obj, const Object *objectToHack, CommandSourceType commandSource, Bool checkSourceRequirements = true );
#ifdef ALLOW_SURRENDER
Bool canPickUpPrisoner( const Object *obj, const Object *prisoner, CommandSourceType commandSource );
#endif
Bool canStealCashViaHacking( const Object *obj, const Object *objectToHack, CommandSourceType commandSource );
Bool canSnipeVehicle( const Object *obj, const Object *objectToSnipe, CommandSourceType commandSource );
Bool canBribeUnit( const Object *obj, const Object *objectToBribe, CommandSourceType commandSource );
Bool canCutBuildingPower( const Object *obj, const Object *building, CommandSourceType commandSource );
Bool canDisableBuildingViaHacking( const Object *obj, const Object *objectToHack, CommandSourceType commandSource );
Bool canDoSpecialPowerAtLocation( const Object *obj, const Coord3D *loc, CommandSourceType commandSource, const SpecialPowerTemplate *spTemplate, const Object *objectInWay, UnsignedInt commandOptions, Bool checkSourceRequirements = true );
Bool canDoSpecialPowerAtObject( const Object *obj, const Object *target, CommandSourceType commandSource, const SpecialPowerTemplate *spTemplate, UnsignedInt commandOptions, Bool checkSourceRequirements = true);
Bool canDoSpecialPower( const Object *obj, const SpecialPowerTemplate *spTemplate, CommandSourceType commandSource, UnsignedInt commandOptions, Bool checkSourceRequirements = true );
Bool canMakeObjectDefector( const Object *obj, const Object *objectToMakeDefector, CommandSourceType commandSource );
Bool canFireWeaponAtLocation( const Object *obj, const Coord3D *loc, CommandSourceType commandSource, const WeaponSlotType slot, const Object *objectInWay );
Bool canFireWeaponAtObject( const Object *obj, const Object *target, CommandSourceType commandSource, const WeaponSlotType slot );
Bool canFireWeapon( const Object *obj, const WeaponSlotType slot, CommandSourceType commandSource );
Bool canGarrison( const Object *obj, const Object *target, CommandSourceType commandSource );
Bool canOverrideSpecialPowerDestination( const Object *obj, const Coord3D *loc, SpecialPowerType spType, CommandSourceType commandSource );
//Player to unit check
Bool canPlayerGarrison( const Player *player, const Object *target, CommandSourceType commandSource );
protected:
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern ActionManager *TheActionManager;
#endif // end __ACTIONMANAGER_H_

View File

@ -0,0 +1,77 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
/////// ArchiveFile.h ////////////////////
// Bryan Cleveland, August 2002
//////////////////////////////////////////
#pragma once
#ifndef __ARCHIVEFILE_H
#define __ARCHIVEFILE_H
#include "Lib/BaseType.h"
#include "Common/AsciiString.h"
#include "Common/ArchiveFileSystem.h"
class File;
/**
* An archive file is itself a collection of sub files. Each file inside the archive file
* has a unique name by which it can be accessed. The ArchiveFile object class is the
* runtime interface to the mix file and the sub files. Each file inside the mix
* file can be accessed by the openFile().
*
* ArchiveFile interfaces can be created by the TheArchiveFileSystem object.
*/
//===============================
class ArchiveFile
{
public:
ArchiveFile();
virtual ~ArchiveFile();
virtual Bool getFileInfo( const AsciiString& filename, FileInfo *fileInfo) const = 0; ///< fill in the fileInfo struct with info about the file requested.
virtual File* openFile( const Char *filename, Int access = 0) = 0; ///< Open the specified file within the archive file
virtual void closeAllFiles( void ) = 0; ///< Close all file opened in this archive file
virtual AsciiString getName( void ) = 0; ///< Returns the name of the archive file
virtual AsciiString getPath( void ) = 0; ///< Returns full path and name of archive file
virtual void setSearchPriority( Int new_priority ) = 0; ///< Set this archive file's search priority
virtual void close( void ) = 0; ///< Close this archive file
void attachFile(File *file);
void getFileListInDirectory(const AsciiString& currentDirectory, const AsciiString& originalDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const;
void getFileListInDirectory(const DetailedArchivedDirectoryInfo *dirInfo, const AsciiString& currentDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const;
void addFile(const AsciiString& path, const ArchivedFileInfo *fileInfo); ///< add this file to our directory tree.
protected:
const ArchivedFileInfo * getArchivedFileInfo(const AsciiString& filename) const; ///< return the ArchivedFileInfo from the directory tree.
File *m_file; ///< file pointer to the archive file on disk. Kept open so we don't have to continuously open and close the file all the time.
DetailedArchivedDirectoryInfo m_rootDirectory;
};
#endif // __ARCHIVEFILE_H

View File

@ -0,0 +1,192 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: Generals
//
// Module: Archive files
//
// File name: Common/ArchiveFileSystem.h
//
// Created: 11/26/01 TR
//
//----------------------------------------------------------------------------
#pragma once
#ifndef __ARCHIVEFILESYSTEM_H_
#define __ARCHIVEFILESYSTEM_H_
#define MUSIC_BIG "Music.big"
//----------------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------------
#include "Common/SubsystemInterface.h"
#include "Common/AsciiString.h"
#include "Common/FileSystem.h" // for typedefs, etc.
#include "Common/STLTypedefs.h"
//----------------------------------------------------------------------------
// Forward References
//----------------------------------------------------------------------------
class File;
class ArchiveFile;
//----------------------------------------------------------------------------
// Type Defines
//----------------------------------------------------------------------------
//===============================
// ArchiveFileSystem
//===============================
/**
* Creates and manages ArchiveFile interfaces. ArchiveFiles can be accessed
* by calling the openArchiveFile() member. ArchiveFiles can be accessed by
* name or by File interface.
*
* openFile() member searches all Archive files for the specified sub file.
*/
//===============================
class ArchivedDirectoryInfo;
class DetailedArchivedDirectoryInfo;
class ArchivedFileInfo;
typedef std::map<AsciiString, DetailedArchivedDirectoryInfo> DetailedArchivedDirectoryInfoMap;
typedef std::map<AsciiString, ArchivedDirectoryInfo> ArchivedDirectoryInfoMap;
typedef std::map<AsciiString, ArchivedFileInfo> ArchivedFileInfoMap;
typedef std::map<AsciiString, ArchiveFile *> ArchiveFileMap;
typedef std::map<AsciiString, AsciiString> ArchivedFileLocationMap; // first string is the file name, second one is the archive filename.
class ArchivedDirectoryInfo
{
public:
AsciiString m_directoryName;
ArchivedDirectoryInfoMap m_directories;
ArchivedFileLocationMap m_files;
void clear()
{
m_directoryName.clear();
m_directories.clear();
m_files.clear();
}
};
class DetailedArchivedDirectoryInfo
{
public:
AsciiString m_directoryName;
DetailedArchivedDirectoryInfoMap m_directories;
ArchivedFileInfoMap m_files;
void clear()
{
m_directoryName.clear();
m_directories.clear();
m_files.clear();
}
};
class ArchivedFileInfo
{
public:
AsciiString m_filename;
AsciiString m_archiveFilename;
UnsignedInt m_offset;
UnsignedInt m_size;
ArchivedFileInfo()
{
clear();
}
void clear()
{
m_filename.clear();
m_archiveFilename.clear();
m_offset = 0;
m_size = 0;
}
};
class ArchiveFileSystem : public SubsystemInterface
{
public:
ArchiveFileSystem();
virtual ~ArchiveFileSystem();
virtual void init( void ) = 0;
virtual void update( void ) = 0;
virtual void reset( void ) = 0;
virtual void postProcessLoad( void ) = 0;
// ArchiveFile operations
virtual ArchiveFile* openArchiveFile( const Char *filename ) = 0; ///< Create new or return existing Archive file from file name
virtual void closeArchiveFile( const Char *filename ) = 0; ///< Close the one specified big file.
virtual void closeAllArchiveFiles( void ) = 0; ///< Close all Archivefiles currently open
// File operations
virtual File* openFile( const Char *filename, Int access = 0); ///< Search Archive files for specified file name and open it if found
virtual void closeAllFiles( void ) = 0; ///< Close all files associated with ArchiveFiles
virtual Bool doesFileExist(const Char *filename) const; ///< return true if that file exists in an archive file somewhere.
void getFileListInDirectory(const AsciiString& currentDirectory, const AsciiString& originalDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const; ///< search the given directory for files matching the searchName (egs. *.ini, *.rep). Possibly search subdirectories. Scans each Archive file.
Bool getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const; ///< see FileSystem.h
virtual Bool loadBigFilesFromDirectory(AsciiString dir, AsciiString fileMask, Bool overwrite = FALSE) = 0;
// Unprotected this for copy-protection routines
AsciiString getArchiveFilenameForFile(const AsciiString& filename) const;
void loadMods( void );
protected:
virtual void loadIntoDirectoryTree(const ArchiveFile *archiveFile, const AsciiString& archiveFilename, Bool overwrite = FALSE); ///< load the archive file's header information and apply it to the global archive directory tree.
ArchiveFileMap m_archiveFileMap;
ArchivedDirectoryInfo m_rootDirectory;
};
extern ArchiveFileSystem *TheArchiveFileSystem;
//----------------------------------------------------------------------------
// Inlining
//----------------------------------------------------------------------------
#endif // __ARCHIVEFILESYSTEM_H_

View File

@ -0,0 +1,551 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AsciiString.h
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: AsciiString.h
//
// Created: Steven Johnson, October 2001
//
// Desc: General-purpose string classes
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef ASCIISTRING_H
#define ASCIISTRING_H
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "Lib/BaseType.h"
#include "Common/Debug.h"
#include "Common/Errors.h"
class UnicodeString;
// -----------------------------------------------------
/**
AsciiString is the fundamental single-byte string type used in the Generals
code base, and should be preferred over all other string constructions
(e.g., array of char, STL string<>, WWVegas StringClass, etc.)
Of course, other string setups may be used when necessary or appropriate!
AsciiString is modeled after the MFC CString class, with some minor
syntactic differences to keep in line with our coding conventions.
Basically, AsciiString allows you to treat a string as an intrinsic
type, rather analogous to 'int' -- when passed by value, a new string
is created, and modifying the new string doesn't modify the original.
This is done fairly efficiently, so that no new memory allocation is done
unless the string is actually modified.
Naturally, AsciiString handles all memory issues, so there's no need
to do anything to free memory... just allow the AsciiString's
destructor to run.
AsciiStrings are suitable for use as automatic, member, or static variables.
*/
class AsciiString
{
private:
// Note, this is a Plain Old Data Structure... don't
// add a ctor/dtor, 'cuz they won't ever be called.
struct AsciiStringData
{
#if defined(_DEBUG) || defined(_INTERNAL)
const char* m_debugptr; // just makes it easier to read in the debugger
#endif
unsigned short m_refCount; // reference count
unsigned short m_numCharsAllocated; // length of data allocated
// char m_stringdata[];
inline char* peek() { return (char*)(this+1); }
};
#ifdef _DEBUG
void validate() const;
#else
inline void validate() const { }
#endif
protected:
AsciiStringData* m_data; // pointer to ref counted string data
char* peek() const;
void releaseBuffer();
void ensureUniqueBufferOfSize(int numCharsNeeded, Bool preserveData, const char* strToCpy, const char* strToCat);
public:
enum
{
MAX_FORMAT_BUF_LEN = 2048, ///< max total len of string created by format/format_va
MAX_LEN = 32767 ///< max total len of any AsciiString, in chars
};
/**
This is a convenient global used to indicate the empty
string, so we don't need to construct temporaries
for such a common thing.
*/
static AsciiString TheEmptyString;
/**
Default constructor -- construct a new, empty AsciiString.
*/
AsciiString();
/**
Copy constructor -- make this AsciiString identical to the
other AsciiString. (This is actually quite efficient, because
they will simply share the same string and increment the
refcount.)
*/
AsciiString(const AsciiString& stringSrc);
/**
Constructor -- from a literal string. Constructs an AsciiString
with the given string. Note that a copy of the string is made;
the input ptr is not saved.
Note that this is no longer explicit, as the conversion is almost
always wanted, anyhow.
*/
AsciiString(const char* s);
/**
Destructor. Not too exciting... clean up the works and such.
*/
~AsciiString();
/**
Return the length, in characters (not bytes!), of the string.
*/
int getLength() const;
/**
Return true iff the length of the string is zero. Equivalent
to (getLength() == 0) but slightly more efficient.
*/
Bool isEmpty() const;
/**
Make the string empty. Equivalent to (str = "") but slightly more efficient.
*/
void clear();
/**
Return the character and the given (zero-based) index into the string.
No range checking is done (except in debug mode).
*/
char getCharAt(int index) const;
/**
Return a pointer to the (null-terminated) string. Note that this is
a const pointer: do NOT change this! It is imperative that it be
impossible (or at least, really difficuly) for someone to change our
private data, since it might be shared amongst other AsciiStrings.
*/
const char* str() const;
/**
Makes sure there is room for a string of len+1 characters, and
returns a pointer to the string buffer. This ensures that the
string buffer is NOT shared. This is intended for the file reader,
that is reading new strings in from a file. jba.
*/
char* getBufferForRead(Int len);
/**
Replace the contents of self with the given string.
(This is actually quite efficient, because
they will simply share the same string and increment the
refcount.)
*/
void set(const AsciiString& stringSrc);
/**
Replace the contents of self with the given string.
Note that a copy of the string is made; the input ptr is not saved.
*/
void set(const char* s);
/**
replace contents of self with the given string. Note the
nomenclature is translate rather than set; this is because
not all single-byte strings translate one-for-one into
UnicodeStrings, so some data manipulation may be necessary,
and the resulting strings may not be equivalent.
*/
void translate(const UnicodeString& stringSrc);
/**
Concatenate the given string onto self.
*/
void concat(const AsciiString& stringSrc);
/**
Concatenate the given string onto self.
*/
void concat(const char* s);
/**
Concatenate the given character onto self.
*/
void concat(const char c);
/**
Remove leading and trailing whitespace from the string.
*/
void trim( void );
/**
Make the string lowercase
*/
void toLower( void );
/**
Remove the final character in the string. If the string is empty,
do nothing. (This is a rather dorky method, but used a lot in
text editing, thus its presence here.)
*/
void removeLastChar();
/**
Analogous to sprintf() -- this formats a string according to the
given sprintf-style format string (and the variable argument list)
and stores the result in self.
*/
void format(AsciiString format, ...);
void format(const char* format, ...);
/**
Identical to format(), but takes a va_list rather than
a variable argument list. (i.e., analogous to vsprintf.)
*/
void format_va(const AsciiString& format, va_list args);
void format_va(const char* format, va_list args);
/**
Conceptually identical to strcmp().
*/
int compare(const AsciiString& stringSrc) const;
/**
Conceptually identical to strcmp().
*/
int compare(const char* s) const;
/**
Conceptually identical to _stricmp().
*/
int compareNoCase(const AsciiString& stringSrc) const;
/**
Conceptually identical to _stricmp().
*/
int compareNoCase(const char* s) const;
/**
Conceptually identical to strchr().
*/
const char* find(char c) const;
/**
Conceptually identical to strrchr().
*/
const char* reverseFind(char c) const;
/**
return true iff self starts with the given string.
*/
Bool startsWith(const char* p) const;
inline Bool startsWith(const AsciiString& stringSrc) const { return startsWith(stringSrc.str()); }
/**
return true iff self starts with the given string. (case insensitive)
*/
Bool startsWithNoCase(const char* p) const;
inline Bool startsWithNoCase(const AsciiString& stringSrc) const { return startsWithNoCase(stringSrc.str()); }
/**
return true iff self ends with the given string.
*/
Bool endsWith(const char* p) const;
Bool endsWith(const AsciiString& stringSrc) const { return endsWith(stringSrc.str()); }
/**
return true iff self ends with the given string. (case insensitive)
*/
Bool endsWithNoCase(const char* p) const;
Bool endsWithNoCase(const AsciiString& stringSrc) const { return endsWithNoCase(stringSrc.str()); }
/**
conceptually similar to strtok():
extract the next seps-delimited token from the front
of 'this' and copy it into 'token', returning true if a nonempty
token was found. (note that this modifies 'this' as well, stripping
the token off!)
*/
Bool nextToken(AsciiString* token, const char* seps = NULL);
/**
return true iff the string is "NONE" (case-insensitive).
Hey, hokey, but we use it a ton.
*/
Bool isNone() const;
Bool isNotEmpty() const { return !isEmpty(); }
Bool isNotNone() const { return !isNone(); }
//
// You might think it would be a good idea to overload the * operator
// to allow for an implicit conversion to an char*. This is
// (in theory) a good idea, but in practice, there's lots of code
// that assumes it should check text fields for null, which
// is meaningless for us, since we never return a null ptr.
//
// operator const char*() const { return str(); }
//
AsciiString& operator=(const AsciiString& stringSrc); ///< the same as set()
AsciiString& operator=(const char* s); ///< the same as set()
void debugIgnoreLeaks();
};
// -----------------------------------------------------
inline char* AsciiString::peek() const
{
DEBUG_ASSERTCRASH(m_data, ("null string ptr"));
validate();
return m_data->peek();
}
// -----------------------------------------------------
inline AsciiString::AsciiString() : m_data(0)
{
validate();
}
// -----------------------------------------------------
inline AsciiString::~AsciiString()
{
validate();
releaseBuffer();
}
// -----------------------------------------------------
inline int AsciiString::getLength() const
{
validate();
return m_data ? strlen(peek()) : 0;
}
// -----------------------------------------------------
inline Bool AsciiString::isEmpty() const
{
validate();
return m_data == NULL || peek()[0] == 0;
}
// -----------------------------------------------------
inline void AsciiString::clear()
{
validate();
releaseBuffer();
validate();
}
// -----------------------------------------------------
inline char AsciiString::getCharAt(int index) const
{
DEBUG_ASSERTCRASH(index >= 0 && index < getLength(), ("bad index in getCharAt"));
validate();
return m_data ? peek()[index] : 0;
}
// -----------------------------------------------------
inline const char* AsciiString::str() const
{
validate();
static const char TheNullChr = 0;
return m_data ? peek() : &TheNullChr;
}
// -----------------------------------------------------
inline AsciiString& AsciiString::operator=(const AsciiString& stringSrc)
{
validate();
set(stringSrc);
validate();
return *this;
}
// -----------------------------------------------------
inline AsciiString& AsciiString::operator=(const char* s)
{
validate();
set(s);
validate();
return *this;
}
// -----------------------------------------------------
inline void AsciiString::concat(const AsciiString& stringSrc)
{
validate();
concat(stringSrc.str());
validate();
}
// -----------------------------------------------------
inline void AsciiString::concat(const char c)
{
validate();
/// this can probably be made more efficient, if necessary
char tmp[2] = { c, 0 };
concat(tmp);
validate();
}
// -----------------------------------------------------
inline int AsciiString::compare(const AsciiString& stringSrc) const
{
validate();
return strcmp(this->str(), stringSrc.str());
}
// -----------------------------------------------------
inline int AsciiString::compare(const char* s) const
{
validate();
return strcmp(this->str(), s);
}
// -----------------------------------------------------
inline int AsciiString::compareNoCase(const AsciiString& stringSrc) const
{
validate();
return _stricmp(this->str(), stringSrc.str());
}
// -----------------------------------------------------
inline int AsciiString::compareNoCase(const char* s) const
{
validate();
return _stricmp(this->str(), s);
}
// -----------------------------------------------------
inline const char* AsciiString::find(char c) const
{
return strchr(this->str(), c);
}
// -----------------------------------------------------
inline const char* AsciiString::reverseFind(char c) const
{
return strrchr(this->str(), c);
}
// -----------------------------------------------------
inline Bool operator==(const AsciiString& s1, const AsciiString& s2)
{
return strcmp(s1.str(), s2.str()) == 0;
}
// -----------------------------------------------------
inline Bool operator!=(const AsciiString& s1, const AsciiString& s2)
{
return strcmp(s1.str(), s2.str()) != 0;
}
// -----------------------------------------------------
inline Bool operator<(const AsciiString& s1, const AsciiString& s2)
{
return strcmp(s1.str(), s2.str()) < 0;
}
// -----------------------------------------------------
inline Bool operator<=(const AsciiString& s1, const AsciiString& s2)
{
return strcmp(s1.str(), s2.str()) <= 0;
}
// -----------------------------------------------------
inline Bool operator>(const AsciiString& s1, const AsciiString& s2)
{
return strcmp(s1.str(), s2.str()) > 0;
}
// -----------------------------------------------------
inline Bool operator>=(const AsciiString& s1, const AsciiString& s2)
{
return strcmp(s1.str(), s2.str()) >= 0;
}
// -----------------------------------------------------
inline Bool operator==(const AsciiString& s1, const char* s2)
{
return strcmp(s1.str(), s2) == 0;
}
// -----------------------------------------------------
inline Bool operator!=(const AsciiString& s1, const char* s2)
{
return strcmp(s1.str(), s2) != 0;
}
// -----------------------------------------------------
inline Bool operator<(const AsciiString& s1, const char* s2)
{
return strcmp(s1.str(), s2) < 0;
}
// -----------------------------------------------------
inline Bool operator<=(const AsciiString& s1, const char* s2)
{
return strcmp(s1.str(), s2) <= 0;
}
// -----------------------------------------------------
inline Bool operator>(const AsciiString& s1, const char* s2)
{
return strcmp(s1.str(), s2) > 0;
}
// -----------------------------------------------------
inline Bool operator>=(const AsciiString& s1, const char* s2)
{
return strcmp(s1.str(), s2) >= 0;
}
#endif // ASCIISTRING_H

View File

@ -0,0 +1,46 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// EA Pacific
// John McDonald, Jr
// Do not distribute
#pragma once
#ifndef _AUDIOAFFECT_H_
#define _AUDIOAFFECT_H_
// if it is set by the options panel, use the system setting parameter. Otherwise, this will be
// appended to whatever the current system volume is.
enum AudioAffect
{
AudioAffect_Music = 0x01,
AudioAffect_Sound = 0x02,
AudioAffect_Sound3D = 0x04,
AudioAffect_Speech = 0x08,
AudioAffect_All = (AudioAffect_Music | AudioAffect_Sound | AudioAffect_Sound3D | AudioAffect_Speech),
AudioAffect_SystemSetting = 0x10,
};
#endif // _AUDIOAFFECT_H_

View File

@ -0,0 +1,125 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AudioEventInfo.h /////////////////////////////////////////////////////////////////////////
// AudioEventInfo structure
// Author: John K. McDonald, March 2002
#pragma once
#ifndef _H_AUDIOEVENTINFO_
#define _H_AUDIOEVENTINFO_
#include "Common/AsciiString.h"
#include "Common/GameMemory.h"
#include "Common/STLTypedefs.h"
// DEFINES
#define NO_INTENSIVE_AUDIO_DEBUG
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////////////////////////
struct FieldParse;
// USEFUL DECLARATIONS ////////////////////////////////////////////////////////////////////////////
enum AudioType
{
AT_Music,
AT_Streaming,
AT_SoundEffect
};
extern char *theAudioPriorityNames[];
enum AudioPriority
{
AP_LOWEST,
AP_LOW,
AP_NORMAL,
AP_HIGH,
AP_CRITICAL
};
extern char *theSoundTypeNames[];
enum SoundType
{
ST_UI = 0x0001,
ST_WORLD = 0x0002,
ST_SHROUDED = 0x0004,
ST_GLOBAL = 0x0008,
ST_VOICE = 0x0010,
ST_PLAYER = 0x0020,
ST_ALLIES = 0x0040,
ST_ENEMIES = 0x0080,
ST_EVERYONE = 0x0100,
};
extern char *theAudioControlNames[];
enum AudioControl
{
AC_LOOP = 0x0001,
AC_RANDOM = 0x0002,
AC_ALL = 0x0004,
AC_POSTDELAY = 0x0008,
AC_INTERRUPT = 0x0010,
};
struct AudioEventInfo : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AudioEventInfo, "AudioEventInfo" )
public:
AsciiString m_audioName; // This name matches the name of the AudioEventRTS
AsciiString m_filename; // For music tracks, this is the filename of the track
Real m_volume; // Desired volume of this audio
Real m_volumeShift; // Desired volume shift of the audio
Real m_minVolume; // Clamped minimum value, useful when muting sound effects
Real m_pitchShiftMin; // minimum pitch shift value
Real m_pitchShiftMax; // maximum pitch shift value
Int m_delayMin; // minimum delay before we'll fire up another one of these
Int m_delayMax; // maximum delay before we'll fire up another one of these
Int m_limit; // Limit to the number of these sounds that can be fired up simultaneously
Int m_loopCount; // number of times to loop this sound
AudioPriority m_priority; // Priority of this sound
UnsignedInt m_type; // Type of sound
UnsignedInt m_control; // control of sound
std::vector<AsciiString> m_soundsMorning; // Sounds to play in the wee hours of the morning
std::vector<AsciiString> m_sounds; // Default sounds to play
std::vector<AsciiString> m_soundsNight; // Sounds to play at night
std::vector<AsciiString> m_soundsEvening; // Sounds to play in the evening
std::vector<AsciiString> m_attackSounds;
std::vector<AsciiString> m_decaySounds;
Real m_lowPassFreq; // When performing low pass filters, what is the maximum frequency heard, expressed as a percentage?
Real m_minDistance; // less than this distance and the sound behaves as though it is at minDistance
Real m_maxDistance; // greater than this distance and the sound behaves as though it is muted
AudioType m_soundType; // This should be either Music, Streaming or SoundEffect
static const FieldParse m_audioEventInfo[]; ///< the parse table for INI definition
const FieldParse *getFieldParse( void ) const { return m_audioEventInfo; }
};
#endif /* _H_AUDIOEVENTINFO_ */

View File

@ -0,0 +1,217 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: AudioEventRTS.h ///////////////////////////////////////////////////////////////////////////////
// AudioEventRTS structure
// Author: John K. McDonald, March 2002
#pragma once
#ifndef _H_AUDIOEVENTRTS_
#define _H_AUDIOEVENTRTS_
#include "Common/AsciiString.h"
#include "Common/GameAudio.h"
#include "Common/GameMemory.h"
#include "Common/GameType.h"
// forward declarations ///////////////////////////////////////////////////////////////////////////
struct AudioEventInfo;
enum OwnerType
{
OT_Positional,
OT_Drawable,
OT_Object,
OT_Dead,
OT_INVALID
};
enum PortionToPlay
{
PP_Attack,
PP_Sound,
PP_Decay,
PP_Done
};
enum AudioPriority;
// This is called AudioEventRTS because AudioEvent is a typedef in ww3d
// You might want this to be memory pooled (I personally do), but it can't
// because we allocate them on the stack frequently.
class AudioEventRTS
{
public:
AudioEventRTS( );
AudioEventRTS( const AsciiString& eventName );
AudioEventRTS( const AsciiString& eventName, ObjectID ownerID );
AudioEventRTS( const AsciiString& eventName, DrawableID drawableID ); // Pass 0 for unused if attaching to drawable
AudioEventRTS( const AsciiString& eventName, const Coord3D *positionOfAudio );
virtual ~AudioEventRTS( );
AudioEventRTS( const AudioEventRTS& right );
AudioEventRTS& operator=( const AudioEventRTS& right );
void setEventName( AsciiString name );
const AsciiString& getEventName( void ) const { return m_eventName; }
// generateFilename is separate from generatePlayInfo because generatePlayInfo should only be called once
// per triggered event. generateFilename will be called once per loop, or once to get each filename if 'all' is
// specified.
void generateFilename( void );
AsciiString getFilename( void );
// The attack and decay sounds are generated in generatePlayInfo, because they will never be played more
// than once during a given sound event.
void generatePlayInfo( void );
Real getPitchShift( void ) const;
Real getVolumeShift( void ) const;
AsciiString getAttackFilename( void ) const;
AsciiString getDecayFilename( void ) const;
Real getDelay( void ) const;
void decrementDelay( Real timeToDecrement );
PortionToPlay getNextPlayPortion( void ) const;
void advanceNextPlayPortion( void );
void setNextPlayPortion( PortionToPlay ptp );
void decreaseLoopCount( void );
Bool hasMoreLoops( void ) const;
void setAudioEventInfo( const AudioEventInfo *eventInfo ) const;
const AudioEventInfo *getAudioEventInfo( void ) const;
void setPlayingHandle( AudioHandle handle ); // for ID of this audio piece.
AudioHandle getPlayingHandle( void ); // for ID of this audio piece
void setPosition( const Coord3D *pos );
const Coord3D* getPosition( void );
void setObjectID( ObjectID objID );
ObjectID getObjectID( void );
Bool isDead() const { return m_ownerType == OT_Dead; }
OwnerType getOwnerType() const { return m_ownerType; }
void setDrawableID( DrawableID drawID );
DrawableID getDrawableID( void );
void setTimeOfDay( TimeOfDay tod );
TimeOfDay getTimeOfDay( void ) const;
void setHandleToKill( AudioHandle handleToKill );
AudioHandle getHandleToKill( void ) const;
void setShouldFade( Bool shouldFade );
Bool getShouldFade( void ) const;
void setIsLogicalAudio( Bool isLogicalAudio );
Bool getIsLogicalAudio( void ) const;
Bool isPositionalAudio( void ) const;
Bool isCurrentlyPlaying( void ) const;
AudioPriority getAudioPriority( void ) const;
void setAudioPriority( AudioPriority newPriority );
Real getVolume( void ) const;
void setVolume( Real vol );
Int getPlayerIndex( void ) const;
void setPlayerIndex( Int playerNdx );
Int getPlayingAudioIndex( void ) { return m_playingAudioIndex; };
void setPlayingAudioIndex( Int pai ) { m_playingAudioIndex = pai; };
Bool getUninterruptable( ) const { return m_uninterruptable; }
void setUninterruptable( Bool uninterruptable ) { m_uninterruptable = uninterruptable; }
// This will retrieve the appropriate position based on type.
const Coord3D *getCurrentPosition( void );
// This will return the directory leading up to the appropriate type, including the trailing '\\'
// If localized is true, we'll append a language specifc directory to the end of the path.
AsciiString generateFilenamePrefix( AudioType audioTypeToPlay, Bool localized );
AsciiString generateFilenameExtension( AudioType audioTypeToPlay );
protected:
void adjustForLocalization( AsciiString &strToAdjust );
protected:
AsciiString m_filenameToLoad;
mutable const AudioEventInfo *m_eventInfo; // Mutable so that it can be modified even on const objects
AudioHandle m_playingHandle;
AudioHandle m_killThisHandle; ///< Sometimes sounds will canabilize other sounds in order to take their handle away.
///< This is one of those instances.
AsciiString m_eventName; ///< This should correspond with an entry in Dialog.ini, Speech.ini, or Audio.ini
AsciiString m_attackName; ///< This is the filename that should be used during the attack.
AsciiString m_decayName; ///< This is the filename that should be used during the decay.
AudioPriority m_priority; ///< This should be the priority as given by the event info, or the overrided priority.
Real m_volume; ///< This is the override for the volume. It will either be the normal
TimeOfDay m_timeOfDay; ///< This should be the current Time Of Day.
Coord3D m_positionOfAudio; ///< Position of the sound if no further positional updates are necessary
union // These are now unioned.
{
ObjectID m_objectID; ///< ObjectID of the object that this sound is tied to. Position can be automatically updated from this.
DrawableID m_drawableID; ///< DrawableID of the drawable that owns this sound
};
OwnerType m_ownerType;
Bool m_shouldFade; ///< This should fade in or out (if it is starting or stopping)
Bool m_isLogicalAudio; ///< Should probably only be true for scripted sounds
Bool m_uninterruptable;
// Playing attributes
Real m_pitchShift; ///< Pitch shift that should occur on this piece of audio
Real m_volumeShift; ///< Volume shift that should occur on this piece of audio
Real m_delay; ///< Amount to delay before playing this sound
Int m_loopCount; ///< The current loop count value. Only valid if this is a looping type event or the override has been set.
Int m_playingAudioIndex; ///< The sound index we are currently playing. In the case of non-random, we increment this to move to the next sound
Int m_allCount; ///< If this sound is an ALL type, then this is how many sounds we have played so far.
Int m_playerIndex; ///< The index of the player who owns this sound. Used for sounds that should have an owner, but don't have an object, etc.
PortionToPlay m_portionToPlayNext; ///< Which portion (attack, sound, decay) should be played next?
};
class DynamicAudioEventRTS : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(DynamicAudioEventRTS, "DynamicAudioEventRTS" )
public:
DynamicAudioEventRTS() { }
DynamicAudioEventRTS(const AudioEventRTS& a) : m_event(a) { }
AudioEventRTS m_event;
};
EMPTY_DTOR(DynamicAudioEventRTS)
#endif /* _H_AUDIOEVENTRTS_ */

View File

@ -0,0 +1,45 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// EA Pacific
// John McDonald, Jr
// Do not distribute
#pragma once
#ifndef _AUDIOHANDLESPECIALVALUES_H_
#define _AUDIOHANDLESPECIALVALUES_H_
enum AudioHandleSpecialValues
{
AHSV_Error = 0x00,
AHSV_NoSound,
AHSV_Muted,
AHSV_NotForLocal,
AHSV_StopTheMusic,
AHSV_StopTheMusicFade,
AHSV_FirstHandle
};
#endif // _AUDIOHANDLESPECIALVALUES_H_

View File

@ -0,0 +1,47 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// AudioRandomValue.h
// Random number generation system
// Author: Michael S. Booth, January 1998
// Split out into separate Logic/Client/Audio headers by MDC Sept 2002
#pragma once
#ifndef _AUDIO_RANDOM_VALUE_H_
#define _AUDIO_RANDOM_VALUE_H_
#include "Lib/BaseType.h"
// do NOT use these functions directly, rather use the macros below
extern Int GetGameAudioRandomValue( int lo, int hi, char *file, int line );
extern Real GetGameAudioRandomValueReal( Real lo, Real hi, char *file, int line );
// use these macros to access the random value functions
#define GameAudioRandomValue( lo, hi ) GetGameAudioRandomValue( lo, hi, __FILE__, __LINE__ )
#define GameAudioRandomValueReal( lo, hi ) GetGameAudioRandomValueReal( lo, hi, __FILE__, __LINE__ )
//--------------------------------------------------------------------------------------------------------------
#endif // _AUDIO_RANDOM_VALUE_H_

View File

@ -0,0 +1,61 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// EA Pacific
// John McDonald, Jr
// Do not distribute
#pragma once
#ifndef _AUDIOREQUEST_H_
#define _AUDIOREQUEST_H_
#include "Common/GameAudio.h"
#include "Common/GameMemory.h"
class AudioEventRTS;
enum RequestType
{
AR_Play,
AR_Pause,
AR_Stop
};
struct AudioRequest : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( AudioRequest, "AudioRequest" )
public:
RequestType m_request;
union
{
AudioEventRTS *m_pendingEvent;
AudioHandle m_handleToInteractOn;
};
Bool m_usePendingEvent;
Bool m_requiresCheckForSample;
};
#endif // _AUDIOREQUEST_H_

View File

@ -0,0 +1,94 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// EA Pacific
// John McDonald, Jr
// Do not distribute
#pragma once
#ifndef _AUDIOSETTINGS_H_
#define _AUDIOSETTINGS_H_
#include "Common/AsciiString.h"
enum { MAX_HW_PROVIDERS = 4 };
struct AudioSettings
{
AsciiString m_audioRoot;
AsciiString m_soundsFolder;
AsciiString m_musicFolder;
AsciiString m_streamingFolder;
AsciiString m_soundsExtension;
Bool m_useDigital;
Bool m_useMidi;
Int m_outputRate;
Int m_outputBits;
Int m_outputChannels;
Int m_sampleCount2D;
Int m_sampleCount3D;
Int m_streamCount;
Int m_globalMinRange;
Int m_globalMaxRange;
Int m_drawableAmbientFrames;
Int m_fadeAudioFrames;
UnsignedInt m_maxCacheSize;
Real m_minVolume; // At volumes less than this, the sample will be culled.
AsciiString m_preferred3DProvider[MAX_HW_PROVIDERS + 1];
//Defaults actually don't ever get changed!
Real m_relative2DVolume; //2D volume compared to 3D
Real m_defaultSoundVolume;
Real m_default3DSoundVolume;
Real m_defaultSpeechVolume;
Real m_defaultMusicVolume;
UnsignedInt m_defaultSpeakerType2D;
UnsignedInt m_defaultSpeakerType3D;
//If you want to change a value, store it somewhere else (like here)
Real m_preferredSoundVolume;
Real m_preferred3DSoundVolume;
Real m_preferredSpeechVolume;
Real m_preferredMusicVolume;
//The desired altitude of the microphone to improve panning relative to terrain.
Real m_microphoneDesiredHeightAboveTerrain;
//When tracing a line between the ground look-at-point and the camera, we want
//to ensure a maximum percentage, so the microphone never goes behind the camera.
Real m_microphoneMaxPercentageBetweenGroundAndCamera;
//Handles changing sound volume whenever the camera is close to the microphone.
Real m_zoomMinDistance; //If we're closer than the minimum distance, then apply the full bonus no matter how close.
Real m_zoomMaxDistance; //The maximum distance from microphone we need to be before benefiting from any bonus.
//NOTE: The higher this value is, the lower normal sounds will be! If you specify a sound volume value of 25%, then sounds will play
//between 75% and 100%, not 100% to 125%!
Real m_zoomSoundVolumePercentageAmount; //The amount of sound volume dedicated to zooming.
};
#endif // _AUDIOSETTINGS_H_

View File

@ -0,0 +1,127 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BattleHonors.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// created: Sep 2002
//
// Filename: BattleHonors.h
//
// author: Chris Huybregts
//
// purpose:
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BATTLE_HONORS_H_
#define __BATTLE_HONORS_H_
//-----------------------------------------------------------------------------
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// TYPE DEFINES ///////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
enum
{
BATTLE_HONOR_LADDER_CHAMP = 0x0000001,
BATTLE_HONOR_STREAK_3 = 0x0000002,
//BATTLE_HONOR_STREAK_5 = 0x0000004,
BATTLE_HONOR_STREAK_10 = 0x0000008,
BATTLE_HONOR_STREAK_25 = 0x0000010,
BATTLE_HONOR_LOYALTY_USA = 0x0000020,
BATTLE_HONOR_LOYALTY_CHINA = 0x0000040,
BATTLE_HONOR_LOYALTY_GLA = 0x0000200, // was 0x60 - not actually gonna work that way, eh?
BATTLE_HONOR_BATTLE_TANK = 0x0000080,
BATTLE_HONOR_AIR_WING = 0x0000100,
//BATTLE_HONOR_SPECIAL_FORCES = 0x0000200,
BATTLE_HONOR_ENDURANCE = 0x0000400,
BATTLE_HONOR_CAMPAIGN_USA = 0x0000800, // not set in battle honors field in persistent storage
BATTLE_HONOR_CAMPAIGN_CHINA = 0x0001000, // not set in battle honors field in persistent storage
BATTLE_HONOR_CAMPAIGN_GLA = 0x0002000, // not set in battle honors field in persistent storage
BATTLE_HONOR_BLITZ5 = 0x0004000,
BATTLE_HONOR_BLITZ10 = 0x0008000,
BATTLE_HONOR_FAIR_PLAY = 0x0010000,
BATTLE_HONOR_APOCALYPSE = 0x0020000,
BATTLE_HONOR_OFFICERSCLUB = 0x0040000,
//BATTLE_HONOR_SOLO_USA_B = 0x0010000,
//BATTLE_HONOR_SOLO_USA_S = 0x0020000,
//BATTLE_HONOR_SOLO_USA_G = 0x0040000,
BATTLE_HONOR_SOLO_CHINA_B = 0x0080000,
BATTLE_HONOR_SOLO_CHINA_S = 0x0100000,
BATTLE_HONOR_SOLO_CHINA_G = 0x0200000,
BATTLE_HONOR_SOLO_GLA_B = 0x0400000,
BATTLE_HONOR_SOLO_GLA_S = 0x0800000,
BATTLE_HONOR_SOLO_GLA_G = 0x1000000,
BATTLE_HONOR_CHALLENGE = 0x2000000, // not set in battle honors field in persistent storage
BATTLE_HONOR_NOT_GAINED = 0x8000000 // This is set in tooltip item data to indicate that the honor isn't actually gained.
};
enum
{
BH_CHALLENGE_MASK_1 = 0x0001,
BH_CHALLENGE_MASK_2 = 0x0002,
BH_CHALLENGE_MASK_3 = 0x0004,
BH_CHALLENGE_MASK_4 = 0x0008,
BH_CHALLENGE_MASK_5 = 0x0010,
BH_CHALLENGE_MASK_6 = 0x0020,
BH_CHALLENGE_MASK_7 = 0x0040,
};
enum
{
MAX_BATTLE_HONOR_COLUMNS = 4,
MAX_BATTLE_HONOR_IMAGE_WIDTH = 50,
MAX_BATTLE_HONOR_IMAGE_HEIGHT = 51,
};
//-----------------------------------------------------------------------------
// INLINING ///////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// EXTERNALS //////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#endif // __BATTLE_HONORS_H_

View File

@ -0,0 +1,51 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Common/BezierSegment.h"
class BezFwdIterator
{
protected:
Int mStep;
Int mStepsDesired;
BezierSegment mBezSeg;
Coord3D mCurrPoint;
Coord3D mDq; // First Derivative
Coord3D mDDq; // Second Derivative
Coord3D mDDDq; // Third Derivative
public:
BezFwdIterator();
BezFwdIterator(Int stepsDesired, const BezierSegment *bezSeg);
void start(void);
Bool done(void);
const Coord3D& getCurrent(void) const;
void next(void);
};

View File

@ -0,0 +1,73 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// BezierSegment.h ////////////////////////////////////////////////////////////////////////////////
// John K McDonald, Jr.
// September 2002
// DO NOT DISTRIBUTE
#pragma once
#ifndef __BEZIERSEGMENT_H__
#define __BEZIERSEGMENT_H__
#include <D3DX8Math.h>
#include "Common/STLTypeDefs.h"
#define USUAL_TOLERANCE 1.0f
class BezierSegment
{
protected:
static const D3DXMATRIX s_bezBasisMatrix;
Coord3D m_controlPoints[4];
public: // Constructors
BezierSegment();
BezierSegment(Real x0, Real y0, Real z0,
Real x1, Real y1, Real z1,
Real x2, Real y2, Real z2,
Real x3, Real y3, Real z3);
BezierSegment(Real cp[16]);
BezierSegment(const Coord3D& cp0,
const Coord3D& cp1,
const Coord3D& cp2,
const Coord3D& cp3);
BezierSegment(Coord3D cp[4]);
public:
void evaluateBezSegmentAtT(Real tValue, Coord3D *outResult) const;
void getSegmentPoints(Int numSegments, VecCoord3D *outResult) const;
Real getApproximateLength(Real withinTolerance = USUAL_TOLERANCE) const;
void splitSegmentAtT(Real tValue, BezierSegment &outSeg1, BezierSegment &outSeg2) const;
public: // He get's friendly access.
friend class BezFwdIterator;
};
#endif /* __BEZIERSEGMENT_H__ */

View File

@ -0,0 +1,304 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BitFlags.h /////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, March 2002
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BitFlags_H_
#define __BitFlags_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/STLTypedefs.h"
class INI;
class Xfer;
class AsciiString;
//-------------------------------------------------------------------------------------------------
/*
BitFlags is a wrapper class that exists primarily because of a flaw in std::bitset<>.
Although quite useful, it has horribly non-useful constructor, which (1) don't let
us initialize stuff in useful ways, and (2) provide a default constructor that implicitly
converts ints into bitsets in a "wrong" way (ie, it treats the int as a mask, not an index).
So we wrap to correct this, but leave the bitset "exposed" so that we can use all the non-ctor
functions on it directly (since it doesn't overload operator= to do the "wrong" thing, strangley enough)
*/
template <size_t NUMBITS>
class BitFlags
{
private:
std::bitset<NUMBITS> m_bits;
static const char* s_bitNameList[];
public:
/*
just a little syntactic sugar so that there is no "foo = 0" compatible constructor
*/
enum BogusInitType
{
kInit = 0
};
inline BitFlags()
{
}
inline BitFlags(BogusInitType k, Int idx1)
{
m_bits.set(idx1);
}
inline BitFlags(BogusInitType k, Int idx1, Int idx2)
{
m_bits.set(idx1);
m_bits.set(idx2);
}
inline BitFlags(BogusInitType k, Int idx1, Int idx2, Int idx3)
{
m_bits.set(idx1);
m_bits.set(idx2);
m_bits.set(idx3);
}
inline BitFlags(BogusInitType k, Int idx1, Int idx2, Int idx3, Int idx4)
{
m_bits.set(idx1);
m_bits.set(idx2);
m_bits.set(idx3);
m_bits.set(idx4);
}
inline BitFlags(BogusInitType k, Int idx1, Int idx2, Int idx3, Int idx4, Int idx5)
{
m_bits.set(idx1);
m_bits.set(idx2);
m_bits.set(idx3);
m_bits.set(idx4);
m_bits.set(idx5);
}
inline BitFlags(BogusInitType k,
Int idx1,
Int idx2,
Int idx3,
Int idx4,
Int idx5,
Int idx6,
Int idx7,
Int idx8,
Int idx9,
Int idx10,
Int idx11,
Int idx12
)
{
m_bits.set(idx1);
m_bits.set(idx2);
m_bits.set(idx3);
m_bits.set(idx4);
m_bits.set(idx5);
m_bits.set(idx6);
m_bits.set(idx7);
m_bits.set(idx8);
m_bits.set(idx9);
m_bits.set(idx10);
m_bits.set(idx11);
m_bits.set(idx12);
}
inline Bool operator==(const BitFlags& that) const
{
return this->m_bits == that.m_bits;
}
inline Bool operator!=(const BitFlags& that) const
{
return this->m_bits != that.m_bits;
}
inline void set(Int i, Int val = 1)
{
m_bits.set(i, val);
}
inline Bool test(Int i) const
{
return m_bits.test(i);
}
inline Int size() const
{
return m_bits.size();
}
inline Int count() const
{
return m_bits.count();
}
inline Bool any() const
{
return m_bits.any();
}
inline void flip()
{
m_bits.flip();
}
inline void clear()
{
m_bits.reset();
}
inline Int countIntersection(const BitFlags& that) const
{
BitFlags tmp = *this;
tmp.m_bits &= that.m_bits;
return tmp.m_bits.count();
}
inline Int countInverseIntersection(const BitFlags& that) const
{
BitFlags tmp = *this;
tmp.m_bits.flip();
tmp.m_bits &= that.m_bits;
return tmp.m_bits.count();
}
inline Bool anyIntersectionWith(const BitFlags& that) const
{
/// @todo srj -- improve me.
BitFlags tmp = that;
tmp.m_bits &= m_bits;
return tmp.m_bits.any();
}
inline void clear(const BitFlags& clr)
{
m_bits &= ~clr.m_bits;
}
inline void set(const BitFlags& set)
{
m_bits |= set.m_bits;
}
inline void clearAndSet(const BitFlags& clr, const BitFlags& set)
{
m_bits &= ~clr.m_bits;
m_bits |= set.m_bits;
}
inline Bool testSetAndClear(const BitFlags& mustBeSet, const BitFlags& mustBeClear) const
{
/// @todo srj -- improve me.
BitFlags tmp = *this;
tmp.m_bits &= mustBeClear.m_bits;
if (tmp.m_bits.any())
return false;
tmp = *this;
tmp.m_bits.flip();
tmp.m_bits &= mustBeSet.m_bits;
if (tmp.m_bits.any())
return false;
return true;
}
static const char** getBitNames()
{
return s_bitNameList;
}
static const char* getNameFromSingleBit(Int i)
{
return (i >= 0 && i < NUMBITS) ? s_bitNameList[i] : NULL;
}
static Int getSingleBitFromName(const char* token)
{
Int i = 0;
for(const char** name = s_bitNameList; *name; ++name, ++i )
{
if( stricmp( *name, token ) == 0 )
{
return i;
}
}
return -1;
}
const char* getBitNameIfSet(Int i) const
{
return test(i) ? s_bitNameList[i] : NULL;
}
Bool setBitByName(const char* token)
{
Int i = getSingleBitFromName(token);
if (i >= 0)
{
set(i);
return true;
}
else
{
return false;
}
}
void parse(INI* ini, AsciiString* str);
void xfer(Xfer* xfer);
static void parseFromINI(INI* ini, void* /*instance*/, void *store, const void* /*userData*/);
void buildDescription( AsciiString* str ) const
{
if ( str == NULL )
return;//sanity
for( Int i = 0; i < size(); ++i )
{
const char* bitName = getBitNameIfSet(i);
if (bitName != NULL)
{
str->concat( bitName );
str->concat( ",\n");
}
}
}
};
#endif // __BitFlags_H_

View File

@ -0,0 +1,221 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BitFlagsIO.h /////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, March 2002
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BitFlagsIO_H_
#define __BitFlagsIO_H_
#include "Common/BitFlags.h"
#include "Common/INI.h"
#include "Common/Xfer.h"
//-------------------------------------------------------------------------------------------------
/*
template <size_t NUMBITS>
void BitFlags<NUMBITS>::buildDescription( AsciiString* str ) const
{
if ( str == NULL )
return;//sanity
for( Int i = 0; i < size(); ++i )
{
const char* bitName = getBitNameIfSet(i);
if (bitName != NULL)
{
str->concat( bitName );
str->concat( ",\n");
}
}
}
*/
//-------------------------------------------------------------------------------------------------
template <size_t NUMBITS>
void BitFlags<NUMBITS>::parse(INI* ini, AsciiString* str)
{
// m_bits.reset();
if (str)
str->clear();
Bool foundNormal = false;
Bool foundAddOrSub = false;
// loop through all tokens
for (const char *token = ini->getNextTokenOrNull(); token != NULL; token = ini->getNextTokenOrNull())
{
if (str)
{
if (str->isNotEmpty())
str->concat(" ");
str->concat(token);
}
if (stricmp(token, "NONE") == 0)
{
if (foundNormal || foundAddOrSub)
{
DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
throw INI_INVALID_NAME_LIST;
}
clear();
break;
}
if (token[0] == '+')
{
if (foundNormal)
{
DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
throw INI_INVALID_NAME_LIST;
}
Int bitIndex = INI::scanIndexList(token+1, s_bitNameList); // this throws if the token is not found
set(bitIndex, 1);
foundAddOrSub = true;
}
else if (token[0] == '-')
{
if (foundNormal)
{
DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
throw INI_INVALID_NAME_LIST;
}
Int bitIndex = INI::scanIndexList(token+1, s_bitNameList); // this throws if the token is not found
set(bitIndex, 0);
foundAddOrSub = true;
}
else
{
if (foundAddOrSub)
{
DEBUG_CRASH(("you may not mix normal and +- ops in bitstring lists"));
throw INI_INVALID_NAME_LIST;
}
if (!foundNormal)
clear();
Int bitIndex = INI::scanIndexList(token, s_bitNameList); // this throws if the token is not found
set(bitIndex, 1);
foundNormal = true;
}
}
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
template <size_t NUMBITS>
/*static*/ void BitFlags<NUMBITS>::parseFromINI(INI* ini, void* /*instance*/, void *store, const void* /*userData*/)
{
((BitFlags*)store)->parse(ini, NULL);
}
//-------------------------------------------------------------------------------------------------
/** Xfer method
* Version Info:
* 1: Initial version */
//-------------------------------------------------------------------------------------------------
template <size_t NUMBITS>
void BitFlags<NUMBITS>::xfer(Xfer* xfer)
{
// this deserves a version number
XferVersion currentVersion = 1;
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
if( xfer->getXferMode() == XFER_SAVE )
{
// save how many entries are to follow
Int c = count();
xfer->xferInt( &c );
// save each of the string data
for( Int i = 0; i < size(); ++i )
{
const char* bitName = getBitNameIfSet(i);
// ignore if this kindof is not set in our mask data
if (bitName == NULL)
continue;
// this bit is set, write the string value
AsciiString bitNameA = bitName;
xfer->xferAsciiString( &bitNameA );
} // end for i
} // end if, save
else if( xfer->getXferMode() == XFER_LOAD )
{
// clear the kind of mask data
clear();
// read how many entries follow
Int c;
xfer->xferInt( &c );
// read each of the string entries
AsciiString string;
for( Int i = 0; i < c; ++i )
{
// read ascii string
xfer->xferAsciiString( &string );
// set in our mask type data
Bool valid = setBitByName( string.str() );
if (!valid)
{
DEBUG_CRASH(("invalid bit name %s",string.str()));
throw XFER_READ_ERROR;
}
} // end for, i
} // end else if, load
else if( xfer->getXferMode() == XFER_CRC )
{
// just call the xfer implementation on the data values
xfer->xferUser( this, sizeof( this ) );
} // end else if, crc
else
{
DEBUG_CRASH(( "BitFlagsXfer - Unknown xfer mode '%d'\n", xfer->getXferMode() ));
throw XFER_MODE_UNKNOWN;
} // end else
} // end xfer
#endif

View File

@ -0,0 +1,41 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// jkmcd
#pragma once
struct BorderColor
{
char *m_colorName;
long m_borderColor;
};
const BorderColor BORDER_COLORS[] =
{
{ "Orange", 0xFFFF8700, },
{ "Green", 0xFF00FF00, },
{ "Blue", 0xFF0000FF, },
{ "Cyan", 0xFF00FFFF, },
{ "Magenta", 0xFFFF00FF, },
{ "Yellow", 0xFFFFFF00, },
{ "Purple", 0xFF9E00FF, },
{ "Pink", 0xFFFF8670, },
};
const long BORDER_COLORS_SIZE = sizeof(BORDER_COLORS) / sizeof (BORDER_COLORS[0]);

View File

@ -0,0 +1,217 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: BuildAssistant.h /////////////////////////////////////////////////////////////////////////
// Author: Colin Day, February 2002
// Desc: Singleton class to encapsulate some of the more common functions or rules
// that apply to building structures and units
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __BUILDASSISTANT_H_
#define __BUILDASSISTANT_H_
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
#include "Common/STLTypedefs.h"
#include "Lib/BaseType.h"
#include "Common/SubsystemInterface.h"
#include "GameLogic/Object.h"
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////////////////////////
class ThingTemplate;
class Player;
class Object;
// ------------------------------------------------------------------------------------------------
// this enum is used for the construction percent of objects
enum { CONSTRUCTION_COMPLETE = -1 };
typedef void (*IterateFootprintFunc)( const Coord3D *samplePoint, void *userData );
// ------------------------------------------------------------------------------------------------
class ObjectSellInfo : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ObjectSellInfo, "ObjectSellInfo" )
public:
ObjectSellInfo( void );
// virtual destructor prototypes provided by memory pool object
ObjectID m_id; ///< id of object to sell
UnsignedInt m_sellFrame; ///< frame the sell occurred on
};
// ------------------------------------------------------------------------------------------------
typedef std::list<ObjectSellInfo *> ObjectSellList;
typedef ObjectSellList::iterator ObjectSellListIterator;
//-------------------------------------------------------------------------------------------------
/** Return codes for queries about being able to build */
//-------------------------------------------------------------------------------------------------
enum CanMakeType
{
CANMAKE_OK,
CANMAKE_NO_PREREQ,
CANMAKE_NO_MONEY,
CANMAKE_FACTORY_IS_DISABLED,
CANMAKE_QUEUE_FULL, // production bldg has full production queue
CANMAKE_PARKING_PLACES_FULL, // production bldg has finite slots for existing units
CANMAKE_MAXED_OUT_FOR_PLAYER // player has as many as they are allowed at once (eg, Black Lotus
};
//-------------------------------------------------------------------------------------------------
/** Return codes for queries about legal build locations */
//-------------------------------------------------------------------------------------------------
enum LegalBuildCode
{
LBC_OK = 0,
LBC_RESTRICTED_TERRAIN,
LBC_NOT_FLAT_ENOUGH,
LBC_OBJECTS_IN_THE_WAY,
LBC_NO_CLEAR_PATH,
LBC_SHROUD,
LBC_TOO_CLOSE_TO_SUPPLIES,
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class BuildAssistant : public SubsystemInterface
{
public:
struct TileBuildInfo
{
Int tilesUsed;
Coord3D *positions;
};
enum LocalLegalToBuildOptions
{
TERRAIN_RESTRICTIONS = 0x00000001, ///< Check for basic terrain restrictions
CLEAR_PATH = 0x00000002, ///< Must be able to path find to location
NO_OBJECT_OVERLAP = 0X00000004, ///< Can't overlap enemy objects, or locally controled objects that can't move out of the way
USE_QUICK_PATHFIND = 0x00000008, ///< Use the quick pathfind method for CLEAR_PATH
SHROUD_REVEALED = 0x00000010, ///< Check to make sure the shroud is revealed
NO_ENEMY_OBJECT_OVERLAP=0x00000020, ///< Can't overlap enemy objects only.
};
public:
BuildAssistant( void );
virtual ~BuildAssistant( void );
virtual void init( void ); ///< for subsytem
virtual void reset( void ); ///< for subsytem
virtual void update( void ); ///< for subsytem
/// iterate the "footprint" area of a structure at the given "sample resolution"
void iterateFootprint( const ThingTemplate *build,
Real buildOrientation,
const Coord3D *worldPos,
Real sampleResolution,
IterateFootprintFunc func,
void *funcUserData );
/// create object from a build and put it in the world now
virtual Object *buildObjectNow( Object *constructorObject, const ThingTemplate *what,
const Coord3D *pos, Real angle, Player *owningPlayer );
/// using the "line placement" for objects (like walls etc) create that line of objects line
virtual void buildObjectLineNow( Object *constructorObject, const ThingTemplate *what,
const Coord3D *start, const Coord3D *end, Real angle,
Player *owningPlayer );
/// query if we can build at this location
virtual LegalBuildCode isLocationLegalToBuild( const Coord3D *worldPos,
const ThingTemplate *build,
Real angle, // angle to construct 'build' at
UnsignedInt options, // use LocationLegalToBuildOptions
Object *builderObject,
Player *player);
/// query if we can build at this location
virtual Bool isLocationClearOfObjects( const Coord3D *worldPos,
const ThingTemplate *build,
Real angle, // angle to construct 'build' a
Object *builderObject,
UnsignedInt options,
Player *thePlayer);
/// Adds bib highlighting for this location.
virtual void addBibs( const Coord3D *worldPos,
const ThingTemplate *build );
/// tiling wall object helper function, we can use this to "tile" walls when building
virtual TileBuildInfo *buildTiledLocations( const ThingTemplate *thingBeingTiled,
Real angle, // angle to consturct thing being tiled
const Coord3D *start, const Coord3D *end,
Real tilingSize, Int maxTiles,
Object *builderObject );
/// return the "scratch pad" array that can be used to create a line of build locations
virtual inline Coord3D *getBuildLocations( void ) { return m_buildPositions; }
/// is the template a line build object, like a wall
virtual Bool isLineBuildTemplate( const ThingTemplate *tTemplate );
/// are all the requirements for making this unit satisfied
virtual CanMakeType canMakeUnit( Object *builder, const ThingTemplate *whatToBuild ) const;
/// are all the requirements for making this unit (except available cash) are satisfied
virtual Bool isPossibleToMakeUnit( Object *builder, const ThingTemplate *whatToBuild ) const;
/// sell an object
virtual void sellObject( Object *obj );
void xferTheSellList(Xfer *xfer );
protected:
/// some objects will be "cleared" automatically when constructing
Bool isRemovableForConstruction( Object *obj );
/// clear the area of removable objects for construction
void clearRemovableForConstruction( const ThingTemplate *whatToBuild,
const Coord3D *pos, Real angle );
/// will move objects that can move out of the way.
/// will return false if there are objects that cannot be moved out of the way.
Bool moveObjectsForConstruction( const ThingTemplate *whatToBuild,
const Coord3D *pos, Real angle, Player *playerToBuild );
Coord3D *m_buildPositions; ///< array used to create a line of build locations (think walls)
Int m_buildPositionSize; ///< number of elements in the build position array
ObjectSellList m_sellList; ///< list of objects currently going through the "sell process"
}; // end BuildAssistant
// EXTERN /////////////////////////////////////////////////////////////////////////////////////////
extern BuildAssistant *TheBuildAssistant;
#endif // __BUILDASSISTANT_H_

View File

@ -0,0 +1,191 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: Generals
//
// Module: Game Engine Common
//
// File name: Common/CDManager.h
//
// Created: 11/26/01 TR
//
//----------------------------------------------------------------------------
#pragma once
#ifndef _COMMON_CDMANAGER_H_
#define _COMMON_CDMANAGER_H_
//----------------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------------
#include "Common/List.h"
#include "Common/SubSystemInterface.h"
#include "Common/AsciiString.h"
//----------------------------------------------------------------------------
// Forward References
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Type Defines
//----------------------------------------------------------------------------
namespace CD
{
enum Disk
{
UNKNOWN_DISK = -3,
NO_DISK = -2,
ANY_DISK = -1,
DISK_1 = 0,
NUM_DISKS
};
};
//===============================
// CDDriveInterface
//===============================
/**
* Interface to a CD ROM drive
*/
//===============================
class CDDriveInterface
{
public:
virtual ~CDDriveInterface() {};
virtual void refreshInfo( void ) = 0; ///< Update drive with least
virtual AsciiString getDiskName( void ) = 0; ///< Returns the drive path for this drive
virtual AsciiString getPath( void ) = 0; ///< Returns the drive path for this drive
virtual CD::Disk getDisk( void ) = 0; ///< Returns ID of current disk in this drive
};
//===============================
// CDDrive
//===============================
class CDDrive : public CDDriveInterface
{
friend class CDManager;
public:
CDDrive();
virtual ~CDDrive();
// CDDriveInterface operations
virtual AsciiString getPath( void ); ///< Returns the drive path for this drive
virtual AsciiString getDiskName( void ); ///< Returns the drive path for this drive
virtual CD::Disk getDisk( void ); ///< Returns ID of current disk in this drive
virtual void refreshInfo( void ); ///< Update drive with least
// CDDrive operations
void setPath( const Char *path ); ///< Set the drive's path
protected:
LListNode m_node; ///< Link list node
AsciiString m_diskName; ///< disk's volume name
AsciiString m_drivePath; ///< drive's device path
CD::Disk m_disk; ///< ID of disk in drive
};
//===============================
// CDManagerInterface
//===============================
class CDManagerInterface : public SubsystemInterface
{
public:
virtual ~CDManagerInterface(){};
virtual Int driveCount( void ) = 0; ///< Number of CD drives detected
virtual CDDriveInterface* getDrive( Int index ) = 0; ///< Return the specified drive
virtual CDDriveInterface* newDrive( const Char *path ) = 0; ///< add new drive of specified path
virtual void refreshDrives( void ) = 0; ///< Refresh drive info
virtual void destroyAllDrives( void ) = 0; ///< Like it says, destroy all drives
protected:
virtual CDDriveInterface* createDrive( void ) = 0;
};
//===============================
// CDManager
//===============================
class CDManager : public CDManagerInterface
{
public:
CDManager();
virtual ~CDManager();
// sub system operations
virtual void init( void );
virtual void update( void );
virtual void reset( void );
//
virtual Int driveCount( void ); ///< Number of CD drives detected
virtual CDDriveInterface* getDrive( Int index ); ///< Return the specified drive
virtual CDDriveInterface* newDrive( const Char *path ); ///< add new drive of specified path
virtual void refreshDrives( void ); ///< Refresh drive info
virtual void destroyAllDrives( void ); ///< Like it says, destroy all drives
protected:
LList m_drives; ///< List of drives detected on this machine
};
//----------------------------------------------------------------------------
// Inlining
//----------------------------------------------------------------------------
extern CDManagerInterface *TheCDManager;
CDManagerInterface* CreateCDManager( void );
#endif // _COMMON_CDMANAGER_H_

View File

@ -0,0 +1,129 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// CRCDebug.h ///////////////////////////////////////////////////////////////
// Macros/functions/etc to help logging values for tracking down sync errors
// Author: Matthew D. Campbell, June 2002
// no #pragma once - we want to be able to conditionally define NO_DEBUG_CRC in indiv .cpp files
#ifndef __CRCDEBUG_H__
#define __CRCDEBUG_H__
#include "Common/Debug.h"
#ifndef NO_DEBUG_CRC
#ifdef DEBUG_LOGGING
#define DEBUG_CRC
#endif
#endif
#ifdef DEBUG_CRC
#include "Common/AsciiString.h"
#include "GameLogic/GameLogic.h"
#include "Lib/BaseType.h"
#include "wwmath/vector3.h"
#include "wwmath/matrix3d.h"
#define AS_INT(x) (*(Int *)(&x))
#define DUMPVEL DUMPCOORD3DNAMED(&m_vel, "m_vel")
#define DUMPACCEL DUMPCOORD3DNAMED(&m_accel, "m_accel")
#define DUMPVECTOR3(x) DUMPVECTOR3NAMED(x, #x)
#define DUMPVECTOR3NAMED(x, y) dumpVector3(x, y, __FILE__, __LINE__)
#define DUMPCOORD3D(x) DUMPCOORD3DNAMED(x, #x)
#define DUMPCOORD3DNAMED(x, y) dumpCoord3D(x, y, __FILE__, __LINE__)
#define DUMPMATRIX3D(x) DUMPMATRIX3DNAMED(x, #x)
#define DUMPMATRIX3DNAMED(x, y) dumpMatrix3D(x, y, __FILE__, __LINE__)
#define DUMPREAL(x) DUMPREALNAMED(x, #x)
#define DUMPREALNAMED(x, y) dumpReal(x, y, __FILE__, __LINE__)
extern Int TheCRCFirstFrameToLog;
extern UnsignedInt TheCRCLastFrameToLog;
void dumpVector3(const Vector3 *v, AsciiString name, AsciiString fname, Int line);
void dumpCoord3D(const Coord3D *c, AsciiString name, AsciiString fname, Int line);
void dumpMatrix3D(const Matrix3D *m, AsciiString name, AsciiString fname, Int line);
void dumpReal(Real r, AsciiString name, AsciiString fname, Int line);
void outputCRCDebugLines( void );
void outputCRCDumpLines( void );
void addCRCDebugLine(const char *fmt, ...);
void addCRCDumpLine(const char *fmt, ...);
void addCRCGenLine(const char *fmt, ...);
#define CRCDEBUG_LOG(x) addCRCDebugLine x
#define CRCDUMP_LOG(x) addCRCDumpLine x
#define CRCGEN_LOG(x) addCRCGenLine x
class CRCVerification
{
public:
CRCVerification();
~CRCVerification();
protected:
UnsignedInt m_startCRC;
};
#define VERIFY_CRC CRCVerification crcVerification;
extern Int lastCRCDebugFrame;
extern Int lastCRCDebugIndex;
extern Bool g_verifyClientCRC;
extern Bool g_clientDeepCRC;
extern Bool g_crcModuleDataFromClient;
extern Bool g_crcModuleDataFromLogic;
extern Bool g_keepCRCSaves;
extern Bool g_logObjectCRCs;
#else // DEBUG_CRC
#define DUMPVEL {}
#define DUMPACCEL {}
#define DUMPVECTOR3(x) {}
#define DUMPVECTOR3NAMED(x, y) {}
#define DUMPCOORD3D(x) {}
#define DUMPCOORD3DNAMED(x, y) {}
#define DUMPMATRIX3D(x) {}
#define DUMPMATRIX3DNAMED(x, y) {}
#define DUMPREAL(x) {}
#define DUMPREALNAMED(x, y) {}
#define CRCDEBUG_LOG(x) {}
#define CRCDUMP_LOG(x) {}
#define CRCGEN_LOG(x) {}
#define VERIFY_CRC {}
#endif
extern Int NET_CRC_INTERVAL;
extern Int REPLAY_CRC_INTERVAL;
extern Bool TheDebugIgnoreSyncErrors;
#endif // __CRCDEBUG_H__

View File

@ -0,0 +1,69 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ClientUpdateModule.h /////////////////////////////////////////////////////////////////////////////////
// Author:
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __ClientUpdateModule_H_
#define __ClientUpdateModule_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include "Common/Module.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
// TYPES //////////////////////////////////////////////////////////////////////////////////////////
typedef ModuleData ClientUpdateModuleData;
//-------------------------------------------------------------------------------------------------
/** DRAWABLE CLIENT UPDATE MODULE base class */
//-------------------------------------------------------------------------------------------------
class ClientUpdateModule : public DrawableModule
{
MEMORY_POOL_GLUE_ABC( ClientUpdateModule )
public:
ClientUpdateModule( Thing *thing, const ModuleData* moduleData );
static ModuleType getModuleType() { return MODULETYPE_CLIENT_UPDATE; }
static Int getInterfaceMask() { return MODULEINTERFACE_CLIENT_UPDATE; }
virtual void clientUpdate() = 0;
};
inline ClientUpdateModule::ClientUpdateModule( Thing *thing, const ModuleData* moduleData ) : DrawableModule( thing, moduleData ) { }
inline ClientUpdateModule::~ClientUpdateModule() { }
//-------------------------------------------------------------------------------------------------
#endif // __ClientUpdateModule_H_

View File

@ -0,0 +1,36 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// CommandLine.h
// The command-line interface
// Author: Matthew D. Campbell, September 2001
#pragma once
#ifndef _COMMAND_LINE_H_
#define _COMMAND_LINE_H_
void parseCommandLine(int argc, char *argv[]); ///< Parse command-line parameters
#endif // _COMMAND_LINE_H_

View File

@ -0,0 +1,55 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: CopyProtection.h ////////////////////////////////////////////////////
// Author: Matthew D. Campbell
// Taken From: Denzil Long's code in Tiberian Sun, by way of Yuri's Revenge
//////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef COPYPROTECTION_H
#define COPYPROTECTION_H
// Comment out the following line to disable copy protection checks
//#define DO_COPY_PROTECTION
#ifdef DO_COPY_PROTECTION
class CopyProtect
{
public:
static Bool isLauncherRunning(void);
static Bool notifyLauncher(void);
static void checkForMessage(UINT message, LPARAM lParam);
static Bool validate(void);
static void shutdown(void);
private:
static LPVOID s_protectedData;
};
#endif // DO_COPY_PROTECTION
#endif // COPYPROTECTION_H

View File

@ -0,0 +1,106 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// CriticalSection.h ///////////////////////////////////////////////////////
// Utility class to use critical sections in areas of code.
// Author: JohnM And MattC, August 13, 2002
#pragma once
#ifndef __CRITICALSECTION_H__
#define __CRITICALSECTION_H__
#include "Common/PerfTimer.h"
#ifdef PERF_TIMERS
extern PerfGather TheCritSecPerfGather;
#endif
class CriticalSection
{
CRITICAL_SECTION m_windowsCriticalSection;
public:
CriticalSection()
{
#ifdef PERF_TIMERS
AutoPerfGather a(TheCritSecPerfGather);
#endif
InitializeCriticalSection( &m_windowsCriticalSection );
}
virtual ~CriticalSection()
{
#ifdef PERF_TIMERS
AutoPerfGather a(TheCritSecPerfGather);
#endif
DeleteCriticalSection( &m_windowsCriticalSection );
}
public: // Use these when entering/exiting a critical section.
void enter( void )
{
#ifdef PERF_TIMERS
AutoPerfGather a(TheCritSecPerfGather);
#endif
EnterCriticalSection( &m_windowsCriticalSection );
}
void exit( void )
{
#ifdef PERF_TIMERS
AutoPerfGather a(TheCritSecPerfGather);
#endif
LeaveCriticalSection( &m_windowsCriticalSection );
}
};
class ScopedCriticalSection
{
private:
CriticalSection *m_cs;
public:
ScopedCriticalSection( CriticalSection *cs ) : m_cs(cs)
{
if (m_cs)
m_cs->enter();
}
virtual ~ScopedCriticalSection( )
{
if (m_cs)
m_cs->exit();
}
};
// These should be NULL on creation then non-NULL in WinMain or equivalent.
// This allows us to be silently non-threadsafe for WB and other single-threaded apps.
extern CriticalSection *TheAsciiStringCriticalSection;
extern CriticalSection *TheUnicodeStringCriticalSection;
extern CriticalSection *TheDmaCriticalSection;
extern CriticalSection *TheMemoryPoolCriticalSection;
extern CriticalSection *TheDebugLogCriticalSection;
#endif /* __CRITICALSECTION_H__ */

View File

@ -0,0 +1,83 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// FILE: CustomMatchPreferences.h
// Author: Matthew D. Campbell, August 2002
// Description: Saving/Loading of custom match preferences
///////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __CUSTOMMATCHPREFERENCES_H__
#define __CUSTOMMATCHPREFERENCES_H__
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "Common/UserPreferences.h"
//-----------------------------------------------------------------------------
// CustomMatchPreferences base class
//-----------------------------------------------------------------------------
class CustomMatchPreferences : public UserPreferences
{
public:
CustomMatchPreferences();
virtual ~CustomMatchPreferences();
void setLastLadder(const AsciiString& addr, UnsignedShort port);
AsciiString getLastLadderAddr( void );
UnsignedShort getLastLadderPort( void );
Int getPreferredFaction(void);
void setPreferredFaction(Int val);
Int getPreferredColor(void);
void setPreferredColor(Int val);
Int getChatSizeSlider(void);
void setChatSizeSlider(Int val);
AsciiString getPreferredMap(void);
void setPreferredMap(AsciiString val);
Bool usesSystemMapDir(void);
void setUsesSystemMapDir(Bool val);
Bool usesLongGameList(void);
void setUsesLongGameList(Bool val);
Bool allowsObservers(void);
void setAllowsObserver(Bool val);
Bool getDisallowAsianText( void );
void setDisallowAsianText(Bool val);
Bool getDisallowNonAsianText( void );
void setDisallowNonAsianText( Bool val );
};
#endif // __CUSTOMMATCHPREFERENCES_H__

View File

@ -0,0 +1,169 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DamageFX.h /////////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, November 2001
// Desc: Damage Effects Descriptions
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _DamageFX_H_
#define _DamageFX_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/GameCommon.h"
#include "Common/NameKeyGenerator.h"
#include "Common/STLTypedefs.h"
#include "GameLogic/Damage.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class DamageFXStore;
class FXList;
class INI;
//-------------------------------------------------------------------------------------------------
typedef const FXList* ConstFXListPtr;
//-------------------------------------------------------------------------------------------------
/**
A DamageFX is an object used to describe how an object reacts to taking a particular type
of damage. (Note that "reacts" here implies only audio-video effects, not logic effects,
damage modifiers, etc.)
Conceptually speaking, every unit with a Body module has a DamageFX object. When it receives damage,
it asks its DamageFX module to produce an appropriate a/v effect, which can vary by type of damage
(eg, explosion, armor-piercing, flame, etc) and amount ("minor" or "major").
Notes:
-- Every particular damage-type within a DamageFX can have a "minor" and/or "major" effect;
basically, if the damage done exceeds a specified threshold (or if there isn't a "minor"
effect), the major effect is used.
-- DamageFX is shared between multiple units; there should generally only be one instance
of any particular class. The implication is that it should not require private data storage
to do what it needs to do, aside from stuff initialized at object instantiation time. To help
enforce this, all it's methods are declared 'const'. If you can't implement the damage you
need within this framework, please *don't* simply de-const things, because it could lead to very
strange side-effects. Instead, the system will have to be enhanced to allow for multiple instances
of each DamageFX.
*/
//-------------------------------------------------------------------------------------------------
class DamageFX
{
public:
DamageFX();
void clear();
/**
This is the main public access point to the system: when you want to execute the
a/v fx used for a specific damage type, call this method. (It is OK for source and/or
victim to be null, but you should pass them when available.)
*/
void doDamageFX(DamageType t, Real damageAmount, const Object* source, const Object* victim) const;
UnsignedInt getDamageFXThrottleTime(DamageType t, const Object* source) const;
const FieldParse* getFieldParse() const;
private:
ConstFXListPtr getDamageFXList(DamageType t, Real damageAmount, const Object* source) const;
static void parseAmount( INI* ini, void *instance, void*, const void* );
static void parseMajorFXList( INI* ini, void *instance, void*, const void* );
static void parseMinorFXList( INI* ini, void *instance, void*, const void* );
static void parseTime( INI* ini, void *instance, void*, const void* );
/*
this isn't terribly efficient since this is pretty sparsely populated
and with lots of redundancy, but since we allocate very few of these,
it's not worth more effort at this time...
*/
struct DFX
{
Real m_amountForMajorFX; ///< if damage done is >= this, use major fx
ConstFXListPtr m_majorDamageFXList; ///< fx to make
ConstFXListPtr m_minorDamageFXList; ///< fx to make
UnsignedInt m_damageFXThrottleTime;
DFX()
{
clear();
}
void clear()
{
m_amountForMajorFX = 0.0f;
m_majorDamageFXList = NULL;
m_minorDamageFXList = NULL;
m_damageFXThrottleTime = 0;
}
};
DFX m_dfx[DAMAGE_NUM_TYPES][LEVEL_COUNT];
};
//-------------------------------------------------------------------------------------------------
/**
The "store" used to hold all the DamageFXs in existence. This is usually used when creating
an Object (actually, a Body module), but can be used at any time after that. (It is explicitly
OK to swap an Object's DamageFX out at any given time.)
*/
//-------------------------------------------------------------------------------------------------
class DamageFXStore : public SubsystemInterface
{
public:
DamageFXStore();
~DamageFXStore();
void init();
void reset();
void update();
/**
Find the DamageFX with the given name. If no such DamageFX exists, return null.
*/
const DamageFX *findDamageFX( AsciiString name ) const;
static void parseDamageFXDefinition(INI* ini);
private:
typedef std::hash_map< NameKeyType, DamageFX, rts::hash<NameKeyType>, rts::equal_to<NameKeyType> > DamageFXMap;
DamageFXMap m_dfxmap;
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern DamageFXStore *TheDamageFXStore;
#endif // _DamageFX_H_

View File

@ -0,0 +1,235 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// DataChunk.h
// Data chunk classes for saving and loading
// Author: Michael S. Booth, October 2000
#pragma once
#ifndef _DATA_CHUNK_H_
#define _DATA_CHUNK_H_
#include "Common/GameMemory.h"
#include "Common/Dict.h"
#include "Common/MapReaderWriterInfo.h"
typedef unsigned short DataChunkVersionType;
// forward declarations
class DataChunkInput;
class DataChunkOutput;
class DataChunkTableOfContents;
//----------------------------------------------------------------------
// Mapping
//----------------------------------------------------------------------
class Mapping : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Mapping, "Mapping")
public:
Mapping* next;
AsciiString name;
UnsignedInt id;
};
EMPTY_DTOR(Mapping)
//----------------------------------------------------------------------
// OutputChunk
//----------------------------------------------------------------------
class OutputChunk : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(OutputChunk, "OutputChunk")
public:
OutputChunk* next;
UnsignedInt id; // chunk symbol type from table of contents
Int filepos; // position of file at start of data offset
};
EMPTY_DTOR(OutputChunk)
//----------------------------------------------------------------------
// InputChunk
//----------------------------------------------------------------------
class InputChunk : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(InputChunk, "InputChunk")
public:
InputChunk* next;
UnsignedInt id; // chunk symbol type from table of contents
DataChunkVersionType version; // version of data
Int chunkStart; // tell position of the start of chunk data (past header).
Int dataSize; // total data size of chunk
Int dataLeft; // data left to read in this chunk
};
EMPTY_DTOR(InputChunk)
//----------------------------------------------------------------------
// DataChunkTableOfContents
//----------------------------------------------------------------------
class DataChunkTableOfContents
{
Mapping* m_list; /// @TODO: This should be a hash table
Int m_listLength;
UnsignedInt m_nextID; // simple ID allocator
Bool m_headerOpened;
Mapping *findMapping( const AsciiString& name ); // return mapping data
public:
DataChunkTableOfContents( void );
~DataChunkTableOfContents();
UnsignedInt getID( const AsciiString& name ); // convert name to integer identifier
AsciiString getName( UnsignedInt id ); // convert integer identifier to name
UnsignedInt allocateID( const AsciiString& name ); // create new ID for given name or return existing mapping
Bool isOpenedForRead(void) {return m_headerOpened;};
void write(OutputStream &out);
void read(ChunkInputStream &in);
};
//----------------------------------------------------------------------
// DataChunkOutput
//----------------------------------------------------------------------
class DataChunkOutput
{
protected:
OutputStream* m_pOut; // The actual output stream.
FILE * m_tmp_file; // tmp output file stream
DataChunkTableOfContents m_contents; // table of contents of data chunk types
OutputChunk* m_chunkStack; // current stack of open data chunks
public:
DataChunkOutput( OutputStream *pOut );
~DataChunkOutput();
void openDataChunk( char *name, DataChunkVersionType ver );
void closeDataChunk( void );
void writeReal(Real r);
void writeInt(Int i);
void writeByte(Byte b);
void writeAsciiString(const AsciiString& string);
void writeUnicodeString(UnicodeString string);
void writeArrayOfBytes(char *ptr, Int len);
void writeDict(const Dict& d);
};
//----------------------------------------------------------------------
// DataChunkInput
//----------------------------------------------------------------------
struct DataChunkInfo
{
AsciiString label;
AsciiString parentLabel;
DataChunkVersionType version;
Int dataSize;
};
typedef Bool (*DataChunkParserPtr)( DataChunkInput &file, DataChunkInfo *info, void *userData );
//----------------------------------------------------------------------
// UserParser
//----------------------------------------------------------------------
class UserParser : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(UserParser, "UserParser")
public:
UserParser *next;
DataChunkParserPtr parser; // the user parsing function
AsciiString label; // the data chunk label to match
AsciiString parentLabel; // the parent chunk's label (the scope)
void *userData; // user data pointer
};
EMPTY_DTOR(UserParser)
//----------------------------------------------------------------------
// DataChunkInput
//----------------------------------------------------------------------
class DataChunkInput
{
enum {CHUNK_HEADER_BYTES = 4}; // 2 shorts in chunk file header.
protected:
ChunkInputStream* m_file; // input file stream
DataChunkTableOfContents m_contents; // table of contents of data chunk types
Int m_fileposOfFirstChunk; // seek position of first data chunk
UserParser* m_parserList; // list of all registered parsers for this input stream
InputChunk* m_chunkStack; // current stack of open data chunks
void clearChunkStack( void ); // clear the stack
void decrementDataLeft( int size ); // update data left in chunk(s)
public:
void *m_currentObject; // user parse routines can use this to allow one chunk
// to create an object, and a subsequent chunk to
// parse values into that object. However, the second
// chunk parser could also create and parse an object
// of its own if this pointer is NULL.
// The parser of the base class should NULL this pointer.
void *m_userData; // user data hook
public:
DataChunkInput( ChunkInputStream *pStream );
~DataChunkInput();
// register a parser function for data chunks with labels matching "label", whose parent
// chunks labels match "parentLabel" (or NULL for global scope)
void registerParser( const AsciiString& label, const AsciiString& parentLabel, DataChunkParserPtr parser, void *userData = NULL );
Bool parse( void *userData = NULL ); // parse the chunk stream using registered parsers
// assumed to be at the start of chunk when called
// can be called recursively
Bool isValidFileType(void); ///< Returns TRUE if it is our file format.
AsciiString openDataChunk(DataChunkVersionType *ver );
void closeDataChunk( void ); // close chunk and move to start of next chunk
Bool atEndOfFile( void ) { return (m_file->eof()) ? true : false; } // return true if at end of file
Bool atEndOfChunk( void ); // return true if all data has been read from this chunk
void reset( void ); // reset to just-opened state
AsciiString getChunkLabel( void ); // return label of current data chunk
DataChunkVersionType getChunkVersion( void ); // return version of current data chunk
unsigned int getChunkDataSize( void ); // return size of data stored in this chunk
unsigned int getChunkDataSizeLeft( void ); // return size of data left to read in this chunk
Real readReal(void);
Int readInt(void);
Byte readByte(void);
AsciiString readAsciiString(void);
UnicodeString readUnicodeString(void);
Dict readDict(void);
void readArrayOfBytes(char *ptr, Int len);
};
#endif // _DATA_CHUNK_H_

View File

@ -0,0 +1,257 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Debug.h
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Debug.h
//
// Created: Steven Johnson, August 2001
//
// Desc: Debug Utilities
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DEBUG_H_
#define __DEBUG_H_
class AsciiString;
#if defined(_DEBUG) && defined(_INTERNAL)
#error "Only one at a time of these should ever be defined"
#endif
// These are stolen from the WW3D Debug file. REALLY useful. :-)
#define STRING_IT(a) #a
#define TOKEN_IT(a) STRING_IT(,##a)
#define MESSAGE(a) message (__FILE__ "(" TOKEN_IT(__LINE__) ") : " a)
// BGC, 3/26/03 - put this in so we can build internal worldbuilder for a patch that doesn't
// have any debugging of any kind.
//#define DISABLE_DEBUG_LOGGING
// by default, turn on ALLOW_DEBUG_UTILS if _DEBUG is turned on.
#if (defined(_DEBUG) || defined(_INTERNAL)) && !defined(ALLOW_DEBUG_UTILS) && !defined(DISABLE_ALLOW_DEBUG_UTILS)
#define ALLOW_DEBUG_UTILS 1
#endif
// these are predicated on ALLOW_DEBUG_UTILS, not _DEBUG, and allow you to selectively disable
// bits of the debug stuff for special builds.
#if defined(ALLOW_DEBUG_UTILS) && !defined(DEBUG_LOGGING) && !defined(DISABLE_DEBUG_LOGGING)
#define DEBUG_LOGGING 1
#endif
#if defined(ALLOW_DEBUG_UTILS) && !defined(DEBUG_CRASHING) && !defined(DISABLE_DEBUG_CRASHING)
#define DEBUG_CRASHING 1
#endif
// BGC - added the DEBUG_LOGGING term...doesn't make sense to do stack debugging without a debug log to print to.
#if defined(ALLOW_DEBUG_UTILS) && !defined(DEBUG_STACKTRACE) && !defined(DISABLE_DEBUG_STACKTRACE) && defined(DEBUG_LOGGING)
#define DEBUG_STACKTRACE 1
#endif
#if defined(ALLOW_DEBUG_UTILS) && !defined(DEBUG_PROFILE) && !defined(DISABLE_DEBUG_PROFILE)
#define DEBUG_PROFILE 1
#endif
#ifdef __cplusplus
#define DEBUG_EXTERN_C extern "C"
#else
#define DEBUG_EXTERN_C extern
#endif
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
// USER INCLUDES //////////////////////////////////////////////////////////////
// FORWARD REFERENCES /////////////////////////////////////////////////////////
// TYPE DEFINES ///////////////////////////////////////////////////////////////
// INLINING ///////////////////////////////////////////////////////////////////
// EXTERNALS //////////////////////////////////////////////////////////////////
/// @todo: the standard line-to-string trick isn't working correctly in vc6; figure out why
#define DEBUG_STRING_IT(b) #b
#define DEBUG_TOKEN_IT(a) DEBUG_STRING_IT(a)
#define DEBUG_FILENLINE __FILE__ ":" DEBUG_TOKEN_IT(__LINE__)
#ifdef ALLOW_DEBUG_UTILS
enum
{
DEBUG_FLAG_LOG_TO_FILE = 0x01,
DEBUG_FLAG_LOG_TO_CONSOLE = 0x02,
DEBUG_FLAG_PREPEND_TIME = 0x04,
#ifdef _INTERNAL
// by default, _INTERNAL builds log to file, but not to console, in the interest
// of speed. want console output? just change this line:
DEBUG_FLAGS_DEFAULT = (DEBUG_FLAG_LOG_TO_FILE)
#else
DEBUG_FLAGS_DEFAULT = (DEBUG_FLAG_LOG_TO_FILE | DEBUG_FLAG_LOG_TO_CONSOLE)
#endif
};
DEBUG_EXTERN_C void DebugInit(int flags);
DEBUG_EXTERN_C void DebugShutdown();
DEBUG_EXTERN_C int DebugGetFlags();
DEBUG_EXTERN_C void DebugSetFlags(int flags);
#define DEBUG_INIT(f) do { DebugInit(f); } while (0)
#define DEBUG_SHUTDOWN() do { DebugShutdown(); } while (0)
#else
#define DEBUG_INIT(f) ((void)0)
#define DEBUG_SHUTDOWN() ((void)0)
#endif
#ifdef DEBUG_LOGGING
DEBUG_EXTERN_C void DebugLog(const char *format, ...);
// This defines a bitmask of log types that we care about, to allow some flexability
// in what gets logged. This should be extended to asserts, too, but the assert box
// is waiting to be rewritten. -MDC 3/19/2003
extern unsigned int DebugLevelMask;
enum
{
DEBUG_LEVEL_NET = 0, // in-game network
DEBUG_LEVEL_MAX
};
extern const char *TheDebugLevels[DEBUG_LEVEL_MAX];
#define DEBUG_LOG(m) do { { DebugLog m ; } } while (0)
#define DEBUG_LOG_LEVEL(l, m) do { if (l & DebugLevelMask) { DebugLog m ; } } while (0)
#define DEBUG_ASSERTLOG(c, m) do { { if (!(c)) DebugLog m ; } } while (0)
#else
#define DEBUG_LOG(m) ((void)0)
#define DEBUG_LOG_LEVEL(l, m) ((void)0)
#define DEBUG_ASSERTLOG(c, m) ((void)0)
#endif
#ifdef DEBUG_CRASHING
DEBUG_EXTERN_C void DebugCrash(const char *format, ...);
/*
Yeah, it's a sleazy global, since we can't reasonably add
any args to DebugCrash due to the varargs nature of it.
We'll just let it slide in this case...
*/
DEBUG_EXTERN_C char* TheCurrentIgnoreCrashPtr;
#define DEBUG_CRASH(m) \
do { \
{ \
static char ignoreCrash = 0; \
if (!ignoreCrash) { \
TheCurrentIgnoreCrashPtr = &ignoreCrash; \
DebugCrash m ; \
TheCurrentIgnoreCrashPtr = NULL; \
} \
} \
} while (0)
#define DEBUG_ASSERTCRASH(c, m) do { { if (!(c)) DEBUG_CRASH(m); } } while (0)
//Note: RELEASE_CRASH(m) is now always defined.
//#define RELEASE_CRASH(m) DEBUG_CRASH((m))
#else
#define DEBUG_CRASH(m) ((void)0)
#define DEBUG_ASSERTCRASH(c, m) ((void)0)
// DEBUG_EXTERN_C void ReleaseCrash(const char* reason);
// #define RELEASE_CRASH(m) do { ReleaseCrash(m); } while (0)
#endif
DEBUG_EXTERN_C void ReleaseCrash(const char* reason);
DEBUG_EXTERN_C void ReleaseCrashLocalized(const AsciiString& p, const AsciiString& m);
#define RELEASE_CRASH(m) do { ReleaseCrash(m); } while (0)
#define RELEASE_CRASHLOCALIZED(p, m) do { ReleaseCrashLocalized(p, m); } while (0)
#ifdef DEBUG_PROFILE
class SimpleProfiler
{
private:
__int64 m_freq;
__int64 m_startThisSession;
__int64 m_totalThisSession;
__int64 m_totalAllSessions;
int m_numSessions;
public:
SimpleProfiler();
void start();
void stop();
void stopAndLog(const char *msg, int howOftenToLog, int howOftenToResetAvg);
double getTime(); // of most recent session, in milliseconds
int getNumSessions();
double getTotalTime(); // total over all sessions, in milliseconds
double getAverageTime(); // averaged over all sessions, in milliseconds
};
#define BEGIN_PROFILE(uniqueid) \
static SimpleProfiler prof_##uniqueid; \
prof_##uniqueid.start();
#define END_PROFILE(uniqueid, msg, howoftentolog, howoftentoreset) \
prof_##uniqueid.stopAndLog(msg, howoftentolog, howoftentoreset);
#else
#define BEGIN_PROFILE(uniqueid)
#define END_PROFILE(uniqueid, msg, howoftentolog, howoftentoreset)
#endif
// MACROS //////////////////////////////////////////////////////////////////
#endif // __DEBUG_H_

View File

@ -0,0 +1,368 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Dict.h
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Dict.h
//
// Created: Steven Johnson, November 2001
//
// Desc: General-purpose dictionary class
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef Dict_H
#define Dict_H
#include "Common/Errors.h"
#include "Common/NameKeyGenerator.h"
// -----------------------------------------------------
/**
Dict provides a general utility class for maintaining
a sorted key-value pair list. Keys are currently required
to be of type NameKeyType, and data may be Bool, int, real,
or string.
Current implementation keeps the pairs sorted by key, and
does a binary search for lookups; this might change in the future,
depending on usage and performance (e.g., to a hashtable). So
don't rely on the quirks of this implementation.
*/
class Dict
{
public:
enum
{
MAX_LEN = 32767 ///< max total len of any Dict, in Pairs
};
enum DataType
{
DICT_NONE = -1, // this is returned by getType and getNthType to indicate "invalid key/index"
DICT_BOOL = 0, // note, we rely on the fact that this constant is zero in the code. so don't change it.
DICT_INT,
DICT_REAL,
DICT_ASCIISTRING,
DICT_UNICODESTRING
};
/**
Default constructor -- construct a new, empty Dict.
*/
Dict(Int numPairsToPreAllocate = 0);
/**
Copy constructor -- make this Dict identical to the
other Dict. (This is actually quite efficient, because
they will simply share the same data and increment the
refcount.)
*/
Dict(const Dict& src);
/**
Destructor. Not too exciting... clean up the works and such.
*/
~Dict();
/**
*/
Dict& operator=(const Dict& src);
/**
remove all pairs.
*/
void clear();
/**
return the number of key-value pairs in the dict.
*/
Int getPairCount() const;
/**
Return the key for the nth pair (0-based index).
return NAMEKEY_INVALID if n is out of range.
*/
NameKeyType getNthKey(Int n) const;
/**
Return the datatype for the pair with the given key.
return DICT_NONE if no pair with the key exists.
*/
DataType getType(NameKeyType key) const;
/**
Return there is a pair with the given key and datatype, return true.
*/
inline Bool known(NameKeyType key, DataType d) const
{
return getType(key) == d;
}
/**
Return the datatype for the nth pair (0-based index).
return DICT_NONE if n is out of range.
*/
DataType getNthType(Int n) const;
/**
return the value for the pair with the given key.
if there is no pair with the given key, or the value is
not of the correct type, 0 is returned.
*/
Bool getBool(NameKeyType key, Bool* exists = NULL) const;
/**
return the value for the pair with the given key.
if there is no pair with the given key, or the value is
not of the correct type, 0 is returned.
*/
Int getInt(NameKeyType key, Bool* exists = NULL) const;
/**
return the value for the pair with the given key.
if there is no pair with the given key, or the value is
not of the correct type, 0 is returned.
*/
Real getReal(NameKeyType key, Bool* exists = NULL) const;
/**
return the value for the pair with the given key.
if there is no pair with the given key, or the value is
not of the correct type, "" is returned.
*/
AsciiString getAsciiString(NameKeyType key, Bool* exists = NULL) const;
/**
return the value for the pair with the given key.
if there is no pair with the given key, or the value is
not of the correct type, "" is returned.
*/
UnicodeString getUnicodeString(NameKeyType key, Bool* exists = NULL) const;
/**
return the value for the pair with the given index.
if the index is out of range, or the value is
not of the correct type, 0 is returned.
*/
Bool getNthBool(Int n) const;
/**
return the value for the pair with the given index.
if the index is out of range, or the value is
not of the correct type, 0 is returned.
*/
Int getNthInt(Int n) const;
/**
return the value for the pair with the given index.
if the index is out of range, or the value is
not of the correct type, 0 is returned.
*/
Real getNthReal(Int n) const;
/**
return the value for the pair with the given index.
if the index is out of range, or the value is
not of the correct type, "" is returned.
*/
AsciiString getNthAsciiString(Int n) const;
/**
return the value for the pair with the given index.
if the index is out of range, or the value is
not of the correct type, "" is returned.
*/
UnicodeString getNthUnicodeString(Int n) const;
/**
set the value for the pair with the given key.
if no such pair exists, it is created.
if such a pair exists, it is replaced.
note that when replacing a pair, the new and old
data types need not match.
*/
void setBool(NameKeyType key, Bool value);
/**
set the value for the pair with the given key.
if no such pair exists, it is created.
if such a pair exists, it is replaced.
note that when replacing a pair, the new and old
data types need not match.
*/
void setInt(NameKeyType key, Int value);
/**
set the value for the pair with the given key.
if no such pair exists, it is created.
if such a pair exists, it is replaced.
note that when replacing a pair, the new and old
data types need not match.
*/
void setReal(NameKeyType key, Real value);
/**
set the value for the pair with the given key.
if no such pair exists, it is created.
if such a pair exists, it is replaced.
note that when replacing a pair, the new and old
data types need not match.
*/
void setAsciiString(NameKeyType key, const AsciiString& value);
/**
set the value for the pair with the given key.
if no such pair exists, it is created.
if such a pair exists, it is replaced.
note that when replacing a pair, the new and old
data types need not match.
*/
void setUnicodeString(NameKeyType key, const UnicodeString& value);
/**
remove the pair with the given key. if such a pair existed, return true.
if no such pair existed, return false.
*/
Bool remove(NameKeyType key);
/**
copy the pair with the given key from 'that', replacing any such pair in 'this'.
if no such pair exists in 'that', any pair with that key will be removed from 'this'.
*/
void copyPairFrom(const Dict& that, NameKeyType key);
private:
struct DictPair;
struct DictPairData;
DictPairData* m_data; // pointer to ref counted Pair data
void sortPairs();
Dict::DictPair *setPrep(NameKeyType key, Dict::DataType type);
DictPair* findPairByKey(NameKeyType key) const;
void releaseData();
DictPair *ensureUnique(int numPairsNeeded, Bool preserveData, DictPair *pairToTranslate);
enum DictPairKeyType
{
DICTPAIRKEY_ILLEGAL = 0
};
// danger... this is Plain Old Data and allocated in a skanky way;
// and thus the ctor/dtor for DictPair will never be called. so don't
// bother writing one.
struct DictPair
{
private:
DictPairKeyType m_key;
void* m_value;
inline static DictPairKeyType createKey(NameKeyType keyVal, DataType nt)
{
return (DictPairKeyType)((((UnsignedInt)(keyVal)) << 8) | ((UnsignedInt)nt));
}
inline static DataType getTypeFromKey(DictPairKeyType nk)
{
return (DataType)(((UnsignedInt)nk) & 0xff);
}
inline static NameKeyType getNameFromKey(DictPairKeyType nk)
{
return (NameKeyType)(((UnsignedInt)nk) >> 8);
}
public:
void clear();
void copyFrom(DictPair* that);
void setNameAndType(NameKeyType key, DataType type);
inline DataType getType() const { return getTypeFromKey(m_key); }
inline NameKeyType getName() const { return getNameFromKey(m_key); }
inline Bool* asBool() { return (Bool*)&m_value; }
inline Int* asInt() { return (Int*)&m_value; }
inline Real* asReal() { return (Real*)&m_value; }
inline AsciiString* asAsciiString() { return (AsciiString*)&m_value; }
inline UnicodeString* asUnicodeString() { return (UnicodeString*)&m_value; }
};
struct DictPairData
{
unsigned short m_refCount; // reference count
unsigned short m_numPairsAllocated; // length of data allocated
unsigned short m_numPairsUsed; // length of data allocated
//DictPair m_pairs[];
inline DictPair* peek() { return (DictPair*)(this+1); }
};
#ifdef _DEBUG
void validate() const;
#else
inline void validate() const { }
#endif
};
// -----------------------------------------------------
inline Dict::Dict(const Dict& src) : m_data(src.m_data)
{
if (m_data)
++m_data->m_refCount;
}
// -----------------------------------------------------
inline Dict::~Dict()
{
releaseData();
}
// -----------------------------------------------------
inline Int Dict::getPairCount() const
{
return m_data ? m_data->m_numPairsUsed : 0;
}
// -----------------------------------------------------
inline NameKeyType Dict::getNthKey(Int n) const
{
if (!m_data || n < 0 || n >= m_data->m_numPairsUsed)
return NAMEKEY_INVALID;
return m_data->peek()[n].getName();
}
// -----------------------------------------------------
inline Dict::DataType Dict::getNthType(Int n) const
{
if (!m_data || n < 0 || n >= m_data->m_numPairsUsed)
return DICT_NONE;
return m_data->peek()[n].getType();
}
#endif // Dict_H

View File

@ -0,0 +1,95 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Directory.h //////////////////////////////////////////////////////////////////////////////
// Author: Matthew D. Campbell, August 2002
// Desc: Directory info class
///////////////////////////////////////////////////////////////////////////////////////////////////
#if (0)
#pragma once
#ifndef __DIRECTORY_H__
#define __DIRECTORY_H__
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/AsciiString.h"
#include "Common/STLTypedefs.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
// TYPES //////////////////////////////////////////////////////////////////////////////////////////
class FileInfo
{
public:
FileInfo() {}
~FileInfo() {}
void set( const WIN32_FIND_DATA& info );
AsciiString filename;
time_t creationTime;
time_t accessTime;
time_t modTime;
DWORD attributes;
DWORD filesize; // only care about 32 bits for our purposes
protected:
};
struct FileInfoComparator
{
bool operator()(const FileInfo& a, const FileInfo& b) const
{
return a.filename < b.filename;
}
};
//-------------------------------------------------------------------------------------------------
typedef std::set<FileInfo, FileInfoComparator> FileInfoSet;
//-------------------------------------------------------------------------------------------------
class Directory
{
public:
Directory(const AsciiString& dirPath);
~Directory() {}
FileInfoSet* getFiles( void );
FileInfoSet* getSubdirs( void );
protected:
AsciiString m_dirPath;
FileInfoSet m_files;
FileInfoSet m_subdirs;
};
//-------------------------------------------------------------------------------------------------
#endif // __DIRECTORY_H__
#endif

View File

@ -0,0 +1,114 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DisabledTypes.h //////////////////////////////////////////////////////////////////////////
// Author: Kris Morness, September 2002
// Desc: Defines all the types of disabled statii any given object can have.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DISABLED_TYPES_H_
#define __DISABLED_TYPES_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Lib/BaseType.h"
#include "Common/BitFlags.h"
//-------------------------------------------------------------------------------------------------
/** Kind of flags for determining groups of things that belong together
* NOTE: You *MUST* keep this in the same order as the DisabledNames[] below */
//-------------------------------------------------------------------------------------------------
enum DisabledType
{
DISABLED_DEFAULT, //Typical disable -- like systems, things that don't need to run.
DISABLED_HACKED, //This unit has been hacked
DISABLED_EMP, //This unit has been disabled via electro-magnetic-pulse.
DISABLED_HELD, //Special case -- held means it can fire and isHeld checks to make sure ONLY held is set!
DISABLED_PARALYZED, //Battle plans have changed, and unit is confused/paralyzed
DISABLED_UNMANNED, //Vehicle is unmanned
DISABLED_UNDERPOWERED,//Seperate from ScriptUnderpowered, the owning player has insufficient power. Energy status controls this
DISABLED_FREEFALL, //This unit has been disabled via being in free fall
//These ones are specificially for scripts to enable/reenable!
DISABLED_SCRIPT_DISABLED,
DISABLED_SCRIPT_UNDERPOWERED,
DISABLED_COUNT,
};
typedef BitFlags<DISABLED_COUNT> DisabledMaskType;
#define MAKE_DISABLED_MASK(k) DisabledMaskType(DisabledMaskType::kInit, (k))
#define MAKE_DISABLED_MASK2(k,a) DisabledMaskType(DisabledMaskType::kInit, (k), (a))
#define MAKE_DISABLED_MASK3(k,a,b) DisabledMaskType(DisabledMaskType::kInit, (k), (a), (b))
#define MAKE_DISABLED_MASK4(k,a,b,c) DisabledMaskType(DisabledMaskType::kInit, (k), (a), (b), (c))
#define MAKE_DISABLED_MASK5(k,a,b,c,d) DisabledMaskType(DisabledMaskType::kInit, (k), (a), (b), (c), (d))
inline Bool TEST_DISABLEDMASK(const DisabledMaskType& m, DisabledType t)
{
return m.test(t);
}
inline Bool TEST_DISABLEDMASK_ANY(const DisabledMaskType& m, const DisabledMaskType& mask)
{
return m.anyIntersectionWith(mask);
}
inline Bool TEST_DISABLEDMASK_MULTI(const DisabledMaskType& m, const DisabledMaskType& mustBeSet, const DisabledMaskType& mustBeClear)
{
return m.testSetAndClear(mustBeSet, mustBeClear);
}
inline Bool DISABLEDMASK_ANY_SET(const DisabledMaskType& m)
{
return m.any();
}
inline void CLEAR_DISABLEDMASK(DisabledMaskType& m)
{
m.clear();
}
inline void SET_ALL_DISABLEDMASK_BITS(DisabledMaskType& m)
{
m.clear();
m.flip();
}
inline void FLIP_DISABLEDMASK(DisabledMaskType& m)
{
m.flip();
}
// defined in Common/System/DisabledTypes.cpp
extern const char *TheDisabledNames[];
extern DisabledMaskType DISABLEDMASK_NONE; // inits to all zeroes
extern DisabledMaskType DISABLEDMASK_ALL; // inits to all bits set.
void initDisabledMasks();
#endif // __DISABLED_TYPES_H_

View File

@ -0,0 +1,79 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// DiscreteCircle.h ///////////////////////////////////////////////////////////////////////////////
// John K McDonald, Jr.
// September 2002
// DO NOT DISTRIBUTE
#pragma once
#ifndef __DISCRETECIRCLE_H__
#define __DISCRETECIRCLE_H__
//-------------------------------------------------------------------------------------------------
/**
One horizontal line of the circle we are going to generate, the points drawn should be from
(xStart, yPos)-(xEnd, yPos), inclusive.
*/
struct HorzLine
{
Int yPos;
Int xStart;
Int xEnd;
};
// Vector and Iterators for the HorzLine struct.
typedef std::vector<HorzLine> VecHorzLine;
typedef VecHorzLine::iterator VecHorzLineIt;
//-------------------------------------------------------------------------------------------------
// Useful if you'd like to not have to deal with the logic of drawing the circle.
typedef void (*ScanlineDrawFunc)(Int xStart, Int xEnd, Int yPos, void *otherParms);
/**
DiscreteCircle generates a circle centered at xCenter, yCenter, including radius. It generates
horizontal segments for the top half of the circle only, so they need to be duplicated for the
bottom half.
*/
class DiscreteCircle
{
VecHorzLine m_edges; // Should be HorzLines
Int m_yPos; // Used to know when to draw the bottom scanline
Int m_yPosDoubled; // Used to draw the bottom half of the circle.
public:
DiscreteCircle(Int xCenter, Int yCenter, Int radius);
__inline const VecHorzLine &getEdges(void) const { return m_edges; }
__inline Int getEdgeCount(void) const { return m_edges.size(); }
void drawCircle(ScanlineDrawFunc functionToDrawWith, void *parmToPass);
protected:
void generateEdgePairs(Int xCenter, Int yCenter, Int radius);
void removeDuplicates();
};
#endif /* __DISCRETECIRCLE_H__ */

View File

@ -0,0 +1,254 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: DrawModule.h /////////////////////////////////////////////////////////////////////////////////
// Author:
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __DRAWMODULE_H_
#define __DRAWMODULE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/GameType.h"
#include "Common/Module.h"
#include "Common/ModelState.h"
#include "GameClient/Color.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Matrix3D;
class RenderCost;
// TYPES //////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
/** DRAWABLE DRAW MODULE base class */
//-------------------------------------------------------------------------------------------------
class ObjectDrawInterface;
class DebrisDrawInterface;
class TracerDrawInterface;
class RopeDrawInterface;
class LaserDrawInterface;
class FXList;
enum TerrainDecalType;
enum ShadowType;
//class ModelConditionFlags;
class DrawModule : public DrawableModule
{
MEMORY_POOL_GLUE_ABC( DrawModule )
MAKE_STANDARD_MODULE_MACRO_ABC( DrawModule )
public:
DrawModule( Thing *thing, const ModuleData* moduleData );
static ModuleType getModuleType() { return MODULETYPE_DRAW; }
static Int getInterfaceMask() { return MODULEINTERFACE_DRAW; }
virtual void doDrawModule(const Matrix3D* transformMtx) = 0;
virtual void setShadowsEnabled(Bool enable) = 0;
virtual void releaseShadows(void) = 0; ///< frees all shadow resources used by this module - used by Options screen.
virtual void allocateShadows(void) = 0; ///< create shadow resources if not already present. Used by Options screen.
#if defined(_DEBUG) || defined(_INTERNAL)
virtual void getRenderCost(RenderCost & rc) const { }; ///< estimates the render cost of this draw module
#endif
virtual void setTerrainDecal(TerrainDecalType type) {};
virtual void setTerrainDecalSize(Real x, Real y) {};
virtual void setTerrainDecalOpacity(Real o) {};
virtual void setFullyObscuredByShroud(Bool fullyObscured) = 0;
virtual Bool isVisible() const { return true; } ///< for limiting tree sway, etc to visible objects
virtual void reactToTransformChange(const Matrix3D* oldMtx, const Coord3D* oldPos, Real oldAngle) = 0;
virtual void reactToGeometryChange() = 0;
virtual Bool isLaser() const { return false; }
// interface acquisition
virtual ObjectDrawInterface* getObjectDrawInterface() { return NULL; }
virtual const ObjectDrawInterface* getObjectDrawInterface() const { return NULL; }
virtual DebrisDrawInterface* getDebrisDrawInterface() { return NULL; }
virtual const DebrisDrawInterface* getDebrisDrawInterface() const { return NULL; }
virtual TracerDrawInterface* getTracerDrawInterface() { return NULL; }
virtual const TracerDrawInterface* getTracerDrawInterface() const { return NULL; }
virtual RopeDrawInterface* getRopeDrawInterface() { return NULL; }
virtual const RopeDrawInterface* getRopeDrawInterface() const { return NULL; }
virtual LaserDrawInterface* getLaserDrawInterface() { return NULL; }
virtual const LaserDrawInterface* getLaserDrawInterface() const { return NULL; }
};
inline DrawModule::DrawModule( Thing *thing, const ModuleData* moduleData ) : DrawableModule( thing, moduleData ) { }
inline DrawModule::~DrawModule() { }
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
/** VARIOUS MODULE INTERFACES */
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class DebrisDrawInterface
{
public:
virtual void setModelName(AsciiString name, Color color, ShadowType t) = 0;
virtual void setAnimNames(AsciiString initial, AsciiString flying, AsciiString final, const FXList* finalFX) = 0;
};
//-------------------------------------------------------------------------------------------------
class TracerDrawInterface
{
public:
virtual void setTracerParms(Real speed, Real length, Real width, const RGBColor& color, Real initialOpacity) = 0;
};
//-------------------------------------------------------------------------------------------------
class RopeDrawInterface
{
public:
virtual void initRopeParms(Real length, Real width, const RGBColor& color, Real wobbleLen, Real wobbleAmp, Real wobbleRate) = 0;
virtual void setRopeCurLen(Real length) = 0;
virtual void setRopeSpeed(Real curSpeed, Real maxSpeed, Real accel) = 0;
};
class LaserDrawInterface
{
public:
virtual Real getLaserTemplateWidth() const = 0;
};
//-------------------------------------------------------------------------------------------------
class ObjectDrawInterface
{
public:
// this method must ONLY be called from the client, NEVER From the logic, not even indirectly.
virtual Bool clientOnly_getRenderObjInfo(Coord3D* pos, Real* boundingSphereRadius, Matrix3D* transform) const = 0;
/**
Find the bone(s) with the given name and return their positions and/or transforms in the given arrays.
We look for a bone named "boneNamePrefixQQ", where QQ is 01, 02, 03, etc, starting at the
value of "startIndex". Want to look for just a specific boneName with no numeric suffix?
just pass zero (0) for startIndex. (no, we never look for "boneNamePrefix00".)
We copy up to 'maxBones' into the array(s), and return the total count found.
NOTE: this returns the positions and transform for the "ideal" model... that is,
at its default rotation and scale, located at (0,0,0). You'll have to concatenate
an Object's position and transform onto these in order to move 'em into "world space"!
NOTE: this isn't very fast. Please call it sparingly and cache the result.
*/
virtual Int getPristineBonePositionsForConditionState(const ModelConditionFlags& condition, const char* boneNamePrefix, Int startIndex, Coord3D* positions, Matrix3D* transforms, Int maxBones) const = 0;
virtual Int getCurrentBonePositions(const char* boneNamePrefix, Int startIndex, Coord3D* positions, Matrix3D* transforms, Int maxBones) const = 0;
virtual Bool getCurrentWorldspaceClientBonePositions(const char* boneName, Matrix3D& transform) const = 0;
virtual Bool getProjectileLaunchOffset(const ModelConditionFlags& condition, WeaponSlotType wslot, Int specificBarrelToUse, Matrix3D* launchPos, WhichTurretType tur, Coord3D* turretRotPos, Coord3D* turretPitchPos) const = 0;
virtual void updateProjectileClipStatus( UnsignedInt shotsRemaining, UnsignedInt maxShots, WeaponSlotType slot ) = 0; ///< This will do the show/hide work if ProjectileBoneFeedbackEnabled is set.
virtual void updateDrawModuleSupplyStatus( Int maxSupply, Int currentSupply ) = 0; ///< This will do visual feedback on Supplies carried
virtual void notifyDrawModuleDependencyCleared( ) = 0; ///< if you were waiting for something before you drew, it's ready now
virtual void setHidden(Bool h) = 0;
virtual void replaceModelConditionState(const ModelConditionFlags& a) = 0;
virtual void replaceIndicatorColor(Color color) = 0;
virtual Bool handleWeaponFireFX(WeaponSlotType wslot, Int specificBarrelToUse, const FXList* fxl, Real weaponSpeed, const Coord3D* victimPos, Real damageRadius) = 0;
virtual Int getBarrelCount(WeaponSlotType wslot) const = 0;
virtual void setSelectable(Bool selectable) = 0;
/**
This call says, "I want the current animation (if any) to take n frames to complete a single cycle".
If it's a looping anim, each loop will take n frames. someday, we may want to add the option to insert
"pad" frames at the start and/or end, but for now, we always just "stretch" the animation to fit.
Note that you must call this AFTER setting the condition codes.
*/
virtual void setAnimationLoopDuration(UnsignedInt numFrames) = 0;
/**
similar to the above, but assumes that the current state is a "ONCE",
and is smart about transition states... if there is a transition state
"inbetween", it is included in the completion time.
*/
virtual void setAnimationCompletionTime(UnsignedInt numFrames) = 0;
virtual Bool updateBonesForClientParticleSystems( void ) = 0;///< this will reposition particle systems on the fly ML
/**
This call is used to pause or resume an animation.
*/
virtual void setPauseAnimation(Bool pauseAnim) = 0;
virtual void updateSubObjects() = 0;
virtual void showSubObject( const AsciiString& name, Bool show ) = 0;
/**
This call asks, "In the current animation (if any) how far along are you, from 0.0f to 1.0f".
*/
#ifdef ALLOW_ANIM_INQUIRIES
// srj sez: not sure if this is a good idea, for net sync reasons...
virtual Real getAnimationScrubScalar( void ) const { return 0.0f;};
#endif
};
//-------------------------------------------------------------------------------------------------
class RenderCost
{
public:
RenderCost(void) { clear(); }
~RenderCost(void) { }
void clear(void) { m_drawCallCount = m_sortedMeshCount = m_boneCount = m_skinMeshCount = m_shadowDrawCount = 0; }
void addDrawCalls(int count) { m_drawCallCount += count; }
void addSortedMeshes(int count) { m_sortedMeshCount += count; }
void addSkinMeshes(int count) { m_skinMeshCount += count; }
void addBones(int count) { m_boneCount += count; }
void addShadowDrawCalls(int count) { m_shadowDrawCount += count; }
int getDrawCallCount(void) { return m_drawCallCount; }
int getSortedMeshCount(void) { return m_sortedMeshCount; }
int getSkinMeshCount(void) { return m_skinMeshCount; }
int getBoneCount(void) { return m_boneCount; }
int getShadowDrawCount(void) { return m_shadowDrawCount; }
protected:
int m_drawCallCount;
int m_sortedMeshCount;
int m_skinMeshCount;
int m_boneCount;
int m_shadowDrawCount;
};
#endif // __DRAWMODULE_H_

View File

@ -0,0 +1,123 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Energy.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Energy.h
//
// Created: Steven Johnson, October 2001
//
// Desc: @todo
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef _ENERGY_H_
#define _ENERGY_H_
// INLCUDES /////////////////////////////////////////////////////////////////////////////////////
#include "Common/Snapshot.h"
// ----------------------------------------------------------------------------------------------
class Player;
class Object;
// ----------------------------------------------------------------------------------------------
/**
This class is used to encapsulate the Player's energy use and production.
for consistent nomenclature, we'll arbitrarily call energy units "kilowatts"
(though that may have no bearing on reality).
*/
class Energy : public Snapshot
{
public:
inline Energy() : m_energyProduction(0), m_energyConsumption(0), m_owner(NULL) { }
// reset energy information to base values.
void init( Player *owner)
{
m_energyProduction = 0;
m_energyConsumption = 0;
m_owner = owner;
}
/// return current energy production in kilowatts
Int getProduction() const { return m_energyProduction; }
/// return current energy consumption in kilowatts
Int getConsumption() const { return m_energyConsumption; }
Bool hasSufficientPower(void) const;
// If adding is false, we're supposed to be removing this.
void adjustPower(Int powerDelta, Bool adding);
/// new 'obj' will now add/subtract from this energy construct
void objectEnteringInfluence( Object *obj );
/// 'obj' will now no longer add/subtrack from this energy construct
void objectLeavingInfluence( Object *obj );
/** Adds an energy bonus to the player's pool if the power bonus status bit is set */
void addPowerBonus( Object *obj );
void removePowerBonus( Object *obj );
/**
return the percentage of energy needed that we actually produce, as a 0.0 ... 1.0 fraction.
*/
Real getEnergySupplyRatio() const;
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
void addProduction(Int amt);
void addConsumption(Int amt);
private:
Int m_energyProduction; ///< level of energy production, in kw
Int m_energyConsumption; ///< level of energy consumption, in kw
Player *m_owner; ///< Tight pointer to the Player I am intrinsic to.
};
#endif // _ENERGY_H_

View File

@ -0,0 +1,72 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Errors.h
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Errors.h
//
// Created: Steven Johnson, August 2001
//
// Desc: Error codes
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __ERRORS_H_
#define __ERRORS_H_
/**
An ErrorCode is the repository for failure modes. In almost all situations,
these values will be THROWN, not returned as error codes. Feel free
to add to this list as necessary; however, there should generally be very
few codes needed.
*/
enum ErrorCode
{
ERROR_BASE = 0xdead0001, // a nice, distinctive value
ERROR_BUG = (ERROR_BASE + 0x0000), ///< should not be possible under normal operation
ERROR_OUT_OF_MEMORY = (ERROR_BASE + 0x0001), ///< unable to allocate memory.
ERROR_BAD_ARG = (ERROR_BASE + 0x0002), ///< generic "bad argument".
ERROR_INVALID_FILE_VERSION = (ERROR_BASE + 0x0003), ///< Unrecognized file version.
ERROR_CORRUPT_FILE_FORMAT = (ERROR_BASE + 0x0004), ///< Invalid file format.
ERROR_BAD_INI = (ERROR_BASE + 0x0005), ///< Bad INI data.
ERROR_INVALID_D3D = (ERROR_BASE + 0x0006), ///< Error initing D3D
ERROR_LAST
};
#endif // __ERRORS_H_

View File

@ -0,0 +1,155 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------=
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright(C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: GameEngine
//
// Module: IO
//
// File name: FileSystem.h
//
// Created:
//
//----------------------------------------------------------------------------
#pragma once
#ifndef __FILESYSTEM_H
#define __FILESYSTEM_H
//----------------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------------
//#include "Common/File.h"
#include "Common/STLTypedefs.h"
#include "Common/SubsystemInterface.h"
//----------------------------------------------------------------------------
// Forward References
//----------------------------------------------------------------------------
class File;
//----------------------------------------------------------------------------
// Type Defines
//----------------------------------------------------------------------------
typedef std::set<AsciiString, rts::less_than_nocase<AsciiString> > FilenameList;
typedef FilenameList::iterator FilenameListIter;
//----------------------------------------------------------------------------
// Type Defines
//----------------------------------------------------------------------------
//#define W3D_DIR_PATH "../FinalArt/W3D/" ///< .w3d files live here
//#define TGA_DIR_PATH "../FinalArt/Textures/" ///< .tga texture files live here
//#define TERRAIN_TGA_DIR_PATH "../FinalArt/Terrain/" ///< terrain .tga texture files live here
#define W3D_DIR_PATH "Art/W3D/" ///< .w3d files live here
#define TGA_DIR_PATH "Art/Textures/" ///< .tga texture files live here
#define TERRAIN_TGA_DIR_PATH "Art/Terrain/" ///< terrain .tga texture files live here
#define MAP_PREVIEW_DIR_PATH "%sMapPreviews/" ///< We need a common place we can copy the map previews to at runtime.
#define USER_W3D_DIR_PATH "%sW3D/" ///< .w3d files live here
#define USER_TGA_DIR_PATH "%sTextures/" ///< User .tga texture files live here
// the following defines are only to be used while maintaining legacy compatability
// with old files until they are completely gone and in the regular art set
#ifdef MAINTAIN_LEGACY_FILES
#define LEGACY_W3D_DIR_PATH "../LegacyArt/W3D/" ///< .w3d files live here
#define LEGACY_TGA_DIR_PATH "../LegacyArt/Textures/" ///< .tga texture files live here
#endif // MAINTAIN_LEGACY_FILES
// LOAD_TEST_ASSETS automatically loads w3d assets from the TEST_W3D_DIR_PATH
// without having to add an INI entry.
///@todo this allows us to use the test art directory, it should be removed for FINAL release
#define LOAD_TEST_ASSETS 1
#ifdef LOAD_TEST_ASSETS
#define ROAD_DIRECTORY "../TestArt/TestRoad/"
#define TEST_STRING "***TESTING"
// the following directories will be used to look for test art
#define LOOK_FOR_TEST_ART
#define TEST_W3D_DIR_PATH "../TestArt/" ///< .w3d files live here
#define TEST_TGA_DIR_PATH "../TestArt/" ///< .tga texture files live here
#endif
struct FileInfo {
Int sizeHigh;
Int sizeLow;
Int timestampHigh;
Int timestampLow;
};
//===============================
// FileSystem
//===============================
/**
* FileSystem is an interface class for creating specific FileSystem objects.
*
* A FileSystem object's implemenation decides what derivative of File object needs to be
* created when FileSystem::Open() gets called.
*/
//===============================
class FileSystem : public SubsystemInterface
{
public:
FileSystem();
virtual ~FileSystem();
void init();
void reset();
void update();
File* openFile( const Char *filename, Int access = 0 ); ///< opens a File interface to the specified file
Bool doesFileExist(const Char *filename) const; ///< returns TRUE if the file exists. filename should have no directory.
void getFileListInDirectory(const AsciiString& directory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const; ///< search the given directory for files matching the searchName (egs. *.ini, *.rep). Possibly search subdirectories.
Bool getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const; ///< fills in the FileInfo struct for the file given. returns TRUE if successful.
Bool createDirectory(AsciiString directory); ///< create a directory of the given name.
Bool areMusicFilesOnCD();
void loadMusicFilesFromCD();
void unloadMusicFilesFromCD();
protected:
};
extern FileSystem* TheFileSystem;
//----------------------------------------------------------------------------
// Inlining
//----------------------------------------------------------------------------
#endif // __WSYS_FILESYSTEM_H

View File

@ -0,0 +1,154 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: FunctionLexicon.h ////////////////////////////////////////////////////////////////////////
// Created: Colin Day, September 2001
// Desc: Collection of function pointers to help us in managing
// and assign callbacks
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __FUNCTIONLEXICON_H_
#define __FUNCTIONLEXICON_H_
#include "Common/SubsystemInterface.h"
#include "Common/NameKeyGenerator.h"
#include "Common/GameMemory.h"
#include "GameClient/GameWindow.h"
#include "GameClient/WindowLayout.h"
//-------------------------------------------------------------------------------------------------
/** Collection of function pointers to help us in managing callbacks */
//-------------------------------------------------------------------------------------------------
class FunctionLexicon : public SubsystemInterface
{
public:
struct TableEntry
{
NameKeyType key;
const char *name;
void *func;
};
enum TableIndex
{
TABLE_ANY = -1, ///< use this when searching to search any table
TABLE_GAME_WIN_SYSTEM = 0,
TABLE_GAME_WIN_INPUT,
TABLE_GAME_WIN_TOOLTIP,
TABLE_GAME_WIN_DEVICEDRAW,
TABLE_GAME_WIN_DRAW,
TABLE_WIN_LAYOUT_INIT,
TABLE_WIN_LAYOUT_DEVICEINIT,
TABLE_WIN_LAYOUT_UPDATE,
TABLE_WIN_LAYOUT_SHUTDOWN,
MAX_FUNCTION_TABLES // keep this last
};
public:
FunctionLexicon( void );
virtual ~FunctionLexicon( void );
virtual void init( void );
virtual void reset( void );
virtual void update( void );
/// validate the tables and make sure all entries are unique
Bool validate( void );
/// get internal function table
TableEntry *getTable( TableIndex index );
//
// !NOTE! We do NOT have a functionToName() method becuase we assume
// that functions in the tables are unique and that there is a 1 to 1
// mapping of a symbol to a function address. However, when compiling
// in release, functions that have the same arguments and the same
// body (mainly empty stub functions) get optimized to the
// SAME ADDRESS. That destroyes our 1 to 1 mapping so it is something
// that we must avoid
//
// translate a function pointer to its symbolic name
// char *functionToName( void *func );
// Game window functions ------------------------------------------------------------------------
GameWinSystemFunc gameWinSystemFunc( NameKeyType key, TableIndex = TABLE_GAME_WIN_SYSTEM );
GameWinInputFunc gameWinInputFunc( NameKeyType key, TableIndex = TABLE_GAME_WIN_INPUT );
GameWinTooltipFunc gameWinTooltipFunc( NameKeyType key, TableIndex = TABLE_GAME_WIN_TOOLTIP );
GameWinDrawFunc gameWinDrawFunc( NameKeyType key, TableIndex = TABLE_ANY );
// Window layout functions ----------------------------------------------------------------------
WindowLayoutInitFunc winLayoutInitFunc( NameKeyType key, TableIndex = TABLE_ANY );
WindowLayoutUpdateFunc winLayoutUpdateFunc( NameKeyType key, TableIndex = TABLE_WIN_LAYOUT_UPDATE );
WindowLayoutShutdownFunc winLayoutShutdownFunc( NameKeyType key, TableIndex = TABLE_WIN_LAYOUT_SHUTDOWN );
protected:
/// load a lookup table with run time values needed and save in table list
void loadTable( TableEntry *table, TableIndex tableIndex );
/** given a key find the function, the index parameter can limit the search
to a single table or to ANY of the tables */
void *findFunction( NameKeyType key, TableIndex index );
#ifdef NOT_IN_USE
const char *funcToName( void *func, TableEntry *table ); ///< internal searching
#endif
void *keyToFunc( NameKeyType key, TableEntry *table ); ///< internal searching
TableEntry *m_tables[ MAX_FUNCTION_TABLES ]; ///< the lookup tables
}; // end class FunctionLexicon
///////////////////////////////////////////////////////////////////////////////////////////////////
// INLINING
///////////////////////////////////////////////////////////////////////////////////////////////////
inline FunctionLexicon::TableEntry *FunctionLexicon::getTable( TableIndex index )
{ return m_tables[ index ]; }
inline GameWinSystemFunc FunctionLexicon::gameWinSystemFunc( NameKeyType key, TableIndex index )
{ return (GameWinSystemFunc)findFunction( key, index ); }
inline GameWinInputFunc FunctionLexicon::gameWinInputFunc( NameKeyType key, TableIndex index )
{ return (GameWinInputFunc)findFunction( key, index ); }
inline GameWinTooltipFunc FunctionLexicon::gameWinTooltipFunc( NameKeyType key, TableIndex index )
{ return (GameWinTooltipFunc)findFunction( key, index ); }
inline WindowLayoutUpdateFunc FunctionLexicon::winLayoutUpdateFunc( NameKeyType key, TableIndex index )
{ return (WindowLayoutUpdateFunc)findFunction( key, index ); }
inline WindowLayoutShutdownFunc FunctionLexicon::winLayoutShutdownFunc( NameKeyType key, TableIndex index )
{ return (WindowLayoutShutdownFunc)findFunction( key, index ); }
///////////////////////////////////////////////////////////////////////////////////////////////////
// EXTERNALS
///////////////////////////////////////////////////////////////////////////////////////////////////
extern FunctionLexicon *TheFunctionLexicon; ///< function dictionary external
#endif // end __FUNCTIONLEXICON_H_

View File

@ -0,0 +1,372 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: RTS 3
//
// File name: Common/GameAudio.h
//
// Created: 5/01/01
//
//----------------------------------------------------------------------------
#pragma once
#ifndef __COMMON_GAMEAUDIO_H_
#define __COMMON_GAMEAUDIO_H_
// Includes
#include "Lib/BaseType.h"
#include "Common/STLTypedefs.h"
#include "Common/SubsystemInterface.h"
// Forward Declarations
class AsciiString;
class AudioEventRTS;
class DebugDisplayInterface;
class Drawable;
class MusicManager;
class Object;
class SoundManager;
enum AudioAffect;
enum AudioType;
struct AudioEventInfo;
struct AudioRequest;
struct AudioSettings;
struct MiscAudio;
typedef std::hash_map<AsciiString, AudioEventInfo*, rts::hash<AsciiString>, rts::equal_to<AsciiString> > AudioEventInfoHash;
typedef AudioEventInfoHash::iterator AudioEventInfoHashIt;
typedef UnsignedInt AudioHandle;
// Defines
enum
{
PROVIDER_ERROR = 0xFFFFFFFF
};
// Class AudioManager
/**
The life of audio.
When audio is requested to play, it is done so in the following manner:
1) An AudioEventRTS is created on the stack.
2) Its guts are copied from elsewhere (for instance, a ThingTemplate, or MiscAudio).
3) It is added to TheAudio via TheAudio->addAudioEvent(...)
The return value from addAudioEvent can be saved in case the sound needs to loop and/or be
terminated at some point.
To reomve a playing sound, the call TheAudio->removeAudioEvent(...) is used. This will search
the list of currently playing audio for the specified handle, and kill the attached sound. It
will play a decay sound, if one is specified.
The important functions of TheAudio, are therefore
GameAudio::addAudioEvent()
GameAudio::removeAudioEvent()
All other functions exist to support these two basic requirements.
In addition to the fundamental requirements, the audio has a fairly complicated sound management
scheme. If all units were always allowed to sound off, the sound engine would be overwhelmed and
would sound awful. Therefore, when an audio event is requested, it goes through a series of
checks to determine if it is near enough to the camera, if it should be heard based on shroud,
local player affiliation, etc. (The entire list of checks is contained in shouldPlayLocally()).
In addition, the world and unit audio are never allowed to exceed their footprint, as specified
in the audio settings INI file. In order to accomodate this, the audio uses an audio cache. The
audio cache will attempt to load a sample, assuming there is enough room. If there is not enough
room, then it goes through and finds any samples that are lower priority, and kills them until
enough room is present for the sample. If it cannot free enough room, nothing happens to the
cache.
Although the audio is multithreaded, most of the operations are performed such that the worst
case scenario for thread miscommunication is that the main thread misses an event for one frame.
One specific case of this is the status of playing audio. Because audio is playing
asynchronously, it can complete at any time. When most audio completes, it sets a flag on the
event noting that it has completed. During the next update (from the main thread), anything with
that flag set is moved to the stopped list, and then is cleaned up. (Basically, the audio uses
a push model for its multithreadedness, which doesn't require thread safety such as mutexes or
semaphores).
All in all, the best way to learn how the audio works is to track the lifetime of an event
through the system. This will give a better understanding than all the documentation I could
write.
-jkmcd
-December 2002
*/
class AudioManager : public SubsystemInterface
{
public:
AudioManager();
virtual ~AudioManager();
#if defined(_DEBUG) || defined(_INTERNAL)
virtual void audioDebugDisplay(DebugDisplayInterface *dd, void *userData, FILE *fp = NULL ) = 0;
#endif
// From SubsystemInterface
virtual void init();
virtual void postProcessLoad();
virtual void reset();
virtual void update();
// device dependent stop, pause and resume
virtual void stopAudio( AudioAffect which ) = 0;
virtual void pauseAudio( AudioAffect which ) = 0;
virtual void resumeAudio( AudioAffect which ) = 0;
virtual void pauseAmbient( Bool shouldPause ) = 0;
// device dependent stops.
virtual void stopAllAmbientsBy( Object* obj ) = 0;
virtual void stopAllAmbientsBy( Drawable* draw ) = 0;
// for focus issues
virtual void loseFocus( void );
virtual void regainFocus( void );
// control for AudioEventsRTS
virtual AudioHandle addAudioEvent( const AudioEventRTS *eventToAdd ); ///< Add an audio event (event must be declared in an INI file)
virtual void removeAudioEvent( AudioHandle audioEvent ); ///< Remove an audio event, stop for instance.
virtual void killAudioEventImmediately( AudioHandle audioEvent ) = 0;
virtual Bool isValidAudioEvent( const AudioEventRTS *eventToCheck ) const; ///< validate that this piece of audio exists
virtual Bool isValidAudioEvent( AudioEventRTS *eventToCheck ) const; ///< validate that this piece of audio exists
// add tracks during INIification
void addTrackName( const AsciiString& trackName );
AsciiString nextTrackName(const AsciiString& currentTrack );
AsciiString prevTrackName(const AsciiString& currentTrack );
// changing music tracks
virtual void nextMusicTrack( void ) = 0;
virtual void prevMusicTrack( void ) = 0;
virtual Bool isMusicPlaying( void ) const = 0;
virtual Bool hasMusicTrackCompleted( const AsciiString& trackName, Int numberOfTimes ) const = 0;
virtual AsciiString getMusicTrackName( void ) const = 0;
virtual void setAudioEventEnabled( AsciiString eventToAffect, Bool enable );
virtual void setAudioEventVolumeOverride( AsciiString eventToAffect, Real newVolume );
virtual void removeAudioEvent( AsciiString eventToRemove );
virtual void removeDisabledEvents();
// Really meant for internal purposes only, but cannot be protected.
virtual void getInfoForAudioEvent( const AudioEventRTS *eventToFindAndFill ) const; // Note: m_eventInfo is Mutable, and so this function will overwrite it if found
///< Return whether the current audio is playing or not.
///< NOTE NOTE NOTE !!DO NOT USE THIS IN FOR GAMELOGIC PURPOSES!! NOTE NOTE NOTE
virtual Bool isCurrentlyPlaying( AudioHandle handle );
// Device Dependent open and close functions
virtual void openDevice( void ) = 0;
virtual void closeDevice( void ) = 0;
virtual void *getDevice( void ) = 0;
// Debice Dependent notification functions
virtual void notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags ) = 0;
// Device Dependent enumerate providers functions. It is okay for there to be only 1 provider (Miles provides a maximum of 64.
virtual UnsignedInt getProviderCount( void ) const = 0;
virtual AsciiString getProviderName( UnsignedInt providerNum ) const = 0;
virtual UnsignedInt getProviderIndex( AsciiString providerName ) const = 0;
virtual void selectProvider( UnsignedInt providerNdx ) = 0;
virtual void unselectProvider( void ) = 0;
virtual UnsignedInt getSelectedProvider( void ) const = 0;
virtual void setSpeakerType( UnsignedInt speakerType ) = 0;
virtual UnsignedInt getSpeakerType( void ) = 0;
virtual UnsignedInt translateSpeakerTypeToUnsignedInt( const AsciiString& speakerType );
virtual AsciiString translateUnsignedIntToSpeakerType( UnsignedInt speakerType );
// Device Dependent calls to get the number of channels for each type of audio (2-D, 3-D, Streams)
virtual UnsignedInt getNum2DSamples( void ) const = 0;
virtual UnsignedInt getNum3DSamples( void ) const = 0;
virtual UnsignedInt getNumStreams( void ) const = 0;
// Device Dependent calls to determine sound prioritization info
virtual Bool doesViolateLimit( AudioEventRTS *event ) const = 0;
virtual Bool isPlayingLowerPriority( AudioEventRTS *event ) const = 0;
virtual Bool isPlayingAlready( AudioEventRTS *event ) const = 0;
virtual Bool isObjectPlayingVoice( UnsignedInt objID ) const = 0;
virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) = 0;
virtual void removePlayingAudio( AsciiString eventName ) = 0;
virtual void removeAllDisabledAudio() = 0;
// Is the audio device on? We can skip a lot of audio processing if not.
virtual Bool isOn( AudioAffect whichToGet ) const;
virtual void setOn( Bool turnOn, AudioAffect whichToAffect );
// Set and get the device Volume
virtual void setVolume( Real volume, AudioAffect whichToAffect );
virtual Real getVolume( AudioAffect whichToGet );
// To get a more 3-D feeling from the universe, we adjust the volume of the 3-D samples based
// on zoom.
virtual void set3DVolumeAdjustment( Real volumeAdjustment );
virtual void *getHandleForBink( void ) = 0;
virtual void releaseHandleForBink( void ) = 0;
// this function will play an audio event rts by loading it into memory. It should not be used
// by anything except for the load screens.
virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) = 0;
// Update Listener position information
virtual void setListenerPosition( const Coord3D *newListenerPos, const Coord3D *newListenerOrientation );
virtual const Coord3D *getListenerPosition( void ) const;
virtual AudioRequest *allocateAudioRequest( Bool useAudioEvent );
virtual void releaseAudioRequest( AudioRequest *requestToRelease );
virtual void appendAudioRequest( AudioRequest *m_request );
virtual void processRequestList( void );
virtual AudioEventInfo *newAudioEventInfo( AsciiString newEventName );
virtual AudioEventInfo *findAudioEventInfo( AsciiString eventName ) const;
const AudioSettings *getAudioSettings( void ) const;
const MiscAudio *getMiscAudio( void ) const;
// This function should only be called by AudioManager, MusicManager and SoundManager
virtual void releaseAudioEventRTS( AudioEventRTS *eventToRelease );
// For INI
AudioSettings *friend_getAudioSettings( void );
MiscAudio *friend_getMiscAudio( void );
const FieldParse *getFieldParseTable( void ) const;
const AudioEventRTS *getValidSilentAudioEvent() const { return m_silentAudioEvent; }
virtual void setHardwareAccelerated(Bool accel) { m_hardwareAccel = accel; }
virtual Bool getHardwareAccelerated() { return m_hardwareAccel; }
virtual void setSpeakerSurround(Bool surround) { m_surroundSpeakers = surround; }
virtual Bool getSpeakerSurround() { return m_surroundSpeakers; }
virtual void refreshCachedVariables();
virtual void setPreferredProvider(AsciiString providerNdx) = 0;
virtual void setPreferredSpeaker(AsciiString speakerType) = 0;
// For Scripting
virtual Real getAudioLengthMS( const AudioEventRTS *event );
virtual Real getFileLengthMS( AsciiString strToLoad ) const = 0;
// For the file cache to know when to remove files.
virtual void closeAnySamplesUsingFile( const void *fileToClose ) = 0;
virtual Bool isMusicAlreadyLoaded(void) const;
virtual Bool isMusicPlayingFromCD(void) const { return m_musicPlayingFromCD; }
Bool getDisallowSpeech( void ) const { return m_disallowSpeech; }
void setDisallowSpeech( Bool disallowSpeech ) { m_disallowSpeech = disallowSpeech; }
// For Worldbuilder, to build lists from which to select
virtual void findAllAudioEventsOfType( AudioType audioType, std::vector<AudioEventInfo*>& allEvents );
Real getZoomVolume() const { return m_zoomVolume; }
protected:
// Is the currently selected provider actually HW accelerated?
virtual Bool isCurrentProviderHardwareAccelerated();
// Is the currently selected speaker type Surround sound?
virtual Bool isCurrentSpeakerTypeSurroundSound();
// Should this piece of audio play on the local machine?
virtual Bool shouldPlayLocally(const AudioEventRTS *audioEvent);
// Set the Listening position for the device
virtual void setDeviceListenerPosition( void ) = 0;
// For tracking purposes
virtual AudioHandle allocateNewHandle( void );
protected:
AudioSettings *m_audioSettings;
MiscAudio *m_miscAudio;
MusicManager *m_music;
SoundManager *m_sound;
Coord3D m_listenerPosition;
Coord3D m_listenerOrientation;
std::list<AudioRequest*> m_audioRequests;
std::vector<AsciiString> m_musicTracks;
AudioEventInfoHash m_allAudioEventInfo;
AudioHandle theAudioHandlePool;
std::list<std::pair<AsciiString, Real> > m_adjustedVolumes;
Real m_musicVolume;
Real m_soundVolume;
Real m_sound3DVolume;
Real m_speechVolume;
Real m_scriptMusicVolume;
Real m_scriptSoundVolume;
Real m_scriptSound3DVolume;
Real m_scriptSpeechVolume;
Real m_systemMusicVolume;
Real m_systemSoundVolume;
Real m_systemSound3DVolume;
Real m_systemSpeechVolume;
Real m_zoomVolume;
AudioEventRTS *m_silentAudioEvent;
enum { NUM_VOLUME_TYPES = 4 };
Real *m_savedValues;
// Group of 8
Bool m_speechOn : 1;
Bool m_soundOn : 1;
Bool m_sound3DOn : 1;
Bool m_musicOn : 1;
Bool m_volumeHasChanged : 1;
Bool m_hardwareAccel : 1;
Bool m_surroundSpeakers : 1;
Bool m_musicPlayingFromCD : 1;
// Next 8
Bool m_disallowSpeech : 1;
};
extern AudioManager *TheAudio;
#endif // __COMMON_GAMEAUDIO_H_

View File

@ -0,0 +1,491 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GameCommon.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: GameCommon.h
//
// Created: Steven Johnson, October 2001
//
// Desc: This is a catchall header for some basic types and definitions
// needed by various bits of the GameLogic/GameClient, but that
// we haven't found a good place for yet. Hopefully this file
// should go away someday, but for now is a convenient spot.
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef _GAMECOMMON_H_
#define _GAMECOMMON_H_
// ----------------------------------------------------------------------------------------------
#include "Lib/BaseType.h"
// ----------------------------------------------------------------------------------------------
#if defined(_INTERNAL) || defined(_DEBUG) || defined(_PLAYTEST)
#define NO_DUMP_PERF_STATS
#else
#define NO_DUMP_PERF_STATS
#endif
// ----------------------------------------------------------------------------------------------
enum
{
LOGICFRAMES_PER_SECOND = 30,
MSEC_PER_SECOND = 1000
};
const Real LOGICFRAMES_PER_MSEC_REAL = (((Real)LOGICFRAMES_PER_SECOND) / ((Real)MSEC_PER_SECOND));
const Real MSEC_PER_LOGICFRAME_REAL = (((Real)MSEC_PER_SECOND) / ((Real)LOGICFRAMES_PER_SECOND));
const Real LOGICFRAMES_PER_SECONDS_REAL = (Real)LOGICFRAMES_PER_SECOND;
const Real SECONDS_PER_LOGICFRAME_REAL = 1.0f / LOGICFRAMES_PER_SECONDS_REAL;
// ----------------------------------------------------------------------------------------------
// note that this returns a REAL value, not an int... most callers will want to
// call ceil() on the result, so that partial frames get converted to full frames!
inline Real ConvertDurationFromMsecsToFrames(Real msec)
{
return (msec * LOGICFRAMES_PER_MSEC_REAL);
}
// ----------------------------------------------------------------------------------------------
inline Real ConvertVelocityInSecsToFrames(Real distPerMsec)
{
// this looks wrong, but is the correct conversion factor.
return (distPerMsec * SECONDS_PER_LOGICFRAME_REAL);
}
// ----------------------------------------------------------------------------------------------
inline Real ConvertAccelerationInSecsToFrames(Real distPerSec2)
{
// this looks wrong, but is the correct conversion factor.
const Real SEC_PER_LOGICFRAME_SQR = (SECONDS_PER_LOGICFRAME_REAL * SECONDS_PER_LOGICFRAME_REAL);
return (distPerSec2 * SEC_PER_LOGICFRAME_SQR);
}
// ----------------------------------------------------------------------------------------------
inline Real ConvertAngularVelocityInDegreesPerSecToRadsPerFrame(Real degPerSec)
{
const Real RADS_PER_DEGREE = PI / 180.0f;
return (degPerSec * (SECONDS_PER_LOGICFRAME_REAL * RADS_PER_DEGREE));
}
// ----------------------------------------------------------------------------------------------
enum
{
MAX_PLAYER_COUNT = 16 ///< max number of Players.
};
// ----------------------------------------------------------------------------------------------
/**
a bitmask that can uniquely represent each player.
*/
#if MAX_PLAYER_COUNT <= 16
typedef UnsignedShort PlayerMaskType;
const PlayerMaskType PLAYERMASK_ALL = 0xffff;
const PlayerMaskType PLAYERMASK_NONE = 0x0;
#else
#error "this is the wrong size"
#endif
//-------------------------------------------------------------------------------------------------
enum GameDifficulty
{
DIFFICULTY_EASY,
DIFFICULTY_NORMAL,
DIFFICULTY_HARD,
DIFFICULTY_COUNT
};
//-------------------------------------------------------------------------------------------------
enum PlayerType
{
PLAYER_HUMAN, ///< player is human-controlled
PLAYER_COMPUTER, ///< player is computer-controlled
PLAYERTYPE_COUNT
};
//-------------------------------------------------------------------------------------------------
/// A PartitionCell can be one of three states for Shroud
enum CellShroudStatus
{
CELLSHROUD_CLEAR,
CELLSHROUD_FOGGED,
CELLSHROUD_SHROUDED,
CELLSHROUD_COUNT
};
//-------------------------------------------------------------------------------------------------
/// Since an object can take up more than a single PartitionCell, this is a status that applies to the whole Object
enum ObjectShroudStatus
{
OBJECTSHROUD_INVALID, ///< indeterminate state, will recompute
OBJECTSHROUD_CLEAR, ///< object is not shrouded at all (ie, completely visible)
OBJECTSHROUD_PARTIAL_CLEAR, ///< object is partly clear (rest is shroud or fog)
OBJECTSHROUD_FOGGED, ///< object is completely fogged
OBJECTSHROUD_SHROUDED, ///< object is completely shrouded
OBJECTSHROUD_INVALID_BUT_PREVIOUS_VALID, ///< indeterminate state, will recompute, BUT previous status is valid, don't reset (used for save/load)
OBJECTSHROUD_COUNT
};
//-------------------------------------------------------------------------------------------------
enum GuardMode
{
GUARDMODE_NORMAL,
GUARDMODE_GUARD_WITHOUT_PURSUIT, // no pursuit out of guard area
GUARDMODE_GUARD_FLYING_UNITS_ONLY // ignore nonflyers
};
// ---------------------------------------------------
enum
{
NEVER = 0,
FOREVER = 0x3fffffff // (we use 0x3fffffff so that we can add offsets and not overflow...
// at 30fps we're still pretty safe!)
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
/// Veterancy level define needed by several files that don't need the full Experience code.
// NOTE NOTE NOTE: Keep TheVeterencyNames in sync with these.
enum VeterancyLevel
{
LEVEL_REGULAR = 0,
LEVEL_VETERAN,
LEVEL_ELITE,
LEVEL_HEROIC,
LEVEL_COUNT,
LEVEL_INVALID,
LEVEL_FIRST = LEVEL_REGULAR,
LEVEL_LAST = LEVEL_HEROIC
};
// TheVeterancyNames is defined in GameCommon.cpp
extern const char *TheVeterancyNames[];
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
enum CommandSourceType
{
CMD_FROM_PLAYER = 0,
CMD_FROM_SCRIPT,
CMD_FROM_AI,
CMD_FROM_DOZER, // Special rare command when the dozer originates a command to attack a mine. Mines are not ai-attackable, and it seems deceitful for the dozer to generate a player or script command. jba.
}; ///< the source of a command
//-------------------------------------------------------------------------------------------------
enum AbleToAttackType
{
_ATTACK_FORCED = 0x01,
_ATTACK_CONTINUED = 0x02,
_ATTACK_TUNNELNETWORK_GUARD = 0x04,
/**
can we attack if this is a new target?
*/
ATTACK_NEW_TARGET = (0),
/**
can we attack if this is a new target, via force-fire?
(The only current difference between this and ATTACK_NEW_TARGET is that disguised units
are force-attackable even when stealthed.)
*/
ATTACK_NEW_TARGET_FORCED= (_ATTACK_FORCED),
/**
can we attack if this is continuation of an existing attack?
(The only current difference between this and ATTACK_NEW_TARGET is you are allowed to follow
immobile shrouded units into the fog)
*/
ATTACK_CONTINUED_TARGET = (_ATTACK_CONTINUED),
/**
can we attack if this is continuation of an existing attack?
(The only current difference between this and ATTACK_NEW_TARGET is you are allowed to follow
immobile shrouded units into the fog)
*/
ATTACK_CONTINUED_TARGET_FORCED = (_ATTACK_FORCED | _ATTACK_CONTINUED),
/**
Special case that bypasses some of the checks for units guarding from within tunnel networks!
For example, a unit inside couldn't normally see outside and would fail.
*/
ATTACK_TUNNEL_NETWORK_GUARD = (_ATTACK_TUNNELNETWORK_GUARD)
};
//-------------------------------------------------------------------------------------------------
inline Bool isForcedAttack(AbleToAttackType t)
{
return (((Int)t) & _ATTACK_FORCED) != 0;
}
//-------------------------------------------------------------------------------------------------
inline Bool isContinuedAttack(AbleToAttackType t)
{
return (((Int)t) & _ATTACK_CONTINUED) != 0;
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
typedef UnsignedInt VeterancyLevelFlags;
const VeterancyLevelFlags VETERANCY_LEVEL_FLAGS_ALL = 0xffffffff;
const VeterancyLevelFlags VETERANCY_LEVEL_FLAGS_NONE = 0x00000000;
inline Bool getVeterancyLevelFlag(VeterancyLevelFlags flags, VeterancyLevel dt)
{
return (flags & (1UL << (dt - 1))) != 0;
}
inline VeterancyLevelFlags setVeterancyLevelFlag(VeterancyLevelFlags flags, VeterancyLevel dt)
{
return (flags | (1UL << (dt - 1)));
}
inline VeterancyLevelFlags clearVeterancyLevelFlag(VeterancyLevelFlags flags, VeterancyLevel dt)
{
return (flags & ~(1UL << (dt - 1)));
}
// ----------------------------------------------------------------------------------------------
#define BOGUSPTR(p) ((((unsigned int)(p)) & 1) != 0)
// ----------------------------------------------------------------------------------------------
#define MAKE_DLINK_HEAD(OBJCLASS, LISTNAME) \
public: \
inline DLINK_ITERATOR<OBJCLASS> iterate_##LISTNAME() const \
{ \
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
return DLINK_ITERATOR<OBJCLASS>(m_dlinkhead_##LISTNAME.m_head, OBJCLASS::dlink_next_##LISTNAME); \
} \
inline OBJCLASS *getFirstItemIn_##LISTNAME() const \
{ \
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
return m_dlinkhead_##LISTNAME.m_head; \
} \
inline Bool isInList_##LISTNAME(OBJCLASS* o) const \
{ \
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
return o->dlink_isInList_##LISTNAME(&m_dlinkhead_##LISTNAME.m_head); \
} \
inline void prependTo_##LISTNAME(OBJCLASS* o) \
{ \
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
if (!isInList_##LISTNAME(o)) \
o->dlink_prependTo_##LISTNAME(&m_dlinkhead_##LISTNAME.m_head); \
} \
inline void removeFrom_##LISTNAME(OBJCLASS* o) \
{ \
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr")); \
if (isInList_##LISTNAME(o)) \
o->dlink_removeFrom_##LISTNAME(&m_dlinkhead_##LISTNAME.m_head); \
} \
typedef void (*RemoveAllProc_##LISTNAME)(OBJCLASS* o); \
inline void removeAll_##LISTNAME(RemoveAllProc_##LISTNAME p = NULL) \
{ \
while (m_dlinkhead_##LISTNAME.m_head) \
{ \
DEBUG_ASSERTCRASH(!BOGUSPTR(m_dlinkhead_##LISTNAME.m_head), ("bogus head ptr"));\
OBJCLASS *tmp = m_dlinkhead_##LISTNAME.m_head; \
removeFrom_##LISTNAME(tmp); \
if (p) (*p)(tmp); \
} \
} \
inline void reverse_##LISTNAME() \
{ \
OBJCLASS* cur = m_dlinkhead_##LISTNAME.m_head; \
OBJCLASS* prev = NULL; \
while (cur) \
{ \
OBJCLASS* originalNext = cur->dlink_next_##LISTNAME(); \
cur->dlink_swapLinks_##LISTNAME(); \
prev = cur; \
cur = originalNext; \
} \
m_dlinkhead_##LISTNAME.m_head = prev; \
} \
private: \
/* a trick: init head to zero */ \
struct DLINKHEAD_##LISTNAME \
{ \
public: \
OBJCLASS* m_head; \
inline DLINKHEAD_##LISTNAME() : \
m_head(0) { } \
inline ~DLINKHEAD_##LISTNAME() \
{ DEBUG_ASSERTCRASH(!m_head,("destroying dlinkhead still in a list " #LISTNAME)); } \
}; \
DLINKHEAD_##LISTNAME m_dlinkhead_##LISTNAME;
// ----------------------------------------------------------------------------------------------
#define MAKE_DLINK(OBJCLASS, LISTNAME) \
public: \
OBJCLASS* dlink_prev_##LISTNAME() const { return m_dlink_##LISTNAME.m_prev; } \
OBJCLASS* dlink_next_##LISTNAME() const { return m_dlink_##LISTNAME.m_next; } \
void dlink_swapLinks_##LISTNAME() \
{ \
OBJCLASS* originalNext = m_dlink_##LISTNAME.m_next; \
m_dlink_##LISTNAME.m_next = m_dlink_##LISTNAME.m_prev; \
m_dlink_##LISTNAME.m_prev = originalNext; \
} \
Bool dlink_isInList_##LISTNAME(OBJCLASS* const* pListHead) const \
{ \
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
return *pListHead == this || m_dlink_##LISTNAME.m_prev || m_dlink_##LISTNAME.m_next; \
} \
void dlink_prependTo_##LISTNAME(OBJCLASS** pListHead) \
{ \
DEBUG_ASSERTCRASH(!dlink_isInList_##LISTNAME(pListHead), ("already in list " #LISTNAME)); \
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
m_dlink_##LISTNAME.m_next = *pListHead; \
if (*pListHead) \
(*pListHead)->m_dlink_##LISTNAME.m_prev = this; \
*pListHead = this; \
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
} \
void dlink_removeFrom_##LISTNAME(OBJCLASS** pListHead) \
{ \
DEBUG_ASSERTCRASH(dlink_isInList_##LISTNAME(pListHead), ("not in list" #LISTNAME)); \
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
if (m_dlink_##LISTNAME.m_next) \
m_dlink_##LISTNAME.m_next->m_dlink_##LISTNAME.m_prev = m_dlink_##LISTNAME.m_prev; \
if (m_dlink_##LISTNAME.m_prev) \
m_dlink_##LISTNAME.m_prev->m_dlink_##LISTNAME.m_next = m_dlink_##LISTNAME.m_next; \
else \
*pListHead = m_dlink_##LISTNAME.m_next; \
m_dlink_##LISTNAME.m_prev = 0; \
m_dlink_##LISTNAME.m_next = 0; \
DEBUG_ASSERTCRASH(!BOGUSPTR(*pListHead) && !BOGUSPTR(m_dlink_##LISTNAME.m_next) && !BOGUSPTR(m_dlink_##LISTNAME.m_prev), ("bogus ptrs")); \
} \
private: \
/* a trick: init links to zero */ \
struct DLINK_##LISTNAME \
{ \
public: \
OBJCLASS* m_prev; \
OBJCLASS* m_next; \
inline DLINK_##LISTNAME() : \
m_prev(0), m_next(0) { } \
inline ~DLINK_##LISTNAME() \
{ DEBUG_ASSERTCRASH(!m_prev && !m_next,("destroying dlink still in a list " #LISTNAME)); } \
}; \
DLINK_##LISTNAME m_dlink_##LISTNAME;
// ------------------------------------------------------------------------
// this is the weird C++ syntax for "call pointer-to-member-function"... see C++ FAQ LITE for details.
#define callMemberFunction(object,ptrToMember) ((object).*(ptrToMember))
// ------------------------------------------------------------------------
template<class OBJCLASS>
class DLINK_ITERATOR
{
public:
// this is the weird C++ syntax for "pointer-to-member-function"
typedef OBJCLASS* (OBJCLASS::*GetNextFunc)() const;
private:
OBJCLASS* m_cur;
GetNextFunc m_getNextFunc; // this is the weird C++ syntax for "pointer-to-member-function"
public:
DLINK_ITERATOR(OBJCLASS* cur, GetNextFunc getNextFunc) : m_cur(cur), m_getNextFunc(getNextFunc)
{
}
void advance()
{
if (m_cur)
m_cur = callMemberFunction(*m_cur, m_getNextFunc)();
}
Bool done() const
{
return m_cur == NULL;
}
OBJCLASS* cur() const
{
return m_cur;
}
};
// ------------------------------------------------------------------------
enum WhichTurretType
{
TURRET_INVALID = -1,
TURRET_MAIN = 0,
TURRET_ALT,
MAX_TURRETS
};
// ------------------------------------------------------------------------
// this normalizes an angle to the range -PI...PI.
extern Real normalizeAngle(Real angle);
// ------------------------------------------------------------------------
// this returns the difference between a1 and a2, normalized.
inline Real stdAngleDiff(Real a1, Real a2)
{
return normalizeAngle(a1 - a2);
}
// ------------------------------------------------------------------------
// NOTE NOTE NOTE: Keep TheRelationShipNames in sync with this enum
enum Relationship
{
ENEMIES = 0,
NEUTRAL,
ALLIES
};
// TheRelationShipNames is defined in Common/GameCommon.cpp
extern const char *TheRelationshipNames[];
#endif // _GAMECOMMON_H_

View File

@ -0,0 +1,120 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GameEngine.h /////////////////////////////////////////////////////////
// The Game engine interface
// Author: Michael S. Booth, April 2001
#pragma once
#ifndef _GAME_ENGINE_H_
#define _GAME_ENGINE_H_
#include "Common/SubsystemInterface.h"
#include "Common/GameType.h"
#define DEFAULT_MAX_FPS 45
// forward declarations
class AudioManager;
class GameLogic;
class GameClient;
class MessageStream; ///< @todo Create a MessageStreamInterface abstract class
class FileSystem;
class Keyboard;
class LocalFileSystem;
class ArchiveFileSystem;
class FileSystem;
class Mouse;
class NetworkInterface;
class ModuleFactory;
class ThingFactory;
class FunctionLexicon;
class Radar;
class WebBrowser;
class ParticleSystemManager;
/**
* The implementation of the game engine
*/
class GameEngine : public SubsystemInterface
{
public:
GameEngine( void );
virtual ~GameEngine();
virtual void init( void ); ///< Init engine by creating client and logic
virtual void init( int argc, char *argv[] ); ///< Init engine by creating client and logic
virtual void reset( void ); ///< reset system to starting state
virtual void update( void ); ///< per frame update
virtual void execute( void ); /**< The "main loop" of the game engine.
It will not return until the game exits. */
virtual void setFramesPerSecondLimit( Int fps ); ///< Set the maximum rate engine updates are allowed to occur
virtual Int getFramesPerSecondLimit( void ); ///< Get maxFPS. Not inline since it is called from another lib.
virtual void setQuitting( Bool quitting ); ///< set quitting status
virtual Bool getQuitting(void); ///< is app getting ready to quit.
virtual Bool isMultiplayerSession( void );
virtual void serviceWindowsOS(void) {}; ///< service the native OS
virtual Bool isActive(void) {return m_isActive;} ///< returns whether app has OS focus.
virtual void setIsActive(Bool isActive) { m_isActive = isActive; };
virtual void checkAbnormalQuitting(void); ///< check if user is quitting at an unusual time - as in cheating!
protected:
virtual FileSystem *createFileSystem( void ); ///< Factory for FileSystem classes
virtual LocalFileSystem *createLocalFileSystem( void ) = 0; ///< Factory for LocalFileSystem classes
virtual ArchiveFileSystem *createArchiveFileSystem( void ) = 0; ///< Factory for ArchiveFileSystem classes
virtual GameLogic *createGameLogic( void ) = 0; ///< Factory for GameLogic classes.
virtual GameClient *createGameClient( void ) = 0; ///< Factory for GameClient classes.
virtual MessageStream *createMessageStream( void ); ///< Factory for the message stream
virtual ModuleFactory *createModuleFactory( void ) = 0; ///< Factory for modules
virtual ThingFactory *createThingFactory( void ) = 0; ///< Factory for the thing factory
virtual FunctionLexicon *createFunctionLexicon( void ) = 0; ///< Factory for Function Lexicon
virtual Radar *createRadar( void ) = 0; ///< Factory for radar
virtual WebBrowser *createWebBrowser( void ) = 0; ///< Factory for embedded browser
virtual ParticleSystemManager* createParticleSystemManager( void ) = 0;
virtual AudioManager *createAudioManager( void ) = 0; ///< Factory for Audio Manager
Int m_maxFPS; ///< Maximum frames per second allowed
Bool m_quitting; ///< true when we need to quit the game
Bool m_isActive; ///< app has OS focus.
};
inline void GameEngine::setQuitting( Bool quitting ) { m_quitting = quitting; }
inline Bool GameEngine::getQuitting(void) { return m_quitting; }
// the game engine singleton
extern GameEngine *TheGameEngine;
/// This function creates a new game engine instance, and is device specific
extern GameEngine *CreateGameEngine( void );
/// The entry point for the game system
extern void GameMain( int argc, char *argv[] );
#endif // _GAME_ENGINE_H_

View File

@ -0,0 +1,252 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GameLOD.h ///////////////////////////////////////////////////////////
//
// Used to set detail levels of various game systems.
//
// Author: Mark Wilczynski, Sept 2002
//
//
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _GAME_LOD_H_
#define _GAME_LOD_H_
enum ParticlePriorityType;
#define MAX_LOD_PRESETS_PER_LEVEL 32 //number of hardware configs preset for each low,medium,high
#define MAX_BENCH_PROFILES 16
//Make sure this enum stays in sync with GameLODNames[]
enum StaticGameLODLevel
{
STATIC_GAME_LOD_UNKNOWN=-1,
STATIC_GAME_LOD_LOW,
STATIC_GAME_LOD_MEDIUM,
STATIC_GAME_LOD_HIGH,
STATIC_GAME_LOD_CUSTOM, //make sure this remains last!
STATIC_GAME_LOD_COUNT
};
enum DynamicGameLODLevel
{
DYNAMIC_GAME_LOD_UNKNOWN=-1,
DYNAMIC_GAME_LOD_LOW,
DYNAMIC_GAME_LOD_MEDIUM,
DYNAMIC_GAME_LOD_HIGH,
DYNAMIC_GAME_LOD_VERY_HIGH,
DYNAMIC_GAME_LOD_COUNT
};
//Make sure this stays in sync with CPUNames[] in gamelod.cpp
enum CpuType
{
XX, //unknown type
P3,
P4,
K7,
};
//Keep this in sync with VideoNames in Gamelod.cpp
enum ChipsetType
{ DC_UNKNOWN,
DC_VOODOO2,
DC_VOODOO3,
DC_VOODOO4,
DC_VOODOO5,
DC_TNT,
DC_TNT2,
DC_GEFORCE2,
DC_RADEON,
DC_GENERIC_PIXEL_SHADER_1_1,
DC_GEFORCE3,
DC_GEFORCE4,
DC_GENERIC_PIXEL_SHADER_1_4,
DC_RADEON_8500,
DC_GENERIC_PIXEL_SHADER_2_0,
DC_RADEON_9700,
DC_MAX
};
struct StaticGameLODInfo
{
StaticGameLODInfo();
//Static LOD constants
Int m_minFPS; ///< minimum fps in order to recommend this LOD.
Int m_minProcessorFPS; ///< minimum CPU time (in ms) to recommend this LOD.
Int m_sampleCount2D; ///<How many 2-D (UI) samples should we allow simultaneously (Note: Hardware may support less than the desired number)
Int m_sampleCount3D; ///<How many 3-D (World) samples should we allow simultaneously (Note: Hardware may support less than the desired number)
Int m_streamCount; ///<How many streaming audio things should we allow simultaneously (Note: Hardware may support less than the desired number)
Int m_maxParticleCount; ///<maximum number of particles that can exist
Bool m_useShadowVolumes; ///<use volumetric shadows if available.
Bool m_useShadowDecals; ///<use 2D Decal shadows.
Bool m_useCloudMap; ///<use cloud shadows scrolling over terrain.
Bool m_useLightMap; ///<use noise pattern over terrain to break up tiling.
Bool m_showSoftWaterEdge; ///<feather water edge if supported by hardware.
Int m_maxTankTrackEdges; ///<maximum length of tank track
Int m_maxTankTrackOpaqueEdges; ///<maximum length of tank track before it starts fading.
Int m_maxTankTrackFadeDelay; ///<maximum amount of time a tank track segment remains visible.
Bool m_useBuildupScaffolds; ///<draw scaffold during structure building.
Bool m_useTreeSway; ///<sway trees to simulate wind.
Bool m_useEmissiveNightMaterials; ///<perform second lighting pass on night buildings.
Int m_textureReduction; ///<reduce texture resolution by dividing in half n times.
Bool m_useFpsLimit; ///<don't lock fps to 30hz
Bool m_enableDynamicLOD; ///<don't do dynamic lod based on current fps.
Bool m_useTrees; ///<don't include trees on map.
};
struct DynamicGameLODInfo
{
DynamicGameLODInfo();
//Dynamic LOD constants
Int m_minFPS; ///< minimum fps in order to recommend his LOD.
UnsignedInt m_dynamicParticleSkipMask;
UnsignedInt m_dynamicDebrisSkipMask;
Real m_slowDeathScale;
ParticlePriorityType m_minDynamicParticlePriority;
ParticlePriorityType m_minDynamicParticleSkipPriority;
};
struct LODPresetInfo
{
LODPresetInfo() : m_cpuType(XX),m_mhz(1),m_cpuPerfIndex(1.0f),m_videoType(DC_UNKNOWN),m_memory(1) {};
CpuType m_cpuType;
Int m_mhz;
Real m_cpuPerfIndex; //used to select preset for unidentified cpu's
ChipsetType m_videoType;
Int m_memory;
};
struct BenchProfile
{
BenchProfile() : m_cpuType(XX),m_mhz(1),m_intBenchIndex(1.0f),m_floatBenchIndex(1.0f),m_memBenchIndex(1.0f) {};
CpuType m_cpuType;
Int m_mhz;
Real m_intBenchIndex;
Real m_floatBenchIndex;
Real m_memBenchIndex;
};
class GameLODManager
{
public:
GameLODManager(void);
~GameLODManager();
const char *getStaticGameLODLevelName(StaticGameLODLevel level);
const char *getDynamicGameLODLevelName(DynamicGameLODLevel level);
StaticGameLODLevel findStaticLODLevel(void); ///< calculate the optimal static LOD level for this system.
Bool setStaticLODLevel(StaticGameLODLevel level); ///< set the current static LOD level.
StaticGameLODLevel getStaticLODLevel(void) { return m_currentStaticLOD;}
DynamicGameLODLevel findDynamicLODLevel(Real averageFPS); ///<given an average fps, return the optimal dynamic LOD.
Bool setDynamicLODLevel(DynamicGameLODLevel level); ///< set the current dynamic LOD level.
DynamicGameLODLevel getDynamicLODLevel(void) { return m_currentDynamicLOD;}
void init(void); ///<initialize tables of preset LOD's.
void setCurrentTextureReduction(Int val) {m_currentTextureReduction = val;}
Int getCurrentTextureReduction(void) {return m_currentTextureReduction;}
Int getStaticGameLODIndex(AsciiString name);
Int getDynamicGameLODIndex(AsciiString name);
inline Bool isParticleSkipped(void);
inline Bool isDebrisSkipped(void);
inline Real getSlowDeathScale(void);
inline ParticlePriorityType getMinDynamicParticlePriority(void); ///<priority at which particles will still render at current FPS.
inline ParticlePriorityType getMinDynamicParticleSkipPriority(void); ///<priority at which particles will never be skipped at any FPS.
Int getRecommendedTextureReduction(void); ///<return the optimal texture reduction for the system.
Int getLevelTextureReduction(StaticGameLODLevel level); ///<return texture reduction specified in INI for this game detail.
LODPresetInfo *newLODPreset(StaticGameLODLevel index);
BenchProfile *newBenchProfile(void);
Bool didMemPass( void );
void setReallyLowMHz(Int mhz) { m_reallyLowMHz = mhz; }
Bool isReallyLowMHz() const { return m_cpuFreq < m_reallyLowMHz; }
StaticGameLODInfo m_staticGameLODInfo[STATIC_GAME_LOD_COUNT];
DynamicGameLODInfo m_dynamicGameLODInfo[DYNAMIC_GAME_LOD_COUNT];
LODPresetInfo m_lodPresets[STATIC_GAME_LOD_CUSTOM][MAX_LOD_PRESETS_PER_LEVEL];
BenchProfile m_benchProfiles[MAX_BENCH_PROFILES];
protected:
void applyStaticLODLevel(StaticGameLODLevel level);
void applyDynamicLODLevel(DynamicGameLODLevel level);
void refreshCustomStaticLODLevel(void); ///<grabs current globaldata values and makes them the custom detail setting.
static const FieldParse m_staticGameLODFieldParseTable[];
StaticGameLODLevel m_currentStaticLOD; ///< current value of static LOD.
DynamicGameLODLevel m_currentDynamicLOD; ///< current value of dynamic LOD.
Int m_numParticleGenerations; ///<number of particles that have been generated since dynamic LOD reduction started.
Int m_dynamicParticleSkipMask; ///<mask used to enable rendering of every Nth particle.
Int m_numDebrisGenerations; ///<number of debris that have been generated since dynamic LOD reduction started.
Int m_dynamicDebrisSkipMask; ///<mask used to enable rendering of every Nth debris.
Real m_slowDeathScale; ///<values < 1.0f are used to accelerate deaths
ParticlePriorityType m_minDynamicParticlePriority; ///<only priorities above/including this value are allowed to render.
ParticlePriorityType m_minDynamicParticleSkipPriority; ///<priorities above/including this value never skip particles.
Bool m_videoPassed;
Bool m_cpuPassed;
Bool m_memPassed;
Int m_numLevelPresets[STATIC_GAME_LOD_CUSTOM];
Int m_numBenchProfiles;
StaticGameLODLevel m_idealDetailLevel;
ChipsetType m_videoChipType;
CpuType m_cpuType;
Int m_numRAM;
Int m_cpuFreq;
Real m_intBenchIndex;
Real m_floatBenchIndex;
Real m_memBenchIndex;
Real m_compositeBenchIndex;
Real m_currentTextureReduction;
Int m_reallyLowMHz;
};
Bool GameLODManager::isParticleSkipped(void)
{
return (++m_numParticleGenerations & m_dynamicParticleSkipMask) != m_dynamicParticleSkipMask;
}
Bool GameLODManager::isDebrisSkipped(void)
{
return (++m_numDebrisGenerations & m_dynamicDebrisSkipMask) != m_dynamicDebrisSkipMask;
}
Real GameLODManager::getSlowDeathScale(void)
{
return m_slowDeathScale;
}
ParticlePriorityType GameLODManager::getMinDynamicParticlePriority(void)
{
return m_minDynamicParticlePriority;
}
ParticlePriorityType GameLODManager::getMinDynamicParticleSkipPriority(void)
{
return m_minDynamicParticleSkipPriority;
}
extern GameLODManager *TheGameLODManager;
#endif _GAME_LOD_H_

View File

@ -0,0 +1,905 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Memory.h
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C); 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Memory.h
//
// Created: Steven Johnson, August 2001
//
// Desc: Memory manager
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _GAME_MEMORY_H_
#define _GAME_MEMORY_H_
// Turn off memory pool checkpointing for now.
#define DISABLE_MEMORYPOOL_CHECKPOINTING 1
#if (defined(_DEBUG) || defined(_INTERNAL)) && !defined(MEMORYPOOL_DEBUG_CUSTOM_NEW) && !defined(DISABLE_MEMORYPOOL_DEBUG_CUSTOM_NEW)
#define MEMORYPOOL_DEBUG_CUSTOM_NEW
#endif
//#if (defined(_DEBUG) || defined(_INTERNAL)) && !defined(MEMORYPOOL_DEBUG) && !defined(DISABLE_MEMORYPOOL_DEBUG)
#if (defined(_DEBUG)) && !defined(MEMORYPOOL_DEBUG) && !defined(DISABLE_MEMORYPOOL_DEBUG)
#define MEMORYPOOL_DEBUG
#endif
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
#include <new.h>
#include <stdio.h>
#ifdef MEMORYPOOL_OVERRIDE_MALLOC
#include <malloc.h>
#endif
// USER INCLUDES //////////////////////////////////////////////////////////////
#include "Lib/BaseType.h"
#include "Common/Debug.h"
#include "Common/Errors.h"
// MACROS //////////////////////////////////////////////////////////////////
#ifdef MEMORYPOOL_DEBUG
// by default, enable free-block-retention for checkpointing in debug mode
#ifndef DISABLE_MEMORYPOOL_CHECKPOINTING
#define MEMORYPOOL_CHECKPOINTING
#endif
// by default, enable bounding walls in debug mode (unless we have specifically disabled them)
#ifndef DISABLE_MEMORYPOOL_BOUNDINGWALL
#define MEMORYPOOL_BOUNDINGWALL
#endif
#define DECLARE_LITERALSTRING_ARG1 const char * debugLiteralTagString
#define PASS_LITERALSTRING_ARG1 debugLiteralTagString
#define DECLARE_LITERALSTRING_ARG2 , const char * debugLiteralTagString
#define PASS_LITERALSTRING_ARG2 , debugLiteralTagString
#define MP_LOC_SUFFIX /*" [" DEBUG_FILENLINE "]"*/
#define allocateBlock(ARGLITERAL) allocateBlockImplementation(ARGLITERAL MP_LOC_SUFFIX)
#define allocateBlockDoNotZero(ARGLITERAL) allocateBlockDoNotZeroImplementation(ARGLITERAL MP_LOC_SUFFIX)
#define allocateBytes(ARGCOUNT,ARGLITERAL) allocateBytesImplementation(ARGCOUNT, ARGLITERAL MP_LOC_SUFFIX)
#define allocateBytesDoNotZero(ARGCOUNT,ARGLITERAL) allocateBytesDoNotZeroImplementation(ARGCOUNT, ARGLITERAL MP_LOC_SUFFIX)
#define newInstanceDesc(ARGCLASS,ARGLITERAL) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED, ARGLITERAL MP_LOC_SUFFIX) ARGCLASS
#define newInstance(ARGCLASS) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED, __FILE__) ARGCLASS
#if !defined(MEMORYPOOL_STACKTRACE) && !defined(DISABLE_MEMORYPOOL_STACKTRACE)
#define MEMORYPOOL_STACKTRACE
#endif
// flags for the memory-report options.
enum
{
#ifdef MEMORYPOOL_CHECKPOINTING
// ------------------------------------------------------
// you usually won't use the _REPORT bits directly; see below for more convenient combinations.
// you must set at least one of the 'allocate' bits.
_REPORT_CP_ALLOCATED_BEFORE = 0x0001,
_REPORT_CP_ALLOCATED_BETWEEN = 0x0002,
_REPORT_CP_ALLOCATED_DONTCARE = (_REPORT_CP_ALLOCATED_BEFORE|_REPORT_CP_ALLOCATED_BETWEEN),
// you must set at least one of the 'freed' bits.
_REPORT_CP_FREED_BEFORE = 0x0010,
_REPORT_CP_FREED_BETWEEN = 0x0020,
_REPORT_CP_FREED_NEVER = 0x0040, // ie, still in existence
_REPORT_CP_FREED_DONTCARE = (_REPORT_CP_FREED_BEFORE|_REPORT_CP_FREED_BETWEEN|_REPORT_CP_FREED_NEVER),
// ------------------------------------------------------
#endif // MEMORYPOOL_CHECKPOINTING
#ifdef MEMORYPOOL_STACKTRACE
/** display the stacktrace for allocation location for all blocks found.
this bit may be mixed-n-matched with any other flag.
*/
REPORT_CP_STACKTRACE = 0x0100,
#endif
/** display stats for each pool, in addition to each block.
(this is useful for finding suitable allocation counts for the pools.)
this bit may be mixed-n-matched with any other flag.
*/
REPORT_POOLINFO = 0x0200,
/** report on the overall memory situation (including all pools and dma's).
this bit may be mixed-n-matched with any other flag.
*/
REPORT_FACTORYINFO = 0x0400,
/** report on pools that have overflowed their initial allocation.
this bit may be mixed-n-matched with any other flag.
*/
REPORT_POOL_OVERFLOW = 0x0800,
/** simple-n-cheap leak checking */
REPORT_SIMPLE_LEAKS = 0x1000,
#ifdef MEMORYPOOL_CHECKPOINTING
/** report on blocks that were allocated between the checkpoints.
(don't care if they were freed or not.)
*/
REPORT_CP_ALLOCATES = (_REPORT_CP_ALLOCATED_BETWEEN | _REPORT_CP_FREED_DONTCARE),
/** report on blocks that were freed between the checkpoints.
(don't care when they were allocated.)
*/
REPORT_CP_FREES = (_REPORT_CP_ALLOCATED_DONTCARE | _REPORT_CP_FREED_BETWEEN),
/** report on blocks that were allocated between the checkpoints, and still exist
(note that this reports *potential* leaks -- some such blocks may be desired)
*/
REPORT_CP_LEAKS = (_REPORT_CP_ALLOCATED_BETWEEN | _REPORT_CP_FREED_NEVER),
/** report on blocks that existed before checkpoint #1 and still exist now.
*/
REPORT_CP_LONGTERM = (_REPORT_CP_ALLOCATED_BEFORE | _REPORT_CP_FREED_NEVER),
/** report on blocks that were allocated-and-freed between the checkpoints.
*/
REPORT_CP_TRANSIENT = (_REPORT_CP_ALLOCATED_BETWEEN | _REPORT_CP_FREED_BETWEEN),
/** report on all blocks that currently exist
*/
REPORT_CP_EXISTING = (_REPORT_CP_ALLOCATED_BEFORE | _REPORT_CP_ALLOCATED_BETWEEN | _REPORT_CP_FREED_NEVER),
/** report on all blocks that have ever existed (!) (or at least, since the last call
to debugResetCheckpoints)
*/
REPORT_CP_ALL = (_REPORT_CP_ALLOCATED_DONTCARE | _REPORT_CP_FREED_DONTCARE)
#endif // MEMORYPOOL_CHECKPOINTING
};
#else
#define DECLARE_LITERALSTRING_ARG1
#define PASS_LITERALSTRING_ARG1
#define DECLARE_LITERALSTRING_ARG2
#define PASS_LITERALSTRING_ARG2
#define allocateBlock(ARGLITERAL) allocateBlockImplementation()
#define allocateBlockDoNotZero(ARGLITERAL) allocateBlockDoNotZeroImplementation()
#define allocateBytes(ARGCOUNT,ARGLITERAL) allocateBytesImplementation(ARGCOUNT)
#define allocateBytesDoNotZero(ARGCOUNT,ARGLITERAL) allocateBytesDoNotZeroImplementation(ARGCOUNT)
#define newInstanceDesc(ARGCLASS,ARGLITERAL) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED) ARGCLASS
#define newInstance(ARGCLASS) new(ARGCLASS::ARGCLASS##_GLUE_NOT_IMPLEMENTED) ARGCLASS
#endif
// FORWARD REFERENCES /////////////////////////////////////////////////////////
class MemoryPoolSingleBlock;
class MemoryPoolBlob;
class MemoryPool;
class MemoryPoolFactory;
class DynamicMemoryAllocator;
class BlockCheckpointInfo;
// TYPE DEFINES ///////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
/**
This class is purely a convenience used to pass optional arguments to initMemoryManager(),
and by extension, to createDynamicMemoryAllocator(). You can specify how many sub-pools you
want, what size each is, what the allocation counts are to be, etc. Most apps will
construct an array of these to pass to initMemoryManager() and never use it elsewhere.
*/
struct PoolInitRec
{
const char *poolName; ///< name of the pool; by convention, "dmaPool_XXX" where XXX is allocationSize
Int allocationSize; ///< size, in bytes, of the pool.
Int initialAllocationCount; ///< initial number of blocks to allocate.
Int overflowAllocationCount; ///< when the pool runs out of space, allocate more blocks in this increment
};
enum
{
MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS = 8 ///< The max number of subpools allowed in a DynamicMemoryAllocator
};
#ifdef MEMORYPOOL_CHECKPOINTING
// ----------------------------------------------------------------------------
/**
This class exists purely for coding convenience, and should never be used by external code.
It simply allows MemoryPool and DynamicMemoryAllocator to share checkpoint-related
code in a seamless way.
*/
class Checkpointable
{
private:
BlockCheckpointInfo *m_firstCheckpointInfo; ///< head of the linked list of checkpoint infos for this pool/dma
Bool m_cpiEverFailed; ///< flag to detect if we ran out of memory accumulating checkpoint info.
protected:
Checkpointable();
~Checkpointable();
/// create a new checkpoint info and add it to the list.
BlockCheckpointInfo *debugAddCheckpointInfo(
const char *debugLiteralTagString,
Int allocCheckpoint,
Int blockSize
);
public:
/// dump a checkpoint report to logfile
void debugCheckpointReport(Int flags, Int startCheckpoint, Int endCheckpoint, const char *poolName);
/// reset all the checkpoints for this pool/dma
void debugResetCheckpoints();
};
#endif
// ----------------------------------------------------------------------------
/**
A MemoryPool provides a way to efficiently allocate objects of the same (or similar)
size. We allocate large a large chunk of memory (a "blob") and subdivide it into
even-size chunks, doling these out as needed. If the first blob gets full, we allocate
additional blobs as necessary. A given pool can allocate blocks of only one size;
if you need a different size, you should use a different pool.
*/
class MemoryPool
#ifdef MEMORYPOOL_CHECKPOINTING
: public Checkpointable
#endif
{
private:
MemoryPoolFactory *m_factory; ///< the factory that created us
MemoryPool *m_nextPoolInFactory; ///< linked list node, managed by factory
const char *m_poolName; ///< name of this pool. (literal string; must not be freed)
Int m_allocationSize; ///< size of the blocks allocated by this pool, in bytes
Int m_initialAllocationCount; ///< number of blocks to be allocated in initial blob
Int m_overflowAllocationCount; ///< number of blocks to be allocated in any subsequent blob(s)
Int m_usedBlocksInPool; ///< total number of blocks in use in the pool.
Int m_totalBlocksInPool; ///< total number of blocks in all blobs of this pool (used or not).
Int m_peakUsedBlocksInPool; ///< high-water mark of m_usedBlocksInPool
MemoryPoolBlob *m_firstBlob; ///< head of linked list: first blob for this pool.
MemoryPoolBlob *m_lastBlob; ///< tail of linked list: last blob for this pool. (needed for efficiency)
MemoryPoolBlob *m_firstBlobWithFreeBlocks; ///< first blob in this pool that has at least one unallocated block.
private:
/// create a new blob with the given number of blocks.
MemoryPoolBlob* createBlob(Int allocationCount);
/// destroy a blob.
Int freeBlob(MemoryPoolBlob *blob);
public:
// 'public' funcs that are really only for use by MemoryPoolFactory
MemoryPool *getNextPoolInList(); ///< return next pool in linked list
void addToList(MemoryPool **pHead); ///< add this pool to head of the linked list
void removeFromList(MemoryPool **pHead); ///< remove this pool from the linked list
#ifdef MEMORYPOOL_DEBUG
static void debugPoolInfoReport( MemoryPool *pool, FILE *fp = NULL ); ///< dump a report about this pool to the logfile
const char *debugGetBlockTagString(void *pBlock); ///< return the tagstring for the given block (assumed to belong to this pool)
void debugMemoryVerifyPool(); ///< perform internal consistency check on this pool.
Int debugPoolReportLeaks( const char* owner );
#endif
#ifdef MEMORYPOOL_CHECKPOINTING
void debugResetCheckpoints(); ///< throw away all checkpoint information for this pool.
#endif
public:
MemoryPool();
/// initialize the given memory pool.
void init(MemoryPoolFactory *factory, const char *poolName, Int allocationSize, Int initialAllocationCount, Int overflowAllocationCount);
~MemoryPool();
/// allocate a block from this pool. (don't call directly; use allocateBlock() macro)
void *allocateBlockImplementation(DECLARE_LITERALSTRING_ARG1);
/// same as allocateBlockImplementation, but memory returned is not zeroed
void *allocateBlockDoNotZeroImplementation(DECLARE_LITERALSTRING_ARG1);
/// free the block. it is OK to pass null.
void freeBlock(void *pMem);
/// return the factory that created (and thus owns) this pool.
MemoryPoolFactory *getOwningFactory();
/// return the name of this pool. the result is a literal string and must not be freed.
const char *getPoolName();
/// return the block allocation size of this pool.
Int getAllocationSize();
/// return the number of free (available) blocks in this pool.
Int getFreeBlockCount();
/// return the number of blocks in use in this pool.
Int getUsedBlockCount();
/// return the total number of blocks in this pool. [ == getFreeBlockCount() + getUsedBlockCount() ]
Int getTotalBlockCount();
/// return the high-water mark for getUsedBlockCount()
Int getPeakBlockCount();
/// return the initial allocation count for this pool
Int getInitialBlockCount();
Int countBlobsInPool();
/// if this pool has any empty blobs, return them to the system.
Int releaseEmpties();
/// destroy all blocks and blobs in this pool.
void reset();
#ifdef MEMORYPOOL_DEBUG
/// return true iff this block was allocated by this pool.
Bool debugIsBlockInPool(void *pBlock);
#endif
};
// ----------------------------------------------------------------------------
/**
The DynamicMemoryAllocator class is used to handle unpredictably-sized
allocation requests. It basically allocates a number of (private) MemoryPools,
then routes request to the smallest-size pool that will satisfy the request.
(Requests too large for any of the pool are routed to the system memory allocator.)
You should normally use this in place of malloc/free or (global) new/delete.
*/
class DynamicMemoryAllocator
#ifdef MEMORYPOOL_CHECKPOINTING
: public Checkpointable
#endif
{
private:
MemoryPoolFactory *m_factory; ///< the factory that created us
DynamicMemoryAllocator *m_nextDmaInFactory; ///< linked list node, managed by factory
Int m_numPools; ///< number of subpools (up to MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS)
Int m_usedBlocksInDma; ///< total number of blocks allocated, from subpools and "raw"
MemoryPool *m_pools[MAX_DYNAMICMEMORYALLOCATOR_SUBPOOLS]; ///< the subpools
MemoryPoolSingleBlock *m_rawBlocks; ///< linked list of "raw" blocks allocated directly from system
/// return the best pool for the given allocSize, or null if none are suitable
MemoryPool *findPoolForSize(Int allocSize);
public:
// 'public' funcs that are really only for use by MemoryPoolFactory
DynamicMemoryAllocator *getNextDmaInList(); ///< return next dma in linked list
void addToList(DynamicMemoryAllocator **pHead); ///< add this dma to the list
void removeFromList(DynamicMemoryAllocator **pHead); ///< remove this dma from the list
#ifdef MEMORYPOOL_DEBUG
Int debugCalcRawBlockBytes(Int *numBlocks); ///< calculate the number of bytes in "raw" (non-subpool) blocks
void debugMemoryVerifyDma(); ///< perform internal consistency check
const char *debugGetBlockTagString(void *pBlock); ///< return the tagstring for the given block (assumed to belong to this dma)
void debugDmaInfoReport( FILE *fp = NULL ); ///< dump a report about this pool to the logfile
Int debugDmaReportLeaks();
#endif
#ifdef MEMORYPOOL_CHECKPOINTING
void debugResetCheckpoints(); ///< toss all checkpoint information
#endif
public:
DynamicMemoryAllocator();
/// initialize the dma. pass 0/null for numSubPool/parms to get some reasonable default subpools.
void init(MemoryPoolFactory *factory, Int numSubPools, const PoolInitRec pParms[]);
~DynamicMemoryAllocator();
/// allocate bytes from this pool. (don't call directly; use allocateBytes() macro)
void *allocateBytesImplementation(Int numBytes DECLARE_LITERALSTRING_ARG2);
/// like allocateBytesImplementation, but zeroes the memory before returning
void *allocateBytesDoNotZeroImplementation(Int numBytes DECLARE_LITERALSTRING_ARG2);
#ifdef MEMORYPOOL_DEBUG
void debugIgnoreLeaksForThisBlock(void* pBlockPtr);
#endif
/// free the bytes. (assumes allocated by this dma.)
void freeBytes(void* pMem);
/**
return the actual number of bytes that would be allocated
if you tried to allocate the given size. (It will generally be slightly
larger than you request.) This lets you use extra space if you're gonna get it anyway...
The idea is that you will call this before doing a memory allocation, to see if
you got any extra "bonus" space.
*/
Int getActualAllocationSize(Int numBytes);
/// destroy all allocations performed by this DMA.
void reset();
Int getDmaMemoryPoolCount() const { return m_numPools; }
MemoryPool* getNthDmaMemoryPool(Int i) const { return m_pools[i]; }
#ifdef MEMORYPOOL_DEBUG
/// return true iff this block was allocated by this dma
Bool debugIsBlockInDma(void *pBlock);
/// return true iff the pool is a subpool of this dma
Bool debugIsPoolInDma(MemoryPool *pool);
#endif // MEMORYPOOL_DEBUG
};
// ----------------------------------------------------------------------------
#ifdef MEMORYPOOL_DEBUG
enum { MAX_SPECIAL_USED = 256 };
#endif
// ----------------------------------------------------------------------------
/**
The class that manages all the MemoryPools and DynamicMemoryAllocators.
Usually you will create exactly one of these (TheMemoryPoolFactory)
and use it for everything.
*/
class MemoryPoolFactory
{
private:
MemoryPool *m_firstPoolInFactory; ///< linked list of pools
DynamicMemoryAllocator *m_firstDmaInFactory; ///< linked list of dmas
#ifdef MEMORYPOOL_CHECKPOINTING
Int m_curCheckpoint; ///< most recent checkpoint value
#endif
#ifdef MEMORYPOOL_DEBUG
Int m_usedBytes; ///< total bytes in use
Int m_physBytes; ///< total bytes allocated to all pools (includes unused blocks)
Int m_peakUsedBytes; ///< high-water mark of m_usedBytes
Int m_peakPhysBytes; ///< high-water mark of m_physBytes
Int m_usedBytesSpecial[MAX_SPECIAL_USED];
Int m_usedBytesSpecialPeak[MAX_SPECIAL_USED];
Int m_physBytesSpecial[MAX_SPECIAL_USED];
Int m_physBytesSpecialPeak[MAX_SPECIAL_USED];
#endif
public:
// 'public' funcs that are really only for use by MemoryPool and friends
#ifdef MEMORYPOOL_DEBUG
/// adjust the usedBytes and physBytes variables by the given amoun ts.
void adjustTotals(const char* tagString, Int usedDelta, Int physDelta);
#endif
#ifdef MEMORYPOOL_CHECKPOINTING
/// return the current checkpoint value.
Int getCurCheckpoint() { return m_curCheckpoint; }
#endif
public:
MemoryPoolFactory();
void init();
~MemoryPoolFactory();
/// create a new memory pool with the given settings. if a pool with the given name already exists, return it.
MemoryPool *createMemoryPool(const PoolInitRec *parms);
/// overloaded version of createMemoryPool with explicit parms.
MemoryPool *createMemoryPool(const char *poolName, Int allocationSize, Int initialAllocationCount, Int overflowAllocationCount);
/// return the pool with the given name. if no such pool exists, return null.
MemoryPool *findMemoryPool(const char *poolName);
/// destroy the given pool.
void destroyMemoryPool(MemoryPool *pMemoryPool);
/// create a DynamicMemoryAllocator with subpools with the given parms.
DynamicMemoryAllocator *createDynamicMemoryAllocator(Int numSubPools, const PoolInitRec pParms[]);
/// destroy the given DynamicMemoryAllocator.
void destroyDynamicMemoryAllocator(DynamicMemoryAllocator *dma);
/// destroy the contents of all pools and dmas. (the pools and dma's are not destroyed, just reset)
void reset();
void memoryPoolUsageReport( const char* filename, FILE *appendToFileInstead = NULL );
#ifdef MEMORYPOOL_DEBUG
/// perform internal consistency checking
void debugMemoryVerify();
/// return true iff the block was allocated by any pool or dma owned by this factory.
Bool debugIsBlockInAnyPool(void *pBlock);
/// return the tag string for the block.
const char *debugGetBlockTagString(void *pBlock);
/// dump a report with the given options to the logfile.
void debugMemoryReport(Int flags, Int startCheckpoint, Int endCheckpoint, FILE *fp = NULL );
void debugSetInitFillerIndex(Int index);
#endif
#ifdef MEMORYPOOL_CHECKPOINTING
/// set a new checkpoint.
Int debugSetCheckpoint();
/// reset all checkpoint information.
void debugResetCheckpoints();
#endif
};
// how many bytes are we allowed to 'waste' per pool allocation before the debug code starts yelling at us...
#define MEMORY_POOL_OBJECT_ALLOCATION_SLOP 16
// ----------------------------------------------------------------------------
#define GCMP_FIND(ARGCLASS, ARGPOOLNAME) \
private: \
static MemoryPool *getClassMemoryPool() \
{ \
/* \
Note that this static variable will be initialized exactly once: the first time \
control flows over this section of code. This allows us to neatly resolve the \
order-of-execution problem for static variables, ensuring this is not executed \
prior to the initialization of TheMemoryPoolFactory. \
*/ \
DEBUG_ASSERTCRASH(TheMemoryPoolFactory, ("TheMemoryPoolFactory is NULL\n")); \
static MemoryPool *The##ARGCLASS##Pool = TheMemoryPoolFactory->findMemoryPool(ARGPOOLNAME); \
DEBUG_ASSERTCRASH(The##ARGCLASS##Pool, ("Pool \"%s\" not found (did you set it up in initMemoryPools?)\n", ARGPOOLNAME)); \
DEBUG_ASSERTCRASH(The##ARGCLASS##Pool->getAllocationSize() >= sizeof(ARGCLASS), ("Pool \"%s\" is too small for this class (currently %d, need %d)\n", ARGPOOLNAME, The##ARGCLASS##Pool->getAllocationSize(), sizeof(ARGCLASS))); \
DEBUG_ASSERTCRASH(The##ARGCLASS##Pool->getAllocationSize() <= sizeof(ARGCLASS)+MEMORY_POOL_OBJECT_ALLOCATION_SLOP, ("Pool \"%s\" is too large for this class (currently %d, need %d)\n", ARGPOOLNAME, The##ARGCLASS##Pool->getAllocationSize(), sizeof(ARGCLASS))); \
return The##ARGCLASS##Pool; \
}
// ----------------------------------------------------------------------------
#define GCMP_CREATE(ARGCLASS, ARGPOOLNAME, ARGINITIAL, ARGOVERFLOW) \
private: \
static MemoryPool *getClassMemoryPool() \
{ \
/* \
Note that this static variable will be initialized exactly once: the first time \
control flows over this section of code. This allows us to neatly resolve the \
order-of-execution problem for static variables, ensuring this is not executed \
prior to the initialization of TheMemoryPoolFactory. \
*/ \
DEBUG_ASSERTCRASH(TheMemoryPoolFactory, ("TheMemoryPoolFactory is NULL\n")); \
static MemoryPool *The##ARGCLASS##Pool = TheMemoryPoolFactory->createMemoryPool(ARGPOOLNAME, sizeof(ARGCLASS), ARGINITIAL, ARGOVERFLOW); \
DEBUG_ASSERTCRASH(The##ARGCLASS##Pool, ("Pool \"%s\" not found (did you set it up in initMemoryPools?)\n", ARGPOOLNAME)); \
DEBUG_ASSERTCRASH(The##ARGCLASS##Pool->getAllocationSize() >= sizeof(ARGCLASS), ("Pool \"%s\" is too small for this class (currently %d, need %d)\n", ARGPOOLNAME, The##ARGCLASS##Pool->getAllocationSize(), sizeof(ARGCLASS))); \
DEBUG_ASSERTCRASH(The##ARGCLASS##Pool->getAllocationSize() <= sizeof(ARGCLASS)+MEMORY_POOL_OBJECT_ALLOCATION_SLOP, ("Pool \"%s\" is too large for this class (currently %d, need %d)\n", ARGPOOLNAME, The##ARGCLASS##Pool->getAllocationSize(), sizeof(ARGCLASS))); \
return The##ARGCLASS##Pool; \
}
// ----------------------------------------------------------------------------
#define MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \
protected: \
virtual ~ARGCLASS(); \
public: \
enum ARGCLASS##MagicEnum { ARGCLASS##_GLUE_NOT_IMPLEMENTED = 0 }; \
public: \
inline void *operator new(size_t s, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \
{ \
DEBUG_ASSERTCRASH(s == sizeof(ARGCLASS), ("The wrong operator new is being called; ensure all objects in the hierarchy have MemoryPoolGlue set up correctly")); \
return ARGCLASS::getClassMemoryPool()->allocateBlockImplementation(PASS_LITERALSTRING_ARG1); \
} \
public: \
/* \
Note that this delete operator can't be called directly; it is called \
only if the analogous new operator is called, AND the constructor \
throws an exception... \
*/ \
inline void operator delete(void *p, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \
{ \
ARGCLASS::getClassMemoryPool()->freeBlock(p); \
} \
protected: \
/* \
Make normal new and delete protected, so they can't be called by the outside world. \
Note that delete is funny, in that it can still be called by the class itself; \
this is safe but not recommended, for consistency purposes. More problematically, \
it can be called by another class that has declared itself 'friend' to us. \
In theory, this shouldn't work, since it may not use the right operator-delete, \
and thus the wrong memory pool; in practice, it seems the right delete IS called \
in MSVC -- it seems to make operator delete virtual if the destructor is also virtual. \
At any rate, this is undocumented behavior as far as I can tell, so we put a big old \
crash into operator delete telling people to do the right thing and call deleteInstance \
instead -- it'd be nice if we could catch this at compile time, but catching it at \
runtime seems to be the best we can do... \
*/ \
inline void *operator new(size_t s) \
{ \
DEBUG_CRASH(("This operator new should normally never be called... please use new(char*) instead.")); \
DEBUG_ASSERTCRASH(s == sizeof(ARGCLASS), ("The wrong operator new is being called; ensure all objects in the hierarchy have MemoryPoolGlue set up correctly")); \
throw ERROR_BUG; \
return 0; \
} \
inline void operator delete(void *p) \
{ \
DEBUG_CRASH(("Please call deleteInstance instead of delete.")); \
ARGCLASS::getClassMemoryPool()->freeBlock(p); \
} \
private: \
virtual MemoryPool *getObjectMemoryPool() \
{ \
return ARGCLASS::getClassMemoryPool(); \
} \
public: /* include this line at the end to reset visibility to 'public' */
// ----------------------------------------------------------------------------
#define MEMORY_POOL_GLUE(ARGCLASS, ARGPOOLNAME) \
MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \
GCMP_FIND(ARGCLASS, ARGPOOLNAME)
// ----------------------------------------------------------------------------
#define MEMORY_POOL_GLUE_WITH_EXPLICIT_CREATE(ARGCLASS, ARGPOOLNAME, ARGINITIAL, ARGOVERFLOW) \
MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \
GCMP_CREATE(ARGCLASS, ARGPOOLNAME, ARGINITIAL, ARGOVERFLOW)
// ----------------------------------------------------------------------------
#define MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ARGCLASS, ARGPOOLNAME) \
MEMORY_POOL_GLUE_WITHOUT_GCMP(ARGCLASS) \
GCMP_CREATE(ARGCLASS, ARGPOOLNAME, -1, -1)
// ----------------------------------------------------------------------------
// this is the version for an Abstract Base Class, which will never be instantiated...
#define MEMORY_POOL_GLUE_ABC(ARGCLASS) \
protected: \
virtual ~ARGCLASS(); \
public: \
enum ARGCLASS##MagicEnum { ARGCLASS##_GLUE_NOT_IMPLEMENTED = 0 }; \
protected: \
inline void *operator new(size_t s, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \
{ \
DEBUG_CRASH(("this should be impossible to call (abstract base class)")); \
DEBUG_ASSERTCRASH(s == sizeof(ARGCLASS), ("The wrong operator new is being called; ensure all objects in the hierarchy have MemoryPoolGlue set up correctly")); \
throw ERROR_BUG; \
return 0; \
} \
protected: \
inline void operator delete(void *p, ARGCLASS##MagicEnum e DECLARE_LITERALSTRING_ARG2) \
{ \
DEBUG_CRASH(("this should be impossible to call (abstract base class)")); \
} \
protected: \
inline void *operator new(size_t s) \
{ \
DEBUG_CRASH(("this should be impossible to call (abstract base class)")); \
DEBUG_ASSERTCRASH(s == sizeof(ARGCLASS), ("The wrong operator new is being called; ensure all objects in the hierarchy have MemoryPoolGlue set up correctly")); \
throw ERROR_BUG; \
return 0; \
} \
inline void operator delete(void *p) \
{ \
DEBUG_CRASH(("this should be impossible to call (abstract base class)")); \
} \
private: \
virtual MemoryPool *getObjectMemoryPool() \
{ \
throw ERROR_BUG; \
return 0; \
} \
public: /* include this line at the end to reset visibility to 'public' */
// ----------------------------------------------------------------------------
/**
Sometimes you want to make a class's destructor protected so that it can only
be destroyed under special circumstances. MemoryPoolObject short-circuits this
by making the destructor always be protected, and the true delete technique
(namely, deleteInstance) always public by default. You can simulate the behavior
you really want by including this macro
*/
#define MEMORY_POOL_DELETEINSTANCE_VISIBILITY(ARGVIS)\
ARGVIS: void deleteInstance() { MemoryPoolObject::deleteInstance(); } public:
// ----------------------------------------------------------------------------
/**
This class is provided as a simple and safe way to integrate C++ object allocation
into MemoryPool usage. To use it, you must have your class inherit from
MemoryPoolObject, then put the macro MEMORY_POOL_GLUE(MyClassName, "MyPoolName")
at the start of your class definition. (This does not create the pool itself -- you
must create that manually using MemoryPoolFactory::createMemoryPool)
*/
class MemoryPoolObject
{
protected:
/** ensure that all destructors are virtual */
virtual ~MemoryPoolObject() { }
protected:
inline void *operator new(size_t s) { DEBUG_CRASH(("This should be impossible")); return 0; }
inline void operator delete(void *p) { DEBUG_CRASH(("This should be impossible")); }
protected:
virtual MemoryPool *getObjectMemoryPool() = 0;
public:
void deleteInstance()
{
if (this)
{
MemoryPool *pool = this->getObjectMemoryPool(); // save this, since the dtor will nuke our vtbl
this->~MemoryPoolObject(); // it's virtual, so the right one will be called.
pool->freeBlock((void *)this);
}
}
};
// ----------------------------------------------------------------------------
/**
A simple utility class to ensure exception safety; this holds a MemoryPoolObject
and deletes it in its destructor. Especially useful for iterators!
*/
class MemoryPoolObjectHolder
{
private:
MemoryPoolObject *m_mpo;
public:
MemoryPoolObjectHolder(MemoryPoolObject *mpo = NULL) : m_mpo(mpo) { }
void hold(MemoryPoolObject *mpo) { DEBUG_ASSERTCRASH(!m_mpo, ("already holding")); m_mpo = mpo; }
void release() { m_mpo = NULL; }
~MemoryPoolObjectHolder() { m_mpo->deleteInstance(); }
};
// INLINING ///////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
inline MemoryPoolFactory *MemoryPool::getOwningFactory() { return m_factory; }
inline MemoryPool *MemoryPool::getNextPoolInList() { return m_nextPoolInFactory; }
inline const char *MemoryPool::getPoolName() { return m_poolName; }
inline Int MemoryPool::getAllocationSize() { return m_allocationSize; }
inline Int MemoryPool::getFreeBlockCount() { return getTotalBlockCount() - getUsedBlockCount(); }
inline Int MemoryPool::getUsedBlockCount() { return m_usedBlocksInPool; }
inline Int MemoryPool::getTotalBlockCount() { return m_totalBlocksInPool; }
inline Int MemoryPool::getPeakBlockCount() { return m_peakUsedBlocksInPool; }
inline Int MemoryPool::getInitialBlockCount() { return m_initialAllocationCount; }
// ----------------------------------------------------------------------------
inline DynamicMemoryAllocator *DynamicMemoryAllocator::getNextDmaInList() { return m_nextDmaInFactory; }
// EXTERNALS //////////////////////////////////////////////////////////////////
/**
Initialize the memory manager. Construct a new MemoryPoolFactory and
DynamicMemoryAllocator and store 'em in the singletons of the relevant
names.
*/
extern void initMemoryManager();
/**
return true if initMemoryManager() has been called.
return false if only preMainInitMemoryManager() has been called.
*/
extern Bool isMemoryManagerOfficiallyInited();
/**
similar to initMemoryManager, but this should be used if the memory manager must be initialized
prior to main() (e.g., from a static constructor). If preMainInitMemoryManager() is called prior
to initMemoryManager(), then subsequent calls to either are quietly ignored, AS IS any subsequent
call to shutdownMemoryManager() [since there's no safe way to ensure that shutdownMemoryManager
will execute after all static destructors].
(Note: this function is actually not externally visible, but is documented here for clarity.)
*/
/* extern void preMainInitMemoryManager(); */
/**
Shut down the memory manager. Throw away TheMemoryPoolFactory and
TheDynamicMemoryAllocator.
*/
extern void shutdownMemoryManager();
extern MemoryPoolFactory *TheMemoryPoolFactory;
extern DynamicMemoryAllocator *TheDynamicMemoryAllocator;
/**
This function is declared in this header, but is not defined anywhere -- you must provide
it in your code. It is called by initMemoryManager() or preMainInitMemoryManager() in order
to get the specifics of the subpool for the dynamic memory allocator. (If you just want
some defaults, set both return arguments to zero.) The reason for this odd setup is that
we may need to init the memory manager prior to main() [due to static C++ ctors] and
this allows us a way to get the necessary parameters.
*/
extern void userMemoryManagerGetDmaParms(Int *numSubPools, const PoolInitRec **pParms);
/**
This function is declared in this header, but is not defined anywhere -- you must provide
it in your code. It is called by initMemoryManager() or preMainInitMemoryManager() in order
to initialize the pools to be used. (You can define an empty function if you like.)
*/
extern void userMemoryManagerInitPools();
/**
This function is declared in this header, but is not defined anywhere -- you must provide
it in your code. It is called by createMemoryPool to adjust the allocation size(s) for a
given pool. Note that the counts are in-out parms!
*/
extern void userMemoryAdjustPoolSize(const char *poolName, Int& initialAllocationCount, Int& overflowAllocationCount);
#ifdef __cplusplus
#ifndef _OPERATOR_NEW_DEFINED_
#define _OPERATOR_NEW_DEFINED_
extern void * __cdecl operator new (size_t size);
extern void __cdecl operator delete (void *p);
extern void * __cdecl operator new[] (size_t size);
extern void __cdecl operator delete[] (void *p);
// additional overloads to account for VC/MFC funky versions
extern void* __cdecl operator new(size_t nSize, const char *, int);
extern void __cdecl operator delete(void *, const char *, int);
extern void* __cdecl operator new[](size_t nSize, const char *, int);
extern void __cdecl operator delete[](void *, const char *, int);
// additional overloads for 'placement new'
//inline void* __cdecl operator new (size_t s, void *p) { return p; }
//inline void __cdecl operator delete (void *, void *p) { }
inline void* __cdecl operator new[] (size_t s, void *p) { return p; }
inline void __cdecl operator delete[] (void *, void *p) { }
#endif
#ifdef MEMORYPOOL_DEBUG_CUSTOM_NEW
#define MSGNEW(MSG) new(MSG, 0)
#define NEW new(__FILE__, __LINE__)
#else
#define MSGNEW(MSG) new
#define NEW new
#endif
#endif
class STLSpecialAlloc
{
public:
static void* allocate(size_t __n);
static void deallocate(void* __p, size_t);
};
#define EMPTY_DTOR(CLASS) inline CLASS::~CLASS() { }
#endif // _GAME_MEMORY_H_

View File

@ -0,0 +1,118 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: RTS 3
//
// File name: Common/GameMusic.h
//
// Created: 5/01/01
//
//----------------------------------------------------------------------------
#pragma once
#ifndef __COMMON_GAMEMUSIC_H_
#define __COMMON_GAMEMUSIC_H_
//----------------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------------
#include "Common/GameAudio.h"
#include "Common/GameMemory.h"
//----------------------------------------------------------------------------
// Forward References
//----------------------------------------------------------------------------
class AudioEventRTS;
struct FieldParse;
//----------------------------------------------------------------------------
// Type Defines
//----------------------------------------------------------------------------
//===============================
// MusicTrack
//===============================
//-------------------------------------------------------------------------------------------------
/** The MusicTrack struct holds all information about a music track.
* Place data in TrackInfo that is useful to the game code in determining
* what tracks to play. */
//-------------------------------------------------------------------------------------------------
class MusicTrack : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( MusicTrack, "MusicTrack" )
public:
MusicTrack();
// virtual destructor prototype defined by memory pool object
const FieldParse *getFieldParse( void ) const { return m_musicTrackFieldParseTable; }
Int index; ///< Track index
AsciiString name; ///< Logical name of track
AsciiString filename; ///< Filename with extension of music track
Real volume; ///< Mixing level for this track
Bool ambient; ///< Game info about this track(public)
MusicTrack *next;
MusicTrack *prev;
static const FieldParse m_musicTrackFieldParseTable[]; ///< the parse table for INI definition
};
class MusicManager
{
public:
MusicManager();
virtual ~MusicManager();
void playTrack( AudioEventRTS *eventToUse );
void stopTrack( AudioHandle eventToRemove );
virtual void addAudioEvent(AudioEventRTS *eventToAdd); // pre-copied
virtual void removeAudioEvent( AudioHandle eventToRemove );
void setVolume( Real m_volume );
};
#endif // __COMMON_GAMEMUSIC_H_

View File

@ -0,0 +1,103 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: RTS 3
//
// File name: Common/GameSounds.h
//
// Created: 5/02/01
//
//----------------------------------------------------------------------------
#pragma once
#ifndef __COMMON_GAMESOUNDS_H_
#define __COMMON_GAMESOUNDS_H_
#include "Common/SubsystemInterface.h"
#include "Common/GameAudio.h"
#include "Common/GameType.h"
// Forward declarations
class AudioEventRTS;
class SoundManager : public SubsystemInterface
{
public:
SoundManager();
virtual ~SoundManager();
virtual void init( void ); ///< Initializes the sounds system
virtual void postProcessLoad();
virtual void update( void ); ///< Services sounds tasks. Called by AudioInterface
virtual void reset( void ); ///< Reset the sounds system
virtual void loseFocus( void ); ///< Called when application loses focus
virtual void regainFocus( void ); ///< Called when application regains focus
virtual void setListenerPosition( const Coord3D *position ); ///< Set the listener position for map3DSound() calculations
virtual void setViewRadius( Real viewRadius );///< Sets the radius of the view from the center of the screen in world coordinate units
virtual void setCameraAudibleDistance( Real audibleDistance );
virtual Real getCameraAudibleDistance( void );
virtual void addAudioEvent(AudioEventRTS *eventToAdd); // pre-copied
virtual void notifyOf2DSampleStart( void );
virtual void notifyOf3DSampleStart( void );
virtual void notifyOf2DSampleCompletion( void );
virtual void notifyOf3DSampleCompletion( void );
virtual Int getAvailableSamples( void );
virtual Int getAvailable3DSamples( void );
// empty string means that this sound wasn't found or some error occurred. CHECK FOR EMPTY STRING.
virtual AsciiString getFilenameForPlayFromAudioEvent( const AudioEventRTS *eventToGetFrom );
// called by this class and MilesAudioManager to determine if a sound can still be played
virtual Bool canPlayNow( AudioEventRTS *event );
protected:
virtual Bool violatesVoice( AudioEventRTS *event );
virtual Bool isInterrupting( AudioEventRTS *event );
protected:
UnsignedInt m_num2DSamples;
UnsignedInt m_num3DSamples;
UnsignedInt m_numPlaying2DSamples;
UnsignedInt m_numPlaying3DSamples;
};
#endif // __COMMON_GAMESOUNDS_H_

View File

@ -0,0 +1,24 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,61 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// FILE: GameSpyMiscPreferences.h
// Author: Matthew D. Campbell, December 2002
// Description: Saving/Loading of misc preferences
///////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __GAMESPYMISCPREFERENCES_H__
#define __GAMESPYMISCPREFERENCES_H__
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "Common/UserPreferences.h"
//-----------------------------------------------------------------------------
// GameSpyMiscPreferences base class
//-----------------------------------------------------------------------------
class GameSpyMiscPreferences : public UserPreferences
{
public:
GameSpyMiscPreferences();
virtual ~GameSpyMiscPreferences();
Int getLocale( void );
void setLocale( Int val );
AsciiString getCachedStats( void );
void setCachedStats( AsciiString val );
Bool getQuickMatchResLocked( void );
Int getMaxMessagesPerUpdate( void );
};
#endif // __GAMESPYMISCPREFERENCES_H__

View File

@ -0,0 +1,247 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GameState.h //////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2002
// Desc: Game state singleton from which to load and save the game state
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __GAME_STATE_H_
#define __GAME_STATE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/STLTypedefs.h"
#include "Common/Snapshot.h"
#include "Common/SubsystemInterface.h"
#include "Common/UnicodeString.h"
#include "GameNetwork/NetworkDefs.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class GameWindow;
class WindowLayout;
///////////////////////////////////////////////////////////////////////////////////////////////////
typedef void (*IterateSaveFileCallback)( AsciiString filename, void *userData );
// ------------------------------------------------------------------------------------------------
/** The save/load window is used for a variety of formats, using this type during the
* save/load menu initialization you can make that menu allow loading only, or allow
* both saving and loading from the same menu */
// ------------------------------------------------------------------------------------------------
enum SaveLoadLayoutType
{
SLLT_INVALID = 0,
SLLT_SAVE_AND_LOAD,
SLLT_LOAD_ONLY,
SLLT_SAVE_ONLY,
SLLT_NUM_TYPES // keep this last, why? don't know, it's not really used, but we like it this way
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
struct SaveDate
{
SaveDate() { year = month = day = dayOfWeek = hour = minute = second = milliseconds = 0; }
Bool isNewerThan( SaveDate *other );
UnsignedShort year;
UnsignedShort month;
UnsignedShort day;
UnsignedShort dayOfWeek;
UnsignedShort hour;
UnsignedShort minute;
UnsignedShort second;
UnsignedShort milliseconds;
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
enum SaveFileType
{
SAVE_FILE_TYPE_NORMAL, ///< a regular save game at any arbitrary point in the game
SAVE_FILE_TYPE_MISSION, ///< a save game in between missions (a mission save)
SAVE_FILE_TYPE_NUM_TYPES
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class SaveGameInfo
{
public:
SaveGameInfo( void );
~SaveGameInfo( void );
AsciiString saveGameMapName; // map name of the "scratch pad" map extracted from save file
AsciiString pristineMapName; // pristine map in the map or user maps directory
AsciiString mapLabel; // pretty name of this level set in the editor
SaveDate date; // date of file save
AsciiString campaignSide; // which campaign side we're playing
Int missionNumber; // mission number in campaign
UnicodeString description; // user description for save game file
SaveFileType saveFileType; // type of save file we're dealing with
AsciiString missionMapName; // used for mission saves
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
struct AvailableGameInfo
{
AsciiString filename;
SaveGameInfo saveGameInfo;
AvailableGameInfo *next;
AvailableGameInfo *prev;
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
enum SaveCode
{
SC_INVALID = -1,
SC_OK,
SC_NO_FILE_AVAILABLE,
SC_FILE_NOT_FOUND,
SC_UNABLE_TO_OPEN_FILE,
SC_INVALID_XFER,
SC_UNKNOWN_BLOCK,
SC_INVALID_DATA,
SC_ERROR,
};
enum SnapshotType {
SNAPSHOT_SAVELOAD,
SNAPSHOT_DEEPCRC_LOGICONLY,
SNAPSHOT_DEEPCRC,
SNAPSHOT_MAX
};
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class GameState : public SubsystemInterface,
public Snapshot
{
public:
GameState( void );
virtual ~GameState( void );
// subsystem interface
virtual void init( void );
virtual void reset( void );
virtual void update( void ) { }
// save game methods
SaveCode saveGame( AsciiString filename,
UnicodeString desc,
SaveFileType saveType,
SnapshotType which = SNAPSHOT_SAVELOAD ); ///< save a game
SaveCode missionSave( void ); ///< do a in between mission save
SaveCode loadGame( AvailableGameInfo gameInfo ); ///< load a save file
SaveGameInfo *getSaveGameInfo( void ) { return &m_gameInfo; }
// snapshot interaction
void addPostProcessSnapshot( Snapshot *snapshot ); ///< add snapshot to post process laod
// manipulating files
Bool doesSaveGameExist( AsciiString filename ); ///< does the save file exist
void populateSaveGameListbox( GameWindow *listbox, SaveLoadLayoutType layoutType ); ///< populate listbox with available save games
void getSaveGameInfoFromFile( AsciiString filename, SaveGameInfo *saveGameInfo ); ///< get save game info from file
void friend_xferSaveDataForCRC( Xfer *xfer, SnapshotType which ); ///< This should only be called to DeepCRC sanity checking
Bool isInLoadGame(void) { return m_isInLoadGame; } // Brutal hack to allow bone pos validation while loading games
void setPristineMapName( AsciiString name ) { m_gameInfo.pristineMapName = name; }
AsciiString getPristineMapName( void ) { return m_gameInfo.pristineMapName; }
AsciiString getSaveDirectory() const;
AsciiString getFilePathInSaveDirectory(const AsciiString& leaf) const;
Bool isInSaveDirectory(const AsciiString& path) const;
AsciiString realMapPathToPortableMapPath(const AsciiString& in) const;
AsciiString portableMapPathToRealMapPath(const AsciiString& in) const;
AsciiString getMapLeafName(const AsciiString& in) const;
protected:
// snapshot methods
virtual void crc( Xfer *xfer ) { }
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void ) { }
private:
AsciiString findNextSaveFilename( UnicodeString desc ); ///< find next acceptable filename for a new save game
void iterateSaveFiles( IterateSaveFileCallback callback, void *userData ); ///< iterate save files on disk
void xferSaveData( Xfer *xfer, SnapshotType which ); ///< save/load the file data
void gameStatePostProcessLoad( void ); ///< post process entry point after a game load
void clearAvailableGames( void ); ///< clear any available games resources we got in our list
struct SnapshotBlock
{
Snapshot *snapshot; ///< the snapshot object that handles this block
AsciiString blockName; ///< the block name
};
typedef std::list< SnapshotBlock > SnapshotBlockList;
typedef SnapshotBlockList::iterator SnapshotBlockListIterator;
void addSnapshotBlock( AsciiString blockName, Snapshot *snapshot, SnapshotType which );
SnapshotBlock *findBlockInfoByToken( AsciiString token, SnapshotType which );
SnapshotBlockList m_snapshotBlockList[SNAPSHOT_MAX]; ///< list of snapshot blocks of save file data
SaveGameInfo m_gameInfo; ///< save game info struct
typedef std::list< Snapshot * > SnapshotList;
typedef SnapshotList::iterator SnapshotListIterator;
typedef SnapshotList::reverse_iterator SnapshotListReverseIterator;
SnapshotList m_snapshotPostProcessList;
AvailableGameInfo *m_availableGames; ///< list of available games we can save over or load from
Bool m_isInLoadGame; // Brutal hack to allow bone pos validation while loading games
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern GameState *TheGameState;
UnicodeString getUnicodeTimeBuffer(SYSTEMTIME timeVal);
UnicodeString getUnicodeDateBuffer(SYSTEMTIME timeVal);
#endif // end __GAME_STATE_H_

View File

@ -0,0 +1,73 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GameStateMap.h ///////////////////////////////////////////////////////////////////////////
// Author: Colin Day, October 2002
// Desc: Chunk in the save game file that will hold a pristine version of the map file
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __GAME_STATE_MAP_H_
#define __GAME_STATE_MAP_H_
// INLCUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/Snapshot.h"
#include "Common/SubsystemInterface.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Xfer;
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
class GameStateMap : public SubsystemInterface,
public Snapshot
{
public:
GameStateMap( void );
virtual ~GameStateMap( void );
// subsystem interface methods
virtual void init( void ) { }
virtual void reset( void ) { }
virtual void update( void ) { }
// snapshot methods
virtual void crc( Xfer *xfer ) { }
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void ) { }
void clearScratchPadMaps( void ); ///< clear any scratch pad maps from the save directory
protected:
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern GameStateMap *TheGameStateMap;
#endif // end __GAME_STATE_MAP_H_

View File

@ -0,0 +1,194 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// GameType.h
// Basic data types needed for the game engine. This is an extension of BaseType.h.
// Author: Michael S. Booth, April 2001
#pragma once
#ifndef _GAME_TYPE_H_
#define _GAME_TYPE_H_
#include "Lib/BaseType.h"
// the default size of the world map
#define DEFAULT_WORLD_WIDTH 64
#define DEFAULT_WORLD_HEIGHT 64
/// A unique, generic "identifier" used to access Objects.
enum ObjectID
{
INVALID_ID = 0,
FORCE_OBJECTID_TO_LONG_SIZE = 0x7ffffff
};
/// A unique, generic "identifier" used to access Drawables.
enum DrawableID
{
INVALID_DRAWABLE_ID = 0,
FORCE_DRAWABLEID_TO_LONG_SIZE = 0x7ffffff
};
/// A unique, generic "identifier" used to identify player specified formations.
enum FormationID
{
NO_FORMATION_ID = 0, // Unit is not a member of any formation
FORCE_FORMATIONID_TO_LONG_SIZE = 0x7ffffff
};
class INI;
//-------------------------------------------------------------------------------------------------
/** The time of day enumeration, keep in sync with TimeOfDayNames[] */
//-------------------------------------------------------------------------------------------------
enum TimeOfDay
{
TIME_OF_DAY_INVALID = 0,
TIME_OF_DAY_FIRST = 1,
TIME_OF_DAY_MORNING = TIME_OF_DAY_FIRST,
TIME_OF_DAY_AFTERNOON,
TIME_OF_DAY_EVENING,
TIME_OF_DAY_NIGHT,
TIME_OF_DAY_COUNT // keep this last
};
extern char *TimeOfDayNames[];
// defined in Common/GameType.cpp
//-------------------------------------------------------------------------------------------------
enum Weather
{
WEATHER_NORMAL = 0,
WEATHER_SNOWY = 1,
WEATHER_COUNT // keep this last
};
extern char *WeatherNames[];
enum Scorches
{
SCORCH_1 = 0,
SCORCH_2 = 1,
SCORCH_3 = 2,
SCORCH_4 = 3,
SHADOW_SCORCH = 4,
/* SCORCH_6 = 5,
SCORCH_7 = 6,
SCORCH_8 = 7,
CRATER_1 = 8,
CRATER_2 = 9,
CRATER_3 = 10,
CRATER_4 = 11,
CRATER_5 = 12,
CRATER_6 = 13,
CRATER_7 = 14,
CRATER_8 = 15,
MISC_DECAL_1 = 16,
MISC_DECAL_2 = 17,
MISC_DECAL_3 = 18,
MISC_DECAL_4 = 19,
MISC_DECAL_5 = 20,
MISC_DECAL_6 = 21,
MISC_DECAL_7 = 22,
MISC_DECAL_8 = 23,
MISC_DECAL_9 = 24,
MISC_DECAL_10 = 25,
MISC_DECAL_11 = 26,
MISC_DECAL_12 = 27,
MISC_DECAL_13 = 28,
MISC_DECAL_14 = 29,
MISC_DECAL_15 = 30,
MISC_DECAL_16 = 31,
MISC_DECAL_17 = 32,
MISC_DECAL_18 = 33,
MISC_DECAL_19 = 34,
MISC_DECAL_20 = 35,
MISC_DECAL_21 = 36,
MISC_DECAL_22 = 37,
MISC_DECAL_23 = 38,
MISC_DECAL_24 = 39,
MISC_DECAL_25 = 40,
MISC_DECAL_26 = 41,
MISC_DECAL_27 = 42,
MISC_DECAL_28 = 43,
MISC_DECAL_29 = 44,
MISC_DECAL_30 = 45,
MISC_DECAL_31 = 46,
MISC_DECAL_32 = 47,
MISC_DECAL_33 = 48,
MISC_DECAL_34 = 49,
MISC_DECAL_35 = 50,
MISC_DECAL_36 = 51,
MISC_DECAL_37 = 52,
MISC_DECAL_38 = 53,
MISC_DECAL_39 = 54,
MISC_DECAL_40 = 55,
MISC_DECAL_41 = 56,
MISC_DECAL_42 = 57,
MISC_DECAL_43 = 58,
MISC_DECAL_44 = 59,
MISC_DECAL_45 = 60,
MISC_DECAL_46 = 61,
MISC_DECAL_47 = 62,
MISC_DECAL_48 = 63,
*/
SCORCH_COUNT
};
//-------------------------------------------------------------------------------------------------
enum WeaponSlotType
{
PRIMARY_WEAPON = 0,
SECONDARY_WEAPON,
TERTIARY_WEAPON,
WEAPONSLOT_COUNT // keep last
};
//-------------------------------------------------------------------------------------------------
// Pathfind layers - ground is the first layer, each bridge is another. jba.
// Layer 1 is the ground.
// Layer 2 is the top layer - bridge if one is present, ground otherwise.
// Layer 2 - LAYER_LAST -1 are bridges.
// Layer_WALL is a special "wall" layer for letting units run aroound on top of a wall
// made of structures.
// Note that the bridges just index in the pathfinder, so you don't actually
// have a LAYER_BRIDGE_1 enum value.
enum PathfindLayerEnum {LAYER_INVALID = 0, LAYER_GROUND = 1, LAYER_WALL = 15, LAYER_LAST=15};
//-------------------------------------------------------------------------------------------------
#endif // _GAME_TYPE_H_

View File

@ -0,0 +1,198 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Geometry.h ///////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, November 2001
// Desc: Geometry descriptions
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __GEOMETRY_H_
#define __GEOMETRY_H_
#include "Lib/BaseType.h"
#include "Common/AsciiString.h"
#include "Common/Snapshot.h"
class INI;
//-------------------------------------------------------------------------------------------------
/** Geometry type descriptions, keep this in the same order as GeometryNames[] below
*
* NOTE: Do *NOT* change the order of these defines unless you update the
* partition manager ... in particular theCollideTestProcs depend on the
* order of this geometry and the fact that the values start at 1
*/
//-------------------------------------------------------------------------------------------------
enum GeometryType
{
GEOMETRY_SPHERE = 0, ///< partition/collision testing as sphere. (majorRadius = radius)
GEOMETRY_CYLINDER, ///< partition/collision testing as cylinder. (majorRadius = radius, height = height)
GEOMETRY_BOX, ///< partition/collision testing as rectangular box (majorRadius = half len in forward dir; minorRadius = half len in side dir; height = height)
GEOMETRY_NUM_TYPES, // keep this last
GEOMETRY_FIRST = GEOMETRY_SPHERE
};
#ifdef DEFINE_GEOMETRY_NAMES
static const char *GeometryNames[] =
{
"SPHERE",
"CYLINDER",
"BOX",
NULL
};
#endif // end DEFINE_GEOMETRY_NAMES
//-------------------------------------------------------------------------------------------------
#if defined(_DEBUG) || defined(_INTERNAL)
enum ExtentModType
{
EXTENTMOD_INVALID = 0,
EXTENTMOD_TYPE = 1,
EXTENTMOD_MAJOR = 2,
EXTENTMOD_MINOR = 3,
EXTENTMOD_HEIGHT = 4,
};
static const Real EXTENT_BIG_CHANGE = 10.0f;
#endif
//-------------------------------------------------------------------------------------------------
/** Geometry information */
//-------------------------------------------------------------------------------------------------
class GeometryInfo : public Snapshot
{
private:
GeometryType m_type;
Bool m_isSmall; ///< if true, geometry is assumed to fit in a single partition cell
Real m_height;
Real m_majorRadius;
Real m_minorRadius;
Real m_boundingCircleRadius; ///< not in INI file -- size of bounding circle (2d)
Real m_boundingSphereRadius; ///< not in INI -- size of bounding sphere (3d)
void calcBoundingStuff();
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
public:
static void parseGeometryType( INI* ini, void * /*instance*/, void *store, const void* /*userData*/ );
static void parseGeometryIsSmall( INI* ini, void * /*instance*/, void *store, const void* /*userData*/ );
static void parseGeometryHeight( INI* ini, void * /*instance*/, void *store, const void* /*userData*/ );
static void parseGeometryMajorRadius( INI* ini, void * /*instance*/, void *store, const void* /*userData*/ );
static void parseGeometryMinorRadius( INI* ini, void * /*instance*/, void *store, const void* /*userData*/ );
GeometryInfo(GeometryType type, Bool isSmall, Real height, Real majorRadius, Real minorRadius)
{
// Added by Sadullah Nader
// Initializations missing and needed
m_boundingCircleRadius = 0.0f;
m_boundingSphereRadius = 0.0f;
//
set(type, isSmall, height, majorRadius, minorRadius);
}
void set(GeometryType type, Bool isSmall, Real height, Real majorRadius, Real minorRadius);
// bleah, icky but needed for legacy code
inline void setMajorRadius(Real majorRadius)
{
m_majorRadius = majorRadius;
calcBoundingStuff();
}
// bleah, icky but needed for legacy code
inline void setMinorRadius(Real minorRadius)
{
m_minorRadius = minorRadius;
calcBoundingStuff();
}
inline GeometryType getGeomType() const { return m_type; }
inline Bool getIsSmall() const { return m_isSmall; }
inline Real getMajorRadius() const { return m_majorRadius; } // x-axis
inline Real getMinorRadius() const { return m_minorRadius; } // y-axis
// this has been removed and should never need to be called...
// you should generally call getMaxHeightAbovePosition() instead. (srj)
//inline Real getGeomHeight() const { return m_height; } // z-axis
inline Real getBoundingCircleRadius() const { return m_boundingCircleRadius; }
inline Real getBoundingSphereRadius() const { return m_boundingSphereRadius; }
Bool isIntersectedByLineSegment(const Coord3D& loc, const Coord3D& from, const Coord3D& to) const;
Real getFootprintArea() const;
// given an object with this geom, how far above the object's canonical position does its max z extend?
Real getMaxHeightAbovePosition() const;
// given an object with this geom, how far below the object's canonical position does its max z extend?
Real getMaxHeightBelowPosition() const;
// given an object with this geom, how far above/below the object's canonical position is its center?
Real getZDeltaToCenterPosition() const;
// given an object with this geom, located at 'pos', where is the "center" of the geometry?
void getCenterPosition(const Coord3D& pos, Coord3D& center) const;
// given an object with this geom, located at 'pos', and another obj with the given
// pos & geom, calc the min and max pitches from this to that.
void calcPitches(const Coord3D& thisPos, const GeometryInfo& that, const Coord3D& thatPos,
Real& minPitch, Real& maxPitch) const;
/// expand the 2d footprint
void expandFootprint(Real radius);
/// get the 2d bounding box
void get2DBounds(const Coord3D& geomCenter, Real angle, Region2D& bounds ) const;
/// note that the pt is generated using game logic random, not game client random!
void makeRandomOffsetWithinFootprint(Coord3D& pt) const;
void clipPointToFootprint(const Coord3D& geomCenter, Coord3D& ptToClip) const;
Bool isPointInFootprint(const Coord3D& geomCenter, const Coord3D& pt) const;
// given an object with this geom, SET how far above the object's canonical position its max z should extend.
void setMaxHeightAbovePosition(Real z);
#if defined(_DEBUG) || defined(_INTERNAL)
void tweakExtents(ExtentModType extentModType, Real extentModAmount);
AsciiString getDescriptiveString() const;
#endif
};
#endif

View File

@ -0,0 +1,524 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: GlobalData.h /////////////////////////////////////////////////////////////////////////////
// Global data used by both the client and logic
// Author: trolfs, Michae Booth, Colin Day, April 2001
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _GLOBALDATA_H_
#define _GLOBALDATA_H_
#include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
#include "Common/AsciiString.h"
#include "Common/GameType.h"
#include "Common/GameMemory.h"
#include "Common/SubsystemInterface.h"
#include "GameClient/Color.h"
#include "Common/STLTypedefs.h"
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////////////////////////
struct FieldParse;
typedef enum _TerrainLOD;
class GlobalData;
class INI;
class WeaponBonusSet;
enum BodyDamageType;
enum AIDebugOptions;
// PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
const Int MAX_GLOBAL_LIGHTS = 3;
//-------------------------------------------------------------------------------------------------
/** Global data container class
* Defines all global game data used by the system
* @todo Change this entire system. Otherwise this will end up a huge class containing tons of variables,
* and will cause re-compilation dependancies throughout the codebase. */
//-------------------------------------------------------------------------------------------------
class GlobalData : public SubsystemInterface
{
public:
GlobalData();
virtual ~GlobalData();
void init();
void reset();
void update() { }
Bool setTimeOfDay( TimeOfDay tod ); ///< Use this function to set the Time of day;
static void parseGameDataDefinition( INI* ini );
//-----------------------------------------------------------------------------------------------
struct TerrainLighting
{
RGBColor ambient;
RGBColor diffuse;
Coord3D lightPos;
};
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
AsciiString m_mapName; ///< hack for now, this whole this is going away
AsciiString m_moveHintName;
Bool m_useTrees;
Bool m_useTreeSway;
Bool m_useDrawModuleLOD;
Bool m_useFpsLimit;
Bool m_dumpAssetUsage;
Int m_framesPerSecondLimit;
Int m_chipSetType; ///<See W3DShaderManager::ChipsetType for options
Bool m_windowed;
Int m_xResolution;
Int m_yResolution;
Int m_maxShellScreens; ///< this many shells layouts can be loaded at once
Bool m_useCloudMap;
Int m_use3WayTerrainBlends; ///< 0 is none, 1 is normal, 2 is debug.
Bool m_useLightMap;
Bool m_bilinearTerrainTex;
Bool m_trilinearTerrainTex;
Bool m_multiPassTerrain;
Bool m_adjustCliffTextures;
Bool m_stretchTerrain;
Bool m_useHalfHeightMap;
Bool m_drawEntireTerrain;
_TerrainLOD m_terrainLOD;
Bool m_enableDynamicLOD;
Bool m_enableStaticLOD;
Int m_terrainLODTargetTimeMS;
Bool m_useAlternateMouse;
Bool m_rightMouseAlwaysScrolls;
Bool m_useWaterPlane;
Bool m_useCloudPlane;
Bool m_useShadowVolumes;
Bool m_useShadowDecals;
Int m_textureReductionFactor; //how much to cut texture resolution: 2 is half, 3 is quarter, etc.
Bool m_enableBehindBuildingMarkers;
Real m_waterPositionX;
Real m_waterPositionY;
Real m_waterPositionZ;
Real m_waterExtentX;
Real m_waterExtentY;
Int m_waterType;
Bool m_showSoftWaterEdge;
Bool m_usingWaterTrackEditor;
Int m_featherWater;
// these are for WATER_TYPE_3 vertex animated water
enum { MAX_WATER_GRID_SETTINGS = 4 };
AsciiString m_vertexWaterAvailableMaps[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterHeightClampLow[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterHeightClampHi[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterAngle[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterXPosition[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterYPosition[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterZPosition[ MAX_WATER_GRID_SETTINGS ];
Int m_vertexWaterXGridCells[ MAX_WATER_GRID_SETTINGS ];
Int m_vertexWaterYGridCells[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterGridSize[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterAttenuationA[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterAttenuationB[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterAttenuationC[ MAX_WATER_GRID_SETTINGS ];
Real m_vertexWaterAttenuationRange[ MAX_WATER_GRID_SETTINGS ];
Real m_downwindAngle;
Real m_skyBoxPositionZ;
Real m_drawSkyBox;
Real m_skyBoxScale;
Real m_cameraPitch;
Real m_cameraYaw;
Real m_cameraHeight;
Real m_maxCameraHeight;
Real m_minCameraHeight;
Real m_terrainHeightAtEdgeOfMap;
Real m_unitDamagedThresh;
Real m_unitReallyDamagedThresh;
Real m_groundStiffness;
Real m_structureStiffness;
Real m_gravity; // acceleration due to gravity, in dist/frame^2
Real m_stealthFriendlyOpacity;
UnsignedInt m_defaultOcclusionDelay; ///<time to delay building occlusion after object is created.
Bool m_preloadAssets;
Bool m_preloadEverything; ///< Preload everything, everywhere (for debugging only)
Bool m_preloadReport; ///< dump a log of all W3D assets that are being preloaded.
Real m_partitionCellSize;
Coord3D m_ammoPipWorldOffset;
Coord3D m_containerPipWorldOffset;
Coord2D m_ammoPipScreenOffset;
Coord2D m_containerPipScreenOffset;
Real m_ammoPipScaleFactor;
Real m_containerPipScaleFactor;
UnsignedInt m_historicDamageLimit;
//Settings for terrain tracks left by vehicles with treads or wheels
Int m_maxTerrainTracks; ///<maximum number of objects allowed to generate tracks.
Int m_maxTankTrackEdges; ///<maximum length of tank track
Int m_maxTankTrackOpaqueEdges; ///<maximum length of tank track before it starts fading.
Int m_maxTankTrackFadeDelay; ///<maximum amount of time a tank track segment remains visible.
AsciiString m_levelGainAnimationName; ///< The animation to play when a level is gained.
Real m_levelGainAnimationDisplayTimeInSeconds; ///< time to play animation for
Real m_levelGainAnimationZRisePerSecond; ///< rise animation up while playing
AsciiString m_getHealedAnimationName; ///< The animation to play when emergency repair does its thing.
Real m_getHealedAnimationDisplayTimeInSeconds; ///< time to play animation for
Real m_getHealedAnimationZRisePerSecond; ///< rise animation up while playing
TimeOfDay m_timeOfDay;
Weather m_weather;
Bool m_makeTrackMarks;
Bool m_hideGarrisonFlags;
Bool m_forceModelsToFollowTimeOfDay;
Bool m_forceModelsToFollowWeather;
TerrainLighting m_terrainLighting[TIME_OF_DAY_COUNT][MAX_GLOBAL_LIGHTS];
TerrainLighting m_terrainObjectsLighting[TIME_OF_DAY_COUNT][MAX_GLOBAL_LIGHTS];
//Settings for each global light
RGBColor m_terrainAmbient[MAX_GLOBAL_LIGHTS];
RGBColor m_terrainDiffuse[MAX_GLOBAL_LIGHTS];
Coord3D m_terrainLightPos[MAX_GLOBAL_LIGHTS];
Real m_infantryLightScale[TIME_OF_DAY_COUNT];
Real m_scriptOverrideInfantryLightScale;
Real m_soloPlayerHealthBonusForDifficulty[PLAYERTYPE_COUNT][DIFFICULTY_COUNT];
Int m_maxVisibleTranslucentObjects;
Int m_maxVisibleOccluderObjects;
Int m_maxVisibleOccludeeObjects;
Int m_maxVisibleNonOccluderOrOccludeeObjects;
Real m_occludedLuminanceScale;
Int m_numGlobalLights; //number of active global lights
Int m_maxRoadSegments;
Int m_maxRoadVertex;
Int m_maxRoadIndex;
Int m_maxRoadTypes;
Bool m_audioOn;
Bool m_musicOn;
Bool m_soundsOn;
Bool m_sounds3DOn;
Bool m_speechOn;
Bool m_videoOn;
Bool m_disableCameraMovement;
Bool m_useFX; ///< If false, don't render effects
Bool m_showClientPhysics;
Bool m_showTerrainNormals;
UnsignedInt m_noDraw; ///< Used to disable drawing, to profile game logic code.
AIDebugOptions m_debugAI; ///< Used to display AI debug information
Bool m_debugAIObstacles; ///< Used to display AI obstacle debug information
Bool m_showObjectHealth; ///< debug display object health
Bool m_scriptDebug; ///< Should we attempt to load the script debugger window (.DLL)
Bool m_particleEdit; ///< Should we attempt to load the particle editor (.DLL)
Bool m_displayDebug; ///< Used to display display debug info
Bool m_winCursors; ///< Should we force use of windows cursors?
Bool m_constantDebugUpdate; ///< should we update the debug stats constantly, vs every 2 seconds?
Bool m_showTeamDot; ///< Shows the little colored team dot representing which team you are controlling.
#ifdef DUMP_PERF_STATS
Bool m_dumpPerformanceStatistics;
#endif
Bool m_forceBenchmark; ///<forces running of CPU detection benchmark, even on known cpu's.
Int m_fixedSeed; ///< fixed random seed for game logic (less than 0 to disable)
Real m_particleScale; ///< Global size modifier for particle effects.
AsciiString m_autoFireParticleSmallPrefix;
AsciiString m_autoFireParticleSmallSystem;
Int m_autoFireParticleSmallMax;
AsciiString m_autoFireParticleMediumPrefix;
AsciiString m_autoFireParticleMediumSystem;
Int m_autoFireParticleMediumMax;
AsciiString m_autoFireParticleLargePrefix;
AsciiString m_autoFireParticleLargeSystem;
Int m_autoFireParticleLargeMax;
AsciiString m_autoSmokeParticleSmallPrefix;
AsciiString m_autoSmokeParticleSmallSystem;
Int m_autoSmokeParticleSmallMax;
AsciiString m_autoSmokeParticleMediumPrefix;
AsciiString m_autoSmokeParticleMediumSystem;
Int m_autoSmokeParticleMediumMax;
AsciiString m_autoSmokeParticleLargePrefix;
AsciiString m_autoSmokeParticleLargeSystem;
Int m_autoSmokeParticleLargeMax;
AsciiString m_autoAflameParticlePrefix;
AsciiString m_autoAflameParticleSystem;
Int m_autoAflameParticleMax;
// Latency insertion, packet loss for network debugging
Int m_netMinPlayers; ///< Min players needed to start a net game
UnsignedInt m_defaultIP; ///< preferred IP address for LAN
UnsignedInt m_firewallBehavior; ///< Last detected firewall behavior
Bool m_firewallSendDelay; ///< Use send delay for firewall connection negotiations
UnsignedInt m_firewallPortOverride; ///< User-specified port to be used
Short m_firewallPortAllocationDelta; ///< the port allocation delta last detected.
Int m_baseValuePerSupplyBox;
Real m_BuildSpeed;
Real m_MinDistFromEdgeOfMapForBuild;
Real m_SupplyBuildBorder;
Real m_allowedHeightVariationForBuilding; ///< how "flat" is still flat enough to build on
Real m_MinLowEnergyProductionSpeed;
Real m_MaxLowEnergyProductionSpeed;
Real m_LowEnergyPenaltyModifier;
Real m_MultipleFactory;
Real m_RefundPercent;
Real m_commandCenterHealRange; ///< radius in which close by ally things are healed
Real m_commandCenterHealAmount; ///< health per logic frame close by things are healed
Int m_maxLineBuildObjects; ///< line style builds can be no longer than this
Int m_maxTunnelCapacity; ///< Max people in Player's tunnel network
Real m_horizontalScrollSpeedFactor; ///< Factor applied to the game screen scrolling speed.
Real m_verticalScrollSpeedFactor; ///< Seperated because of our aspect ratio
Real m_scrollAmountCutoff; ///< Scroll speed to not adjust camera height
Real m_cameraAdjustSpeed; ///< Rate at which we adjust camera height
Bool m_enforceMaxCameraHeight; ///< Enfoce max camera height while scrolling?
Bool m_buildMapCache;
AsciiString m_initialFile; ///< If this is specified, load a specific map/replay from the command-line
AsciiString m_pendingFile; ///< If this is specified, use this map at the next game start
Int m_maxParticleCount; ///< maximum number of particles that can exist
Int m_maxFieldParticleCount; ///< maximum number of field-type particles that can exist (roughly)
WeaponBonusSet* m_weaponBonusSet;
Real m_healthBonus[LEVEL_COUNT]; ///< global bonuses to health for veterancy.
Real m_defaultStructureRubbleHeight; ///< for rubbled structures, compress height to this if none specified
AsciiString m_shellMapName; ///< Holds the shell map name
Bool m_shellMapOn; ///< User can set the shell map not to load
Bool m_playIntro; ///< Flag to say if we're to play the intro or not
Bool m_afterIntro; ///< we need to tell the game our intro is done
Bool m_allowExitOutOfMovies; ///< flag to allow exit out of movies only after the Intro has played
Bool m_loadScreenRender; ///< flag to disallow rendering of almost everything during a loadscreen
Real m_keyboardScrollFactor; ///< Factor applied to game scrolling speed via keyboard scrolling
Real m_keyboardDefaultScrollFactor; ///< Factor applied to game scrolling speed via keyboard scrolling
Real m_musicVolumeFactor; ///< Factor applied to loudness of music volume
Real m_SFXVolumeFactor; ///< Factor applied to loudness of SFX volume
Real m_voiceVolumeFactor; ///< Factor applied to loudness of voice volume
Bool m_3DSoundPref; ///< Whether user wants to use 3DSound or not
Bool m_animateWindows; ///< Should we animate window transitions?
Bool m_incrementalAGPBuf;
UnsignedInt m_iniCRC; ///< CRC of important INI files
UnsignedInt m_exeCRC; ///< CRC of the executable
BodyDamageType m_movementPenaltyDamageState; ///< at this body damage state, we have movement penalties
Int m_groupSelectMinSelectSize; // min number of units to treat as group select for audio feedback
Real m_groupSelectVolumeBase; // base volume for group select sound
Real m_groupSelectVolumeIncrement;// increment to volume for selecting more units
Int m_maxUnitSelectSounds; // max number of select sounds to play per selection
Real m_selectionFlashSaturationFactor; /// how colorful should the selection flash be? 0-4
Bool m_selectionFlashHouseColor ; /// skip the house color and just use white.
Real m_cameraAudibleRadius; ///< If the camera is being used as the position of audio, then how far can we hear?
Real m_groupMoveClickToGatherFactor; /** if you take all the selected units and calculate the smallest possible rectangle
that contains them all, and click within that, all the selected units will break
formation and gather at the point the user clicked (if the value is 1.0). If it's 0.0,
units will always keep their formation. If it's <1.0, then the user must click a
smaller area within the rectangle to order the gather. */
Int m_antiAliasBoxValue; ///< value of selected antialias from combo box in options menu
Bool m_languageFilterPref; ///< Bool if user wants to filter language
Bool m_loadScreenDemo; ///< Bool if true, run the loadscreen demo movie
Bool m_disableRender; ///< if true, no rendering!
Bool m_saveCameraInReplay;
Bool m_useCameraInReplay;
Real m_shakeSubtleIntensity; ///< Intensity for shaking a camera with SHAKE_SUBTLE
Real m_shakeNormalIntensity; ///< Intensity for shaking a camera with SHAKE_NORMAL
Real m_shakeStrongIntensity; ///< Intensity for shaking a camera with SHAKE_STRONG
Real m_shakeSevereIntensity; ///< Intensity for shaking a camera with SHAKE_SEVERE
Real m_shakeCineExtremeIntensity; ///< Intensity for shaking a camera with SHAKE_CINE_EXTREME
Real m_shakeCineInsaneIntensity; ///< Intensity for shaking a camera with SHAKE_CINE_INSANE
Real m_maxShakeIntensity; ///< The maximum shake intensity we can have
Real m_maxShakeRange; ///< The maximum shake range we can have
Real m_sellPercentage; ///< when objects are sold, you get this much of the cost it would take to build it back
Real m_baseRegenHealthPercentPerSecond; ///< auto healing for bases
UnsignedInt m_baseRegenDelay; ///< delay in frames we must be damage free before we can auto heal
#ifdef ALLOW_SURRENDER
Real m_prisonBountyMultiplier; ///< the cost of the unit is multiplied by this and given to the player when prisoners are returned to the a prison with KINDOF_COLLECTS_PRISON_BOUNTY
Color m_prisonBountyTextColor; ///< color of the text that displays the money acquired at the prison
#endif
Color m_hotKeyTextColor; ///< standard color for all hotkeys.
AsciiString m_specialPowerViewObjectName; ///< Created when certain special powers are fired so players can watch.
std::vector<AsciiString> m_standardPublicBones;
Real m_standardMinefieldDensity;
Real m_standardMinefieldDistance;
Bool m_showMetrics; ///< whether or not to show the metrics.
Int m_defaultStartingCash; ///< The amount of cash a player starts with by default.
Bool m_debugShowGraphicalFramerate; ///< Whether or not to show the graphical framerate bar.
Int m_powerBarBase; ///< Logrithmic base for the power bar scale
Real m_powerBarIntervals; ///< how many logrithmic intervals the width will be divided into
Int m_powerBarYellowRange; ///< Red if consumption exceeds production, yellow if consumption this close but under, green if further under
Real m_displayGamma; ///<display gamma that's adjusted with "brightness" control on options screen.
UnsignedInt m_unlookPersistDuration; ///< How long after unlook until the sighting info executes the undo
Bool m_shouldUpdateTGAToDDS; ///< Should we attempt to update old TGAs to DDS stuff on loadup?
UnsignedInt m_doubleClickTimeMS; ///< What is the maximum amount of time that can seperate two clicks in order
///< for us to generate a double click message?
RGBColor m_shroudColor; ///< What color should the shroud be? Remember, this is a lighting multiply, not an add
UnsignedByte m_clearAlpha; ///< 255 means perfect visibility
UnsignedByte m_fogAlpha; ///< 127 means fog is half as obscuring as shroud
UnsignedByte m_shroudAlpha; ///< 0 makes this opaque, but they may get fancy
// network timing values.
UnsignedInt m_networkFPSHistoryLength; ///< The number of fps history entries
UnsignedInt m_networkLatencyHistoryLength; ///< The number of ping history entries.
UnsignedInt m_networkRunAheadMetricsTime; ///< The number of miliseconds between run ahead metrics things
UnsignedInt m_networkCushionHistoryLength; ///< The number of cushion values to keep.
UnsignedInt m_networkRunAheadSlack; ///< The amount of slack in the run ahead value. This is the percentage of the calculated run ahead that is added.
UnsignedInt m_networkKeepAliveDelay; ///< The number of seconds between when the connections to each player send a keep-alive packet.
UnsignedInt m_networkDisconnectTime; ///< The number of milliseconds between when the game gets stuck on a frame for a network stall and when the disconnect dialog comes up.
UnsignedInt m_networkPlayerTimeoutTime; ///< The number of milliseconds between when a player's last keep alive command was recieved and when they are considered disconnected from the game.
UnsignedInt m_networkDisconnectScreenNotifyTime; ///< The number of milliseconds between when the disconnect screen comes up and when the other players are notified that we are on the disconnect screen.
Real m_keyboardCameraRotateSpeed; ///< How fast the camera rotates when rotated via keyboard controls.
Int m_playStats; ///< Int whether we want to log play stats or not, if <= 0 then we don't log
#if defined(_DEBUG) || defined(_INTERNAL)
Bool m_wireframe;
Bool m_stateMachineDebug;
Bool m_useCameraConstraints;
Bool m_specialPowerUsesDelay;
Bool m_shroudOn;
Bool m_fogOfWarOn;
Bool m_jabberOn;
Bool m_munkeeOn;
Bool m_allowUnselectableSelection; ///< Are we allowed to select things that are unselectable?
Bool m_disableCameraFade; ///< if true, script commands affecting camera are disabled
Bool m_disableScriptedInputDisabling; ///< if true, script commands can't disable input
Bool m_disableMilitaryCaption; ///< if true, military briefings go fast
Int m_benchmarkTimer; ///< how long to play the game in benchmark mode?
Bool m_checkForLeaks;
Bool m_vTune;
Bool m_debugCamera; ///< Used to display Camera debug information
Bool m_debugVisibility; ///< Should we actively debug the visibility
Int m_debugVisibilityTileCount; ///< How many tiles we should show when debugging visibility
Real m_debugVisibilityTileWidth; ///< How wide should these tiles be?
Int m_debugVisibilityTileDuration; ///< How long should these tiles stay around, in frames?
Bool m_debugThreatMap; ///< Should we actively debug the threat map
UnsignedInt m_maxDebugThreat; ///< This value (and any values greater) will appear full RED.
Int m_debugThreatMapTileDuration; ///< How long should these tiles stay around, in frames?
Bool m_debugCashValueMap; ///< Should we actively debug the threat map
UnsignedInt m_maxDebugValue; ///< This value (and any values greater) will appear full GREEN.
Int m_debugCashValueMapTileDuration; ///< How long should these tiles stay around, in frames?
RGBColor m_debugVisibilityTargettableColor; ///< What color should the targettable cells be?
RGBColor m_debugVisibilityDeshroudColor; ///< What color should the deshrouding cells be?
RGBColor m_debugVisibilityGapColor; ///< What color should the gap generator cells be?
Bool m_debugProjectilePath; ///< Should we actively debug the bezier paths on projectiles
Real m_debugProjectileTileWidth; ///< How wide should these tiles be?
Int m_debugProjectileTileDuration; ///< How long should these tiles stay around, in frames?
RGBColor m_debugProjectileTileColor; ///< What color should these tiles be?
Bool m_debugIgnoreAsserts; ///< Ignore all asserts.
Bool m_debugIgnoreStackTrace; ///< No stacktraces for asserts.
Bool m_showCollisionExtents; ///< Used to display collision extents
Bool m_saveStats;
Bool m_saveAllStats;
Bool m_useLocalMOTD;
AsciiString m_baseStatsDir;
AsciiString m_MOTDPath;
Int m_latencyAverage; ///< Average latency to insert
Int m_latencyAmplitude; ///< Amplitude of sinusoidal modulation of latency
Int m_latencyPeriod; ///< Period of sinusoidal modulation of latency
Int m_latencyNoise; ///< Max amplitude of jitter to throw in
Int m_packetLoss; ///< Percent of packets to drop
#endif
Bool m_isBreakableMovie; ///< if we enter a breakable movie, set this flag
Bool m_breakTheMovie; ///< The user has hit escape!
AsciiString m_modDir;
AsciiString m_modBIG;
// the trailing '\' is included!
AsciiString getPath_UserData() const;
private:
static const FieldParse s_GlobalDataFieldParseTable[];
// this is private, since we read the info from Windows and cache it for
// future use. No one is allowed to change it, ever. (srj)
AsciiString m_userDataDir;
// just the "leaf name", read from INI. private because no one is ever allowed
// to look at it directly; they must go thru getPath_UserData(). (srj)
AsciiString m_userDataLeafName;
static GlobalData *m_theOriginal; ///< the original global data instance (no overrides)
GlobalData *m_next; ///< next instance (for overrides)
GlobalData *newOverride( void ); /** create a new override, copy data from previous
override, and return it */
GlobalData(const GlobalData& that) { DEBUG_CRASH(("unimplemented")); }
GlobalData& operator=(const GlobalData& that) { DEBUG_CRASH(("unimplemented")); return *this; }
};
// singleton
extern GlobalData* TheWritableGlobalData;
#define TheGlobalData ((const GlobalData*)TheWritableGlobalData)
#endif

View File

@ -0,0 +1,121 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Handicap.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Handicap.h
//
// Created: Steven Johnson, October 2001
//
// Desc: @todo
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef _HANDICAP_H_
#define _HANDICAP_H_
#include "Lib/BaseType.h"
// ----------------------------------------------------------------------------------------------
class Object;
class Dict;
class ThingTemplate;
// ----------------------------------------------------------------------------------------------
/**
Handicap encapsulates the sets of modifiers to abilities used to balance
the game and give different abilities to different Players.
Conceptually, it's a large set of coefficients (typically, but not necessarily,
in the range of 0.0...1.0).
Usage example (conceptual):
Real armorCoef = this->m_handicap->getHandicap(ARMOR, this);
Real actualArmor = this->getArmorValue() * armorCoef;
*/
class Handicap
{
public:
// NOTE: if you ever add/remove/change the enums in HandicapType,
// you must also modify initFromDict()!
enum HandicapType
{
BUILDCOST,
BUILDTIME,
HANDICAP_TYPE_COUNT
};
Handicap();
/// reset all handicaps to a default value.
void init();
/**
initialize from the fields in the Dict. Note that this does NOT call init()
internally, so only those fields that are present in the dict will be set.
if you want to ensure all fields are something reasonable, you should call init()
prior to calling this.
*/
void readFromDict(const Dict* d);
/**
return the multiplier for the given Handicap type on the given Object.
The Object's type (unit, building, etc.) will generally be examined
to determine what value to return.
*/
Real getHandicap(HandicapType t, const ThingTemplate *tmpl) const;
protected:
private:
// NOTE: if you ever add/remove/change the enums in ThingType,
// you must also modify initFromDict()!
enum ThingType
{
GENERIC, // if a thing is nothing else, it's generic.
BUILDINGS,
THING_TYPE_COUNT
};
Real m_handicaps[HANDICAP_TYPE_COUNT][THING_TYPE_COUNT];
static ThingType getBestThingType(const ThingTemplate *tmpl);
};
#endif // _HANDICAP_H_

View File

@ -0,0 +1,408 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: INI.h ////////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, November 2001
// Desc: INI Reader
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __INI_H_
#define __INI_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include <stddef.h> // for offsetof, which we don't use but everyone who includes us does
#include "Common/STLTypedefs.h"
#include "Common/AsciiString.h"
#include "Common/GameCommon.h"
//-------------------------------------------------------------------------------------------------
class INI;
class Xfer;
class File;
enum ScienceType;
//-------------------------------------------------------------------------------------------------
/** These control the behavior of loading the INI data into items */
//-------------------------------------------------------------------------------------------------
enum INILoadType
{
INI_LOAD_INVALID, ///< invalid load type
INI_LOAD_OVERWRITE, ///< create new or load *over* existing data instance
INI_LOAD_CREATE_OVERRIDES, ///< create new or load into *new* override data instance
INI_LOAD_MULTIFILE ///< create new or continue loading into existing data instance.
};
//-------------------------------------------------------------------------------------------------
/** INI constant defines */
//-------------------------------------------------------------------------------------------------
enum
{
INI_MAX_CHARS_PER_LINE = 1028, ///< max characters per line entry in any ini file
};
//-------------------------------------------------------------------------------------------------
/** Status return codes for the INI reader */
//-------------------------------------------------------------------------------------------------
enum
{
// we map all of these to the same "real" error code, because
// we generally don't care why it failed; but since the code distinguishes,
// I didn't want to wipe out that intelligence. if we ever need to distinguish
// failure modes at runtime, just put in real values for these.
INI_CANT_SEARCH_DIR = ERROR_BAD_INI,
INI_INVALID_DIRECTORY = ERROR_BAD_INI,
INI_INVALID_PARAMS = ERROR_BAD_INI,
INI_INVALID_NAME_LIST = ERROR_BAD_INI,
INI_INVALID_DATA = ERROR_BAD_INI,
INI_MISSING_END_TOKEN = ERROR_BAD_INI,
INI_UNKNOWN_TOKEN = ERROR_BAD_INI,
INI_BUFFER_TOO_SMALL = ERROR_BAD_INI,
INI_FILE_NOT_OPEN = ERROR_BAD_INI,
INI_FILE_ALREADY_OPEN = ERROR_BAD_INI,
INI_CANT_OPEN_FILE = ERROR_BAD_INI,
INI_UNKNOWN_ERROR = ERROR_BAD_INI,
INI_END_OF_FILE = ERROR_BAD_INI
};
//-------------------------------------------------------------------------------------------------
/** Function typedef for parsing data block fields.
*
* buffer - the character buffer of the line from INI that we are reading and parsing
* instance - instance of what we're loading (for example a thingtemplate instance)
* store - where to store the data parsed, this is a field in the *instance* 'instance'
*/
//-------------------------------------------------------------------------------------------------
typedef void (*INIFieldParseProc)( INI *ini, void *instance, void *store, const void* userData );
//-------------------------------------------------------------------------------------------------
typedef const char* ConstCharPtr;
typedef const ConstCharPtr* ConstCharPtrArray;
//-------------------------------------------------------------------------------------------------
struct LookupListRec
{
const char* name;
Int value;
};
typedef const LookupListRec *ConstLookupListRecArray;
//-------------------------------------------------------------------------------------------------
/** Parse tables for all fields of each data block are created using these */
//-------------------------------------------------------------------------------------------------
struct FieldParse
{
const char* token; ///< token of the field
INIFieldParseProc parse; ///< the parse function
const void* userData; ///< field-specific data
Int offset; ///< offset to data field
inline void set(const char* t, INIFieldParseProc p, const void* u, Int o)
{
token = t;
parse = p;
userData = u;
offset = o;
}
};
//-------------------------------------------------------------------------------------------------
class MultiIniFieldParse
{
private:
enum { MAX_MULTI_FIELDS = 16 };
const FieldParse* m_fieldParse[MAX_MULTI_FIELDS];
UnsignedInt m_extraOffset[MAX_MULTI_FIELDS];
Int m_count;
public:
MultiIniFieldParse() : m_count(0)
{
//Added By Sadullah Nader
//Initializations missing and needed
for(Int i = 0; i < MAX_MULTI_FIELDS; i++)
m_extraOffset[i] = 0;
//
}
void add(const FieldParse* f, UnsignedInt e = 0);
inline Int getCount() const { return m_count; }
inline const FieldParse* getNthFieldParse(Int i) const { return m_fieldParse[i]; }
inline UnsignedInt getNthExtraOffset(Int i) const { return m_extraOffset[i]; }
};
//-------------------------------------------------------------------------------------------------
/** Function typedef for parsing INI types blocks */
//-------------------------------------------------------------------------------------------------
typedef void (*INIBlockParse)( INI *ini );
typedef void (*BuildMultiIniFieldProc)(MultiIniFieldParse& p);
//-------------------------------------------------------------------------------------------------
/** INI Reader interface */
//-------------------------------------------------------------------------------------------------
class INI
{
public:
INI();
~INI();
void loadDirectory( AsciiString dirName, Bool subdirs, INILoadType loadType, Xfer *pXfer ); ///< load directory of INI files
void load( AsciiString filename, INILoadType loadType, Xfer *pXfer ); ///< load INI file
static Bool isDeclarationOfType( AsciiString blockType, AsciiString blockName, char *bufferToCheck );
static Bool isEndOfBlock( char *bufferToCheck );
// data type parsing (the highest level of what type of thing we're parsing)
static void parseObjectDefinition( INI *ini );
static void parseObjectReskinDefinition( INI *ini );
static void parseWeaponTemplateDefinition( INI *ini );
static void parseScienceDefinition( INI *ini );
static void parseRankDefinition( INI *ini );
static void parseCrateTemplateDefinition( INI *ini );
static void parseLocomotorTemplateDefinition( INI *ini );
static void parseLanguageDefinition( INI *ini );
static void parsePlayerTemplateDefinition( INI *ini );
static void parseGameDataDefinition( INI *ini );
static void parseMapDataDefinition( INI *ini );
static void parseAnim2DDefinition( INI *ini );
static void parseAudioEventDefinition( INI *ini );
static void parseDialogDefinition( INI *ini );
static void parseMusicTrackDefinition( INI *ini );
static void parseWebpageURLDefinition( INI *ini );
static void parseHeaderTemplateDefinition( INI *ini );
static void parseParticleSystemDefinition( INI *ini );
static void parseWaterSettingDefinition( INI *ini );
static void parseWaterTransparencyDefinition( INI *ini );
static void parseMappedImageDefinition( INI *ini );
static void parseArmorDefinition( INI *ini );
static void parseDamageFXDefinition( INI *ini );
static void parseDrawGroupNumberDefinition( INI *ini );
static void parseTerrainDefinition( INI *ini );
static void parseTerrainRoadDefinition( INI *ini );
static void parseTerrainBridgeDefinition( INI *ini );
static void parseMetaMapDefinition( INI *ini );
static void parseFXListDefinition( INI *ini );
static void parseObjectCreationListDefinition( INI* ini );
static void parseMultiplayerSettingsDefinition( INI* ini );
static void parseMultiplayerColorDefinition( INI* ini );
static void parseOnlineChatColorDefinition( INI* ini );
static void parseMapCacheDefinition( INI* ini );
static void parseVideoDefinition( INI* ini );
static void parseCommandButtonDefinition( INI *ini );
static void parseCommandSetDefinition( INI *ini );
static void parseUpgradeDefinition( INI *ini );
static void parseMouseDefinition( INI* ini );
static void parseMouseCursorDefinition( INI* ini );
static void parseAIDataDefinition( INI *ini );
static void parseSpecialPowerDefinition( INI *ini );
static void parseInGameUIDefinition( INI *ini );
static void parseControlBarSchemeDefinition( INI *ini );
static void parseControlBarResizerDefinition( INI *ini );
static void parseShellMenuSchemeDefinition( INI *ini );
static void parseCampaignDefinition( INI *ini );
static void parseAudioSettingsDefinition( INI *ini );
static void parseMiscAudio( INI *ini );
static void parseStaticGameLODDefinition( INI *ini);
static void parseDynamicGameLODDefinition( INI *ini);
static void parseStaticGameLODLevel( INI* ini, void * , void *store, const void*);
static void parseDynamicGameLODLevel( INI* ini, void * , void *store, const void*);
static void parseLODPreset( INI* ini);
static void parseBenchProfile( INI* ini);
static void parseEvaEvent( INI* ini );
static void parseCredits( INI* ini );
static void parseWindowTransitions( INI* ini );
inline AsciiString getFilename( void ) const { return m_filename; }
inline INILoadType getLoadType( void ) const { return m_loadType; }
inline UnsignedInt getLineNum( void ) const { return m_lineNum; }
inline const char *getSeps( void ) const { return m_seps; }
inline const char *getSepsPercent( void ) const { return m_sepsPercent; }
inline const char *getSepsColon( void ) const { return m_sepsColon; }
inline const char *getSepsQuote( void ) { return m_sepsQuote; }
inline Bool isEOF( void ) const { return m_endOfFile; }
void initFromINI( void *what, const FieldParse* parseTable );
void initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList );
void initFromINIMultiProc( void *what, BuildMultiIniFieldProc proc );
static void parseUnsignedByte( INI *ini, void *instance, void *store, const void* userData );
static void parseShort( INI *ini, void *instance, void *store, const void* userData );
static void parseUnsignedShort( INI *ini, void *instance, void *store, const void* userData );
static void parseInt( INI *ini, void *instance, void *store, const void* userData );
static void parseUnsignedInt( INI *ini, void *instance, void *store, const void* userData );
static void parseReal( INI *ini, void *instance, void *store, const void* userData );
static void parsePositiveNonZeroReal( INI *ini, void *instance, void *store, const void* userData );
static void parseBool( INI *ini, void *instance, void *store, const void* userData );
static void parseBitInInt32( INI *ini, void *instance, void *store, const void* userData );
static void parseAsciiString( INI *ini, void *instance, void *store, const void* userData );
static void parseQuotedAsciiString( INI *ini, void *instance, void *store, const void* userData );
static void parseAsciiStringVector( INI *ini, void *instance, void *store, const void* userData );
static void parseAsciiStringVectorAppend( INI *ini, void *instance, void *store, const void* userData );
static void parseAndTranslateLabel( INI *ini, void *instance, void *store, const void* userData );
static void parseMappedImage( INI *ini, void *instance, void *store, const void *userData );
static void parseAnim2DTemplate( INI *ini, void *instance, void *store, const void *userData );
static void parsePercentToReal( INI *ini, void *instance, void *store, const void* userData );
static void parseRGBColor( INI *ini, void *instance, void *store, const void* userData );
static void parseRGBAColorInt( INI *ini, void *instance, void *store, const void* userData );
static void parseColorInt( INI *ini, void *instance, void *store, const void* userData );
static void parseCoord3D( INI *ini, void *instance, void *store, const void* userData );
static void parseCoord2D( INI *ini, void *instance, void *store, const void *userData );
static void parseICoord2D( INI *ini, void *instance, void *store, const void *userData );
static void parseDynamicAudioEventRTS( INI *ini, void *instance, void *store, const void* userData );
static void parseAudioEventRTS( INI *ini, void *instance, void *store, const void* userData );
static void parseFXList( INI *ini, void *instance, void *store, const void* userData );
static void parseParticleSystemTemplate( INI *ini, void *instance, void *store, const void *userData );
static void parseObjectCreationList( INI *ini, void *instance, void *store, const void* userData );
static void parseSpecialPowerTemplate( INI *ini, void *instance, void *store, const void *userData );
static void parseUpgradeTemplate( INI *ini, void *instance, void *store, const void *userData );
static void parseScience( INI *ini, void *instance, void *store, const void *userData );
static void parseScienceVector( INI *ini, void *instance, void *store, const void *userData );
static void parseGameClientRandomVariable( INI* ini, void *instance, void *store, const void* userData );
static void parseBitString8( INI *ini, void *instance, void *store, const void* userData );
static void parseBitString32( INI *ini, void *instance, void *store, const void* userData );
static void parseByteSizedIndexList( INI *ini, void *instance, void *store, const void* userData );
static void parseIndexList( INI *ini, void *instance, void *store, const void* userData );
static void parseLookupList( INI *ini, void *instance, void *store, const void* userData );
static void parseThingTemplate( INI *ini, void *instance, void *store, const void* userData );
static void parseArmorTemplate( INI *ini, void *instance, void *store, const void* userData );
static void parseDamageFX( INI *ini, void *instance, void *store, const void* userData );
static void parseWeaponTemplate( INI *ini, void *instance, void *store, const void* userData );
// parse a duration in msec and convert to duration in frames
static void parseDurationReal( INI *ini, void *instance, void *store, const void* userData );
// parse a duration in msec and convert to duration in integral number of frames, (unsignedint) rounding UP
static void parseDurationUnsignedInt( INI *ini, void *instance, void *store, const void* userData );
static void parseDurationUnsignedShort( INI *ini, void *instance, void *store, const void *userData );
// parse acceleration in (dist/sec) and convert to (dist/frame)
static void parseVelocityReal( INI *ini, void *instance, void *store, const void* userData );
// parse acceleration in (dist/sec^2) and convert to (dist/frame^2)
static void parseAccelerationReal( INI *ini, void *instance, void *store, const void* userData );
// parse angle in degrees and convert to radians
static void parseAngleReal( INI *ini, void *instance, void *store, const void *userData );
// note that this parses in degrees/sec, and converts to rads/frame!
static void parseAngularVelocityReal( INI *ini, void *instance, void *store, const void *userData );
static void parseDamageTypeFlags(INI* ini, void* instance, void* store, const void* userData);
static void parseDeathTypeFlags(INI* ini, void* instance, void* store, const void* userData);
static void parseVeterancyLevelFlags(INI* ini, void* instance, void* store, const void* userData);
static void parseSoundsList( INI* ini, void *instance, void *store, const void* /*userData*/ );
/**
return the next token. if seps is null (or omitted), the standard seps are used.
this will *never* return null; if there are no more tokens, an exception will be thrown.
*/
const char* getNextToken(const char* seps = NULL);
/**
just like getNextToken(), except that null is returned if no more tokens are present
(rather than throwing an exception). usually you should call getNextToken(),
but for some cases this is handier (ie, parsing a variable-length number of tokens).
*/
const char* getNextTokenOrNull(const char* seps = NULL);
/**
This is called when the next thing you expect is something like:
Tag:value
pass "Tag" (without the colon) for 'expected', and you will have the 'value'
token returned.
If "Tag" is not the next token, an error is thrown.
*/
const char* getNextSubToken(const char* expected);
/**
return the next ascii string. this is usually the same the result of getNextToken(),
except that it allows for quote-delimited strings (eg, "foo bar"), so you can
get strings with spaces, and/or empty strings.
*/
AsciiString getNextAsciiString();
AsciiString getNextQuotedAsciiString(); //fixed version of above. We can't fix the regular one for fear of breaking existing code. :-(
/**
utility routine that does a sscanf() on the string to get the Science, and throws
an exception if not of the right form.
*/
static ScienceType scanScience(const char* token);
/**
utility routine that does a sscanf() on the string to get the int, and throws
an exception if not of the right form.
*/
static Int scanInt(const char* token);
/**
utility routine that does a sscanf() on the string to get the unsigned int, and throws
an exception if not of the right form.
*/
static UnsignedInt scanUnsignedInt(const char* token);
/**
utility routine that does a sscanf() on the string to get the real, and throws
an exception if not of the right form.
*/
static Real scanReal(const char* token);
static Real scanPercentToReal(const char* token);
static Int scanIndexList(const char* token, ConstCharPtrArray nameList);
static Int scanLookupList(const char* token, ConstLookupListRecArray lookupList);
static Bool scanBool(const char* token);
protected:
static Bool isValidINIFilename( const char *filename ); ///< is this a valid .ini filename
void prepFile( AsciiString filename, INILoadType loadType );
void unPrepFile();
void readLine( void );
// FILE *m_file; ///< file pointer of file currently loading
File *m_file; ///< file pointer of file currently loading
AsciiString m_filename; ///< filename of file currently loading
INILoadType m_loadType; ///< load time for current file
UnsignedInt m_lineNum; ///< current line number that's been read
char m_buffer[ INI_MAX_CHARS_PER_LINE ]; ///< buffer to read file contents into
const char *m_seps; ///< for strtok parsing
const char *m_sepsPercent; ///< m_seps with percent delimiter as well
const char *m_sepsColon; ///< m_seps with colon delimiter as well
const char *m_sepsQuote; ///< token to represent a quoted ascii string
const char *m_blockEndToken; ///< token to represent end of data block
Bool m_endOfFile; ///< TRUE when we've hit EOF
#if defined(_DEBUG) || defined(_INTERNAL)
char m_curBlockStart[ INI_MAX_CHARS_PER_LINE ]; ///< first line of cur block
#endif
};
#endif // __INI_H_

View File

@ -0,0 +1,52 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: INIException.h ///////////////////////////////////////////////////////////////////////////
// Author: John McDonald, Jr, October 2002
// Desc: INI Exception class. Thrown when INIs fail to read.
///////////////////////////////////////////////////////////////////////////////////////////////////
class INIException
{
// This is a stack based exception class. It is used to output useful information
// when thrown from an INI message
public:
char *mFailureMessage;
INIException(const char* errorMessage) : mFailureMessage(NULL)
{
if (errorMessage) {
mFailureMessage = new char[strlen(errorMessage) + 1];
strcpy(mFailureMessage, errorMessage);
}
}
~INIException()
{
if (mFailureMessage) {
delete [] mFailureMessage;
}
}
};

View File

@ -0,0 +1,86 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: IgnorePreferences.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// created: Sep 2002
//
// Filename: IgnorePreferences.h
//
// author: Chris Huybregts
//
// purpose:
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __IGNORE_PREFERENCES_H_
#define __IGNORE_PREFERENCES_H_
//-----------------------------------------------------------------------------
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "Common/UserPreferences.h"
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// TYPE DEFINES ///////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
typedef std::map<Int, AsciiString> IgnorePrefMap;
class IgnorePreferences : public UserPreferences
{
public:
IgnorePreferences();
virtual ~IgnorePreferences();
void setIgnore(const AsciiString& userName, Int profileID, Bool ignore);
IgnorePrefMap getIgnores(void);
};
//-----------------------------------------------------------------------------
// INLINING ///////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// EXTERNALS //////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#endif // __IGNORE_PREFERENCES_H_

View File

@ -0,0 +1,194 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: KindOf.h //////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, Dec 2001
// Desc:
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __KINDOF_H_
#define __KINDOF_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Lib/BaseType.h"
#include "Common/BitFlags.h"
//-------------------------------------------------------------------------------------------------
/** Kind of flags for determining groups of things that belong together
* NOTE: You *MUST* keep this in the same order as the KindOfNames[] below */
//-------------------------------------------------------------------------------------------------
enum KindOfType
{
KINDOF_INVALID = -1,
KINDOF_FIRST = 0,
KINDOF_OBSTACLE = KINDOF_FIRST, ///< an obstacle to land-based pathfinders
KINDOF_SELECTABLE, ///< Selectable
KINDOF_IMMOBILE, ///< fixed in location
KINDOF_CAN_ATTACK, ///< can attack
KINDOF_STICK_TO_TERRAIN_SLOPE, ///< should be stuck at ground level, aligned to terrain slope. requires that IMMOBILE bit is also set.
KINDOF_CAN_CAST_REFLECTIONS, ///< can cast reflections in water
KINDOF_SHRUBBERY, ///< tree, bush, etc.
KINDOF_STRUCTURE, ///< structure of some sort (buildable or not)
KINDOF_INFANTRY, ///< unit like soldier etc
KINDOF_VEHICLE, ///< unit like tank, jeep, plane, helicopter, etc.
KINDOF_AIRCRAFT, ///< unit like plane, helicopter, etc., that is predominantly a flyer. (hovercraft are NOT aircraft)
KINDOF_HUGE_VEHICLE, ///< unit that is, technically, a vehicle, but WAY larger than normal (eg, Overlord)
KINDOF_DOZER, ///< a dozer
KINDOF_HARVESTER, ///< a harvester
KINDOF_COMMANDCENTER, ///< a command center
#ifdef ALLOW_SURRENDER
KINDOF_PRISON, ///< a prison detention center kind of thing
KINDOF_COLLECTS_PRISON_BOUNTY, ///< when prisoners are delivered to these, the player gets money
KINDOF_POW_TRUCK, ///< a pow truck can pick up and return prisoners
#endif
KINDOF_LINEBUILD, ///< wall-type thing that is built in a line
KINDOF_SALVAGER, ///< something that can create and use Salvage Crates
KINDOF_WEAPON_SALVAGER, ///< subset of salvager that can get weapon upgrades from salvage
KINDOF_TRANSPORT, ///< a true transport (has TransportContain)
KINDOF_BRIDGE, ///< a Bridge. (special structure)
KINDOF_LANDMARK_BRIDGE, ///< a landmark bridge (special bridge that isn't resizable)
KINDOF_BRIDGE_TOWER, ///< a bridge tower that we can target for bridge destruction
KINDOF_PROJECTILE, ///< Instead of being a ground or air unit, this object is special
KINDOF_PRELOAD, ///< all model data will be preloaded even if not on map
KINDOF_NO_GARRISON, ///< unit may not garrison bldgs, even if infantry bit is set
KINDOF_WAVEGUIDE, ///< water wave object
KINDOF_WAVE_EFFECT, ///< wave effect point
KINDOF_NO_COLLIDE, ///< Never collide with or be collided with
KINDOF_REPAIR_PAD, ///< is a repair pad object that can repair other machines
KINDOF_HEAL_PAD, ///< is a heal pad object that can heal flesh and bone units
KINDOF_STEALTH_GARRISON, /** enemy teams can't tell that unit is in building.. and if they
garrison that building, they stealth unit will eject. */
KINDOF_CASH_GENERATOR, ///< used to check if the unit generates cash... checked by cash hackers and whatever else comes up
KINDOF_AIRFIELD, ///< unit has a runway that planes can takeoff/land on
KINDOF_DRAWABLE_ONLY, ///< template is used only to create drawables (not Objects)
KINDOF_MP_COUNT_FOR_VICTORY, ///< If a player loses all his buildings that have this kindof in a multiplayer game, he loses.
KINDOF_REBUILD_HOLE, ///< a GLA rebuild hole
KINDOF_SCORE, ///< Object counts for Multiplayer scores, and short-game calculations (for buildings)
KINDOF_SCORE_CREATE, ///< Object only counts for multiplayer score for creation.
KINDOF_SCORE_DESTROY, ///< Object only counts for multiplayer score for destruction.
KINDOF_NO_HEAL_ICON, ///< do not ever display healing icons on these objects
KINDOF_CAN_RAPPEL, ///< can rappel. duh.
KINDOF_PARACHUTABLE, ///< parachutable object
#ifdef ALLOW_SURRENDER
KINDOF_CAN_SURRENDER, ///< object that can surrender
#endif
KINDOF_CAN_BE_REPULSED, ///< object that runs away from a repulsor object.
KINDOF_MOB_NEXUS, ///< object that cooyrdinates the members of a mob (i.e. GLAInfantryAngryMob)
KINDOF_IGNORED_IN_GUI, ///< object that is the members of a mob (i.e. GLAInfantryAngryMob)
KINDOF_CRATE, ///< a bonus crate
KINDOF_CAPTURABLE, ///< is "capturable" even if not an enemy (should generally be used only for structures, eg, Tech bldgs)
KINDOF_CLEARED_BY_BUILD, ///< is auto-cleared from the map when built over via construction
KINDOF_SMALL_MISSILE, ///< Missile object: ONLY USED FOR ANTI-MISSILE TARGETTING PURPOSES! Keep using PROJECTILE!
KINDOF_ALWAYS_VISIBLE, ///< is never obscured by fog of war or shroud. mostly for UI feedback objects.
KINDOF_UNATTACKABLE, ///< You cannot target this thing, it probably doesn't really exist
KINDOF_MINE, ///< a landmine. (possibly also extend to Col. Burton timed charges?)
KINDOF_CLEANUP_HAZARD, ///< radiation and bio-poison are samples of area conditions that can be cleaned up (or avoided)
KINDOF_PORTABLE_STRUCTURE, ///< Flag to identify building like subobjects an Overlord is allowed to Contain.
KINDOF_ALWAYS_SELECTABLE, ///< is never unselectable (even if effectively dead). mostly for UI feedback objects.
KINDOF_ATTACK_NEEDS_LINE_OF_SIGHT, ///< Unit has to have clear line of sight (los) to attack.
KINDOF_WALK_ON_TOP_OF_WALL, ///< Units can walk on top of a wall made of these kind of objects.
KINDOF_DEFENSIVE_WALL, ///< wall can't be driven thru, even if crusher, so pathfinder must path around it
KINDOF_FS_POWER, ///< Faction structure power building
KINDOF_FS_FACTORY, ///< Faction structure power building
KINDOF_FS_BASE_DEFENSE, ///< Faction structure base defense
KINDOF_FS_TECHNOLOGY, ///< Faction structure technology building
KINDOF_AIRCRAFT_PATH_AROUND, ///< Tall enough that aircraft need to path around this.
KINDOF_LOW_OVERLAPPABLE, ///< When overlapped, things always overlap at a 'low' height rather than our object geom
KINDOF_FORCEATTACKABLE, ///< unit is always attackable via force-attack, even if not selectable
KINDOF_AUTO_RALLYPOINT, ///< When immobile-structure-object is selected, left clicking on ground will set new rally point without requiring command button.
KINDOF_TECH_BUILDING, ///< Neutral tech building - Oil derrick, Hospital, Radio Station, Refinery.
KINDOF_POWERED, ///< This object gets the Underpowered disabled condition when its owning player has power consumption exceed supply
KINDOF_PRODUCED_AT_HELIPAD, ///< ugh... hacky fix for comanche. (srj)
KINDOF_DRONE, ///< Object drone type -- used for filtering them out of battle plan bonuses and whatever else may come up.
KINDOF_CAN_SEE_THROUGH_STRUCTURE,///< Structure does not block line of sight.
KINDOF_BALLISTIC_MISSILE, ///< Large ballistic missiles that are specifically large enough to be targetted by base defenses.
KINDOF_CLICK_THROUGH, ///< Objects with this will never be picked by mouse interactions!
KINDOF_SUPPLY_SOURCE_ON_PREVIEW,///< Any thing that we can get "supplies" from that we want to show up on the map preview
KINDOF_PARACHUTE, ///< it's a parachute
KINDOF_GARRISONABLE_UNTIL_DESTROYED, ///< Object is capable of garrisoning troops until completely destroyed.
KINDOF_BOAT, ///< It's a boat!
KINDOF_IMMUNE_TO_CAPTURE, ///< Under no circumstances can this building ever be captured.
KINDOF_HULK, ///< Hulk types so we can do special things to them via scripts or other things that may come up.
KINDOF_SHOW_PORTRAIT_WHEN_CONTROLLED, ///< Only shows portraits when controlled.
KINDOF_SPAWNS_ARE_THE_WEAPONS, ///< Evaluate the spawn slaves as this object's weapons.
KINDOF_CANNOT_BUILD_NEAR_SUPPLIES, ///< you can't be built "too close" to anything that provides supplies
KINDOF_SUPPLY_SOURCE, ///< this object provides supplies
KINDOF_REVEAL_TO_ALL, ///< this object reveals shroud for all players
KINDOF_DISGUISER, ///< This object has the ability to disguise.
KINDOF_INERT, ///< this object shouldn't be considered for any sort of interaction with any player.
KINDOF_HERO, ///< Any of the single-instance infantry, JarmenKell, BlackLotus, ColonelBurton
KINDOF_IGNORES_SELECT_ALL, ///< Too late to figure out intelligently if something should respond to a Select All command
KINDOF_DONT_AUTO_CRUSH_INFANTRY, ///< These units don't try to crush the infantry if ai.
KINDOF_COUNT // total number of kindofs
};
typedef BitFlags<KINDOF_COUNT> KindOfMaskType;
#define MAKE_KINDOF_MASK(k) KindOfMaskType(KindOfMaskType::kInit, (k))
inline Bool TEST_KINDOFMASK(const KindOfMaskType& m, KindOfType t)
{
return m.test(t);
}
inline Bool TEST_KINDOFMASK_ANY(const KindOfMaskType& m, const KindOfMaskType& mask)
{
return m.anyIntersectionWith(mask);
}
inline Bool TEST_KINDOFMASK_MULTI(const KindOfMaskType& m, const KindOfMaskType& mustBeSet, const KindOfMaskType& mustBeClear)
{
return m.testSetAndClear(mustBeSet, mustBeClear);
}
inline Bool KINDOFMASK_ANY_SET(const KindOfMaskType& m)
{
return m.any();
}
inline void CLEAR_KINDOFMASK(KindOfMaskType& m)
{
m.clear();
}
inline void SET_ALL_KINDOFMASK_BITS(KindOfMaskType& m)
{
m.clear();
m.flip();
}
inline void FLIP_KINDOFMASK(KindOfMaskType& m)
{
m.flip();
}
// defined in Common/System/Kindof.cpp
extern KindOfMaskType KINDOFMASK_NONE; // inits to all zeroes
#endif // __KINDOF_H_

View File

@ -0,0 +1,80 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// FILE: LadderPreferences.h
// Author: Matthew D. Campbell, August 2002
// Description: Saving/Loading of ladder preferences
///////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __LADDERPREFERENCES_H__
#define __LADDERPREFERENCES_H__
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "Common/UserPreferences.h"
//-----------------------------------------------------------------------------
// LadderPreferences base class
//-----------------------------------------------------------------------------
class LadderPref
{
public:
UnicodeString name;
AsciiString address;
UnsignedShort port;
time_t lastPlayDate;
bool operator== (const LadderPref& other)
{
return ( address==other.address && port==other.port );
}
};
typedef std::map<time_t, LadderPref> LadderPrefMap;
//-----------------------------------------------------------------------------
// LadderPreferences base class
//-----------------------------------------------------------------------------
class LadderPreferences : public UserPreferences
{
public:
LadderPreferences();
virtual ~LadderPreferences();
Bool loadProfile( Int profileID );
virtual bool write( void );
const LadderPrefMap& getRecentLadders( void );
void addRecentLadder( LadderPref ladder );
private:
LadderPrefMap m_ladders;
};
#endif // __LADDERPREFERENCES_H__

View File

@ -0,0 +1,108 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Language.h ///////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Language.h
//
// Created: Colin Day, June 2001
//
// Desc: Header for dealing with multiple languages
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __LANGUAGE_H_
#define __LANGUAGE_H_
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
// USER INCLUDES //////////////////////////////////////////////////////////////
// FORWARD REFERENCES /////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// TYPE DEFINES ///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// IMPORTANT: Make sure this enum is identical to the one in Noxstring tool
typedef enum
{
LANGUAGE_ID_US = 0,
LANGUAGE_ID_UK,
LANGUAGE_ID_GERMAN,
LANGUAGE_ID_FRENCH,
LANGUAGE_ID_SPANISH,
LANGUAGE_ID_ITALIAN,
LANGUAGE_ID_JAPANESE,
LANGUAGE_ID_JABBER,
LANGUAGE_ID_KOREAN,
LANGUAGE_ID_UNKNOWN
} LanguageID;
#define GameStrcpy wcscpy
#define GameStrncpy wcsncpy
#define GameStrlen wcslen
#define GameStrcat wcscat
#define GameStrcmp wcscmp
#define GameStrncmp wcsncmp
#define GameStricmp wcsicmp
#define GameStrnicmp wcsnicmp
#define GameStrtok wcstok
#define GameSprintf swprintf
#define GameVsprintf vswprintf
/// @todo -- add a non-malloc-based string dup func #define GameStrdup wcsdup
#define GameAtoi(S) wcstol( (S), NULL, 10)
#define GameAtod(S) wcstod( (S), NULL )
#define GameItoa _itow
#define GameSscanf swscanf
#define GameStrstr wcsstr
#define GameStrchr wcschr
#define GameIsDigit iswdigit
#define GameIsAscii iswascii
#define GameIsAlNum iswalnum
#define GameIsAlpha iswalpha
#define GameArrayEnd(array) (array)[(sizeof(array)/sizeof((array)[0]))-1] = 0
// INLINING ///////////////////////////////////////////////////////////////////
// EXTERNALS //////////////////////////////////////////////////////////////////
extern LanguageID OurLanguage; ///< our current language definition
#endif // __LANGUAGE_H_

View File

@ -0,0 +1,117 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// LatchRestore.h /////////////////////////////////////////////////////////////////////////////////
// Author: John K. McDonald, Jr.
// 09/19/2002
// DO NOT DISTRIBUTE
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __LATCHRESTORE_H__
#define __LATCHRESTORE_H__
/*
The purpose of the LatchRestore class is to allow you to override member variables for the scope
of a function. Here's the code that this saves:
void Foo::func(Team *overrideTeam)
{
Team *saveTeam = m_saveTeam;
m_saveTeam = overrideTeam;
// ... stuff ...
if (fu)
{
// early return
m_saveTeam = saveTeam;
return true;
}
if (bar)
{
// early return
m_saveTeam = saveTeam;
return true;
}
if (munkees)
{
// early return
m_saveTeam = saveTeam;
return true;
}
m_saveTeam = saveTeam;
return false;
}
Instead, the code would simply be:
void Foo::func(Team *overrideTeam)
{
LatchRestore<Team *> latch(m_saveTeam, overrideTeam);
// ... stuff ...
if (fu)
return true;
if (bar)
return true;
if (munkees)
return true;
return false;
}
*/
template <typename T>
class LatchRestore
{
protected:
T valueToRestore;
T& whereToRestore;
public:
LatchRestore(T& dest, const T& src) : whereToRestore(dest)
{
valueToRestore = dest;
dest = src;
}
virtual ~LatchRestore()
{
whereToRestore = valueToRestore;
}
};
#endif /* __LATCHRESTORE_H__ */

View File

@ -0,0 +1,181 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------=
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright(C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: WSYS Library
//
// Module:
//
// File name: wsys/List.h
//
// Created: 10/31/01
//
//----------------------------------------------------------------------------
#pragma once
#ifndef __WSYS_LIST_H
#define __WSYS_LIST_H
//----------------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------------
#ifndef _BASE_TYPE_H_
#include <lib/BaseType.h>
#endif
//----------------------------------------------------------------------------
// Forward References
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Type Defines
//----------------------------------------------------------------------------
//================================
// LLNode
//================================
/**
* Link list node abstraction for WSYS.
*/
//================================
class LListNode
{
friend class LList;
protected:
LListNode *m_next; ///< Next node in list
LListNode *m_prev; ///< Previous node in list
Int m_pri; ///< Node's priority, used for sorting
void *m_item; ///< Item we are referencing if any
Bool m_autoDelete; ///< destroy() should call delete
public:
LListNode(); ///< Constructor
void remove( void ); ///< Removes node from list
void insert( LListNode *new_node ); ///< Inserts new_node infront of itself
void append( LListNode *new_node ); ///< Appends new node after itself
LListNode* next( void ); ///< Returns next node in list
LListNode* prev( void ); ///< Returns previous node in list
LListNode* loopNext( void ); ///< Returns next node in list, warpping round to start of list if nessecary
LListNode* loopPrev( void ); ///< Returns previous node in list, wrapping round to end of list if nessecary
Bool inList( void ); ///< Returns whether or not node in list
Bool isHead( void ); ///< Returns whether or not this node is the head/tail node
Int priority( void ); ///< Returns node's priority
void setPriority( Int new_pri ); ///< Sets node's priority
void* item( void ); ///< Returns the item this links to, if any
void setItem( void *item ); ///< Make node point to an item
void destroy( void ); ///< Delete node
void autoDelete( void );
} ;
//================================
// LList
//================================
/**
* Linked list abstraction.
*/
//================================
class LList
{
public:
/// Enumeration of list sorting methods
enum SortMode
{
ASCENDING, ///< Lower priority numbers to front of list
DESCENDING ///< Higher priority numbers to front of list
};
protected:
LListNode m_head; ///< List head node
SortMode m_sortMode; ///< What sorting method to use for this list's Add() operation
Bool m_addToEndOfGroup; ///< Add nodes to end of group of nodes with same priority
public:
LList( );
void addToHead( LListNode *new_node ); ///< Adds new node to the front of the list
void addToTail( LListNode *new_node ); ///< Adds new node to the end of the list
void add( LListNode *new_node ); ///< Adds new node to list sorted by priority
void addItemToHead( void *item ); ///< Adds new item to the front of the list
void addItemToTail( void *item ); ///< Adds new item to the end of the list
void addItem( Int pri, void *item ); ///< Adds new item to list sorted by priority
Int nodeCount( void ); ///< Returns number of nodes currently in list
LListNode* firstNode( void ); ///< Returns first node in list
LListNode* lastNode( void ); ///< Returns last node in list
LListNode* getNode( Int index ); ///< Returns node in list addressed by the zero-based index passed
void setSortMode( SortMode new_mode ); ///< Sets the sorting mode for the Add() operation
void addToEndOfGroup( Bool yes = TRUE ); ///< Add node to end or start of group with same priority
Bool isEmpty( void ); ///< Returns whether or not the the list is empty
void clear( void ); ///< Deletes all items in the list. Use with care!!
void merge( LList *list ); ///< Move the contents of the specified list in to this list
Bool hasItem( void *item ); ///< Tests if list has the specified item
LListNode* findItem( void *item ); ///< Returns the LListNode that references item
void destroy( void ); ///< Free up the list items
} ;
//----------------------------------------------------------------------------
// Inlining
//----------------------------------------------------------------------------
inline Bool LListNode::inList( void ) { return m_prev != this; };
inline Bool LListNode::isHead( void ) { return ( m_item == (void*)&this->m_item ); };
inline Int LListNode::priority( void ) { return m_pri; };
inline void LListNode::setPriority( Int new_pri ) { m_pri = new_pri; };
inline void LListNode::autoDelete( void ) { m_autoDelete = TRUE; };
inline void* LListNode::item( void ) { return m_item; };
inline void LListNode::setItem( void *item ) { m_item = item; };
inline void LList::addToHead( LListNode *new_node ) { m_head.append( new_node); };
inline void LList::addToTail( LListNode *new_node ) { m_head.insert( new_node); };
inline LListNode* LList::firstNode( void ) { return m_head.next();} ;
inline LListNode* LList::lastNode( void ) { return m_head.prev();} ;
inline void LList::setSortMode( SortMode new_mode ) { m_sortMode = new_mode; };
inline Bool LList::isEmpty( void ) { return !m_head.inList(); };
inline void LList::destroy( void ) { clear();};
#endif // __GDF_LIST_H_

View File

@ -0,0 +1,132 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------=
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright(C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: WSYS Library
//
// Module: IO
//
// File name: LocalFile.h
//
// Created: 4/23/01
//
//----------------------------------------------------------------------------
#pragma once
#ifndef __LOCALFILE_H
#define __LOCALFILE_H
//----------------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------------
#include "Common/File.h"
// srj sez: this was purely an experiment in optimization.
// at the present time, it doesn't appear to be a good one.
// but I am leaving the code in for now.
// if still present in 2003, please nuke.
#define NO_USE_BUFFERED_IO
#ifdef USE_BUFFERED_IO
#include <stdio.h>
#endif
//----------------------------------------------------------------------------
// Forward References
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Type Defines
//----------------------------------------------------------------------------
//===============================
// LocalFile
//===============================
/**
* File abstraction for standard C file operators: open, close, lseek, read, write
*/
//===============================
class LocalFile : public File
{
MEMORY_POOL_GLUE_ABC(LocalFile)
private:
#ifdef USE_BUFFERED_IO
FILE* m_file;
enum { BUF_SIZE = 32768 };
char m_vbuf[BUF_SIZE];
#else
int m_handle; ///< Local C file handle
#endif
public:
LocalFile();
//virtual ~LocalFile();
virtual Bool open( const Char *filename, Int access = 0 ); ///< Open a file for access
virtual void close( void ); ///< Close the file
virtual Int read( void *buffer, Int bytes ); ///< Read the specified number of bytes in to buffer: See File::read
virtual Int write( const void *buffer, Int bytes ); ///< Write the specified number of bytes from the buffer: See File::write
virtual Int seek( Int new_pos, seekMode mode = CURRENT ); ///< Set file position: See File::seek
virtual void nextLine(Char *buf = NULL, Int bufSize = 0); ///< moves file position to after the next new-line
virtual Bool scanInt(Int &newInt); ///< return what gets read in as an integer at the current file position.
virtual Bool scanReal(Real &newReal); ///< return what gets read in as a float at the current file position.
virtual Bool scanString(AsciiString &newString); ///< return what gets read in as a string at the current file position.
/**
Allocate a buffer large enough to hold entire file, read
the entire file into the buffer, then close the file.
the buffer is owned by the caller, who is responsible
for freeing is (via delete[]). This is a Good Thing to
use because it minimizes memory copies for BIG files.
*/
virtual char* readEntireAndClose();
virtual File* convertToRAMFile();
};
//----------------------------------------------------------------------------
// Inlining
//----------------------------------------------------------------------------
#endif // __LOCALFILE_H

View File

@ -0,0 +1,59 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
/////// LocalFileSystem.h ////////////////////////////////
// Bryan Cleveland, August 2002
//////////////////////////////////////////////////////////
#pragma once
#ifndef __LOCALFILESYSTEM_H
#define __LOCALFILESYSTEM_H
#include "Common/SubsystemInterface.h"
#include "FileSystem.h" // for typedefs, etc.
class File;
class LocalFileSystem : public SubsystemInterface
{
public:
virtual ~LocalFileSystem() {}
virtual void init() = 0;
virtual void reset() = 0;
virtual void update() = 0;
virtual File * openFile(const Char *filename, Int access = 0) = 0;
virtual Bool doesFileExist(const Char *filename) const = 0;
virtual void getFileListInDirectory(const AsciiString& currentDirectory, const AsciiString& originalDirectory, const AsciiString& searchName, FilenameList &filenameList, Bool searchSubdirectories) const = 0; ///< search the given directory for files matching the searchName (egs. *.ini, *.rep). Possibly search subdirectories.
virtual Bool getFileInfo(const AsciiString& filename, FileInfo *fileInfo) const = 0; ///< see FileSystem.h
virtual Bool createDirectory(AsciiString directory) = 0; ///< see FileSystem.h
protected:
};
extern LocalFileSystem *TheLocalFileSystem;
#endif // __LOCALFILESYSTEM_H

View File

@ -0,0 +1,175 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// MapObject.h
// Class to encapsulate height map.
// Author: John Ahlquist, April 2001
#pragma once
#ifndef MapObject_H
#define MapObject_H
#include "Common/Dict.h"
#include "Common/GameMemory.h"
#include "GameClient/TerrainRoads.h"
/** MapObject class
Not ref counted. Do not store pointers to this class. */
class WorldHeightMap;
class RenderObjClass;
class ThingTemplate;
class Shadow;
enum WaypointID;
#define MAP_XY_FACTOR (10.0f) //How wide and tall each height map square is in world space.
#define MAP_HEIGHT_SCALE (MAP_XY_FACTOR/16.0f) //divide all map heights by 8.
// m_flags bit values.
enum {
FLAG_DRAWS_IN_MIRROR = 0x00000001, ///< If set, draws in water mirror.
FLAG_ROAD_POINT1 = 0x00000002, ///< If set, is the first point in a road segment.
FLAG_ROAD_POINT2 = 0x00000004, ///< If set, is the second point in a road segment.
FLAG_ROAD_FLAGS = (FLAG_ROAD_POINT1|FLAG_ROAD_POINT2), ///< If nonzero, object is a road piece.
FLAG_ROAD_CORNER_ANGLED = 0x00000008, ///< If set, the road corner is angled rather than curved.
FLAG_BRIDGE_POINT1 = 0x00000010, ///< If set, is the first point in a bridge.
FLAG_BRIDGE_POINT2 = 0x00000020, ///< If set, is the second point in a bridge.
FLAG_BRIDGE_FLAGS = (FLAG_BRIDGE_POINT1|FLAG_BRIDGE_POINT2), ///< If nonzero, object is a bridge piece.
FLAG_ROAD_CORNER_TIGHT = 0x00000040,
FLAG_ROAD_JOIN = 0x00000080, ///< If set, this road end does a generic alpha join.
FLAG_DONT_RENDER = 0x00000100 ///< If set, do not render this object. Only WB pays attention to this. (Right now, anyways)
};
class MapObject : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(MapObject, "MapObject")
// friend doesn't play well with MPO -- srj
// friend class WorldHeightMap;
// friend class WorldHeightMapEdit;
// friend class AddObjectUndoable;
// friend class DeleteInfo;
enum
{
MO_SELECTED = 0x01,
MO_LIGHT = 0x02,
MO_WAYPOINT = 0x04,
MO_SCORCH = 0x08
};
// This data is currently written out into the map data file.
Coord3D m_location; ///< Location of the center of the object.
AsciiString m_objectName; ///< The object name.
const ThingTemplate* m_thingTemplate; ///< thing template for map object
Real m_angle; ///< positive x is 0 degrees, angle is counterclockwise in degrees.
MapObject* m_nextMapObject; ///< linked list.
Int m_flags; ///< Bit flags.
Dict m_properties; ///< general property sheet.
// This data is runtime data that is used by the worldbuider editor, but
// not saved in the map file.
Int m_color; ///< Display color.
RenderObjClass* m_renderObj; ///< object that renders in the 3d scene.
Shadow* m_shadowObj; ///< object that renders shadow in the 3d scene.
RenderObjClass* m_bridgeTowers[ BRIDGE_MAX_TOWERS ]; ///< for bridge towers
Int m_runtimeFlags;
public:
static MapObject *TheMapObjectListPtr;
static Dict TheWorldDict;
public:
MapObject(Coord3D loc, AsciiString name, Real angle, Int flags, const Dict* props,
const ThingTemplate *thingTemplate );
//~MapObject(void); ///< Note that deleting the head of a list deletes all linked objects in the list.
public:
Dict *getProperties() { return &m_properties; } ///< return the object's property sheet.
void setNextMap(MapObject *nextMap) {m_nextMapObject = nextMap;} ///< Link the next map object.
const Coord3D *getLocation(void) const {return &m_location;} ///< Get the center point.
Real getAngle(void) const {return m_angle;} ///< Get the angle.
Int getColor(void) const {return m_color;} ///< Gets whatever ui color we set.
void setColor(Int color) {m_color=color;} ///< Sets the ui color.
AsciiString getName(void) const {return m_objectName;} ///< Gets the object name
void setName(AsciiString name); ///< Sets the object name
void setThingTemplate( const ThingTemplate* thing ); ///< set template
const ThingTemplate *getThingTemplate( void ) const;
MapObject *getNext(void) const {return m_nextMapObject;} ///< Next map object in the list. Not a copy, don't delete it.
MapObject *duplicate(void); ///< Allocates a copy. Caller is responsible for delete-ing this when done with it.
void setAngle(Real angle) {m_angle = normalizeAngle(angle);}
void setLocation(Coord3D *pLoc) {m_location = *pLoc;}
void setFlag(Int flag) {m_flags |= flag;}
void clearFlag(Int flag) {m_flags &= (~flag);}
Bool getFlag(Int flag) const {return (m_flags&flag)?true:false;}
Int getFlags(void) const {return (m_flags);}
Bool isSelected(void) const {return (m_runtimeFlags & MO_SELECTED) != 0;}
void setSelected(Bool sel) { if (sel) m_runtimeFlags |= MO_SELECTED; else m_runtimeFlags &= ~MO_SELECTED; }
Bool isLight(void) const {return (m_runtimeFlags & MO_LIGHT) != 0;}
Bool isWaypoint(void) const {return (m_runtimeFlags & MO_WAYPOINT) != 0;}
Bool isScorch(void) const {return (m_runtimeFlags & MO_SCORCH) != 0;}
void setIsLight() {m_runtimeFlags |= MO_LIGHT;}
void setIsWaypoint() { m_runtimeFlags |= MO_WAYPOINT; }
void setIsScorch() { m_runtimeFlags |= MO_SCORCH; }
void setRenderObj(RenderObjClass *pObj);
RenderObjClass *getRenderObj(void) const {return m_renderObj;}
void setShadowObj(Shadow *pObj) {m_shadowObj=pObj;}
Shadow *getShadowObj(void) const {return m_shadowObj;}
RenderObjClass* getBridgeRenderObject( BridgeTowerType type );
void setBridgeRenderObject( BridgeTowerType type, RenderObjClass* renderObj );
WaypointID getWaypointID();
AsciiString getWaypointName();
void setWaypointID(Int i);
void setWaypointName(AsciiString n);
// calling validate will call verifyValidTeam and verifyValidUniqueID.
void validate(void);
// verifyValidTeam will either place the map object on an approrpriate team, or leave the
// current team (if it is valid)
void verifyValidTeam(void);
// verifyValidUniqueID will ensure that this unit isn't sharing a number with another unit.
void verifyValidUniqueID(void);
// The fast version doesn't attempt to verify uniqueness. It goes
static void fastAssignAllUniqueIDs(void);
static MapObject *getFirstMapObject(void) { return TheMapObjectListPtr; }
static Dict* getWorldDict() { return &TheWorldDict; }
static Int countMapObjectsWithOwner(const AsciiString& n);
};
#endif

View File

@ -0,0 +1,129 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// MapReaderWriterInfo.h
// Version and interface info for map file writers and reader.
// Author: John Ahlquist, October 2001
#pragma once
#ifndef _MAP_READER_WRITER_INFO_H_
#define _MAP_READER_WRITER_INFO_H_
#define K_HEIGHT_MAP_VERSION_1 1 // Height map cell = 5.0
#define K_HEIGHT_MAP_VERSION_2 2 // Height map cell = 10.0
#define K_HEIGHT_MAP_VERSION_3 3 // Added m_borderSize
#define K_HEIGHT_MAP_VERSION_4 4 // Major rev. See comments at bottom of file.
#define K_BLEND_TILE_VERSION_1 1 // Height map cell = 5.0
#define K_BLEND_TILE_VERSION_2 2 // Height map cell = 10.0
#define K_BLEND_TILE_VERSION_3 3 // Added long diagonal blends.
#define K_BLEND_TILE_VERSION_4 4 // Added custom edge blends.
#define K_BLEND_TILE_VERSION_5 5 // Added custom cliff u/v coordinates.
#define K_BLEND_TILE_VERSION_6 6 // Added extra blend layer for 3 textures in cell.
#define K_BLEND_TILE_VERSION_7 7 // Added flag for painting passable/impassable to cells.
#define K_OBJECTS_VERSION_1 1 // no dict
#define K_OBJECTS_VERSION_2 2 // includes dict
#define K_OBJECTS_VERSION_3 3 // includes dict
#define K_MAP_OBJECT_VERSION_1 1
#define K_WAYPOINTS_VERSION_1 1
#define K_PLAYERLIST_VERSION_1 1
#define K_TRIGGERS_VERSION_1 1
#define K_TRIGGERS_VERSION_2 2 // Added m_isWaterArea
#define K_TRIGGERS_VERSION_3 3 // Added m_isRiver & m_riverStart
#define K_LIGHTING_VERSION_1 1
#define K_LIGHTING_VERSION_2 2 // Added 2 additional global lights for objects.
#define K_LIGHTING_VERSION_3 3 // Added 2 additional global lights for terrain.
#define K_WORLDDICT_VERSION_1 1
#define K_MAPPREVIEW_VERSION_1 1
/** Virtual helper class, so that we can write map data using FILE* or CFile. */
class OutputStream {
public:
virtual Int write(const void *pData, Int numBytes) = 0;
};
/** Virtual helper class, so that we can read in tile and map data from a
variety of sources, such as FILE* or CFile. */
class InputStream {
public:
virtual Int read(void *pData, Int numBytes) = 0;
};
/** Virtual helper class, so that we can read in tile and map data from a
variety of sources, such as FILE* or CFile. */
class ChunkInputStream : public InputStream{
public:
virtual Int read(void *pData, Int numBytes) = 0;
virtual UnsignedInt tell(void) = 0;
virtual Bool absoluteSeek(UnsignedInt pos) = 0;
virtual Bool eof(void) = 0;
};
/** An instance of InputStream that uses a FILE* to read data. */
class CachedFileInputStream : public ChunkInputStream
{
protected:
int m_size;
char* m_buffer;
int m_pos;
public:
CachedFileInputStream(void);
~CachedFileInputStream(void);
Bool open(AsciiString path); ///< Returns true if open succeeded.
void close(void); ///< Explict close. Destructor closes if file is left open.
virtual Int read(void *pData, Int numBytes);
virtual UnsignedInt tell(void);
virtual Bool absoluteSeek(UnsignedInt pos);
virtual Bool eof(void);
void rewind(void);
};
/** An instance of InputStream that uses a FILE* to read data. */
/* Always using Cached version, as that lets us do compression, etc easily
class FileInputStream : public ChunkInputStream
{
protected:
File *m_file;
public:
FileInputStream(void);
~FileInputStream(void);
Bool open(AsciiString path); ///< Returns true if open succeeded.
void close(void); ///< Explict close. Destructor closes if file is left open.
virtual Int read(void *pData, Int numBytes);
virtual UnsignedInt tell(void);
virtual Bool absoluteSeek(UnsignedInt pos);
virtual Bool eof(void);
void rewind(void);
};
*/
#endif // _MAP_READER_WRITER_INFO_H_
/*
rev K_HEIGHT_MAP_VERSION_4
This is a major rev of the heightmap chunk. Here's the basic overview of what has happened:
We now support multiple boundary areas. They are stored in a vector of ICoord2Ds. The lower-
left corner is always (0,0), and the ICoord2D specifies the top-right coordinate.
The boundary also contains a name.
*/

View File

@ -0,0 +1,798 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: MessageStream.h //////////////////////////////////////////////////////
// The message stream propagates all messages thru a series of "translators"
// Author: Michael S. Booth, February 2001
#pragma once
#ifndef _MESSAGE_STREAM_H_
#define _MESSAGE_STREAM_H_
#include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
#include "Common/SubsystemInterface.h"
#include "Lib/BaseType.h"
#include "Common/GameMemory.h"
enum { TRANSLATOR_ID_INVALID = -1 };
// how far the the cursor moves before a click becomes a drag
typedef UnsignedInt TranslatorID; ///< Unique identifiers for message stream translators
class Drawable;
class GameMessageList;
enum ObjectID;
enum DrawableID;
union GameMessageArgumentType ///< Union of possible data for given message type
{
Int integer;
Real real;
Bool boolean;
ObjectID objectID;
DrawableID drawableID;
UnsignedInt teamID;
UnsignedInt squadID;
Coord3D location;
ICoord2D pixel;
IRegion2D pixelRegion;
UnsignedInt timestamp;
WideChar wChar;
};
enum GameMessageArgumentDataType
{
ARGUMENTDATATYPE_INTEGER,
ARGUMENTDATATYPE_REAL,
ARGUMENTDATATYPE_BOOLEAN,
ARGUMENTDATATYPE_OBJECTID,
ARGUMENTDATATYPE_DRAWABLEID,
ARGUMENTDATATYPE_TEAMID,
ARGUMENTDATATYPE_LOCATION,
ARGUMENTDATATYPE_PIXEL,
ARGUMENTDATATYPE_PIXELREGION,
ARGUMENTDATATYPE_TIMESTAMP,
ARGUMENTDATATYPE_WIDECHAR,
ARGUMENTDATATYPE_UNKNOWN
};
class GameMessageArgument : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessageArgument, "GameMessageArgument")
public:
GameMessageArgument* m_next; ///< The next argument
GameMessageArgumentType m_data; ///< The data storage of an argument
GameMessageArgumentDataType m_type; ///< The type of the argument.
};
EMPTY_DTOR(GameMessageArgument)
/**
* A game message that either lives on TheMessageStream or TheCommandList.
* Messages consist of a type, defining what the message is, and zero or more arguments
* of various data types. The user of a message must know how many and what type of
* arguments are valid for a given message type.
*/
class GameMessage : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(GameMessage, "GameMessage")
public:
/// The various messages which can be sent in a MessageStream
/// @todo Replace this hardcoded enum with a generalized system that can be easily changed and updated
/** @todo Because the Client will run faster than Logic, we'll need "superceding" messages for events
such as mouse movements so we only send the latest one over the net */
/** @todo Create two classes of message: raw input messages, and command messages. Raw input messages
will be destroyed when they reach the end of the stream, whereas command messages will be
transferred to TheCommandList */
enum Type
{
MSG_INVALID, ///< (none) this msg should never actually occur
MSG_FRAME_TICK, ///< (timestamp) once each frame this message is sent thru the stream
// Client to Server messages
// Note: Please keep MSG_RAW_MOUSE between MSG_RAW_MOUSE_BEGIN and MSG_RAW_MOUSE_END
MSG_RAW_MOUSE_BEGIN,
MSG_RAW_MOUSE_POSITION, ///< (pixel) the cursor's position
MSG_RAW_MOUSE_LEFT_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_LEFT_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_MIDDLE_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_MIDDLE_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_RIGHT_BUTTON_DOWN, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_DOUBLE_CLICK, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_BUTTON_UP, ///< (pixel, modifiers, time)
MSG_RAW_MOUSE_RIGHT_DRAG, ///< drag of the mouse with a button held down
MSG_RAW_MOUSE_WHEEL, ///< (Int spin, + is away, - is toward user)
MSG_RAW_MOUSE_END,
MSG_RAW_KEY_DOWN, ///< (KeyDefType) the given key was pressed (uses Microsoft VK_ codes)
MSG_RAW_KEY_UP, ///< (KeyDefType) the given key was released
// Refined Mouse messages
// NOTE: All processing should attempt to use these refined mouse messages, rather than the
// RAW_* variants. (Please.) :-) jkmcd
MSG_MOUSE_LEFT_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_LEFT_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_MIDDLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_MIDDLE_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_RIGHT_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
MSG_MOUSE_RIGHT_DOUBLE_CLICK, ///< (pixelRegion, 0 sized means its a point), (Int, modifier keys)
// End Refined Mouse Messages
MSG_CLEAR_GAME_DATA, ///< Clear all game data in memory
MSG_NEW_GAME, ///< Start a new game
// "meta" messages should be thought of as "virtual keystrokes" -- they exist
// solely to provide an abstraction layer useful for keyboard/mouse remapping.
// they should NEVER be sent over the network.
MSG_BEGIN_META_MESSAGES, ///< Marker to delineate "meta" messages
MSG_META_SAVE_VIEW1, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW2, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW3, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW4, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW5, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW6, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW7, ///< save current view as the given user-defined view
MSG_META_SAVE_VIEW8, ///< save current view as the given user-defined view
MSG_META_VIEW_VIEW1, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW2, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW3, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW4, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW5, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW6, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW7, ///< center view on the given user-defined view
MSG_META_VIEW_VIEW8, ///< center view on the given user-defined view
MSG_META_CREATE_TEAM0, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM1, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM2, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM3, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM4, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM5, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM6, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM7, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM8, ///< create user-defined team from the selected objects
MSG_META_CREATE_TEAM9, ///< create user-defined team from the selected objects
MSG_META_SELECT_TEAM0, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM1, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM2, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM3, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM4, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM5, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM6, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM7, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM8, ///< deselect all, then select all units in the given user-defined team
MSG_META_SELECT_TEAM9, ///< deselect all, then select all units in the given user-defined team
MSG_META_ADD_TEAM0, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM1, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM2, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM3, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM4, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM5, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM6, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM7, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM8, ///< add the user-defined team to the current selection
MSG_META_ADD_TEAM9, ///< add the user-defined team to the current selection
MSG_META_VIEW_TEAM0, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM1, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM2, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM3, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM4, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM5, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM6, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM7, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM8, ///< center view on given user-defined team (but do not affect selection)
MSG_META_VIEW_TEAM9, ///< center view on given user-defined team (but do not affect selection)
MSG_META_SELECT_MATCHING_UNITS, ///< selects mathcing units, used for both on screen and across map
MSG_META_SELECT_NEXT_UNIT, ///< select 'next' unit
MSG_META_SELECT_PREV_UNIT, ///< select 'prev' unit
MSG_META_SELECT_NEXT_WORKER, ///< select 'next' worker
MSG_META_SELECT_PREV_WORKER, ///< select 'prev' worker
MSG_META_VIEW_COMMAND_CENTER, ///< center view on command center
MSG_META_VIEW_LAST_RADAR_EVENT, ///< center view on last radar event
MSG_META_SELECT_HERO, ///< selects player's hero character, if exists...
MSG_META_SELECT_ALL, ///< selects all units across screen
MSG_META_SCATTER, ///< selected units scatter
MSG_META_STOP, ///< selected units stop
MSG_META_DEPLOY, ///< selected units 'deploy'
MSG_META_CREATE_FORMATION, ///< selected units become a formation
MSG_META_FOLLOW, ///< selected units 'follow'
MSG_META_CHAT_PLAYERS, ///< send chat msg to all players
MSG_META_CHAT_ALLIES, ///< send chat msg to allied players
MSG_META_CHAT_EVERYONE, ///< send chat msg to everyone (incl. observers)
MSG_META_DIPLOMACY, ///< bring up diplomacy screen
MSG_META_OPTIONS, ///< bring up options screen
#if defined(_DEBUG) || defined(_INTERNAL)
MSG_META_HELP, ///< bring up help screen
#endif
MSG_META_TOGGLE_LOWER_DETAILS, ///< toggles graphics options to crappy mode instantly
MSG_META_TOGGLE_CONTROL_BAR, ///< show/hide controlbar
MSG_META_BEGIN_PATH_BUILD, ///< enter path-building mode
MSG_META_END_PATH_BUILD, ///< exit path-building mode
MSG_META_BEGIN_FORCEATTACK, ///< enter force-attack mode
MSG_META_END_FORCEATTACK, ///< exit force-attack mode
MSG_META_BEGIN_FORCEMOVE, ///< enter force-move mode
MSG_META_END_FORCEMOVE, ///< exit force-move mode
MSG_META_BEGIN_WAYPOINTS, ///< enter waypoint mode
MSG_META_END_WAYPOINTS, ///< exit waypoint mode
MSG_META_BEGIN_PREFER_SELECTION, ///< The Shift key has been depressed alone
MSG_META_END_PREFER_SELECTION, ///< The Shift key has been released.
MSG_META_TAKE_SCREENSHOT, ///< take screenshot
MSG_META_ALL_CHEER, ///< Yay! :)
MSG_META_TOGGLE_ATTACKMOVE, ///< enter attack-move mode
MSG_META_BEGIN_CAMERA_ROTATE_LEFT,
MSG_META_END_CAMERA_ROTATE_LEFT,
MSG_META_BEGIN_CAMERA_ROTATE_RIGHT,
MSG_META_END_CAMERA_ROTATE_RIGHT,
MSG_META_BEGIN_CAMERA_ZOOM_IN,
MSG_META_END_CAMERA_ZOOM_IN,
MSG_META_BEGIN_CAMERA_ZOOM_OUT,
MSG_META_END_CAMERA_ZOOM_OUT,
MSG_META_CAMERA_RESET,
// META items that are really for debug/demo/development use only...
// They do not get built into RELEASE builds.
#if defined(_DEBUG) || defined(_INTERNAL)
MSG_META_DEMO_TOGGLE_BEHIND_BUILDINGS, ///< Toggles showing units behind buildings or not
MSG_META_DEMO_TOGGLE_LETTERBOX, ///< enable/disable letterbox mode
MSG_META_DEMO_TOGGLE_MESSAGE_TEXT, ///< toggle the text from the UI messages
MSG_META_DEMO_LOD_DECREASE, ///< decrease LOD by 1
MSG_META_DEMO_LOD_INCREASE, ///< increase LOD by 1
MSG_META_DEMO_TOGGLE_ZOOM_LOCK, ///< Toggle the camera zoom lock on/off
MSG_META_DEMO_PLAY_CAMEO_MOVIE, ///< Play a movie in the cameo spot
MSG_META_DEMO_INSTANT_QUIT, ///< bail out of game immediately
MSG_META_DEMO_TOGGLE_SPECIAL_POWER_DELAYS, ///< Toggle special power delays on/off
MSG_META_DEMO_BATTLE_CRY, ///< battle cry
MSG_META_DEMO_SWITCH_TEAMS, ///< switch local control to another team
MSG_META_DEMO_SWITCH_TEAMS_BETWEEN_CHINA_USA, ///< switch the local player between china and usa
MSG_META_DEMO_TOGGLE_PARTICLEDEBUG, ///< show/hide the particle system debug info
MSG_META_DEMO_TOGGLE_SHADOW_VOLUMES, ///< show/hide shadow volumes
MSG_META_DEMO_TOGGLE_FOGOFWAR,
MSG_META_DEMO_KILL_ALL_ENEMIES, ///< kill ALL ENEMIES! (yeah!)
MSG_META_DEMO_KILL_SELECTION, ///< kill the selected units (yeah!)
MSG_META_DEMO_TOGGLE_HURT_ME_MODE, ///< do 10% damage to the selected units (yeah!)
MSG_META_DEMO_TOGGLE_HAND_OF_GOD_MODE, ///< do 100% damage to the selected units (w00t!)
MSG_META_DEMO_DEBUG_SELECTION, ///< select a given unit for state-machine debugging
MSG_META_DEMO_LOCK_CAMERA_TO_SELECTION, ///< lock the view camera to the selected object
MSG_META_DEMO_TOGGLE_SOUND, ///< toggle sound/video on/off
MSG_META_DEMO_TOGGLE_TRACKMARKS, ///< toggle tank tread marks on/off
MSG_META_DEMO_TOGGLE_WATERPLANE, ///< toggle waterplane on/off
MSG_META_DEMO_TIME_OF_DAY, ///< change time-of-day lighting
MSG_META_DEMO_TOGGLE_MUSIC, ///< turn background music on/off
MSG_META_DEMO_MUSIC_NEXT_TRACK, ///< play next track
MSG_META_DEMO_MUSIC_PREV_TRACK, ///< play prev track
MSG_META_DEMO_NEXT_OBJECTIVE_MOVIE, ///< play next "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE1, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE2, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE3, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE4, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE5, ///< play specific "Objective" movie
MSG_META_DEMO_PLAY_OBJECTIVE_MOVIE6, ///< play specific "Objective" movie
MSG_META_DEMO_BEGIN_ADJUST_PITCH, ///< enter adjust-pitch mode
MSG_META_DEMO_END_ADJUST_PITCH, ///< exit adjust-pitch mode
MSG_META_DEMO_BEGIN_ADJUST_FOV, ///< enter adjust-FOV mode
MSG_META_DEMO_END_ADJUST_FOV, ///< exit adjust-FOV mode
MSG_META_DEMO_LOCK_CAMERA_TO_PLANES, ///< lock camera to airborne thingies
MSG_META_DEMO_REMOVE_PREREQ, ///< Turn of Prerequisite checks in building legality
MSG_META_DEMO_INSTANT_BUILD, ///< All building is with a timer of 1
MSG_META_DEMO_FREE_BUILD, ///< All building is for 0 money
MSG_META_DEMO_RUNSCRIPT1, ///< run script named "KEY_F1"
MSG_META_DEMO_RUNSCRIPT2, ///< run script named "KEY_F2"
MSG_META_DEMO_RUNSCRIPT3, ///< run script named "KEY_F3"
MSG_META_DEMO_RUNSCRIPT4, ///< run script named "KEY_F4"
MSG_META_DEMO_RUNSCRIPT5, ///< run script named "KEY_F5"
MSG_META_DEMO_RUNSCRIPT6, ///< run script named "KEY_F6"
MSG_META_DEMO_RUNSCRIPT7, ///< run script named "KEY_F7"
MSG_META_DEMO_RUNSCRIPT8, ///< run script named "KEY_F8"
MSG_META_DEMO_RUNSCRIPT9, ///< run script named "KEY_F9"
MSG_META_DEMO_ENSHROUD, ///< re-shroud the world for the local player
MSG_META_DEMO_DESHROUD, ///< de-shroud the world for the local player
MSG_META_DEBUG_SHOW_EXTENTS, ///< show object extents
MSG_META_DEBUG_SHOW_HEALTH, ///< show object health
MSG_META_DEBUG_GIVE_VETERANCY, ///< give a veterancy level to selected objects
MSG_META_DEBUG_TAKE_VETERANCY, ///< take a veterancy level from selected objects
MSG_META_DEMO_TOGGLE_AI_DEBUG, ///< show/hide the ai debug stats
MSG_META_DEMO_TOGGLE_CAMERA_DEBUG, ///< show/hide the camera debug stats
MSG_META_DEMO_TOGGLE_AVI, ///< start capturing video
MSG_META_DEMO_TOGGLE_BW_VIEW, ///< enable/disable black & white camera mode
MSG_META_DEMO_TOGGLE_RED_VIEW, ///< enable/disable red tinted view
MSG_META_DEMO_TOGGLE_GREEN_VIEW, ///< enable/disable green view
MSG_META_DEMO_TOGGLE_MOTION_BLUR_ZOOM, ///< enable/disable green view
MSG_META_DEMO_TOGGLE_MILITARY_SUBTITLES, ///< enable/disable military subtitles
MSG_META_DEMO_ADD_CASH, ///< adds 10000 cash to the player
#ifdef ALLOW_SURRENDER
MSG_META_DEMO_TEST_SURRENDER, ///< Test key to show surrender animation in game.
#endif
MSG_META_DEMO_TOGGLE_RENDER, ///< toggle rendering on/off
MSG_META_DEMO_KILL_AREA_SELECTION, ///< (teamID, objectID1, objectID2, ... objectIDN)
MSG_META_DEMO_CYCLE_LOD_LEVEL, ///< cycles through dynamic game detail levels.
MSG_META_DEBUG_INCR_ANIM_SKATE_SPEED, ///< for debugging anim skate speeds
MSG_META_DEBUG_DECR_ANIM_SKATE_SPEED, ///< for debugging anim skate speeds
MSG_META_DEBUG_CYCLE_EXTENT_TYPE, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_MAJOR, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_MAJOR_BIG, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_MAJOR, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_MAJOR_BIG, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_MINOR, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_MINOR_BIG, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_MINOR, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_MINOR_BIG, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT, ///< change extent
MSG_META_DEBUG_INCREASE_EXTENT_HEIGHT_BIG, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT, ///< change extent
MSG_META_DEBUG_DECREASE_EXTENT_HEIGHT_BIG, ///< change extent
MSG_META_DEBUG_VTUNE_ON, ///< turn on/off Vtune
MSG_META_DEBUG_VTUNE_OFF, ///< turn on/off Vtune
MSG_META_DEBUG_TOGGLE_FEATHER_WATER, ///< toggle lorenzen's feather water
MSG_META_DEBUG_DUMP_ASSETS, ///< dumps currently used map assets to a file.
MSG_NO_DRAW, ///< show/hide all objects to test Drawing code
MSG_META_DEMO_TOGGLE_METRICS, ///< Toggle the metrics on/off
MSG_META_DEMO_TOGGLE_PROJECTILEDEBUG, ///< Toggles bezier curves on projectiles on/off
MSG_META_DEMO_TOGGLE_VISIONDEBUG, ///< Toggles vision debug circles on/off
MSG_META_DEMO_TOGGLE_THREATDEBUG, ///< Toggle the threat debugger on/off
MSG_META_DEMO_TOGGLE_CASHMAPDEBUG, ///< Toggle the cash map debugger on/off
MSG_META_DEMO_TOGGLE_GRAPHICALFRAMERATEBAR, ///< Toggle the graphical framerate bar on/off
MSG_META_DEMO_GIVE_ALL_SCIENCES, ///< grant all grantable sciences
MSG_META_DEMO_GIVE_RANKLEVEL, ///< up one RankLevel
MSG_META_DEMO_TAKE_RANKLEVEL, ///< up one RankLevel
MSG_META_DEMO_GIVE_SCIENCEPURCHASEPOINTS, ///< give yourself an SPP (but no rank change)
MSG_META_DEBUG_TOGGLE_NETWORK, ///< toggle between having and not having network traffic.
MSG_META_DEBUG_DUMP_PLAYER_OBJECTS, ///< Dump numbers of objects owned by each player to the script debug window
MSG_META_DEBUG_DUMP_ALL_PLAYER_OBJECTS, ///< Dump numbers of objects owned by each player to the script debug window, and additional object info
MSG_META_DEBUG_WIN, ///< Instant Win
MSG_META_DEMO_TOGGLE_DEBUG_STATS, ///< show/hide the debug stats
/// @todo END section to REMOVE (not disable) for release
#endif // defined(_DEBUG) || defined(_INTERNAL)
#if defined(_INTERNAL) || defined(_DEBUG) || defined(_PLAYTEST)
MSG_META_DEMO_TOGGLE_AUDIODEBUG, ///< show/hide the audio debug info
#endif//defined(_INTERNAL) || defined(_DEBUG) || defined(_PLAYTEST)
#ifdef DUMP_PERF_STATS
MSG_META_DEMO_PERFORM_STATISTICAL_DUMP, ///< dump performance stats for this frame to StatisticsDump.txt
#endif//DUMP_PERF_STATS
MSG_META_PLACE_BEACON,
MSG_META_REMOVE_BEACON,
MSG_END_META_MESSAGES, ///< Marker to delineate "meta" messages
MSG_MOUSEOVER_DRAWABLE_HINT, ///< (drawableid) the given drawable is under the mouse, regardless of button states
MSG_MOUSEOVER_LOCATION_HINT, ///< (location) The cursor is not over a drawable, but is here.
MSG_VALID_GUICOMMAND_HINT, ///< posted when the gui command is valid if the user clicked to execute it.
MSG_INVALID_GUICOMMAND_HINT, ///< posted when the gui command is not valid if the user were to click to attempt to execute it.
MSG_AREA_SELECTION_HINT, ///< (pixelRegion) rectangular selection area under construction, not confirmed
//Command hints
MSG_DO_ATTACK_OBJECT_HINT, ///< (victim objectID) If clicked, an attack would be ordered, "Current Selection" is assumed
MSG_IMPOSSIBLE_ATTACK_HINT, ///< we can't do anything, and target is out of range.
MSG_DO_FORCE_ATTACK_OBJECT_HINT, ///< (victim objectID) If clicked, an attack would be ordered, "Current Selection" is assumed
MSG_DO_FORCE_ATTACK_GROUND_HINT, ///< (victim objectID) If clicked, an attack would be ordered, "Current Selection" is assumed
MSG_GET_REPAIRED_HINT, ///< If clicked, selected unit will go get repaired at clicked object
MSG_GET_HEALED_HINT, ///< If clicked, selected unit will go get healed at clicked object
MSG_DO_REPAIR_HINT, ///< if clicked, dozer will go repair the clicked target
MSG_RESUME_CONSTRUCTION_HINT, ///< if clicked, dozer will go construct a partially constructed building
MSG_ENTER_HINT, ///< if clicked, selected unit(s) will attempt to enter clicked object
MSG_DOCK_HINT, ///< If clicked, selected unit(s) will dock
MSG_DO_MOVETO_HINT, ///< (location) If clicked, a move would be ordered, "Current Selection" is assumed
MSG_DO_ATTACKMOVETO_HINT, ///< (location) If clicked, a move would be ordered, "Current Selection" is assumed
MSG_ADD_WAYPOINT_HINT, ///< (location) If clicked, a waypoint will be added for currently selected units.
//Context command hints
MSG_HIJACK_HINT, ///< if clicked, selected unit(s) will attempt to take over vehicle.
MSG_FIREBOMB_HINT, ///< throw a molotov cocktail
MSG_CONVERT_TO_CARBOMB_HINT, ///< if clicked, selected unit(s) will attempt to convert clicked object into a carbomb.
MSG_CAPTUREBUILDING_HINT,
#ifdef ALLOW_SURRENDER
MSG_PICK_UP_PRISONER_HINT,
#endif
MSG_SNIPE_VEHICLE_HINT,
MSG_DEFECTOR_HINT,
MSG_SET_RALLY_POINT_HINT, ///< (location) if clicked, we will place a rally point here.
MSG_DO_SPECIAL_POWER_OVERRIDE_DESTINATION_HINT,
MSG_DO_SALVAGE_HINT,
MSG_DO_INVALID_HINT, ///< Display invalid cursor because no real command can be done in this context.
MSG_DO_ATTACK_OBJECT_AFTER_MOVING_HINT,
MSG_HACK_HINT,
//*********************************************************************************************************
//*********************************************************************************************************
/*
Note that we start this at a fixed value, so that (regardless of ifdefs upstream from us) we have the same
numeric values for all enums that are saved in replay files. This helps improve compatibility between
replay files created in internal vs. release builds (though they will still generate sync errors in
some situations due to other reasons, e.g., DEBUG_LOG using the FPU and thus changing its state).
there should be NO IFDEFS OF ANY KIND FROM HERE UNTIL MSG_END_NETWORK_MESSAGES.
there should be NO IFDEFS OF ANY KIND FROM HERE UNTIL MSG_END_NETWORK_MESSAGES.
there should be NO IFDEFS OF ANY KIND FROM HERE UNTIL MSG_END_NETWORK_MESSAGES.
*/
MSG_BEGIN_NETWORK_MESSAGES = 1000, ///< MARKER TO DELINEATE MESSAGES THAT GO OVER THE NETWORK
//*********************************************************************************************************
MSG_CREATE_SELECTED_GROUP, /**< (Bool createNewGroup, objectID1, objectID2, ... objectIDN)
* The selected team is created/augmented with the given team members
*/
MSG_CREATE_SELECTED_GROUP_NO_SOUND, /**< (Bool createNewGroup, objectID1, objectID2, ... objectIDN)
* The selected team is created/augmented with the given team members.
* Do not play their selection sounds.
*/
MSG_DESTROY_SELECTED_GROUP, ///< (teamID) the given team is no longer valid
MSG_REMOVE_FROM_SELECTED_GROUP, /**< (objectID1, objectID2, ... objectIDN)
* Remove these units from the selected group. (N should almost always be 1)
*/
MSG_SELECTED_GROUP_COMMAND, ///< (teamID) the NEXT COMMAND acts upon all members of this team
MSG_CREATE_TEAM0, ///< Creates a hotkey squad from the currently selected units.
MSG_CREATE_TEAM1,
MSG_CREATE_TEAM2,
MSG_CREATE_TEAM3,
MSG_CREATE_TEAM4,
MSG_CREATE_TEAM5,
MSG_CREATE_TEAM6,
MSG_CREATE_TEAM7,
MSG_CREATE_TEAM8,
MSG_CREATE_TEAM9,
MSG_SELECT_TEAM0, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM1, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM2, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM3, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM4, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM5, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM6, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM7, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM8, ///< Set a hotkey squad to be the currently selected units.
MSG_SELECT_TEAM9, ///< Set a hotkey squad to be the currently selected units.
MSG_ADD_TEAM0, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM1, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM2, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM3, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM4, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM5, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM6, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM7, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM8, ///< Add hotkey squad to the currently selected units.
MSG_ADD_TEAM9, ///< Add hotkey squad to the currently selected units.
MSG_DO_ATTACKSQUAD, ///< (numObjects) (numObjects * objectID)
MSG_DO_WEAPON, ///< fire specific weapon
MSG_DO_WEAPON_AT_LOCATION, ///< fire a specific weapon at location
MSG_DO_WEAPON_AT_OBJECT, ///< fire a specific weapon at a target object
MSG_DO_SPECIAL_POWER, ///< do special
MSG_DO_SPECIAL_POWER_AT_LOCATION, ///< do special with target location
MSG_DO_SPECIAL_POWER_AT_OBJECT, ///< do special at with target object
MSG_SET_RALLY_POINT, ///< (objectID, location)
MSG_PURCHASE_SCIENCE, ///< purchase a science
MSG_QUEUE_UPGRADE, ///< queue the "research" of an upgrade
MSG_CANCEL_UPGRADE, ///< cancel the "research" of an upgrade
MSG_QUEUE_UNIT_CREATE, ///< clicked on a button to queue the production of a unit
MSG_CANCEL_UNIT_CREATE, ///< clicked on UI button to cancel production of a unit
MSG_DOZER_CONSTRUCT, /**< building things requires clicking on a dozer
selecting what to build, selecting where to
build it ... this construct message will
start the actual build process */
MSG_DOZER_CONSTRUCT_LINE, ///< Like MSG_CONSTRUCT, but for build procesess that occur in a line (like walls)
MSG_DOZER_CANCEL_CONSTRUCT, ///< cancel construction of a building
MSG_SELL, ///< sell a structure
MSG_EXIT, ///< WE want to exit from whatever WE are inside of
MSG_EVACUATE, ///< Dump out all of OUR contained objects
MSG_EXECUTE_RAILED_TRANSPORT, ///< Execute railed transport sequence
MSG_COMBATDROP_AT_LOCATION, ///< dump out all rappellers
MSG_COMBATDROP_AT_OBJECT, ///< dump out all rappellers
MSG_AREA_SELECTION, ///< (pixelRegion) rectangular selection area
MSG_DO_ATTACK_OBJECT, ///< (objectID, victim objectID)
MSG_DO_FORCE_ATTACK_OBJECT, ///< force attack the given object if picked
MSG_DO_FORCE_ATTACK_GROUND, ///< (locationID) bombard the given location if picked
MSG_GET_REPAIRED, ///< selected unit will go get repaired at clicked object
MSG_GET_HEALED, ///< selected unit will go get healed at clicked object
MSG_DO_REPAIR, ///< dozer will go repair the clicked target
MSG_RESUME_CONSTRUCTION, ///< resume construction on a structure
MSG_ENTER, ///< Enter object
MSG_DOCK, ///< Dock with this object
MSG_DO_MOVETO, ///< location
MSG_DO_ATTACKMOVETO, ///< location
MSG_DO_FORCEMOVETO, ///< location
MSG_ADD_WAYPOINT, ///< location
MSG_DO_GUARD_POSITION, ///< Guard with the currently selected group
MSG_DO_GUARD_OBJECT, ///< Guard with the currently selected group
MSG_DO_STOP, ///< Stop with the currently selected group
MSG_DO_SCATTER, ///< Scatter the currently selected group
MSG_INTERNET_HACK, ///< Begin a persistent internet hack (free slow income)
MSG_DO_CHEER, ///< Orders selected units to play cheer animation (if possible)
MSG_TOGGLE_OVERCHARGE, ///< Toggle overcharge status of a power plant
MSG_SWITCH_WEAPONS, ///< Switches which weapon slot to use for an object
MSG_CONVERT_TO_CARBOMB,
MSG_CAPTUREBUILDING,
MSG_DISABLEVEHICLE_HACK,
MSG_STEALCASH_HACK,
MSG_DISABLEBUILDING_HACK,
MSG_SNIPE_VEHICLE,
MSG_DO_SPECIAL_POWER_OVERRIDE_DESTINATION,
MSG_DO_SALVAGE,
MSG_CLEAR_INGAME_POPUP_MESSAGE, ///< If we want a replay to work with the popup messages then we need it to be passed
MSG_PLACE_BEACON,
MSG_REMOVE_BEACON,
MSG_SET_BEACON_TEXT,
MSG_SET_REPLAY_CAMERA, ///< Track camera pos for replays
MSG_SELF_DESTRUCT, ///< Destroys a player's units (for copy protection or to quit to observer)
MSG_CREATE_FORMATION, ///< Creates a formation.
MSG_LOGIC_CRC, ///< CRC from the logic passed around in a network game :)
MSG_SET_MINE_CLEARING_DETAIL, ///< CRC from the logic passed around in a network game :)
MSG_BEGIN_DEBUG_NETWORK_MESSAGES = 1900, ///< network messages that exist only in debug/internal builds. all grouped separately.
#if defined(_DEBUG) || defined(_INTERNAL)
// all debug/internal-only messages must go here.
MSG_DEBUG_KILL_SELECTION,
MSG_DEBUG_HURT_OBJECT,
MSG_DEBUG_KILL_OBJECT,
#endif
//*********************************************************************************************************
MSG_END_NETWORK_MESSAGES = 1999, ///< MARKER TO DELINEATE MESSAGES THAT GO OVER THE NETWORK
//*********************************************************************************************************
//*********************************************************************************************************
// Server to Client messages
MSG_TIMESTAMP, ///< The current frame number
MSG_OBJECT_CREATED, ///< (objectID, Int type) Cause a drawable to be created and bound to this ID
MSG_OBJECT_DESTROYED, ///< (objectID) Free bound drawable
MSG_OBJECT_POSITION, ///< (objectID, location) New position of object
MSG_OBJECT_ORIENTATION, ///< (objectID, angle) New orientation of object
MSG_OBJECT_JOINED_TEAM, ///< (objectID) New team affiliation of object
MSG_COUNT
};
GameMessage( Type type );
GameMessage *next( void ) { return m_next; } ///< Return next message in the stream
GameMessage *prev( void ) { return m_prev; } ///< Return prev message in the stream
Type getType( void ) const { return m_type; } ///< Return the message type
UnsignedByte getArgumentCount( void ) const { return m_argCount; } ///< Return the number of arguments for this msg
AsciiString getCommandAsAsciiString( void ); ///< returns a string representation of the command type.
static AsciiString getCommandTypeAsAsciiString(GameMessage::Type t);
Int getPlayerIndex( void ) const { return m_playerIndex; } ///< Return the originating player
// access methods for GameMessageArgumentType enum
void appendIntegerArgument( Int arg );
void appendRealArgument( Real arg );
void appendBooleanArgument( Bool arg );
void appendDrawableIDArgument( DrawableID arg );
void appendObjectIDArgument( ObjectID arg );
void appendTeamIDArgument( UnsignedInt arg );
void appendLocationArgument( const Coord3D& arg );
void appendPixelArgument( const ICoord2D& arg );
void appendPixelRegionArgument( const IRegion2D& arg );
void appendWideCharArgument( const WideChar& arg );
void appendTimestampArgument( UnsignedInt arg );
/**
* Return the given argument union.
* @todo This should be a more list-like interface. Very inefficient.
*/
const GameMessageArgumentType *getArgument( Int argIndex ) const;
GameMessageArgumentDataType getArgumentDataType( Int argIndex );
void friend_setNext(GameMessage* m) { m_next = m; }
void friend_setPrev(GameMessage* m) { m_prev = m; }
void friend_setList(GameMessageList* m) { m_list = m; }
void friend_setPlayerIndex(Int i) { m_playerIndex = i; }
private:
// friend classes are bad. don't use them. no, really.
// if for no other reason than the fact that they subvert MemoryPoolObject. (srj)
GameMessage *m_next, *m_prev; ///< List links for message list
GameMessageList *m_list; ///< The list this message is on
Type m_type; ///< The type of this message
Int m_playerIndex; ///< The Player who issued the command
/// @todo If a GameMessage needs more than 255 arguments, it needs to be split up into multiple GameMessage's.
UnsignedByte m_argCount; ///< The number of arguments of this message
GameMessageArgument *m_argList, *m_argTail; ///< This message's arguments
/// allocate a new argument, add it to list, return pointer to its data
GameMessageArgument *allocArg( void );
};
/**
* The GameMessageList class encapsulates the manipulation of lists of GameMessages.
* Both MessageStream and CommandList derive from this class.
*/
class GameMessageList : public SubsystemInterface
{
public:
GameMessageList( void );
virtual ~GameMessageList();
virtual void init( void ) { }; ///< Initialize system
virtual void reset( void ) { }; ///< Reset system
virtual void update( void ) { }; ///< Update system
GameMessage *getFirstMessage( void ) { return m_firstMessage; } ///< Return the first message
virtual void appendMessage( GameMessage *msg ); ///< Add message to end of the list
virtual void insertMessage( GameMessage *msg, GameMessage *messageToInsertAfter ); // Insert message after messageToInsertAfter.
virtual void removeMessage( GameMessage *msg ); ///< Remove message from the list
virtual Bool containsMessageOfType( GameMessage::Type type ); ///< Return true if a message of type is in the message stream
protected:
GameMessage *m_firstMessage; ///< The first message on the list
GameMessage *m_lastMessage; ///< The last message on the list
};
/**
What to do with a GameMessage after a translator has handled it.
Use a custom enum (rather than a Bool) to make the code more obvious.
*/
enum GameMessageDisposition
{
KEEP_MESSAGE, ///< continue processing this message thru other translators
DESTROY_MESSAGE ///< destroy this message immediately and don't hand it to any other translators
};
class GameMessageTranslator
{
public:
virtual GameMessageDisposition translateGameMessage(const GameMessage *msg) = 0;
virtual ~GameMessageTranslator() { }
};
/**
* A MessageStream contains an ordered list of messages which can have one or more
* prioritized message handler functions ("translators") attached to it.
*/
class MessageStream : public GameMessageList
{
public:
MessageStream( void );
virtual ~MessageStream();
// Inherited Methods ----------------------------------------------------------------------------
virtual void init( void );
virtual void reset( void );
virtual void update( void );
virtual GameMessage *appendMessage( GameMessage::Type type ); ///< Append a message to the end of the stream
virtual GameMessage *insertMessage( GameMessage::Type type, GameMessage *messageToInsertAfter ); // Insert message after messageToInsertAfter.
// Methods NOT Inherited ------------------------------------------------------------------------
void propagateMessages( void ); ///< Propagate messages through attached translators
/**
Attach a translator function to the stream at a priority value. Lower priorities are executed first.
Note that MessageStream assumes ownership of the translator, and is responsible for freeing it!
*/
TranslatorID attachTranslator( GameMessageTranslator *translator, UnsignedInt priority);
GameMessageTranslator* findTranslator( TranslatorID id );
void removeTranslator( TranslatorID ); ///< Remove a previously attached translator
protected:
struct TranslatorData
{
TranslatorData *m_next, *m_prev; ///< List links for list of translators
TranslatorID m_id; ///< The unique ID of this translator
GameMessageTranslator *m_translator; ///< The translor's interface function
UnsignedInt m_priority; ///< The priority level of this translator
TranslatorData() : m_next(0), m_prev(0), m_id(0), m_translator(0), m_priority(0)
{
}
~TranslatorData()
{
delete m_translator;
}
};
TranslatorData *m_firstTranslator; ///< List of registered translators, in order of priority
TranslatorData *m_lastTranslator;
TranslatorID m_nextTranslatorID; ///< For issuing unique translator ID's
};
/**
* The CommandList is the final set of messages that have made their way through
* all of the Translators of the MessageStream, and reached the end.
* This set of commands will be executed by the GameLogic on its next iteration.
*/
class CommandList : public GameMessageList
{
public:
CommandList( void );
virtual ~CommandList();
virtual void init( void ); ///< Init command list
virtual void reset( void ); ///< Destroy all messages and reset list to empty
virtual void update( void ); ///< Update hook
void appendMessageList( GameMessage *list ); ///< Adds messages to the end of the command list
protected:
void destroyAllMessages( void ); ///< The meat of a reset and a shutdown
};
//
// The message stream that filters client input into game commands
//
extern MessageStream *TheMessageStream;
//
// The list of commands awaiting execution by the GameLogic
//
extern CommandList *TheCommandList;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Functions used in multiple translators should go here.
//
/**
* Given an "anchor" point and the current mouse position (dest),
* construct a valid 2D bounding region.
*/
extern void buildRegion( const ICoord2D *anchor, const ICoord2D *dest, IRegion2D *region );
#endif // _MESSAGE_STREAM_H_

View File

@ -0,0 +1,48 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: MiniLog.h /////////////////////////////////////////////////////////////
// Alternative logging
// Author: Matthew D. Campbell, January 2003
////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifdef DEBUG_LOGGING
#include "Lib/BaseType.h"
#include "GameLogic/GameLogic.h"
#include <cstdarg>
class LogClass
{
public:
LogClass(const char *fname);
~LogClass();
void log(const char *fmt, ...);
protected:
FILE *m_fp;
};
#endif // DEBUG_LOGGING

View File

@ -0,0 +1,76 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///MiscAudio.h/////////////////////////////////////////////////////////////////////////////////////
// This file is for miscellaneous sound hooks that don't have another happy home.
#pragma once
#ifndef _MISCAUDIO_H_
#define _MISCAUDIO_H_
#include "Common/AudioEventRTS.h"
struct MiscAudio
{
static const FieldParse m_fieldParseTable[];
AudioEventRTS m_radarUnitUnderAttackSound; ///< radar sounds to play when unit under attack
AudioEventRTS m_radarHarvesterUnderAttackSound; ///< radar sounds to play when harvester under attack
AudioEventRTS m_radarStructureUnderAttackSound; ///< radar sounds to play when structure under attack
AudioEventRTS m_radarUnderAttackSound; ///< radar sounds to play when ? under attack
AudioEventRTS m_radarInfiltrationSound; ///< radar sounds to play when something is infiltrated
AudioEventRTS m_radarOnlineSound; ///< radar sounds to play when radar goes online
AudioEventRTS m_radarOfflineSound; ///< radar sounds to play when radar goes offline
AudioEventRTS m_defectorTimerTickSound; ///< snd to play during transient invulnerability while defecting // lorenzen
AudioEventRTS m_defectorTimerDingSound; ///< snd to play when you become vulnerable again // lorenzen
AudioEventRTS m_lockonTickSound; ///< snd to play during stealth-fighter-lockon period
AudioEventRTS m_allCheerSound; ///< snd to play when user presses 'cheer' key
AudioEventRTS m_battleCrySound; ///< snd to play when user presses 'battlecry' key
AudioEventRTS m_guiClickSound; ///< snd to play when user presses button in GUI
AudioEventRTS m_noCanDoSound; ///< Global "No Can Do" sound
AudioEventRTS m_stealthDiscoveredSound; ///< I have just discovered an enemy stealth unit
AudioEventRTS m_stealthNeutralizedSound; ///< One of my stealthed units has just been discovered by the enemy
AudioEventRTS m_moneyDepositSound; ///< Money was deposited in my bank
AudioEventRTS m_moneyWithdrawSound; ///< Money was withdrawn from my bank
AudioEventRTS m_buildingDisabled; ///< Building has lost power, been hit with an EMP, or disable hacked.
AudioEventRTS m_buildingReenabled; ///< Building has recovered from being disabled.
AudioEventRTS m_vehicleDisabled; ///< Vehicle has been disabled via EMP or hacker attack.
AudioEventRTS m_vehicleReenabled; ///< Vehicle has recovered from being disabled.
AudioEventRTS m_splatterVehiclePilotsBrain; ///< Pilot has been sniped by Jarmen Kell.
AudioEventRTS m_terroristInCarMoveVoice; ///< Terrorist issues a move order while in a car.
AudioEventRTS m_terroristInCarAttackVoice; ///< Terrorist issues attack order while in a car.
AudioEventRTS m_terroristInCarSelectVoice; ///< Terrorist is selected while in a car.
AudioEventRTS m_crateHeal; ///< When heal crate is picked up.
AudioEventRTS m_crateShroud; ///< When shroud crate is picked up.
AudioEventRTS m_crateSalvage; ///< When salvage crate is picked up.
AudioEventRTS m_crateFreeUnit; ///< When free unit crate is picked up.
AudioEventRTS m_crateMoney; ///< When money crate is picked up.
AudioEventRTS m_unitPromoted; ///< Unit is promoted.
AudioEventRTS m_repairSparks; ///< Battle drone repairs unit.
AudioEventRTS m_aircraftWheelScreech; ///< When a jet lands on a runway.
};
#endif /* _MISCAUDIO_H_ */

View File

@ -0,0 +1,90 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: MissionStats.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: MissionStats.h
//
// Created: Steven Johnson, October 2001
//
// Desc: @todo
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef _MISSIONSTATS_H_
#define _MISSIONSTATS_H_
#include "Lib/BaseType.h"
#include "Common/GameCommon.h"
#include "Common/Snapshot.h"
// ----------------------------------------------------------------------------------------------
/**
Class that accumulates stats during a mission. Some of this will be for scoring purposes,
and some will probably be used by AI to determine future moves.
@todo: not sure what need to be here. Alas. For now, I have just put in the fields from RA2
that are indicated as being used for scoring in multiplayer games, so this will certainly
increase.
*/
class MissionStats : public Snapshot
{
public:
MissionStats();
/// reset all stats to "nothing".
void init();
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
Int m_unitsKilled[MAX_PLAYER_COUNT]; ///< how many units for each Player were killed by us?
Int m_unitsLost; ///< how many of our units were destroyed?
Int m_buildingsKilled[MAX_PLAYER_COUNT]; ///< how many buildings for each Player were killed by us?
Int m_buildingsLost; ///< how many of our buildings were destroyed?
//Int m_whoLastHurtMe; ///< last Player to destroy one of my units
};
#endif // _MISSIONSTATS_H_

View File

@ -0,0 +1,238 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// ModelState.h
// Basic data types needed for the game engine. This is an extension of BaseType.h.
// Author: Michael S. Booth, April 2001
#pragma once
#ifndef _ModelState_H_
#define _ModelState_H_
#include "Lib/BaseType.h"
#include "Common/INI.h"
#include "Common/BitFlags.h"
//-------------------------------------------------------------------------------------------------
/**
THE PROBLEM
-----------
-- there are lots of different states. (consider that structures can be: day/night, snow/nosnow,
powered/not, garrisoned/empty, damaged/not... you do the math.)
-- some states are mutually exclusive (idle vs. moving), others are not (snow/nosnow, day/night).
generally, humanoid units have mostly the former, while structure units have mostly the latter.
The current ModelState system really only supports the mutually-exclusive states well.
-- we'd rather not have to specify every state in the INI files, BUT we do want to be able
to intelligently choose the best model for a given state, whether or not a "real" state exists for it.
-- it would be desirable to have a unified way of representing "ModelState" so that we don't
have multiple similar-yet-different systems.
YUCK, WHAT NOW
--------------
Let's represent the Model State with two dictinct pieces:
-- an "ActionState" piece, representing the mutually-exclusive states, which are almost
always an action of some sort
-- and a "ConditionState" piece, which is a set of bitflags to indicate the static "condition"
of the model.
Note that these are usually set independently in code, but they are lumped together in order to
determine the actual model to be used.
(Let's require all objects would be required to have an "Idle" ActionState, which is the
normal, just-sitting there condition.)
From a code point of view, this becomes an issue of requesting a certain state, and
finding the best-fit match for it. So, what are the rules for finding a good match?
-- Action states must match exactly. If the desired action state is not found, then the
IDLE state is substituted (but this should generally be considered an error condition).
-- Condition states choose the match with the closest match among the "Condition" bits in the
INI file, based on satisfying the most of the "required" conditions and the fewest of the
"forbidden" conditions.
*/
//-------------------------------------------------------------------------------------------------
// IMPORTANT NOTE: you should endeavor to set up states such that the most "normal"
// state is defined by the bit being off. That is, the typical "normal" condition
// has all condition flags set to zero.
enum ModelConditionFlagType
{
MODELCONDITION_INVALID = -1,
MODELCONDITION_FIRST = 0,
//
// Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE
// existing values!
//
MODELCONDITION_TOPPLED = MODELCONDITION_FIRST,
MODELCONDITION_FRONTCRUSHED,
MODELCONDITION_BACKCRUSHED,
MODELCONDITION_DAMAGED,
MODELCONDITION_REALLY_DAMAGED,
MODELCONDITION_RUBBLE,
MODELCONDITION_SPECIAL_DAMAGED,
MODELCONDITION_NIGHT,
MODELCONDITION_SNOW,
MODELCONDITION_PARACHUTING,
MODELCONDITION_GARRISONED,
MODELCONDITION_ENEMYNEAR,
MODELCONDITION_WEAPONSET_VETERAN,
MODELCONDITION_WEAPONSET_ELITE,
MODELCONDITION_WEAPONSET_HERO,
MODELCONDITION_WEAPONSET_CRATEUPGRADE_ONE,
MODELCONDITION_WEAPONSET_CRATEUPGRADE_TWO,
MODELCONDITION_WEAPONSET_PLAYER_UPGRADE,
MODELCONDITION_DOOR_1_OPENING,
MODELCONDITION_DOOR_1_CLOSING,
MODELCONDITION_DOOR_1_WAITING_OPEN,
MODELCONDITION_DOOR_1_WAITING_TO_CLOSE,
MODELCONDITION_DOOR_2_OPENING,
MODELCONDITION_DOOR_2_CLOSING,
MODELCONDITION_DOOR_2_WAITING_OPEN,
MODELCONDITION_DOOR_2_WAITING_TO_CLOSE,
MODELCONDITION_DOOR_3_OPENING,
MODELCONDITION_DOOR_3_CLOSING,
MODELCONDITION_DOOR_3_WAITING_OPEN,
MODELCONDITION_DOOR_3_WAITING_TO_CLOSE,
MODELCONDITION_DOOR_4_OPENING,
MODELCONDITION_DOOR_4_CLOSING,
MODELCONDITION_DOOR_4_WAITING_OPEN,
MODELCONDITION_DOOR_4_WAITING_TO_CLOSE,
MODELCONDITION_ATTACKING, //Simply set when a unit is fighting -- terrorist moving with a target will flail arms like a psycho.
MODELCONDITION_PREATTACK_A, //Use for pre-attack animations (like aiming, pulling out a knife, or detonating explosives).
MODELCONDITION_FIRING_A,
MODELCONDITION_BETWEEN_FIRING_SHOTS_A,
MODELCONDITION_RELOADING_A,
MODELCONDITION_PREATTACK_B, //Use for pre-attack animations (like aiming, pulling out a knife, or detonating explosives).
MODELCONDITION_FIRING_B,
MODELCONDITION_BETWEEN_FIRING_SHOTS_B,
MODELCONDITION_RELOADING_B,
MODELCONDITION_PREATTACK_C, //Use for pre-attack animations (like aiming, pulling out a knife, or detonating explosives).
MODELCONDITION_FIRING_C,
MODELCONDITION_BETWEEN_FIRING_SHOTS_C,
MODELCONDITION_RELOADING_C,
MODELCONDITION_TURRET_ROTATE,
MODELCONDITION_POST_COLLAPSE,
MODELCONDITION_MOVING,
MODELCONDITION_DYING,
MODELCONDITION_AWAITING_CONSTRUCTION,
MODELCONDITION_PARTIALLY_CONSTRUCTED,
MODELCONDITION_ACTIVELY_BEING_CONSTRUCTED,
MODELCONDITION_PRONE,
MODELCONDITION_FREEFALL,
MODELCONDITION_ACTIVELY_CONSTRUCTING,
MODELCONDITION_CONSTRUCTION_COMPLETE,
MODELCONDITION_RADAR_EXTENDING,
MODELCONDITION_RADAR_UPGRADED,
MODELCONDITION_PANICKING, // yes, it's spelled with a "k". look it up.
MODELCONDITION_AFLAME,
MODELCONDITION_SMOLDERING,
MODELCONDITION_BURNED,
MODELCONDITION_DOCKING, ///< This encloses the whole time you are Entering, Actioning, and Exiting a dock
MODELCONDITION_DOCKING_BEGINNING, ///< From Enter to Action
MODELCONDITION_DOCKING_ACTIVE, ///< From Action to Exit
MODELCONDITION_DOCKING_ENDING, ///< Exit all the way to next enter (use only animations that end with this)
MODELCONDITION_CARRYING,
MODELCONDITION_FLOODED,
MODELCONDITION_LOADED, // loaded woot! ... like a transport is loaded
MODELCONDITION_JETAFTERBURNER,// shows "flames" for extra motive force (eg, when taking off)
MODELCONDITION_JETEXHAUST, // shows "exhaust" for motive force
MODELCONDITION_PACKING, // packs an object
MODELCONDITION_UNPACKING, // unpacks an object
MODELCONDITION_DEPLOYED, // a deployed object state
MODELCONDITION_OVER_WATER, // Units that can go over water want cool effects for doing so
MODELCONDITION_POWER_PLANT_UPGRADED, // to show special control rods on the cold fusion plant
MODELCONDITION_CLIMBING, //For units climbing up or down cliffs.
MODELCONDITION_SOLD, // object is being sold
#ifdef ALLOW_SURRENDER
MODELCONDITION_SURRENDER, //When units surrender...
#endif
MODELCONDITION_RAPPELLING,
MODELCONDITION_ARMED, // armed like a mine or bomb is armed (not like a human is armed)
MODELCONDITION_POWER_PLANT_UPGRADING, // while special control rods on the cold fusion plant are extending
//Special model conditions work as following:
//Something turns it on... but a timer in the object will turn them off after a given
//amount of time. If you add any more special animations, then you'll need to add the
//code to turn off the state.
MODELCONDITION_SPECIAL_CHEERING, //When units do a victory cheer (or player initiated cheer).
MODELCONDITION_CONTINUOUS_FIRE_SLOW,
MODELCONDITION_CONTINUOUS_FIRE_MEAN,
MODELCONDITION_CONTINUOUS_FIRE_FAST,
MODELCONDITION_RAISING_FLAG,
MODELCONDITION_CAPTURED,
MODELCONDITION_EXPLODED_FLAILING,
MODELCONDITION_EXPLODED_BOUNCING,
MODELCONDITION_SPLATTED,
// this is an easier-to-use variant on the whole FIRING_A deal...
// these bits are set if firing, reloading, between shots, or preattack.
MODELCONDITION_USING_WEAPON_A,
MODELCONDITION_USING_WEAPON_B,
MODELCONDITION_USING_WEAPON_C,
MODELCONDITION_PREORDER,
//
// Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE
// existing values!
//
MODELCONDITION_COUNT // keep last!
};
//-------------------------------------------------------------------------------------------------
typedef BitFlags<MODELCONDITION_COUNT> ModelConditionFlags;
#define MAKE_MODELCONDITION_MASK(k) ModelConditionFlags(ModelConditionFlags::kInit, (k))
#define MAKE_MODELCONDITION_MASK2(k,a) ModelConditionFlags(ModelConditionFlags::kInit, (k), (a))
#define MAKE_MODELCONDITION_MASK3(k,a,b) ModelConditionFlags(ModelConditionFlags::kInit, (k), (a), (b))
#define MAKE_MODELCONDITION_MASK4(k,a,b,c) ModelConditionFlags(ModelConditionFlags::kInit, (k), (a), (b), (c))
#define MAKE_MODELCONDITION_MASK5(k,a,b,c,d) ModelConditionFlags(ModelConditionFlags::kInit, (k), (a), (b), (c), (d))
#define MAKE_MODELCONDITION_MASK12(a,b,c,d,e,f,g,h,i,j,k,l) ModelConditionFlags(ModelConditionFlags::kInit, (a), (b), (c), (d), (e), (f), (g), (h), (i), (j), (k), (l))
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
#endif // _ModelState_H_

View File

@ -0,0 +1,320 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Module.h /////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc: Object and drawable modules and actions. These are simply just class
// instances that we can assign to objects, drawables, and things to contain
// data and code for specific events, or just to hold data
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __MODULE_H_
#define __MODULE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/INI.h"
#include "Common/GameMemory.h"
#include "Common/NameKeyGenerator.h"
#include "Common/Snapshot.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
enum TimeOfDay;
enum StaticGameLODLevel;
class Drawable;
class Object;
class Player;
class Thing;
class W3DModelDrawModuleData; // ugh, hack (srj)
struct FieldParse;
// TYPES //////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
enum ModuleType
{
MODULETYPE_BEHAVIOR = 0,
//
// drawable module types - you should *NOT* remove drawable module types, we write
// modules into save game files in buckets of module types ... if you do remove one
// here you will have to update the xfer code for a drawable.
//
// ALSO note that new drawable module types should go at the end of the existing drawable modules
//
MODULETYPE_DRAW = 1,
MODULETYPE_CLIENT_UPDATE = 2,
// put new drawable module types here
NUM_MODULE_TYPES, // keep this last!
FIRST_DRAWABLE_MODULE_TYPE = MODULETYPE_DRAW,
LAST_DRAWABLE_MODULE_TYPE = MODULETYPE_CLIENT_UPDATE,
NUM_DRAWABLE_MODULE_TYPES = (LAST_DRAWABLE_MODULE_TYPE - FIRST_DRAWABLE_MODULE_TYPE + 1)
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
enum ModuleInterfaceType
{
MODULEINTERFACE_UPDATE = 0x00000001,
MODULEINTERFACE_DIE = 0x00000002,
MODULEINTERFACE_DAMAGE = 0x00000004,
MODULEINTERFACE_CREATE = 0x00000008,
MODULEINTERFACE_COLLIDE = 0x00000010,
MODULEINTERFACE_BODY = 0x00000020,
MODULEINTERFACE_CONTAIN = 0x00000040,
MODULEINTERFACE_UPGRADE = 0x00000080,
MODULEINTERFACE_SPECIAL_POWER = 0x00000100,
MODULEINTERFACE_DESTROY = 0x00000200,
MODULEINTERFACE_DRAW = 0x00000400,
MODULEINTERFACE_CLIENT_UPDATE = 0x00000800
};
//-------------------------------------------------------------------------------------------------
/** Base class for data-read-from-INI for modules. */
//-------------------------------------------------------------------------------------------------
/// @todo srj -- make ModuleData be MemoryPool based
class ModuleData : public Snapshot
{
public:
ModuleData() { }
virtual ~ModuleData() { }
void setModuleTagNameKey( NameKeyType key ) { m_moduleTagNameKey = key; }
NameKeyType getModuleTagNameKey() const { return m_moduleTagNameKey; }
virtual Bool isAiModuleData() const { return false; }
// ugh, hack
virtual const W3DModelDrawModuleData* getAsW3DModelDrawModuleData() const { return NULL; }
virtual StaticGameLODLevel getMinimumRequiredGameLOD() const { return (StaticGameLODLevel)0;}
static void buildFieldParse(MultiIniFieldParse& p)
{
// nothing
}
public:
virtual void crc( Xfer *xfer ) {}
virtual void xfer( Xfer *xfer ) {}
virtual void loadPostProcess( void ) {}
private:
NameKeyType m_moduleTagNameKey; ///< module tag key, unique among all modules for an object instance
};
//-------------------------------------------------------------------------------------------------
// This macro is to assist in the creation of new modules, contains the common
// things that all module definitions must have in order to work with
// the module creation factory
//-------------------------------------------------------------------------------------------------
#define MAKE_STANDARD_MODULE_MACRO( cls ) \
public: \
static Module* friend_newModuleInstance( Thing *thing, const ModuleData* moduleData ) { return newInstance( cls )( thing, moduleData ); } \
virtual NameKeyType getModuleNameKey() const { static NameKeyType nk = NAMEKEY(#cls); return nk; } \
protected: \
virtual void crc( Xfer *xfer ); \
virtual void xfer( Xfer *xfer ); \
virtual void loadPostProcess( void );
// ------------------------------------------------------------------------------------------------
// For the creation of abstract module classes
// ------------------------------------------------------------------------------------------------
#define MAKE_STANDARD_MODULE_MACRO_ABC( cls ) \
protected: \
virtual void crc( Xfer *xfer ); \
virtual void xfer( Xfer *xfer ); \
virtual void loadPostProcess( void );
//-------------------------------------------------------------------------------------------------
// only use this macro for an ABC. for a real class, use MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA.
#define MAKE_STANDARD_MODULE_DATA_MACRO_ABC( cls, clsmd ) \
private: \
const clsmd* get##clsmd() const { return (clsmd*)getModuleData(); } \
public: \
static ModuleData* friend_newModuleData(INI* ini) \
{ \
clsmd* data = MSGNEW( "AllModuleData" ) clsmd; \
if (ini) ini->initFromINIMultiProc(data, clsmd::buildFieldParse); \
return data; \
}
//-------------------------------------------------------------------------------------------------
#define MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( cls, clsmd ) \
MAKE_STANDARD_MODULE_MACRO(cls) \
MAKE_STANDARD_MODULE_DATA_MACRO_ABC(cls, clsmd)
//-------------------------------------------------------------------------------------------------
/** Common interface for thing modules, we want a single common base class
* for all the modules (either object or drawable) so that we can use
* a single module factory to handle instancing them ... it's just
* convenient this way */
//-------------------------------------------------------------------------------------------------
class Module : public MemoryPoolObject,
public Snapshot
{
MEMORY_POOL_GLUE_ABC( Module ) ///< this abstract class needs memory pool hooks
public:
Module(const ModuleData* moduleData) : m_moduleData(moduleData) { }
// virtual destructor prototype defined by MemoryPoolObject
// this method should NEVER be overridden by user code, only via the MAKE_STANDARD_MODULE_xxx macros!
// it should also NEVER be called directly; it's only for use by ModuleFactory!
static ModuleData* friend_newModuleData(INI* ini);
virtual NameKeyType getModuleNameKey() const = 0;
inline NameKeyType getModuleTagNameKey() const { return getModuleData()->getModuleTagNameKey(); }
/** this is called after all the Modules for a given Thing are created; it
allows Modules to resolve any inter-Module dependencies.
*/
virtual void onObjectCreated() { }
/**
this is called whenever a drawable is bound to the object.
drawable is NOT guaranteed to be non-null.
*/
virtual void onDrawableBoundToObject() { }
/// preload any assets we might have for this time of day
virtual void preloadAssets( TimeOfDay timeOfDay ) { }
/** onDelete() will be called on all modules contained by an object or drawable before
the actual deletion of each of those modules happens */
virtual void onDelete( void ) { }
protected:
inline const ModuleData* getModuleData() const { return m_moduleData; }
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
const ModuleData* m_moduleData;
}; // end Module
//-------------------------------------------------------------------------------------------------
//=================================================================================================
// OBJECT Module interface and modules
//=================================================================================================
//-------------------------------------------------------------------------------------------------
/** Module interface specific for Objects, this is really just to make a clear distinction
* between modules intended for use in objects and modules intended for use
* in drawables */
//-------------------------------------------------------------------------------------------------
class ObjectModule : public Module
{
MEMORY_POOL_GLUE_ABC( ObjectModule ) ///< this abstract class needs memory pool hooks
public:
ObjectModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
virtual void onCapture( Player *oldOwner, Player *newOwner ) { }
protected:
inline Object *getObject() { return m_object; }
inline const Object *getObject() const { return m_object; }
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
// it shouldn't be legal for subclasses to ever modify this, only to look at it;
// so, we'll enforce this by making it private and providing a protected access method.
Object *m_object; ///< the object this module is a part of
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//=================================================================================================
// DRAWABLE module interface and modules
//=================================================================================================
//-------------------------------------------------------------------------------------------------
/** Module interface specific for Drawbles, this is really just to make a clear distinction
* between modules intended for use in objects and modules intended for use
* in drawables */
//-------------------------------------------------------------------------------------------------
class DrawableModule : public Module
{
MEMORY_POOL_GLUE_ABC( DrawableModule ) ///< this abstract class needs memory pool hooks
public:
DrawableModule( Thing *thing, const ModuleData* moduleData );
// virtual destructor prototype defined by MemoryPoolObject
protected:
inline Drawable *getDrawable() { return m_drawable; }
inline const Drawable *getDrawable() const { return m_drawable; }
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
// it shouldn't be legal for subclasses to ever modify this, only to look at it;
// so, we'll enforce this by making it private and providing a protected access method.
Drawable *m_drawable; ///< the drawble this module is a part of
};
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
/** VARIOUS MODULE INTERFACES */
//-------------------------------------------------------------------------------------------------
#endif // __MODULE_H_

View File

@ -0,0 +1,131 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ModuleFactory.h //////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2001
// Desc: TheModuleFactory is where we actually instance modules for objects
// and drawbles. Those modules are things such as an UpdateModule
// or DamageModule or DrawModule etc.
//
// TheModuleFactory will contain a list of ModuleTemplates, when we
// request a new module, we will look for that template in our
// list and create it
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __MODULEFACTORY_H_
#define __MODULEFACTORY_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include "Common/GameMemory.h"
#include "Common/SubsystemInterface.h"
#include "Common/AsciiString.h"
#include "Common/NameKeyGenerator.h"
#include "Common/Module.h"
#include "Common/STLTypedefs.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class Thing;
class Object;
class Drawable;
class INI;
// TYPE DEFINITIONS ///////////////////////////////////////////////////////////////////////////////
typedef Module *(*NewModuleProc)(Thing *thing, const ModuleData* moduleData);
typedef ModuleData* (*NewModuleDataProc)(INI* ini);
//-------------------------------------------------------------------------------------------------
/** We use TheModulyFactory to register classes that will be attached
* to objects and drawables which will be executed or "called back" in the
* correct situations ... such as Die, Damage, Update etc or just as
* a place to store data specific to that type of thing */
//-------------------------------------------------------------------------------------------------
class ModuleFactory : public SubsystemInterface, public Snapshot
{
public:
ModuleFactory( void );
virtual ~ModuleFactory( void );
virtual void init( void );
virtual void reset( void ) { } ///< We don't reset during the lifetime of the app
virtual void update( void ) { } ///< As of now, we don't have a need for an update
Module *newModule( Thing *thing, const AsciiString& name, const ModuleData* data, ModuleType type ); ///< allocate a new module
// module-data
ModuleData* newModuleDataFromINI(INI* ini, const AsciiString& name, ModuleType type, const AsciiString& moduleTag);
Int findModuleInterfaceMask(const AsciiString& name, ModuleType type);
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
protected:
class ModuleTemplate
{
public:
ModuleTemplate() : m_createProc(NULL), m_createDataProc(NULL), m_whichInterfaces(0)
{
}
NewModuleProc m_createProc; ///< creation method
NewModuleDataProc m_createDataProc; ///< creation method
Int m_whichInterfaces;
};
const ModuleTemplate* findModuleTemplate(const AsciiString& name, ModuleType type);
/// adding a new module template to the factory, and assisting macro to make it easier
void addModuleInternal( NewModuleProc proc, NewModuleDataProc dataproc, ModuleType type, const AsciiString& name, Int whichIntf );
#define addModule( classname ) \
addModuleInternal( classname::friend_newModuleInstance, \
classname::friend_newModuleData, \
classname::getModuleType(), \
AsciiString( #classname ), \
classname::getInterfaceMask())
static NameKeyType makeDecoratedNameKey(const AsciiString& name, ModuleType type);
typedef std::map< NameKeyType, ModuleTemplate, std::less<NameKeyType> > ModuleTemplateMap;
typedef std::vector<const ModuleData*> ModuleDataList;
ModuleTemplateMap m_moduleTemplateMap;
ModuleDataList m_moduleDataList;
}; // end class ModuleFactory
// EXTERN /////////////////////////////////////////////////////////////////////////////////////////
extern ModuleFactory *TheModuleFactory; ///< singleton definition
#endif // __MODULEFACTORY_H_

View File

@ -0,0 +1,99 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Money.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Money.h
//
// Created: Steven Johnson, October 2001
//
// Desc: @todo
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef _MONEY_H_
#define _MONEY_H_
#include "Lib/BaseType.h"
#include "Common/Debug.h"
#include "Common/Snapshot.h"
// ----------------------------------------------------------------------------------------------
/**
How much "money" (Tiberium, Gems, Magic Resource Boxes, whatever) the Player has.
This is currently a Very Simple Class but is encapsulated
in anticipation of future expansion.
*/
class Money : public Snapshot
{
public:
inline Money() : m_money(0), m_playerIndex(0)
{
}
void init()
{
m_money = 0;
}
inline UnsignedInt countMoney() const
{
return m_money;
}
/// returns the actual amount withdrawn, which may be less than you want. (sorry, can't go into debt...)
UnsignedInt withdraw(UnsignedInt amountToWithdraw, Bool playSound = TRUE);
void deposit(UnsignedInt amountToDeposit, Bool playSound = TRUE);
void setPlayerIndex(Int ndx) { m_playerIndex = ndx; }
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
UnsignedInt m_money; ///< amount of money
Int m_playerIndex; ///< what is my player index?
};
#endif // _MONEY_H_

View File

@ -0,0 +1,131 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: MultiplayerSettings.h /////////////////////////////////////////////////////////////////////////////
// Settings common to multiplayer games
// Author: Matthew D. Campbell, January 2002
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef _MULTIPLAYERSETTINGS_H_
#define _MULTIPLAYERSETTINGS_H_
#include "GameClient/Color.h"
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////////////////////////
struct FieldParse;
class MultiplayerSettings;
// PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
class MultiplayerColorDefinition
{
public:
MultiplayerColorDefinition();
//-----------------------------------------------------------------------------------------------
static const FieldParse m_colorFieldParseTable[]; ///< the parse table for INI definition
const FieldParse *getFieldParse( void ) const { return m_colorFieldParseTable; }
inline AsciiString getTooltipName(void) const { return m_tooltipName; };
inline RGBColor getRGBValue(void) const { return m_rgbValue; };
inline RGBColor getRGBNightValue(void) const { return m_rgbValueNight; };
inline Color getColor(void) const { return m_color; }
inline Color getNightColor(void) const { return m_colorNight; }
void setColor( RGBColor rgb );
void setNightColor( RGBColor rgb );
MultiplayerColorDefinition * operator =(const MultiplayerColorDefinition& other);
private:
AsciiString m_tooltipName; ///< tooltip name for color combo box (AsciiString to pass to TheGameText->fetch())
RGBColor m_rgbValue; ///< RGB color value
Color m_color;
RGBColor m_rgbValueNight; ///< RGB color value
Color m_colorNight;
};
typedef std::map<Int, MultiplayerColorDefinition> MultiplayerColorList;
typedef std::map<Int, MultiplayerColorDefinition>::iterator MultiplayerColorIter;
//-------------------------------------------------------------------------------------------------
/** Multiplayer Settings container class
* Defines multiplayer settings */
//-------------------------------------------------------------------------------------------------
class MultiplayerSettings : public SubsystemInterface
{
public:
MultiplayerSettings( void );
void init() { }
void update() { }
void reset() { }
//-----------------------------------------------------------------------------------------------
static const FieldParse m_multiplayerSettingsFieldParseTable[]; ///< the parse table for INI definition
const FieldParse *getFieldParse( void ) const { return m_multiplayerSettingsFieldParseTable; }
// Color management --------------------
MultiplayerColorDefinition * findMultiplayerColorDefinitionByName(AsciiString name);
MultiplayerColorDefinition * newMultiplayerColorDefinition(AsciiString name);
inline Int getInitialCreditsMin( void ) { return m_initialCreditsMin; }
inline Int getInitialCreditsMax( void ) { return m_initialCreditsMax; }
inline Int getStartCountdownTimerSeconds( void ) { return m_startCountdownTimerSeconds; }
inline Int getMaxBeaconsPerPlayer( void ) { return m_maxBeaconsPerPlayer; }
inline Bool isShroudInMultiplayer( void ) { return m_isShroudInMultiplayer; }
inline Bool showRandomPlayerTemplate( void ) { return m_showRandomPlayerTemplate; }
inline Bool showRandomStartPos( void ) { return m_showRandomStartPos; }
inline Bool showRandomColor( void ) { return m_showRandomColor; }
inline Int getNumColors( void )
{
if (m_numColors == 0) {
m_numColors = m_colorList.size();
}
return m_numColors;
}
MultiplayerColorDefinition * getColor(Int which);
private:
Int m_initialCreditsMin;
Int m_initialCreditsMax;
Int m_startCountdownTimerSeconds;
Int m_maxBeaconsPerPlayer;
Bool m_isShroudInMultiplayer;
Bool m_showRandomPlayerTemplate;
Bool m_showRandomStartPos;
Bool m_showRandomColor;
MultiplayerColorList m_colorList;
Int m_numColors;
MultiplayerColorDefinition m_observerColor;
MultiplayerColorDefinition m_randomColor;
};
// singleton
extern MultiplayerSettings *TheMultiplayerSettings;
#endif

View File

@ -0,0 +1,153 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: NameKeyGenerator.h ///////////////////////////////////////////////////////////////////////
// Created: Michael Booth, May 2001
// Colin Day, May 2001
// Desc: Name key system to translate between names and unique key ids
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __NAMEKEYGENERATOR_H_
#define __NAMEKEYGENERATOR_H_
#include "Lib/BaseType.h"
#include "Common/SubsystemInterface.h"
#include "Common/GameMemory.h"
#include "Common/AsciiString.h"
//-------------------------------------------------------------------------------------------------
/**
Note that NameKeyType isn't a "real" enum, but an enum type used to enforce the
fact that NameKeys are really magic cookies, and aren't really interchangeable
with ints. NAMEKEY_INVALID is always a legal value, but all other values are dynamically
determined at runtime. (The generated code is basically identical, of course.)
*/
//-------------------------------------------------------------------------------------------------
enum NameKeyType
{
NAMEKEY_INVALID = 0,
NAMEKEY_MAX = 1<<23, // max ordinal value of a NameKey (some code relies on these fitting into 24 bits safely)
FORCE_NAMEKEYTYPE_LONG = 0x7fffffff // a trick to ensure the NameKeyType is a 32-bit int
};
//-------------------------------------------------------------------------------------------------
/** A bucket entry for the name key generator */
//-------------------------------------------------------------------------------------------------
class Bucket : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( Bucket, "NameKeyBucketPool" );
public:
Bucket();
//~Bucket();
Bucket *m_nextInSocket;
NameKeyType m_key;
AsciiString m_nameString;
};
inline Bucket::Bucket() : m_nextInSocket(NULL), m_key(NAMEKEY_INVALID) { }
inline Bucket::~Bucket() { }
//-------------------------------------------------------------------------------------------------
/** This class implements the conversion of an arbitrary string into a unique
* integer "key". Calling the nameToKey() method with the same string is
* guaranteed to return the same key. Also, all keys generated by an
* instance of this class are guaranteed to be unique with respect to that
* instance's catalog of names. Multiple instances of this class can be
* created to service multiple namespaces. */
//-------------------------------------------------------------------------------------------------
class NameKeyGenerator : public SubsystemInterface
{
public:
NameKeyGenerator();
virtual ~NameKeyGenerator();
virtual void init();
virtual void reset();
virtual void update() { }
/// Given a string, convert into a unique integer key.
NameKeyType nameToKey(const AsciiString& name) { return nameToKey(name.str()); }
/// Given a string, convert into a unique integer key.
NameKeyType nameToKey(const char* name);
/**
given a key, return the name. this is almost never needed,
except for a few rare cases like object serialization. also
note that it's not particularly fast; it does a dumb linear
search for the key.
*/
AsciiString keyToName(NameKeyType key);
private:
enum
{
// socketcount should be prime, and not "close" to a power of 2, for best results.
// if this one isn't large enough, try this website:
// http://www.utm.edu/research/primes/lists/small/1000.txt
SOCKET_COUNT = 6473
};
void freeSockets();
Bucket* m_sockets[SOCKET_COUNT]; ///< Catalog of all Buckets already generated
UnsignedInt m_nextID; ///< Next available ID
}; // end class NameKeyGenerator
//-------------------------------------------------------------------------------------------------
// Externals
//-------------------------------------------------------------------------------------------------
extern NameKeyGenerator *TheNameKeyGenerator; ///< just one namespace for now
// typing "TheNameKeyGenerator->nameToKey()" is awfully wordy. Here are shorter synonyms:
inline NameKeyType NAMEKEY(const AsciiString& name) { return TheNameKeyGenerator->nameToKey(name); }
inline NameKeyType NAMEKEY(const char* name) { return TheNameKeyGenerator->nameToKey(name); }
inline AsciiString KEYNAME(NameKeyType nk) { return TheNameKeyGenerator->keyToName(nk); }
//-------------------------------------------------------------------------------------------------
class StaticNameKey
{
private:
mutable NameKeyType m_key;
const char* m_name;
public:
StaticNameKey(const char* p) : m_key(NAMEKEY_INVALID), m_name(p) {}
NameKeyType key() const;
// ugh, this is a little hokey, but lets us pretend that a StaticNameKey == NameKeyType
inline operator NameKeyType() const { return key(); }
};
#endif // __NAMEKEYGENERATOR_H_

View File

@ -0,0 +1,66 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// Overridable.h //////////////////////////////////////////////////////////////////////////////////
// Electronic Arts Pacific
// Do Not Distribute
#pragma once
#ifndef __OSDISPLAY_H__
#define __OSDISPLAY_H__
#include "Lib/Basetype.h"
class AsciiString;
enum OSDisplayButtonType
{
OSDBT_OK = 0x00000001,
OSDBT_CANCEL = 0x00000002,
OSDBT_ERROR = 0x80000000
};
enum OSDisplayOtherFlags
{
OSDOF_SYSTEMMODAL = 0x00000001,
OSDOF_APPLICATIONMODAL = 0x00000002,
OSDOF_TASKMODAL = 0x00000004,
OSDOF_EXCLAMATIONICON = 0x00000008,
OSDOF_INFORMATIONICON = 0x00000010,
OSDOF_ERRORICON = 0x00000011,
OSDOF_STOPICON = 0x00000012,
ODDOF_ERROR = 0x80000000
};
// Display a warning box to the user with the specified localized prompt, message, and
// buttons. (Feel free to add buttons as appropriate to the enum above).
// This function will return the button pressed to close the dialog.
OSDisplayButtonType OSDisplayWarningBox(AsciiString p, AsciiString m, UnsignedInt buttonFlags, UnsignedInt otherFlags);
#endif /* __OSDISPLAY_H__ */

View File

@ -0,0 +1,128 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// Overridable.h //////////////////////////////////////////////////////////////////////////////////
// Electronic Arts Pacific
// Do Not Distribute
#pragma once
#ifndef _OVERRIDABLE_H_
#define _OVERRIDABLE_H_
/*
In order for something to live in an OVERRIDE<> object, it must be derived from Overridable
(publicly).
This is useful for things like templates, where we want to override the template and make sure
that all instances get the updated values (for instance, via map.ini)
*/
class Overridable : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( Overridable, "Overridable" )
private:
Overridable *m_nextOverride;
Bool m_isOverride;
public:
Overridable() : m_nextOverride(NULL), m_isOverride(false) {}
// return a constant version of m_nextOverride, which can be NULL if there is no
// override
const Overridable *getNextOverride( void ) const
{
return m_nextOverride;
}
// recursively ask if there is a next override, and if not, return this.
const Overridable *getFinalOverride( void ) const
{
if (m_nextOverride)
return m_nextOverride->getFinalOverride();
return this;
}
// set the next override on this object. This currently makes no attempt to prevent leaks.
// it probably shouldn't because doing so could cause infinite loops
void setNextOverride(Overridable *nextOverridable)
{
m_nextOverride = nextOverridable;
}
// useful for the LocomotorStore to cleanup overrides.
Overridable *friend_getNextOverride( void )
{
return m_nextOverride;
}
// useful for the LocomotorStore to create an override dangling off the final override.
Overridable *friend_getFinalOverride( void )
{
if (m_nextOverride)
return m_nextOverride->friend_getFinalOverride();
return this;
}
// useful for the LocomotorStore to create an override dangling off the final override.
const Overridable *friend_getFinalOverride( void ) const
{
if (m_nextOverride)
return m_nextOverride->friend_getFinalOverride();
return this;
}
// used by ini-parsing functions to mark specific Overridables as overrides
void markAsOverride( void )
{
m_isOverride = true;
}
// used in factory reset() calls at the end of a game to clean up overrides. Can return NULL
// if the first Overridable is itself an override
Overridable *deleteOverrides( void )
{
if ( m_isOverride )
{
deleteInstance();
return NULL;
}
else if ( m_nextOverride )
{
m_nextOverride = m_nextOverride->deleteOverrides();
}
return this;
}
};
// cleans up and dangling overrides.
__inline Overridable::~Overridable()
{
if (m_nextOverride)
m_nextOverride->deleteInstance();
}
#endif /* _OVERRIDABLE_H_ */

View File

@ -0,0 +1,141 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// Override.h /////////////////////////////////////////////////////////////////////////////////////
// Electronic Arts Pacific
// Do Not Distribute
#pragma once
#ifndef _OVERRIDE_H_
#define _OVERRIDE_H_
#include "Common/Overridable.h"
/*
An OVERRIDE is a replacement for a pointer of its contained type, ie, rather than containing
a LocomotorTemplate*, you would contain an OVERRIDE<LocomotorTemplate>.
OVERRIDE pretends in all ways (dereference via *, -> and casting to type*) to be a type*, so
there should be very little code that needs to be rewritten to work with these.
In order to make something overridable, these are the steps:
1) Make the desired class derive from Overridable.
2) Make the container class contain an instance of OVERRIDE<Type>
3) Make the newOverride function (wherever an override is new'd) request the overridables lastOverride,
to ensure that no leaks are created.
See LocomotorTemplate for an example.
*/
template <class T> class OVERRIDE
{
public:
// Provide useful constructores to go from a T* to an OVERRIDE<T>
OVERRIDE(const T *overridable = NULL);
// Copy constructor
OVERRIDE(OVERRIDE<T> &overridable);
// Operator= for copying from another OVERRIDE and T*
__inline OVERRIDE &operator=( const OVERRIDE<T>& override );
__inline OVERRIDE &operator=( const T* overridable );
// these are the methods which we can use to access data in a pointer. (Dereference*, ->, and cast
// to T*). They are all overloaded to recurse to the lowest override and use that.
__inline const T *operator->( void ) const; // overload const ->
__inline const T *operator*( void ) const; // overload const *(dereference operator)
__inline operator const T*( ) const; // overload casting to (const T*)
// this is useful in case you want to get the pointer that this object is actually looking at.
__inline const T *getNonOverloadedPointer( void ) const;
private:
// Because OVERRIDE is meant to live on the object and not in the store, it currently contains
// a constant pointer. We could change this if it seems weird.
const T *m_overridable;
};
//-------------------------------------------------------------------------------------------------
template <class T>
OVERRIDE<T>::OVERRIDE(const T *overridable)
{
m_overridable = overridable;
}
//-------------------------------------------------------------------------------------------------
template <class T>
OVERRIDE<T>::OVERRIDE(OVERRIDE<T> &overridable)
{
m_overridable = overridable.m_overridable;
}
//-------------------------------------------------------------------------------------------------
template <class T>
OVERRIDE<T> &OVERRIDE<T>::operator=( const OVERRIDE<T>& override )
{
m_overridable = override.m_overridable;
return *this;
}
//-------------------------------------------------------------------------------------------------
template <class T>
OVERRIDE<T> &OVERRIDE<T>::operator=(const T* overridable)
{
m_overridable = overridable;
return *this;
}
//-------------------------------------------------------------------------------------------------
template <class T>
const T *OVERRIDE<T>::operator->() const
{
if (!m_overridable)
return NULL;
return (T*) m_overridable->getFinalOverride();
}
//-------------------------------------------------------------------------------------------------
template <class T>
const T *OVERRIDE<T>::operator*() const
{
if (!m_overridable)
return NULL;
return (T*) m_overridable->getFinalOverride();
}
//-------------------------------------------------------------------------------------------------
template <class T>
const T *OVERRIDE<T>::getNonOverloadedPointer( void ) const
{
return (T*) m_overridable;
}
//-------------------------------------------------------------------------------------------------
template <class T>
OVERRIDE<T>::operator const T*( ) const
{
return operator*();
}
#endif /* _OVERRIDE_H_ */

View File

@ -0,0 +1,87 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Statistics.h
/*---------------------------------------------------------------------------*/
/* EA Pacific */
/* Confidential Information */
/* Copyright (C) 2001 - All Rights Reserved */
/* DO NOT DISTRIBUTE */
/*---------------------------------------------------------------------------*/
/* Project: RTS3 */
/* File name: PartitionSolver.h */
/* Created: John K. McDonald, Jr., 4/2/2002 */
/* Desc: General purpose partition problem-solver */
/* Revision History: */
/* 4/12/2002 : Initial creation */
/*---------------------------------------------------------------------------*/
#pragma once
#ifndef _H_PARTITIONSOLVER_
#define _H_PARTITIONSOLVER_
// INCLUDES ///////////////////////////////////////////////////////////////////
// DEFINES ////////////////////////////////////////////////////////////////////
// TYPE DEFINES ///////////////////////////////////////////////////////////////
// FORWARD DECLARATIONS ///////////////////////////////////////////////////////
typedef std::pair<ObjectID, UnsignedInt> PairObjectIDAndUInt;
typedef std::pair<ObjectID, ObjectID> PairObjectID;
// the first unsigned int is the identifying nugget, while the second is the size of the nugget
typedef std::vector<PairObjectIDAndUInt> EntriesVec;
// the first unsigned int is the identifying nugget, while the second is the size of the hole we get to fill
typedef std::vector<PairObjectIDAndUInt> SpacesVec;
// the first ObjectID is the id of the entry, while the second is the id of the hole
typedef std::vector<PairObjectID> SolutionVec;
enum SolutionType
{
PREFER_FAST_SOLUTION = 0,
PREFER_CORRECT_SOLUTION = 0x7FFFFFFF
};
class PartitionSolver
{
protected:
SolutionType m_howToSolve;
EntriesVec m_data;
SpacesVec m_spacesForData;
SolutionVec m_currentSolution;
UnsignedInt m_currentSolutionLeftovers;
SolutionVec m_bestSolution;
public:
PartitionSolver(const EntriesVec& elements, const SpacesVec& spaces, SolutionType solveHow);
// Solve could potentially take a LONG TIME (as in NEVER complete). This problem is NP-complete.
void solve(void);
const SolutionVec& getSolution( void ) const;
};
#endif /* _H_PARTITIONSOLVER_ */

View File

@ -0,0 +1,48 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// PerfMetrics.h //////////////////////////////////////////////////////////////////////////////////
// Author: John McDonald, Jr August 2002
// Do Not Distribute
#pragma once
#ifndef __PERFMETRICS_H__
#define __PERFMETRICS_H__
// For load timings
enum { PERFMETRICS_LOAD_STARTFRAME = 0 };
enum { PERFMETRICS_LOAD_STOPFRAME = 1 };
// For engine timings
enum { PERFMETRICS_LOGIC_STARTFRAME = 1 };
enum { PERFMETRICS_LOGIC_STOPFRAME = 1000 };
// For showing metrics
enum { PERFMETRICS_BETWEEN_METRICS = 150 };
#endif /* __PERFMETRICS_H__ */

View File

@ -0,0 +1,326 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// PerfTimer.h ////////////////////////////////////////////////////////////////////////////////////
// John McDonald
// July 2002
#pragma once
#ifndef __PERFTIMER_H__
#define __PERFTIMER_H__
#if defined(_DEBUG) || defined(_INTERNAL)
/*
NOTE NOTE NOTE: never check this in with this enabled, since there is a nonzero time penalty
for running in this mode. Only enable it for local builds for testing purposes! (srj)
*/
#define NO_PERF_TIMERS
#else
#define NO_PERF_TIMERS
#endif
#include "Common/GameCommon.h" // ensure we get DUMP_PERF_STATS, or not
#ifdef PERF_TIMERS
#include "GameLogic/GameLogic.h"
#include "Common/PerfMetrics.h"
#include "Common/GlobalData.h"
#endif
// Forward Declarations
class DebugDisplayInterface;
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
#define NO_USE_QPF // non-QPF is much faster.
#if defined(PERF_TIMERS) || defined(DUMP_PERF_STATS)
//-------------------------------------------------------------------------------------------------
void InitPrecisionTimer();
//-------------------------------------------------------------------------------------------------
void GetPrecisionTimerTicksPerSec(Int64* t);
//-------------------------------------------------------------------------------------------------
__forceinline void GetPrecisionTimer(Int64* t)
{
#ifdef USE_QPF
QueryPerformanceCounter((LARGE_INTEGER*)t);
#else
// CPUID is needed to force serialization of any previous instructions.
__asm
{
// for now, I am commenting this out. It throws the timings off a bit more (up to .001%) jkmcd
// CPUID
RDTSC
MOV ECX,[t]
MOV [ECX], EAX
MOV [ECX+4], EDX
}
#endif
}
#endif
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
#ifdef PERF_TIMERS
//-------------------------------------------------------------------------------------------------
class PerfGather
{
public:
PerfGather( const char *identifier );
virtual ~PerfGather( );
__forceinline void startTimer();
__forceinline void stopTimer();
enum
{
PERF_GROSSTIME = 0x01,
PERF_NETTIME = 0x02,
PERF_CALLCOUNT = 0x04
};
static void resetAll();
static void initPerfDump(const char* fname, Int options);
static void termPerfDump();
static void dumpAll(UnsignedInt frame);
static void displayGraph(UnsignedInt frame);
void reset();
private:
enum { MAX_ACTIVE_STACK = 256 };
static PerfGather* m_active[MAX_ACTIVE_STACK];
static PerfGather** m_activeHead;
static Int64 s_stopStartOverhead; // overhead for stop+start a timer
static PerfGather*& getHeadPtr();
void addToList();
void removeFromList();
const char* m_identifier;
Int64 m_startTime;
Int64 m_runningTimeGross;
Int64 m_runningTimeNet;
Int m_callCount;
PerfGather* m_next;
PerfGather* m_prev;
Bool m_ignore;
};
//-------------------------------------------------------------------------------------------------
void PerfGather::startTimer()
{
*++m_activeHead = this;
GetPrecisionTimer(&m_startTime);
}
//-------------------------------------------------------------------------------------------------
void PerfGather::stopTimer()
{
DEBUG_ASSERTCRASH(this != NULL, ("I am null, uh oh"));
Int64 runTime;
GetPrecisionTimer(&runTime);
runTime -= m_startTime;
m_runningTimeGross += runTime;
m_runningTimeNet += runTime;
++m_callCount;
#ifdef _DEBUG
DEBUG_ASSERTCRASH(*m_activeHead != NULL, ("m_activeHead is null, uh oh"));
DEBUG_ASSERTCRASH(*m_activeHead == this, ("I am not the active timer, uh oh"));
DEBUG_ASSERTCRASH(m_activeHead >= &m_active[0] && m_activeHead <= &m_active[MAX_ACTIVE_STACK-1], ("active under/over flow"));
#endif
--m_activeHead;
if (*m_activeHead)
{
// don't add the time it took for us to actually get the ticks (in startTimer) to our parent...
(*m_activeHead)->m_runningTimeGross -= (s_stopStartOverhead);
(*m_activeHead)->m_runningTimeNet -= (runTime + s_stopStartOverhead);
}
}
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class AutoPerfGather
{
private:
PerfGather& m_g;
public:
__forceinline AutoPerfGather(PerfGather& g);
__forceinline ~AutoPerfGather();
};
//-------------------------------------------------------------------------------------------------
AutoPerfGather::AutoPerfGather(PerfGather& g) : m_g(g)
{
m_g.startTimer();
}
//-------------------------------------------------------------------------------------------------
AutoPerfGather::~AutoPerfGather()
{
m_g.stopTimer();
}
//-------------------------------------------------------------------------------------------------
class AutoPerfGatherIgnore
{
private:
static Bool s_ignoring;
PerfGather& m_g;
Bool m_oldIgnore;
public:
__forceinline AutoPerfGatherIgnore(PerfGather& g);
__forceinline ~AutoPerfGatherIgnore();
};
//-------------------------------------------------------------------------------------------------
AutoPerfGatherIgnore::AutoPerfGatherIgnore(PerfGather& g) : m_g(g)
{
m_oldIgnore = s_ignoring;
s_ignoring = true;
m_g.startTimer();
}
//-------------------------------------------------------------------------------------------------
AutoPerfGatherIgnore::~AutoPerfGatherIgnore()
{
m_g.stopTimer();
if (s_ignoring)
m_g.reset();
s_ignoring = m_oldIgnore;
}
//-------------------------------------------------------------------------------------------------
#define DECLARE_PERF_TIMER(id) static PerfGather s_##id(#id);
#define USE_PERF_TIMER(id) AutoPerfGather a_##id(s_##id);
#define IGNORE_PERF_TIMER(id) AutoPerfGatherIgnore a_##id(s_##id);
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
class PerfTimer
{
public:
PerfTimer( const char *identifier, Bool crashWithInfo = true, Int startFrame = 0, Int endFrame = -1);
virtual ~PerfTimer( );
__forceinline void startTimer( void );
__forceinline void stopTimer( void );
protected:
Int64 m_startTime;
protected:
void outputInfo( void );
void showMetrics( void );
protected:
const char *m_identifier;
Bool m_crashWithInfo;
UnsignedInt m_startFrame;
UnsignedInt m_endFrame;
UnsignedInt m_lastFrame; // last frame we got data from
Bool m_outputInfo;
// total running time so far.
Int64 m_runningTime;
Int m_callCount;
friend void StatMetricsDisplay( DebugDisplayInterface *dd, void *, FILE *fp );
friend void EndStatMetricsDisplay( DebugDisplayInterface *dd, void *, FILE *fp );
};
//-------------------------------------------------------------------------------------------------
void PerfTimer::startTimer( void )
{
UnsignedInt frm = (TheGameLogic ? TheGameLogic->getFrame() : m_startFrame);
if (frm >= m_startFrame && (m_endFrame == -1 || frm <= m_endFrame))
{
GetPrecisionTimer(&m_startTime);
}
}
//-------------------------------------------------------------------------------------------------
void PerfTimer::stopTimer( void )
{
UnsignedInt frm = (TheGameLogic ? TheGameLogic->getFrame() : m_startFrame);
if (frm >= m_startFrame && (m_endFrame == -1 || frm <= m_endFrame))
{
Int64 tmp;
GetPrecisionTimer(&tmp);
m_runningTime += (tmp - m_startTime);
++m_callCount;
m_lastFrame = frm;
}
if (TheGlobalData && TheGlobalData->m_showMetrics && m_endFrame > m_startFrame + PERFMETRICS_BETWEEN_METRICS) {
m_endFrame = m_startFrame + PERFMETRICS_BETWEEN_METRICS;
}
if (m_endFrame > 0 && frm >= m_endFrame) {
if (TheGlobalData->m_showMetrics) {
showMetrics();
}
outputInfo();
}
}
//-------------------------------------------------------------------------------------------------
extern void StatMetricsDisplay( DebugDisplayInterface *dd, void *, FILE *fp );
#else // PERF_TIMERS
#define DECLARE_PERF_TIMER(id)
#define USE_PERF_TIMER(id)
#define IGNORE_PERF_TIMER(id)
#endif // PERF_TIMERS
#endif /* __PERFTIMER_H__ */

View File

@ -0,0 +1,792 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Player.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: Player.h
//
// Created: Steven Johnson, October 2001
//
// Desc: @todo
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef _PLAYER_H_
#define _PLAYER_H_
#include "Common/Debug.h"
#include "Common/Energy.h"
#include "Common/GameType.h"
#include "Common/Handicap.h"
#include "Common/KindOf.h"
#include "Common/MissionStats.h"
#include "Common/Money.h"
#include "Common/Science.h"
#include "Common/UnicodeString.h"
#include "Common/NameKeyGenerator.h"
#include "Common/Thing.h"
#include "Common/STLTypedefs.h"
#include "Common/ScoreKeeper.h"
#include "Common/Team.h"
#include "Common/STLTypedefs.h"
// ----------------------------------------------------------------------------------------------
class BuildListInfo;
class PolygonTrigger;
class ThingTemplate;
class AIPlayer;
class AIGroup;
class GameMessage;
class ResourceGatheringManager;
class PlayerTemplate;
class Squad;
class Team;
class TeamPrototype;
class TeamRelationMap;
class TunnelTracker;
class Upgrade;
class UpgradeTemplate;
class SpecialPowerModule;
class BattlePlanBonuses;
enum BattlePlanStatus;
enum UpgradeStatusType;
enum CommandSourceType;
enum ScienceAvailabilityType
{
SCIENCE_AVAILABILITY_INVALID = -1,
SCIENCE_AVAILABLE,
SCIENCE_DISABLED,
SCIENCE_HIDDEN,
SCIENCE_AVAILABILITY_COUNT,
};
#ifdef DEFINE_SCIENCE_AVAILABILITY_NAMES
static const char *ScienceAvailabilityNames[] =
{
"Available",
"Disabled",
"Hidden",
NULL
};
#endif // end DEFINE_SCIENCE_AVAILABILITY_NAMES
static const Int NUM_HOTKEY_SQUADS = 10;
enum { NO_HOTKEY_SQUAD = -1 };
// ------------------------------------------------------------------------------------------------
typedef Int PlayerIndex;
#define PLAYER_INDEX_INVALID -1
// ------------------------------------------------------------------------------------------------
class KindOfPercentProductionChange : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(KindOfPercentProductionChange, "KindOfPercentProductionChange")
public:
KindOfMaskType m_kindOf;
Real m_percent;
UnsignedInt m_ref;
};
EMPTY_DTOR(KindOfPercentProductionChange)
// ------------------------------------------------------------------------------------------------
struct SpecialPowerReadyTimerType
{
SpecialPowerReadyTimerType()
{
clear();
}
void clear( void )
{
m_readyFrame = 0xffffffff;
m_templateID = INVALID_ID;
};
UnsignedInt m_templateID; ///< The ID of the specialpower template associated with this timer... no dupes allowed
UnsignedInt m_readyFrame; ///< on what game frame will this special power be ready?
};
// ------------------------------------------------------------------------------------------------
typedef std::hash_map< PlayerIndex, Relationship, std::hash<PlayerIndex>, std::equal_to<PlayerIndex> > PlayerRelationMapType;
class PlayerRelationMap : public MemoryPoolObject,
public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( PlayerRelationMap, "PlayerRelationMapPool" )
public:
PlayerRelationMap( void );
// virtual destructor provided by memory pool object
/** @todo I'm jsut wrappign this up in a nice snapshot object, we really should isolate
* m_map from public access and make access methods for our operations */
PlayerRelationMapType m_map;
protected:
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
};
// ----------------------------------------------------------------------------------------------
/**
A "Player" as an entity that contains the persistent info of the Player, as well as containing
transient mission data.
Some of the Player's attributes persist between missions, whereas others are "transient" and only
have meaning in a mission, wherein they change a lot (current tech tree state, current buildings
built, units trained, money, etc). (For clarity of nomenclature, we'll refer to all "persistent"
vs "non-persistent" attributes, since "transient" has an unclear duration.)
A "Player" consists of an entity controlling a single set of units in a mission.
A Player may be human or computer controlled.
All Players have a (transient) "Player Index" associated which allows us to do some shorthand for
representing Players in some cases (mainly in bitfields). This is always a 0-based
number (-1 is used as an illegal index). Note that a logical conclusion of this
is that it makes it desirable to limit the maximum number of simultaneous Players
to 32, but that seems quite reasonable.
All persistent data associated with the Player will be saved to local storage and/or
synchronized with one of our servers for online play.
Note, simple accessor methods are omitted for brevity... for now, you may infer
them from the data structures.
Note also that the class (and the relevant subclasses) are almost certainly incomplete;
a short perusal of the RA2 equivalent class(es) have waaay more tweaky data fields,
some of which will probably be necessary (in some form, at some point), some of
which won't ever be necessary. Rather than trying to guess at all of them here,
we're limiting the initial setup to be the almost-certainly-necessary, filling in
the extra things as needed. (Note that most of these will be non-persistent!)
*/
class Player : public Snapshot
{
public:
Player( Int playerIndex );
virtual ~Player();
void update(); ///< player update opportunity
void newMap(); ///< player after map loaded opportunity
void init(const PlayerTemplate* pt);
void initFromDict(const Dict* d);
void setDefaultTeam(void);
inline UnicodeString getPlayerDisplayName() { return m_playerDisplayName; }
inline NameKeyType getPlayerNameKey() const { return m_playerNameKey; }
inline AsciiString getSide() const { return m_side; }
inline const PlayerTemplate* getPlayerTemplate() const { return m_playerTemplate; }
/// return the Player's Handicap sub-object
inline const Handicap *getHandicap() const { return &m_handicap; }
inline Handicap *getHandicap() { return &m_handicap; }
/// return the Player's Money sub-object
inline Money *getMoney() { return &m_money; }
inline const Money *getMoney() const { return &m_money; }
UnsignedInt getSupplyBoxValue();///< Many things can affect the alue of a crate, but at heart it is a GlobalData ratio.
inline Energy *getEnergy() { return &m_energy; }
inline const Energy *getEnergy() const { return &m_energy; }
// adds a power bonus to this player because of energy upgrade at his power plants
inline void addPowerBonus(Object *obj) { m_energy.addPowerBonus(obj); }
inline void removePowerBonus(Object *obj) { m_energy.removePowerBonus(obj); }
inline ResourceGatheringManager *getResourceGatheringManager(){ return m_resourceGatheringManager; }
inline TunnelTracker* getTunnelSystem(){ return m_tunnelSystem; }
inline Color getPlayerColor() const { return m_color; }
inline Color getPlayerNightColor() const { return m_nightColor;}
/// return the type of controller
inline PlayerType getPlayerType() const { return m_playerType; }
void setPlayerType(PlayerType t, Bool skirmish);
inline PlayerIndex getPlayerIndex() const { return m_playerIndex; }
/// return a bitmask that is unique to this player.
inline PlayerMaskType getPlayerMask() const { return 1 << m_playerIndex; }
/// a convenience function to test the ThingTemplate against the players canBuild flags
/// called by canBuild
Bool allowedToBuild(const ThingTemplate *tmplate) const;
/// true if we have the prereqs for this item
Bool canBuild(const ThingTemplate *tmplate) const;
// Can we afford to build?
Bool canAffordBuild( const ThingTemplate *whatToBuild ) const;
/// Difficulty level for this player.
GameDifficulty getPlayerDifficulty(void) const;
/** return the player's command center. (must be one of his "normal" ones,
not a captured one.)
if he has none, return null.
if he has multiple, return one arbitrarily. */
Object* findNaturalCommandCenter();
/// return t if the player has the given science, either intrinsically, via specialization, or via capture.
Bool hasScience(ScienceType t) const;
Bool isScienceDisabled( ScienceType t ) const; ///< Can't purchase this science because of script reasons.
Bool isScienceHidden( ScienceType t ) const; ///< This science is effectively hidden due to script reasons.
//Allows scripts to make specific sciences available, hidden, or disabled.
void setScienceAvailability( ScienceType science, ScienceAvailabilityType type );
ScienceAvailabilityType getScienceAvailabilityTypeFromString( const AsciiString& name );
/// return t iff the player has all sciences that are prereqs for knowing the given science
Bool hasPrereqsForScience(ScienceType t) const;
Bool hasUpgradeComplete( const UpgradeTemplate *upgradeTemplate ); ///< does player have totally done and produced upgrade
Bool hasUpgradeComplete( Int64 testMask ); ///< does player have totally done and produced upgrade
Int64 getCompletedUpgradeMask() const { return m_upgradesCompleted; } ///< get list of upgrades that are completed
Bool hasUpgradeInProduction( const UpgradeTemplate *upgradeTemplate ); ///< does player have this upgrade in progress right now
Upgrade *addUpgrade( const UpgradeTemplate *upgradeTemplate,
UpgradeStatusType status ); ///< add upgrade, or update existing upgrade status
void removeUpgrade( const UpgradeTemplate *upgradeTemplate ); ///< remove thsi upgrade from us
/** find upgrade, NOTE, the upgrade may *NOT* be "complete" and therefore "active", it could be in production
This function is for actually retrieving the Upgrade. To test existance, use the fast bit testers hasUpgradeX()
*/
Upgrade *findUpgrade( const UpgradeTemplate *upgradeTemplate );
void onUpgradeCompleted( const UpgradeTemplate *upgradeTemplate ); ///< An upgrade just finished, do things like tell all objects to recheck UpgradeModules
void onUpgradeRemoved(){} ///< An upgrade just got removed, this doesn't do anything now.
#if defined(_DEBUG) || defined(_INTERNAL)
/// Prereq disabling cheat key
void toggleIgnorePrereqs(){ m_DEMO_ignorePrereqs = !m_DEMO_ignorePrereqs; }
Bool ignoresPrereqs() const { return m_DEMO_ignorePrereqs; }
/// No cost building cheat key
void toggleFreeBuild(){ m_DEMO_freeBuild = !m_DEMO_freeBuild; }
Bool buildsForFree() const { return m_DEMO_freeBuild; }
/// No time building cheat key
void toggleInstantBuild(){ m_DEMO_instantBuild = !m_DEMO_instantBuild; }
Bool buildsInstantly() const { return m_DEMO_instantBuild; }
#endif
///< Power just changed at all. Didn't make two functions so you can't forget to undo something you didin one of them.
///< @todo Can't do edge trigger until after demo; make things check for power on creation
void onPowerBrownOutChange( Bool brownOut );
///< one of my command centers just fired a special power, let us reset timers for all command centers.
void resetOrStartSpecialPowerReadyFrame( const SpecialPowerTemplate *temp );
///< my new command center wants to init his timers to the status quo
UnsignedInt getOrStartSpecialPowerReadyFrame( const SpecialPowerTemplate *temp);
void expressSpecialPowerReadyFrame( const SpecialPowerTemplate *temp, UnsignedInt frame );
void addNewSharedSpecialPowerTimer( const SpecialPowerTemplate *temp, UnsignedInt frame );
void addRadar( Bool disableProof );///< One more producer of Radar exists
void removeRadar( Bool disableProof );///< One less thing produces radar
void disableRadar(); ///< No matter how many radar producers I have, I do not have radar
void enableRadar(); ///< remove the restriction imposed by disableRadar
Bool hasRadar() const;///< A positive number of radar producers, plus my radar is not disabled
Bool okToPlayRadarEdgeSound();///< just like it "sounds"
//Battle plans effect the players abilities... so may as well add it here. Also
//it's possible for multiple strategy centers to have the same plan, so we need
//to keep track of that like radar. Keep in mind multiple strategy centers with
//same plan do not stack, but different strategy centers with different plans do.
void changeBattlePlan( BattlePlanStatus plan, Int delta, BattlePlanBonuses *bonus );
Int getNumBattlePlansActive() const { return m_bombardBattlePlans + m_holdTheLineBattlePlans + m_searchAndDestroyBattlePlans; }
Int getBattlePlansActiveSpecific( BattlePlanStatus plan ) const;
void applyBattlePlanBonusesForObject( Object *obj ) const; //New object or converted object gaining our current battle plan bonuses.
void removeBattlePlanBonusesForObject( Object *obj ) const; //Object left team
void applyBattlePlanBonusesForPlayerObjects( const BattlePlanBonuses *bonus ); //Battle plan bonuses changing, so apply to all of our objects!
Bool doesObjectQualifyForBattlePlan( Object *obj ) const;
// If apply is false, then we are repealing already granted bonuses.
// Note: Should only be called by Object.
void friend_applyDifficultyBonusesForObject(Object* obj, Bool apply) const;
/// Decrement the ref counter on the typeof production list node
void removeKindOfProductionCostChange(KindOfMaskType kindOf, Real percent);
/// add type of production cost change (Used for upgrades)
void addKindOfProductionCostChange( KindOfMaskType kindOf, Real percent);
/// Returns production cost change based on typeof (Used for upgrades)
Real getProductionCostChangeBasedOnKindOf( KindOfMaskType kindOf ) const;
/** Return bonus or penalty for construction of this thing.
*/
Real getProductionCostChangePercent( AsciiString buildTemplateName ) const;
/** Return bonus or penalty for construction of this thing.
*/
Real getProductionTimeChangePercent( AsciiString buildTemplateName ) const;
/** Return starting veterancy level of a newly built thing of this type
*/
VeterancyLevel getProductionVeterancyLevel( AsciiString buildTemplateName ) const;
// Friend function for the script engine's usage.
void friend_setSkillset(Int skillSet);
/**
the given object has just become (or just ceased to be) a member of one of our teams (or subteams)
*/
void becomingTeamMember(Object *obj, Bool yes);
/**
this is called when the player becomes the local player (yes==true)
or ceases to be the local player (yes==false). you can't stop this
from happening; you can only react to it.
*/
void becomingLocalPlayer(Bool yes);
/// Is this player the local player?
Bool isLocalPlayer() const;
/// this player should be listed in the score screen.
void setListInScoreScreen(Bool listInScoreScreen);
/// return TRUE if this player should be listed in the score screen.
Bool getListInScoreScreen();
/// A unit was just created and is ready to control
void onUnitCreated( Object *factory, Object *unit );
/// A team is about to be destroyed.
void preTeamDestroy( const Team *team );
/// Is the nearest supply source safe?
Bool isSupplySourceSafe( Int minSupplies );
/// Is a supply source attacked?
Bool isSupplySourceAttacked( void );
/// Set delay between team production.
void setTeamDelaySeconds(Int delay);
/// Have the team guard a supply center.
void guardSupplyCenter( Team *team, Int minSupplies );
virtual void computeSuperweaponTarget(const SpecialPowerTemplate *power, Coord3D *pos, Int playerNdx, Real weaponRadius); ///< Calculates best pos for weapon given radius.
/// Get the enemy an ai player is currently focused on. NOTE - Can be NULL.
Player *getCurrentEnemy( void );
/// Is this player a skirmish ai player?
Bool isSkirmishAIPlayer( void );
/// Have the ai check for bridges.
virtual Bool checkBridges(Object *unit, Waypoint *way);
/// Get the center of the ai's base.
virtual Bool getAiBaseCenter(Coord3D *pos);
/// Have the ai check for bridges.
virtual void repairStructure(ObjectID structureID);
/// a structuer was just created, but is under construction
void onStructureCreated( Object *builder, Object *structure );
/// a structure that was under construction has become completed
void onStructureConstructionComplete( Object *builder, Object *structure, Bool isRebuild );
/// a structure that was created has been pre-emptively removed and shouldn't be counted in the score.
void onStructureUndone(Object *structure);
/**
a convenience routine to count the number of owned objects that match a set of ThingTemplates.
You input the count and an array of ThingTemplate*, and provide an array of Int of the same
size. It fills in the array to the correct counts. This is handy because we must traverse
the player's list-of-objects only once.
*/
void countObjectsByThingTemplate(Int numTmplates, const ThingTemplate* const * things, Bool ignoreDead, Int *counts, Bool ignoreUnderConstruction = TRUE ) const;
/**
simply returns the number of buildings owned by this player
*/
Int countBuildings(void);
/**
simply returns the number of objects owned by this player with a specific KindOfMaskType
*/
Int countObjects(KindOfMaskType setMask, KindOfMaskType clearMask);
/// Returns the closest of a given type to the given object
Object *findClosestByKindOf( Object *queryObject, KindOfMaskType setMask, KindOfMaskType clearMask );
/**
a convenience routine to quickly check if any buildings are owned.
*/
Bool hasAnyBuildings(void) const;
/**
a convenience routine to quickly check if any buildings with a specific KindOfType flag are owned.
*/
Bool hasAnyBuildings(KindOfMaskType kindOf) const;
/**
a convenience routine to quickly check if any units are owned.
*/
Bool hasAnyUnits(void) const;
/**
a convenience routine to quickly check if any objects are owned.
*/
Bool hasAnyObjects(void) const;
/**
a convenience routine to quickly check if any buildfacilities are owned.
*/
Bool hasAnyBuildFacility(void) const;
/**
a convenience routine to quickly update the state flags on all teams.
*/
void updateTeamStates(void);
/**
This player will heal everything owned by it
*/
void healAllObjects();
/**
* Iterate all objects that this player has
*/
void iterateObjects( ObjectIterateFunc func, void *userData );
/**
return this player's "default" team.
*/
Team *getDefaultTeam() { DEBUG_ASSERTCRASH(m_defaultTeam!=NULL,("default team is null")); return m_defaultTeam; }
const Team *getDefaultTeam() const { DEBUG_ASSERTCRASH(m_defaultTeam!=NULL,("default team is null")); return m_defaultTeam; }
void setBuildList(BuildListInfo *pBuildList); ///< sets the build list.
BuildListInfo *getBuildList( void ) { return m_pBuildList; } ///< returns the build list. (build list might be modified by the solo AI)
void addToBuildList(Object *obj); ///< Adds this to the build list. Used for factories placed instead of in build list.
void addToPriorityBuildList(AsciiString templateName, Coord3D *pos, Real angle); ///< Adds this to the build list. Used for factories placed instead of in build list.
/// get the relationship between this->that.
Relationship getRelationship(const Team *that) const;
/// set the relationship between this->that. (note that this doesn't affect the that->this relationship.)
void setPlayerRelationship(const Player *that, Relationship r);
Bool removePlayerRelationship(const Player *that);
void setTeamRelationship(const Team *that, Relationship r);
Bool removeTeamRelationship(const Team *that);
void addTeamToList(TeamPrototype* team);
void removeTeamFromList(TeamPrototype* team);
typedef std::list<TeamPrototype*> PlayerTeamList;
inline const PlayerTeamList* getPlayerTeams() const { return &m_playerTeamPrototypes; }
inline Int getMpStartIndex(void) {return m_mpStartIndex;}
/// Set that all units should begin hunting.
void setUnitsShouldHunt(Bool unitsShouldHunt, CommandSourceType source);
Bool getUnitsShouldHunt() const { return m_unitsShouldHunt; }
/// All of our units are new spied upon; they sight for the given enemy
void setUnitsVisionSpied( Bool setting, PlayerIndex byWhom );
/// This will be asked by units when they look to get extra people to sight for
PlayerMaskType getVisionSpiedMask() const;
/// Destroy all of the teams for this player, causing him to DIE.
void killPlayer(void);
/// Enabled/Disable all objects of type templateTypeToAffect
void setObjectsEnabled(AsciiString templateTypeToAffect, Bool enable);
/// Build an instance of a specific team. Gets passed to aiPlayer.
void buildSpecificTeam(TeamPrototype *teamProto);
/// Build an instance of a specific building. Gets passed to aiPlayer.
void buildSpecificBuilding(const AsciiString &thingName);
/// Build a building near a supply dump with at least cash. Gets passed to aiPlayer.
void buildBySupplies(Int minimumCash, const AsciiString &thingName);
/// Build an upgrade. Gets passed to aiPlayer.
void buildUpgrade(const AsciiString &upgrade);
/// Build base defense on front or flank of base. Gets passed to aiPlayer.
void buildBaseDefense(Bool flank);
/// Build structure type on front or flank of base. Gets passed to aiPlayer.
void buildBaseDefenseStructure(const AsciiString &thingName, Bool flank);
/// Recruits an instance of a specific team. Gets passed to aiPlayer.
void recruitSpecificTeam(TeamPrototype *teamProto, Real recruitRadius);
/// Enable/Disable the construction of units
Bool getCanBuildUnits(void) { return m_canBuildUnits; }
void setCanBuildUnits(Bool canProduce) { m_canBuildUnits = canProduce; }
/// Enable/Disable the construction of base buildings.
Bool getCanBuildBase(void) { return m_canBuildBase; }
void setCanBuildBase(Bool canProduce) { m_canBuildBase = canProduce; }
/// Transfer all assets from player that to this
void transferAssetsFromThat(Player* that);
/// Sell everything this player owns.
void sellEverythingUnderTheSun(void);
void garrisonAllUnits(CommandSourceType source);
void ungarrisonAllUnits(CommandSourceType source);
void setUnitsShouldIdleOrResume(Bool idle);
Bool isPlayableSide( void ) const;
Bool isPlayerObserver( void ) const; // Favor !isActive() - this is used for Observer GUI mostly, not in-game stuff
Bool isPlayerDead(void) const; // Favor !isActive() - this is used so OCLs don't give us stuff after death.
Bool isPlayerActive(void) const;
Bool didPlayerPreorder( void ) const { return m_isPreorder; }
/// Grab the scorekeeper so we can score up in here!
ScoreKeeper* getScoreKeeper( void ) { return &m_scoreKeeper; }
/// time to create a hotkey team based on this GameMessage
void processCreateTeamGameMessage(Int hotkeyNum, GameMessage *msg);
/// time to select a hotkey team based on this GameMessage
void processSelectTeamGameMessage(Int hotkeyNum, GameMessage *msg);
// add to the player's current selection this hotkey team.
void processAddTeamGameMessage(Int hotkeyNum, GameMessage *msg);
// returns an AIGroup object that is the currently selected group.
void getCurrentSelectionAsAIGroup(AIGroup *group);
// sets the currently selected group to be the given AIGroup
void setCurrentlySelectedAIGroup(AIGroup *group);
// adds the given AIGroup to the current selection of this player.
void addAIGroupToCurrentSelection(AIGroup *group);
// return the requested hotkey squad
Squad *getHotkeySquad(Int squadNumber);
// return the hotkey squad that a unit is in, or NO_HOTKEY_SQUAD if it isn't in one.
Int getSquadNumberForObject(const Object *objToFind) const;
// remove an object from any hotkey squads that its in.
void removeObjectFromHotkeySquad(Object *objToRemove);
void setAttackedBy( Int playerNdx );
Bool getAttackedBy( Int playerNdx ) const;
UnsignedInt getAttackedFrame(void) {return m_attackedFrame;} // Return last frame attacked.
Real getCashBounty() const { return m_cashBountyPercent; }
void setCashBounty(Real percentage) { m_cashBountyPercent = percentage; }
void doBountyForKill(const Object* killer, const Object* victim);
private:
/** give the science. doesn't check prereqs, nor charge to purchase points...
just grants it! so be careful! NOTE that this is private to Player,
and for a good reason; if public, this could be used to grant sciences
that shouldn't be directly granted (e.g., SCIENCE_RankX, which should
be managed via setRankLevel instead). If you think you need to use
this call externally, you probably don't... you should probably be
using grantScience() instead.
*/
Bool addScience(ScienceType science);
public:
Int getSkillPoints() const { return m_skillPoints; }
Int getSciencePurchasePoints() const { return m_sciencePurchasePoints; }
Int getRankLevel() const { return m_rankLevel; }
Int getSkillPointsLevelUp() const { return m_levelUp; }
Int getSkillPointsLevelDown() const { return m_levelDown; }
UnicodeString getGeneralName() const { return m_generalName; }
void setGeneralName( UnicodeString name ){ m_generalName = name; }
/// returns TRUE if rank level really changed.
Bool setRankLevel(Int level);
/// returns TRUE if the player gained/lost levels as a result.
Bool addSkillPoints(Int delta);
/// returns TRUE if the player gained/lost levels as a result.
Bool addSkillPointsForKill(const Object* killer, const Object* victim);
void addSciencePurchasePoints(Int delta);
void setSkillPointsModifier(Real expMod) { m_skillPointsModifier = expMod; }
Real getSkillPointsModifier(void) const { return m_skillPointsModifier; }
/// reset the sciences to just the intrinsic ones from the playertemplate, if any.
void resetSciences();
/// reset rank to 1.
void resetRank();
/**
attempt to purchase the science, but use prereqs, and charge points.
return true if successful.
*/
Bool attemptToPurchaseScience(ScienceType science);
/**
grant the science, ignore prereqs & charge no points,
but still restrict you to purchasable sciences (ie, intrinsic and rank sciences
are not allowed)
return true if successful.
*/
Bool grantScience(ScienceType science);
/** return true attemptToPurchaseScience() would succeed for this science. */
Bool isCapableOfPurchasingScience(ScienceType science) const;
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
void deleteUpgradeList( void ); ///< delete all our upgrades
private:
const PlayerTemplate* m_playerTemplate; ///< Pointer back to the Player Template
UnicodeString m_playerDisplayName; ///< This player's persistent name.
Handicap m_handicap; ///< adjustment to varied capabilities (@todo: is this persistent or recalced each time?)
AsciiString m_playerName; ///< player's itnernal name 9for matching map objects)
NameKeyType m_playerNameKey; ///< This player's internal name (for matching map objects)
PlayerIndex m_playerIndex; ///< player unique index.
AsciiString m_side; ///< the "side" this player is on
PlayerType m_playerType; ///< human/computer control
Money m_money; ///< Player's current wealth
Upgrade* m_upgradeList; ///< list of all upgrades this player has
Int m_radarCount; ///< # of facilities that have a radar under the players control
Int m_disableProofRadarCount; ///< # of disable proof radars. A disable proof one will be in both refcounts
Bool m_radarDisabled; ///< The radar is disabled regardless of the number of radar objects
Int m_bombardBattlePlans; ///< Number of strategy centers with active bombardment plan
Int m_holdTheLineBattlePlans; ///< Number of strategy centers with active hold the line plan
Int m_searchAndDestroyBattlePlans;///< Number of strategy centers with active search and destroy plan
BattlePlanBonuses* m_battlePlanBonuses;
Int64 m_upgradesInProgress; ///< Bit field of In Production status upgrades
Int64 m_upgradesCompleted; ///< Bit field of upgrades completed. Bits are assigned by UpgradeCenter
Energy m_energy; ///< current energy production & consumption
MissionStats m_stats; ///< stats about the current mission (units destroyed, etc)
BuildListInfo* m_pBuildList; ///< linked list of buildings for PLAYER_COMPUTER.
Color m_color; ///< color for our units
Color m_nightColor; ///<tweaked version of regular color to make it easier to see on night maps.
ProductionChangeMap m_productionCostChanges; ///< Map to keep track of Faction specific discounts or penalties on prices of units
ProductionChangeMap m_productionTimeChanges; ///< Map to keep track of Faction specific discounts or penalties on build times of units
ProductionVeterancyMap m_productionVeterancyLevels; ///< Map to keep track of starting level of produced units
#if !defined(_PLAYTEST)
AIPlayer* m_ai; ///< if PLAYER_COMPUTER, the entity that does the thinking
#endif
Int m_mpStartIndex; ///< The player's starting index for multiplayer.
ResourceGatheringManager* m_resourceGatheringManager; ///< Keeps track of all Supply Centers and Warehouses
TunnelTracker* m_tunnelSystem; ///< All TunnelContain buildings use this part of me for actual conatinment
Team* m_defaultTeam; ///< our "default" team.
ScienceVec m_sciences; ///< (SAVE) sciences that we know (either intrinsically or via later purchases)
ScienceVec m_sciencesDisabled; ///< (SAVE) sciences that we are not permitted to purchase "yet". Controlled by mission scripts.
ScienceVec m_sciencesHidden; ///< (SAVE) sciences that aren't shown. Controlled by mission scripts.
Int m_rankLevel; ///< (SAVE) our RankLevel, 1...n
Int m_skillPoints; ///< (SAVE) our cumulative SkillPoint total
Int m_sciencePurchasePoints; ///< (SAVE) our unspent SciencePurchasePoint total
Int m_levelUp, m_levelDown; ///< (NO-SAVE) skill points to go up/down a level (runtime only)
UnicodeString m_generalName; ///< (SAVE) This is the name of the general the player is allowed to change.
PlayerTeamList m_playerTeamPrototypes; ///< ALL the teams we control, via prototype
PlayerRelationMap *m_playerRelations; ///< allies & enemies
TeamRelationMap *m_teamRelations; ///< allies & enemies
Bool m_canBuildUnits; ///< whether the current player is allowed to build units
Bool m_canBuildBase; ///< whether the current player is allowed to build Base buildings
Bool m_observer;
Bool m_isPreorder;
Real m_skillPointsModifier; ///< Multiplied by skill points before they are applied
Bool m_listInScoreScreen; ///< should this player be listed in the score screen or not.
Bool m_unitsShouldHunt;
Bool m_attackedBy[MAX_PLAYER_COUNT]; ///< For each player, have they attacked me?
UnsignedInt m_attackedFrame; ///< Last frame attacked.
Int m_visionSpiedBy[MAX_PLAYER_COUNT]; ///< Reference count of having units spied on by players.
PlayerMaskType m_visionSpiedMask; ///< For quick lookup and edge triggered maintenance
Real m_cashBountyPercent;
/// @todo REMOVE (not disable) these cheat keys
#if defined(_DEBUG) || defined(_INTERNAL)
Bool m_DEMO_ignorePrereqs; ///< Can I ignore prereq checks?
Bool m_DEMO_freeBuild; ///< Can I build everything for no money?
Bool m_DEMO_instantBuild; ///< Can I build anything in one frame?
#endif
ScoreKeeper m_scoreKeeper; ///< The local scorekeeper for this player
typedef std::list<KindOfPercentProductionChange*> KindOfPercentProductionChangeList;
typedef KindOfPercentProductionChangeList::iterator KindOfPercentProductionChangeListIt;
mutable KindOfPercentProductionChangeList m_kindOfPercentProductionChangeList;
typedef std::list<SpecialPowerReadyTimerType> SpecialPowerReadyTimerList;
typedef SpecialPowerReadyTimerList::iterator SpecialPowerReadyTimerListIterator;
SpecialPowerReadyTimerList m_specialPowerReadyTimerList;
Squad *m_squads[NUM_HOTKEY_SQUADS]; ///< The hotkeyed squads
Squad *m_currentSelection; ///< This player's currently selected group
Bool m_isPlayerDead;
};
#endif // _PLAYER_H_

View File

@ -0,0 +1,175 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: PlayerList.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: PlayerList.h
//
// Created: Steven Johnson, October 2001
//
// Desc: @todo
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef _PLAYERLIST_H_
#define _PLAYERLIST_H_
#include "Common/SubsystemInterface.h"
#include "Common/GameCommon.h"
#include "Common/NameKeyGenerator.h"
#include "Common/Snapshot.h"
class DataChunkInput;
struct DataChunkInfo;
class DataChunkOutput;
class Player;
class Team;
class TeamFactory;
//-------------------------------------------------------------------------------------------------
enum AllowPlayerRelationship
{
ALLOW_SAME_PLAYER = 0x01, ///< allow only objects of the same player as m_obj
ALLOW_ALLIES = 0x02, ///< allow objects that m_obj considers allies
ALLOW_ENEMIES = 0x04, ///< allow objects that m_obj considers enemy
ALLOW_NEUTRAL = 0x08 ///< allow objects that m_obj considers neutral
};
//-------------------------------------------------------------------------------------------------
/**
This is a singleton class that maintains the list of Players.
*/
class PlayerList : public SubsystemInterface,
public Snapshot
{
public:
PlayerList();
~PlayerList();
// subsystem methods
virtual void init( void );
virtual void reset( void );
virtual void update( void );
virtual void newGame( void ); // called during GameLogic::startNewGame()
virtual void newMap( void ); // Called after a new map is loaded.
void teamAboutToBeDeleted(Team* team);
/**
return the total number of players (including the neutral player).
*/
inline Int getPlayerCount() { return m_playerCount; }
/**
return the nth player. Note that players are in an arbitrary order.
you should generally only use this if you want to iterate thru
all players, NOT to get a specific player!
*/
Player *getNthPlayer(Int i);
/**
return the "neutral" Player. there is always a player that is "neutral" wrt
all other players (this is so that everything can be associated with a nonnull
Player, to simplify the universe). This will never return null.
*/
Player *getNeutralPlayer() { DEBUG_ASSERTCRASH(m_players[0] != NULL, ("null neutral")); return m_players[0]; }
/**
return the Player with the given internal name, or null if none found.
*/
Player *findPlayerWithNameKey(NameKeyType key);
/**
Return the "local" player (ie, the human playing the game).
This will never return null.
*/
inline Player *getLocalPlayer() { DEBUG_ASSERTCRASH(m_local != NULL, ("null m_local")); return m_local; }
/**
Set the local player. You cannot set it to null; if you pass null, you'll
end up setting the local player to be the neutral player.
*/
void setLocalPlayer(Player *player);
/**
Return the player matching the player mask
*/
Player *getPlayerFromMask( PlayerMaskType mask );
/**
Get each player in numerical order that this mask represents.
Note that maskToAdjust will be adjusted by removing the associated player's mask from it.
*/
Player *getEachPlayerFromMask( PlayerMaskType& maskToAdjust );
Team *validateTeam( AsciiString owner );
/**
a convenience routine to quickly clear the entered/exited flags on all teams.
*/
void updateTeamStates(void);
/**
a convenience routine to return the players who srcPlayer considers to have one of the
relationships specified in allowedRelationships. Note that allowedRelationships should be
a bitwise OR of AllowPlayerRelationship flags.
*/
PlayerMaskType getPlayersWithRelationship( Int srcPlayerIndex, UnsignedInt allowedRelationships );
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
Player *m_local;
Int m_playerCount;
Player *m_players[MAX_PLAYER_COUNT];
};
// ----------------------------------------------------------------------------------------------
extern PlayerList *ThePlayerList; ///< singleton instance of PlayerList
#endif // _PLAYERLIST_H_

View File

@ -0,0 +1,218 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: PlayerTemplate.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: PlayerTemplate.h
//
// Created: Steven Johnson, October 2001
//
// Desc: @todo
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef _PLAYERTEMPLATE_H_
#define _PLAYERTEMPLATE_H_
#include "Common/SubsystemInterface.h"
#include "Common/GameMemory.h"
#include "Common/Debug.h"
#include "Common/Handicap.h"
#include "Common/Money.h"
#include "Common/Science.h"
#include "Common/AsciiString.h"
#include "Common/UnicodeString.h"
#include "Common/NameKeyGenerator.h"
#include "Common/STLTypedefs.h"
// ----------------------------------------------------------------------------------------------
class INI;
struct FieldParse;
class Image;
// ----------------------------------------------------------------------------------------------
#define MAX_MP_STARTING_UNITS 10
// ----------------------------------------------------------------------------------------------
class PlayerTemplate
{
public:
PlayerTemplate();
inline void setNameKey(NameKeyType namekey) { m_nameKey = namekey; }
inline NameKeyType getNameKey() const { DEBUG_ASSERTCRASH(m_nameKey != NAMEKEY_INVALID, ("bad namekey")); return m_nameKey; }
inline AsciiString getName() const { return KEYNAME(m_nameKey); }
inline UnicodeString getDisplayName() const { return m_displayName; }
inline AsciiString getSide() const { return m_side; }
/// return the tech tree for the player.
inline const Handicap *getHandicap() const { return &m_handicap; }
/// return the money for the player.
inline const Money *getMoney() const { return &m_money; }
inline const RGBColor* getPreferredColor() const { return &m_preferredColor; }
inline AsciiString getStartingBuilding( void ) const { return m_startingBuilding; }
AsciiString getStartingUnit( Int i ) const;
inline const ProductionChangeMap& getProductionCostChanges() const { return m_productionCostChanges; }
inline const ProductionChangeMap& getProductionTimeChanges() const { return m_productionTimeChanges; }
inline const ProductionVeterancyMap& getProductionVeterancyLevels() const { return m_productionVeterancyLevels; }
inline Bool isObserver() const { return m_observer; }
inline Bool isPlayableSide() const { return m_playableSide; }
inline AsciiString getScoreScreen (void ) const { return m_scoreScreenImage; }
inline AsciiString getLoadScreen (void ) const { return m_loadScreenImage; }
inline AsciiString getBeaconTemplate( void ) const { return m_beaconTemplate; }
const Image *getHeadWaterMarkImage( void ) const;
const Image *getFlagWaterMarkImage( void ) const;
const Image *getEnabledImage( void ) const;
//const Image *getDisabledImage( void ) const;
//const Image *getHiliteImage( void ) const;
//const Image *getPushedImage( void ) const;
const Image *getSideIconImage( void ) const;
const ScienceVec& getIntrinsicSciences() const { return m_intrinsicSciences; }
Int getIntrinsicSciencePurchasePoints() const { return m_intrinsicSPP; }
AsciiString getPurchaseScienceCommandSetRank1( void ) const {return m_purchaseScienceCommandSetRank1; }
AsciiString getPurchaseScienceCommandSetRank3( void ) const {return m_purchaseScienceCommandSetRank3; }
AsciiString getPurchaseScienceCommandSetRank8( void ) const {return m_purchaseScienceCommandSetRank8; }
AsciiString getSpecialPowerShortcutCommandSet( void ) const {return m_specialPowerShortcutCommandSet; }
AsciiString getSpecialPowerShortcutWinName( void ) const {return m_specialPowerShortcutWinName; }
Int getSpecialPowerShortcutButtonCount( void ) const {return m_specialPowerShortcutButtonCount; }
AsciiString getLoadScreenMusic( void ) const {return m_loadScreenMusic; }
static const FieldParse* getFieldParse();
protected:
// for parsing from INI
static void parseStartMoney( INI* ini, void *instance, void *store, const void* /*userData*/ );
static void parseProductionCostChange( INI* ini, void *instance, void *store, const void* /*userData*/ );
static void parseProductionTimeChange( INI* ini, void *instance, void *store, const void* /*userData*/ );
static void parseProductionVeterancyLevel( INI* ini, void *instance, void *store, const void* /*userData*/ );
private:
NameKeyType m_nameKey;
UnicodeString m_displayName;
AsciiString m_side;
Handicap m_handicap; ///< initial baseline for Player capabilities
Money m_money; ///< starting credits, if any
RGBColor m_preferredColor; ///< our preferred starting color
AsciiString m_startingBuilding; ///< template name of our multiplayer start building (con yard, i'd expect)
AsciiString m_startingUnits[MAX_MP_STARTING_UNITS]; ///< template names of our multiplayer start units
ProductionChangeMap m_productionCostChanges;
ProductionChangeMap m_productionTimeChanges;
ProductionVeterancyMap m_productionVeterancyLevels;
ScienceVec m_intrinsicSciences; ///< sciences that this Player will always know
AsciiString m_purchaseScienceCommandSetRank1; ///< the command set we'll use when we want to purchase sciences
AsciiString m_purchaseScienceCommandSetRank3; ///< the command set we'll use when we want to purchase sciences
AsciiString m_purchaseScienceCommandSetRank8; ///< the command set we'll use when we want to purchase sciences
AsciiString m_specialPowerShortcutCommandSet; ///< the command set we'll use when we want to show the shortcut to the special powers
AsciiString m_specialPowerShortcutWinName; ///< The name of the window we'll be using for the shortcut bar
Int m_specialPowerShortcutButtonCount; ///< The number of buttons located on the shortcut bar
AsciiString m_loadScreenMusic; ///< the load screen music we want to play
Bool m_observer;
Bool m_playableSide;
Int m_intrinsicSPP;
AsciiString m_scoreScreenImage; ///< Image that will be shown on the score screen
AsciiString m_loadScreenImage;
AsciiString m_headWaterMark; ///< Image that will be the background on the observer control bar
AsciiString m_flagWaterMark; ///< Imabe that will be the background on the observer control bar
AsciiString m_enabledImage; ///< enable button image
//AsciiString m_disabledImage; ///< disabled button image
//AsciiString m_hiliteImage; ///< hilite button image
//AsciiString m_pushedImage; ///< pushed button image
AsciiString m_sideIconImage; ///< The little icon we show on game info screens for the sides
AsciiString m_beaconTemplate; ///< ThingTemplate name for beacons
};
// ----------------------------------------------------------------------------------------------
/**
This is a singleton class that maintains the list of PlayerTemplates.
*/
class PlayerTemplateStore : public SubsystemInterface
{
public:
PlayerTemplateStore();
~PlayerTemplateStore();
virtual void init();
virtual void reset();
virtual void update();
static void parsePlayerTemplateDefinition( INI* ini );
const PlayerTemplate* getNthPlayerTemplate(Int i) const;
const PlayerTemplate* findPlayerTemplate(NameKeyType namekey) const;
inline Int getPlayerTemplateCount() const { return m_playerTemplates.size(); }
// This function will fill outStringList with all the sides found in all the templates
void getAllSideStrings(AsciiStringList *outStringList);
private:
typedef std::vector<PlayerTemplate> PlayerTemplateVector;
PlayerTemplateVector m_playerTemplates;
};
// ----------------------------------------------------------------------------------------------
extern PlayerTemplateStore *ThePlayerTemplateStore; ///< singleton instance of PlayerTemplateStore
#endif // _PLAYERTEMPLATE_H_

View File

@ -0,0 +1,125 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ProductionPrerequisite.h //////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: ProductionPrerequisite.h
//
// Created: Steven Johnson, October 2001
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef __ProductionPrerequisite_H_
#define __ProductionPrerequisite_H_
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "Common/GameMemory.h"
#include "Common/GameCommon.h"
#include "Common/Science.h"
//#include "GameClient/ControlBar.h"
//-----------------------------------------------------------------------------
class ThingTemplate;
class Player;
//-----------------------------------------------------------------------------
class ProductionPrerequisite
{
public:
ProductionPrerequisite();
~ProductionPrerequisite();
/// init to safe default values.
void init();
void resetSciences( void ) { m_prereqSciences.clear(); }
void addSciencePrereq( ScienceType science ) { m_prereqSciences.push_back(science); }
void resetUnits( void ) { m_prereqUnits.clear(); }
void addUnitPrereq( AsciiString units, Bool orUnitWithPrevious );
void addUnitPrereq( const std::vector<AsciiString>& units );
/// called after all ThingTemplates have been loaded.
void resolveNames();
/// returns an asciistring which is a list of all the prerequisites
/// not satisfied yet
UnicodeString getRequiresList(const Player *player) const;
/// return true iff the player satisfies our set of prerequisites
Bool isSatisfied(const Player *player) const;
/**
return the BuildFacilityTemplate, if any.
if this template needs no build facility, null is returned.
if the template needs a build facility but the given player doesn't have any in existence,
null will be returned.
you may not pass 'null' for player.
*/
const ThingTemplate *getExistingBuildFacilityTemplate( const Player *player ) const;
Int getAllPossibleBuildFacilityTemplates(const ThingTemplate* tmpls[], Int maxtmpls) const;
private:
enum
{
UNIT_OR_WITH_PREV = 0x01 // if set, unit is "or-ed" with prev unit, so that either one's presence satisfies
};
struct PrereqUnitRec
{
const ThingTemplate* unit;
Int flags;
AsciiString name;
};
enum { MAX_PREREQ = 32 };
Int calcNumPrereqUnitsOwned(const Player *player, Int counts[MAX_PREREQ]) const;
std::vector<PrereqUnitRec> m_prereqUnits;
ScienceVec m_prereqSciences;
};
//-----------------------------------------------------------------------------
#endif

View File

@ -0,0 +1,158 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: QuickTrig.h ////////////////////////////////////////////////////////////////////////////////
// Author: Mark Lorenzen (adapted by srj)
// Desc: fast trig
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __QUICKTRIG_H_
#define __QUICKTRIG_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
extern Real TheQuickSinTable[];
extern Real TheQuickTanTable[];
// yes, Real. No, really.
extern Real TheQuickSinTableCount;
extern Real TheQuickTanTableCount;
//-----------------------------------------------------------------------------
#define QUARTER_CIRCLE (PI/2)
//-----------------------------------------------------------------------------
// quick magnitude estimation, without the square root
// NOTE, this is a very rough estimate, and may be off by 10% or more, so
// use it only when you don't need accuracy
//-----------------------------------------------------------------------------
inline Real QMag(Real x, Real y, Real z)
{
Real sTempV;
Real sMaxV = fabs(x);
Real sMedV = fabs(y);
Real sMinV = fabs(z);
if (sMaxV < sMedV)
{
sTempV = sMaxV;
sMaxV = sMedV;
sMedV = sTempV;
}
if (sMaxV < sMinV)
{
sTempV = sMaxV;
sMaxV = sMinV;
sMinV = sTempV;
}
sMedV += sMinV;
sMaxV += (sMedV*0.25f);
return sMaxV;
}
//-----------------------------------------------------------------------------
// table based trig functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline Real QSin(Real a)
{
register Real angle = a;
register long sgn = 1;
if (angle < 0) // DO POSITIVE MATH AND PRESERVE SIGN
{
sgn = -1;
angle = -angle;
}
while ( angle > (PI)) // MODULATE ANGLE INTO RANGE OF PI
{
angle -= PI;
sgn = -sgn;
}
if (angle > PI/2)
{
angle = PI - angle; // FLIP
}
register int index = REAL_TO_INT((angle/QUARTER_CIRCLE) * TheQuickTanTableCount);
register Real x = TheQuickSinTable[index];
return x * sgn;
/*
Real remainder = node - index;
Real next = TheQuickSinTable[index + 1];
Real range = next - x;
Real scalar = remainder / SIN_TABLE_BRACKET;
Real finetune = scalar * range;
x += finetune;
*/
}
//-----------------------------------------------------------------------------
inline Real QCos(Real angle)
{
return QSin((QUARTER_CIRCLE) - angle);
}
//-----------------------------------------------------------------------------
inline Real QTan(Real angle)
{
return TheQuickTanTable[REAL_TO_INT(angle * TheQuickSinTableCount)];
}
//-----------------------------------------------------------------------------
inline Real QCsc(Real angle)
{
return 1.0f / QSin(angle);
}
//-----------------------------------------------------------------------------
inline Real QSec(Real angle)
{
return 1.0f / QCos(angle);
}
//-----------------------------------------------------------------------------
inline Real QCot(Real angle)
{
return 1.0f / QTan(angle);
}
#endif

View File

@ -0,0 +1,82 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// FILE: QuickmatchPreferences.h
// Author: Matthew D. Campbell, August 2002
// Description: Saving/Loading of quickmatch preferences
///////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __QUICKMATCHPREFERENCES_H__
#define __QUICKMATCHPREFERENCES_H__
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "Common/UserPreferences.h"
//-----------------------------------------------------------------------------
// QuickMatchPreferences base class
//-----------------------------------------------------------------------------
class QuickMatchPreferences : public UserPreferences
{
public:
QuickMatchPreferences();
virtual ~QuickMatchPreferences();
void setMapSelected(const AsciiString& mapName, Bool selected);
Bool isMapSelected(const AsciiString& mapName);
void setLastLadder(const AsciiString& addr, UnsignedShort port);
AsciiString getLastLadderAddr( void );
UnsignedShort getLastLadderPort( void );
void setMaxDisconnects(Int val);
Int getMaxDisconnects( void );
void setMaxPoints(Int val);
Int getMaxPoints( void );
void setMinPoints(Int val);
Int getMinPoints( void );
void setWaitTime(Int val);
Int getWaitTime( void );
void setNumPlayers(Int val);
Int getNumPlayers( void );
void setMaxPing(Int val);
Int getMaxPing( void );
void setColor(Int val);
Int getColor( void );
void setSide(Int val);
Int getSide( void );
};
#endif // __QUICKMATCHPREFERENCES_H__

View File

@ -0,0 +1,41 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: QuotedPrintable.h /////////////////////////////////////////////////////////
// Author: Matt Campbell, February 2002
// Description: Quoted-printable encode/decode
////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __QUOTEDPRINTABLE_H__
#define __QUOTEDPRINTABLE_H__
UnicodeString QuotedPrintableToUnicodeString(AsciiString original);
AsciiString UnicodeStringToQuotedPrintable(UnicodeString original);
AsciiString QuotedPrintableToAsciiString(AsciiString original);
AsciiString AsciiStringToQuotedPrintable(AsciiString original);
#endif // __QUOTEDPRINTABLE_H__

View File

@ -0,0 +1,124 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------------=
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright(C) 2001 - All Rights Reserved
//
//----------------------------------------------------------------------------
//
// Project: WSYS Library
//
// Module: IO
//
// File name: wsys/RAMFile.h
//
// Created: 11/08/01
//
//----------------------------------------------------------------------------
#pragma once
#ifndef __RAMFILE_H
#define __RAMFILE_H
//----------------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------------
#include "Common/File.h"
//----------------------------------------------------------------------------
// Forward References
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Type Defines
//----------------------------------------------------------------------------
//===============================
// RAMFile
//===============================
/**
* File abstraction for standard C file operators: open, close, lseek, read, write
*/
//===============================
class RAMFile : public File
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(RAMFile, "RAMFile")
protected:
Char *m_data; ///< File data in memory
Int m_pos; ///< current read position
Int m_size; ///< size of file in memory
public:
RAMFile();
//virtual ~RAMFile();
virtual Bool open( const Char *filename, Int access = 0 ); ///< Open a file for access
virtual void close( void ); ///< Close the file
virtual Int read( void *buffer, Int bytes ); ///< Read the specified number of bytes in to buffer: See File::read
virtual Int write( const void *buffer, Int bytes ); ///< Write the specified number of bytes from the buffer: See File::write
virtual Int seek( Int new_pos, seekMode mode = CURRENT ); ///< Set file position: See File::seek
virtual void nextLine(Char *buf = NULL, Int bufSize = 0); ///< moves current position to after the next new-line
virtual Bool scanInt(Int &newInt); ///< return what gets read as an integer from the current memory position.
virtual Bool scanReal(Real &newReal); ///< return what gets read as a float from the current memory position.
virtual Bool scanString(AsciiString &newString); ///< return what gets read as a string from the current memory position.
virtual Bool open( File *file ); ///< Open file for fast RAM access
virtual Bool openFromArchive(File *archiveFile, const AsciiString& filename, Int offset, Int size); ///< copy file data from the given file at the given offset for the given size.
virtual Bool copyDataToFile(File *localFile); ///< write the contents of the RAM file to the given local file. This could be REALLY slow.
/**
Allocate a buffer large enough to hold entire file, read
the entire file into the buffer, then close the file.
the buffer is owned by the caller, who is responsible
for freeing is (via delete[]). This is a Good Thing to
use because it minimizes memory copies for BIG files.
*/
virtual char* readEntireAndClose();
virtual File* convertToRAMFile();
};
//----------------------------------------------------------------------------
// Inlining
//----------------------------------------------------------------------------
#endif // __WSYS_RAMFILE_H

View File

@ -0,0 +1,296 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Radar.h //////////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, January 2002
// Desc: Logical radar implementation
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __RADAR_H_
#define __RADAR_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Lib/BaseType.h"
#include "Common/SubsystemInterface.h"
#include "Common/GameMemory.h"
#include "GameClient/Display.h" // for ShroudLevel
#include "GameClient/Color.h"
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
class GameWindow;
class Object;
class Player;
class TerrainLogic;
// GLOBAL /////////////////////////////////////////////////////////////////////////////////////////
//
// the following is used for the resolution of the radar "cells" ... this is how accurate
// the radar is and also reflects directly the size of the image we build ... which with
// WW3D must be a square power of two as well
//
enum
{
RADAR_CELL_WIDTH = 128, // radar created at this horz resolution
RADAR_CELL_HEIGHT = 128 // radar created at this vert resolution
};
//-------------------------------------------------------------------------------------------------
/** These event types determine the colors radar events happen in to make it easier for us
* to play events with a consistent color scheme */
//-------------------------------------------------------------------------------------------------
enum RadarEventType
{
RADAR_EVENT_INVALID = 0,
RADAR_EVENT_CONSTRUCTION,
RADAR_EVENT_UPGRADE,
RADAR_EVENT_UNDER_ATTACK,
RADAR_EVENT_INFORMATION,
RADAR_EVENT_BEACON_PULSE,
RADAR_EVENT_INFILTRATION, //for defection, hijacking, hacking, carbombing, and other sneaks
RADAR_EVENT_BATTLE_PLAN,
RADAR_EVENT_STEALTH_DISCOVERED, // we discovered a stealth unit
RADAR_EVENT_STEALTH_NEUTRALIZED, // our stealth unit has been revealed
RADAR_EVENT_FAKE, //Internally creates a radar event, but doesn't notify the player (unit lost
//for example, so we can use the spacebar to jump to the event).
RADAR_EVENT_NUM_EVENTS // keep this last
};
// PROTOTYPES /////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------
/** Radar objects are objects that are on the radar, go figure :) */
//-------------------------------------------------------------------------------------------------
class RadarObject : public MemoryPoolObject,
public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( RadarObject, "RadarObject" )
public:
RadarObject( void );
// destructor prototype defined by memory pool glue
// color management
void setColor( Color c ) { m_color = c; }
inline Color getColor( void ) const { return m_color; }
inline void friend_setObject( Object *obj ) { m_object = obj; }
inline Object *friend_getObject( void ) { return m_object; }
inline const Object *friend_getObject( void ) const { return m_object; }
inline void friend_setNext( RadarObject *next ) { m_next = next; }
inline RadarObject *friend_getNext( void ) { return m_next; }
inline const RadarObject *friend_getNext( void ) const { return m_next; }
Bool isTemporarilyHidden() const;
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
Object *m_object; ///< the object
RadarObject *m_next; ///< next radar object
Color m_color; ///< color to draw for this object on the radar
};
//-------------------------------------------------------------------------------------------------
/** Radar priorities. Keep this in sync with the priority names list below */
//-------------------------------------------------------------------------------------------------
enum RadarPriorityType
{
RADAR_PRIORITY_INVALID, // a priority that has not been set (in general it won't show up on the radar)
RADAR_PRIORITY_NOT_ON_RADAR, // object specifically forbidden from being on the radar
RADAR_PRIORITY_STRUCTURE, // structure level drawing priority
RADAR_PRIORITY_UNIT, // unit level drawing priority
RADAR_PRIORITY_LOCAL_UNIT_ONLY, // unit priority, but only on the radar if controlled by the local player
RADAR_PRIORITY_NUM_PRIORITIES // keep this last
};
#ifdef DEFINE_RADAR_PRIORITY_NAMES
static const char *RadarPriorityNames[] =
{
"INVALID", // a priority that has not been set (in general it won't show up on the radar)
"NOT_ON_RADAR", // object specifically forbidden from being on the radar
"STRUCTURE", // structure level drawing priority
"UNIT", // unit level drawing priority
"LOCAL_UNIT_ONLY", // unit priority, but only on the radar if controlled by the local player
NULL // keep this last
};
#endif // DEFINE_RADAR_PRIOTITY_NAMES
//-------------------------------------------------------------------------------------------------
/** Interface for the radar */
//-------------------------------------------------------------------------------------------------
class Radar : public Snapshot,
public SubsystemInterface
{
public:
Radar( void );
virtual ~Radar( void );
virtual void init( void ) { } ///< subsystem initialization
virtual void reset( void ); ///< subsystem reset
virtual void update( void ); ///< subsystem per frame update
// is the game window parameter the radar window
Bool isRadarWindow( GameWindow *window ) { return (m_radarWindow == window) && (m_radarWindow != NULL); }
Bool radarToWorld( const ICoord2D *radar, Coord3D *world ); ///< radar point to world point on terrain
Bool worldToRadar( const Coord3D *world, ICoord2D *radar ); ///< translate world point to radar (x,y)
Bool localPixelToRadar( const ICoord2D *pixel, ICoord2D *radar ); ///< translate pixel (with UL of radar being (0,0)) to logical radar coords
Bool screenPixelToWorld( const ICoord2D *pixel, Coord3D *world ); ///< translate pixel (with UL of the screen being (0,0)) to world position in the world
Object *objectUnderRadarPixel( const ICoord2D *pixel ); ///< return the object (if any) represented by the pixel coords passed in
void findDrawPositions( Int startX, Int startY, Int width, Int height,
ICoord2D *ul, ICoord2D *lr ); ///< make translation for screen area of radar square to scaled aspect ratio preserving points inside the radar area
// priority inquiry
Bool isPriorityVisible( RadarPriorityType priority ) const; ///< is the priority passed in a "visible" one on the radar
// radar events
void createEvent( const Coord3D *world, RadarEventType type, Real secondsToLive = 4.0f ); ///< create radar event at location in world
void createPlayerEvent( Player *player, const Coord3D *world, RadarEventType type, Real secondsToLive = 4.0f ); ///< create radar event using player colors
Bool getLastEventLoc( Coord3D *eventPos ); ///< get last event loc (if any)
void tryUnderAttackEvent( const Object *obj ); ///< try to make an "under attack" event if it's the proper time
void tryInfiltrationEvent( const Object *obj ); ///< try to make an "infiltration" event if it's the proper time
Bool tryEvent( RadarEventType event, const Coord3D *pos ); ///< try to make a "stealth" event
// adding and removing objects from the radar
void addObject( Object *obj ); ///< add object to radar
void removeObject( Object *obj ); ///< remove object from radar
void examineObject( Object *obj ); ///< re-examine object and resort if needed
// radar options
void hide( Bool hide ) { m_radarHidden = hide; } ///< hide/unhide the radar
Bool isRadarHidden( void ) { return m_radarHidden; } ///< is radar hidden
// other radar option methods here like the ability to show a certain
// team, show buildings, show units at all, etc
// forcing the radar on/off regardless of player situation
void forceOn( Bool force ) { m_radarForceOn = force; } ///< force the radar to be on
Bool isRadarForced( void ) { return m_radarForceOn; } ///< is radar forced on?
/// refresh the water values for the radar
virtual void refreshTerrain( TerrainLogic *terrain );
/// queue a refresh of the terran at the next available time
virtual void queueTerrainRefresh( void );
virtual void newMap( TerrainLogic *terrain ); ///< reset radar for new map
virtual void draw( Int pixelX, Int pixelY, Int width, Int height ) = 0; ///< draw the radar
/// empty the entire shroud
virtual void clearShroud() = 0;
/// set the shroud level at shroud cell x,y
virtual void setShroudLevel( Int x, Int y, CellShroudStatus setting ) = 0;
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
/// internal method for creating a radar event with specific colors
void internalCreateEvent( const Coord3D *world, RadarEventType type, Real secondsToLive,
const RGBAColorInt *color1, const RGBAColorInt *color2 );
void deleteListResources( void ); ///< delete list radar resources used
Bool deleteFromList( Object *obj, RadarObject **list ); ///< try to remove object from specific list
inline Real getTerrainAverageZ() const { return m_terrainAverageZ; }
inline Real getWaterAverageZ() const { return m_waterAverageZ; }
inline const RadarObject* getObjectList() const { return m_objectList; }
inline const RadarObject* getLocalObjectList() const { return m_localObjectList; }
void clearAllEvents( void ); ///< remove all radar events in progress
// search the object list for an object that maps to the given logical radar coords
Object *searchListForRadarLocationMatch( RadarObject *listHead, ICoord2D *radarMatch );
Bool m_radarHidden; ///< true when radar is not visible
Bool m_radarForceOn; ///< true when radar is forced to be on
RadarObject *m_objectList; ///< list of objects in the radar
RadarObject *m_localObjectList; /** list of objects for the local player, sorted
* in exactly the same priority as the regular
* object list for all other objects */
Real m_terrainAverageZ; ///< average Z for terrain samples
Real m_waterAverageZ; ///< average Z for water samples
//
// when dealing with world sampling we will sample at these intervals so that
// the whole map can be accounted for within our RADAR_CELL_WIDTH and
// RADAR_CELL_HEIGHT resolutions
//
Real m_xSample;
Real m_ySample;
enum { MAX_RADAR_EVENTS = 64 };
struct RadarEvent
{
RadarEventType type; ///< type of this radar event
Bool active; ///< TRUE when event is "active", otherwise it's just historical information in the event array to look through
UnsignedInt createFrame; ///< frame event was created on
UnsignedInt dieFrame; ///< frame the event will go away on
UnsignedInt fadeFrame; ///< start fading out on this frame
RGBAColorInt color1; ///< color 1 for drawing
RGBAColorInt color2; ///< color 2 for drawing
Coord3D worldLoc; ///< location of event in the world
ICoord2D radarLoc; ///< 2D radar location of the event
Bool soundPlayed; ///< TRUE when we have played the radar sound for this
};
RadarEvent m_event[ MAX_RADAR_EVENTS ];///< our radar events
Int m_nextFreeRadarEvent; ///< index into m_event for where to store the next event
Int m_lastRadarEvent; ///< index of the most recent radar event
GameWindow *m_radarWindow; ///< window we display the radar in
Region3D m_mapExtent; ///< extents of the current map
UnsignedInt m_queueTerrainRefreshFrame; ///< frame we requested the last terrain refresh on
};
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
extern Radar *TheRadar; ///< the radar singleton extern
#endif // __RADAR_H_

View File

@ -0,0 +1,44 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// RandomValue.h
// Random number generation system
// Author: Michael S. Booth, January 1998
#pragma once
#ifndef _RANDOM_VALUE_H_
#define _RANDOM_VALUE_H_
#include "Lib/BaseType.h"
extern void InitRandom( void );
extern void InitRandom( UnsignedInt seed );
extern void InitGameLogicRandom( UnsignedInt seed ); ///< Set the GameLogic seed to a known value at game start
extern UnsignedInt GetGameLogicRandomSeed( void ); ///< Get the seed (used for replays)
extern UnsignedInt GetGameLogicRandomSeedCRC( void );///< Get the seed (used for CRCs)
//--------------------------------------------------------------------------------------------------------------
#endif // _RANDOM_VALUE_H_

View File

@ -0,0 +1,159 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Common/MessageStream.h"
#include "GameNetwork/GameInfo.h"
/**
* The ReplayGameInfo class holds information about the replay game and
* the contents of its slot list for reconstructing multiplayer games.
*/
class ReplayGameInfo : public GameInfo
{
private:
GameSlot m_ReplaySlot[MAX_SLOTS];
public:
ReplayGameInfo()
{
for (Int i = 0; i< MAX_SLOTS; ++i)
setSlotPointer(i, &m_ReplaySlot[i]);
}
};
enum RecorderModeType {
RECORDERMODETYPE_RECORD,
RECORDERMODETYPE_PLAYBACK,
RECORDERMODETYPE_NONE // this is a valid state to be in on the shell map, or in saved games
};
class CRCInfo;
class RecorderClass : public SubsystemInterface {
public:
RecorderClass(); ///< Constructor.
virtual ~RecorderClass(); ///< Destructor.
void init(); ///< Initialize TheRecorder.
void reset(); ///< Reset the state of TheRecorder.
void update(); ///< General purpose update function.
// Methods dealing with recording.
void updateRecord(); ///< The update function for recording.
// Methods dealing with playback.
void updatePlayback(); ///< The update function for playing back a file.
Bool playbackFile(AsciiString filename); ///< Starts playback of the specified file.
Bool testVersionPlayback(AsciiString filename); ///< Returns if the playback is a valid playback file for this version or not.
AsciiString getCurrentReplayFilename( void ); ///< valid during playback only
void stopPlayback(); ///< Stops playback. Its fine to call this even if not playing back a file.
#if defined _DEBUG || defined _INTERNAL
Bool analyzeReplay( AsciiString filename );
Bool isAnalysisInProgress( void );
#endif
public:
void handleCRCMessage(UnsignedInt newCRC, Int playerIndex, Bool fromPlayback);
protected:
CRCInfo *m_crcInfo;
public:
// read in info relating to a replay, conditionally setting up m_file for playback
struct ReplayHeader
{
AsciiString filename;
Bool forPlayback;
UnicodeString replayName;
SYSTEMTIME timeVal;
UnicodeString versionString;
UnicodeString versionTimeString;
UnsignedInt versionNumber;
UnsignedInt exeCRC;
UnsignedInt iniCRC;
time_t startTime;
time_t endTime;
UnsignedInt frameDuration;
Bool quitEarly;
Bool desyncGame;
Bool playerDiscons[MAX_SLOTS];
AsciiString gameOptions;
Int localPlayerIndex;
};
Bool readReplayHeader( ReplayHeader& header );
RecorderModeType getMode(); ///< Returns the current operating mode.
void initControls(); ///< Show or Hide the Replay controls
AsciiString getReplayDir(); ///< Returns the directory that holds the replay files.
AsciiString getReplayExtention(); ///< Returns the file extention for replay files.
AsciiString getLastReplayFileName(); ///< Returns the filename used for the default replay.
GameInfo *getGameInfo( void ) { return &m_gameInfo; } ///< Returns the slot list for playback game start
Bool isMultiplayer( void ); ///< is this a multiplayer game (record OR playback)?
Int getGameMode( void ) { return m_originalGameMode; }
void logPlayerDisconnect(UnicodeString player, Int slot);
void logCRCMismatch( void );
void cleanUpReplayFile( void ); ///< after a crash, send replay/debug info to a central repository
void stopRecording(); ///< Stop recording and close m_file.
protected:
void startRecording(GameDifficulty diff, Int originalGameMode, Int rankPoints, Int maxFPS); ///< Start recording to m_file.
void writeToFile(GameMessage *msg); ///< Write this GameMessage to m_file.
void logGameStart(AsciiString options);
void logGameEnd( void );
AsciiString readAsciiString(); ///< Read the next string from m_file using ascii characters.
UnicodeString readUnicodeString(); ///< Read the next string from m_file using unicode characters.
void readNextFrame(); ///< Read the next frame number to execute a command on.
void appendNextCommand(); ///< Read the next GameMessage and append it to TheCommandList.
void writeArgument(GameMessageArgumentDataType type, const GameMessageArgumentType arg);
void readArgument(GameMessageArgumentDataType type, GameMessage *msg);
void cullBadCommands(); ///< prevent the user from giving mouse commands that he shouldn't be able to do during playback.
FILE *m_file;
AsciiString m_fileName;
Int m_currentFilePosition;
RecorderModeType m_mode;
AsciiString m_currentReplayFilename; ///< valid during playback only
ReplayGameInfo m_gameInfo;
Bool m_wasDesync;
Bool m_doingAnalysis;
Int m_originalGameMode; // valid in replays
UnsignedInt m_nextFrame; ///< The Frame that the next message is to be executed on. This can be -1.
};
extern RecorderClass *TheRecorder;
RecorderClass *createRecorder();

View File

@ -0,0 +1,51 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// Registry.h
// Simple interface for storing/retreiving registry values
// Author: Matthew D. Campbell, December 2001
#pragma once
#ifndef __REGISTRY_H__
#define __REGISTRY_H__
#include <Common/AsciiString.h>
/**
* Get a string from the registry
*/
Bool GetStringFromRegistry(AsciiString path, AsciiString key, AsciiString& val);
/**
* Get an unsigned int from the registry
*/
Bool GetUnsignedIntFromRegistry(AsciiString path, AsciiString key, UnsignedInt& val);
AsciiString GetRegistryLanguage(void); // convenience function
AsciiString GetRegistryGameName(void); // convenience function
UnsignedInt GetRegistryVersion(void); // convenience function
UnsignedInt GetRegistryMapPackVersion(void); // convenience function
#endif // __REGISTRY_H__

View File

@ -0,0 +1,76 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ResourceGatheringManager.h ///////////////////////////////////////////////////////////
// The part of a Player's brain that keeps track of all Resource type Objects and makes
// gathering type decisions based on them.
// Author: Graham Smallwood, January, 2002
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef RESOURCE_GATHER_MANAGER_H
#define RESOURCE_GATHER_MANAGER_H
#include "Common/GameType.h"
#include "Common/Snapshot.h"
class Object;
// ------------------------------------------------------------------------------------------------
class ResourceGatheringManager : public MemoryPoolObject,
public Snapshot
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ResourceGatheringManager, "ResourceGatheringManager" );
public:
ResourceGatheringManager();
Object *findBestSupplyWarehouse( Object *queryObject ); ///< What Warehouse should this truck go to?
Object *findBestSupplyCenter( Object *queryObject ); ///< What Center should this truck return to?
void addSupplyCenter( Object *newCenter ); ///< I captured or built a Supply Center, so record it
void removeSupplyCenter( Object *oldCenter ); ///< Lost a supply center
void addSupplyWarehouse( Object *newWarehouse ); ///< Warehouse created, or this is starrt of game recording
void removeSupplyWarehouse( Object *oldWarehouse ); ///< Warehouse that doesn't replinish has run out of Supply
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
/// @todo Make sure the allocator for std::list<> is a good one. Otherwise override it.
typedef std::list<ObjectID> objectIDList;
typedef std::list<ObjectID>::iterator objectIDListIterator;
objectIDList m_supplyWarehouses;
objectIDList m_supplyCenters;
};
#endif

View File

@ -0,0 +1,225 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: STLTypedefs.h ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Westwood Studios Pacific.
//
// Confidential Information
// Copyright (C) 2001 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Project: RTS3
//
// File name: STLTypedefs.h
//
// Created: John McDonald
//
// Desc: @todo
//
//-----------------------------------------------------------------------------
#pragma once
#ifndef __STLTYPEDEFS_H__
#define __STLTYPEDEFS_H__
//-----------------------------------------------------------------------------
// srj sez: this must come first, first, first.
#define _STLP_USE_NEWALLOC 1
//#define _STLP_USE_CUSTOM_NEWALLOC STLSpecialAlloc
class STLSpecialAlloc;
//-----------------------------------------------------------------------------
#include "Common/AsciiString.h"
#include "Common/UnicodeString.h"
#include "Common/GameCommon.h"
#include "Common/GameMemory.h"
//-----------------------------------------------------------------------------
// FORWARD DECLARATIONS
class Object;
enum NameKeyType;
enum ObjectID;
enum DrawableID;
#include <algorithm>
#include <bitset>
#include <hash_map>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
// List of AsciiStrings to allow list of ThingTemplate names from INI and such
typedef std::list< AsciiString > AsciiStringList;
typedef std::list< AsciiString >::iterator AsciiStringListIterator;
typedef std::list< AsciiString >::const_iterator AsciiStringListConstIterator;
// One is used in GameLogic to keep track of objects to be destroyed
typedef std::list<Object *> ObjectPointerList;
typedef std::list<Object *>::iterator ObjectPointerListIterator;
typedef std::vector<ObjectID> ObjectIDVector;
typedef std::vector<ObjectID>::iterator ObjectIDVectorIterator;
// Terribly useful, especially with Bezier curves
typedef std::vector<Coord3D> VecCoord3D;
typedef VecCoord3D::iterator VecCoord3DIt;
// Used for cursor->3D position request caching in the heightmap
typedef std::pair<ICoord2D, Coord3D> PosRequest;
typedef std::vector<PosRequest> VecPosRequests;
typedef std::vector<PosRequest>::iterator VecPosRequestsIt;
// Used to cache off names of objects for faster lookup
typedef std::pair<AsciiString, Object*> NamedRequest;
typedef std::vector<NamedRequest> VecNamedRequests;
typedef std::vector<NamedRequest>::iterator VecNamedRequestsIt;
// Rumor has it that a Vector of Bools gets stored as a bitfield internally.
typedef std::vector<Bool> BoolVector;
typedef std::vector<Bool>::iterator BoolVectorIterator;
typedef std::map< NameKeyType, Real, std::less<NameKeyType> > ProductionChangeMap;
typedef std::map< NameKeyType, VeterancyLevel, std::less<NameKeyType> > ProductionVeterancyMap;
// Some useful, common hash and equal_to functors for use with hash_map
namespace rts
{
// Generic hash functor. This should almost always be overridden for
// specific types.
template<typename T> struct hash
{
size_t operator()(const T& __t) const
{
std::hash<T> tmp;
return tmp(__t);
}
};
// Generic equal_to functor. This should be overridden if there is no
// operator==, or if that isn't the behavior desired. (For instance, in
// the case of pointers.)
template<typename T> struct equal_to
{
Bool operator()(const T& __t1, const T& __t2) const
{
return (__t1 == __t2);
}
};
// Generic less_than_nocase functor. This should be overridden if there is no
// operator<, or if that isn't the behavior desired. (For instance, in
// the case of pointers, or strings.)
template<typename T> struct less_than_nocase
{
bool operator()(const T& __t1, const T& __t2) const
{
return (__t1 < __t2);
}
};
template<> struct hash<NameKeyType>
{
size_t operator()(NameKeyType nkt) const
{
std::hash<UnsignedInt> tmp;
return tmp((UnsignedInt)nkt);
}
};
template<> struct hash<DrawableID>
{
size_t operator()(DrawableID nkt) const
{
std::hash<UnsignedInt> tmp;
return tmp((UnsignedInt)nkt);
}
};
template<> struct hash<ObjectID>
{
size_t operator()(ObjectID nkt) const
{
std::hash<UnsignedInt> tmp;
return tmp((UnsignedInt)nkt);
}
};
// This is the equal_to overload for char* comparisons. We compare the
// strings to determine whether they are equal or not.
// Other overloads should go into specific header files, not here (unless
// they are ot be used in lots of places.)
template<> struct equal_to<const char*>
{
Bool operator()(const char* s1, const char* s2) const
{
return strcmp(s1, s2) == 0;
}
};
template<> struct hash<AsciiString>
{
size_t operator()(AsciiString ast) const
{
std::hash<const char *> tmp;
return tmp((const char *) ast.str());
}
};
template<> struct equal_to<AsciiString>
{
Bool operator()(const AsciiString& __t1, const AsciiString& __t2) const
{
return (__t1 == __t2);
}
};
template<> struct less_than_nocase<AsciiString>
{
bool operator()(const AsciiString& __t1, const AsciiString& __t2) const
{
return (__t1.compareNoCase(__t2) < 0);
}
};
template<> struct less_than_nocase<UnicodeString>
{
bool operator()(const UnicodeString& __t1, const UnicodeString& __t2) const
{
return (__t1.compareNoCase(__t2) < 0);
}
};
}
#endif /* __STLTYPEDEFS_H__ */

View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -0,0 +1,138 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: Science.h ////////////////////////////////////////////////////////////////////////////////
// Author: Steven Johnson, Colin Day November 2001
// Desc: Science descriptoins
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __SCIENCE_H_
#define __SCIENCE_H_
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "Common/Overridable.h"
#include "Common/NameKeyGenerator.h"
#include "Common/UnicodeString.h"
class Player;
//-------------------------------------------------------------------------------------------------
enum ScienceType
{
SCIENCE_INVALID = -1
};
//-------------------------------------------------------------------------------------------------
typedef std::vector<ScienceType> ScienceVec;
//-------------------------------------------------------------------------------------------------
class ScienceInfo : public Overridable
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ScienceInfo, "ScienceInfo" )
friend class ScienceStore;
private:
ScienceType m_science;
UnicodeString m_name;
UnicodeString m_description;
ScienceVec m_rootSciences; // this is calced at runtime, NOT read from INI
ScienceVec m_prereqSciences;
Int m_sciencePurchasePointCost;
Bool m_grantable;
ScienceInfo() :
m_science(SCIENCE_INVALID),
m_sciencePurchasePointCost(0), // 0 means "cannot be purchased"
m_grantable(true)
{
}
void addRootSciences(ScienceVec& v) const;
};
EMPTY_DTOR(ScienceInfo);
//-------------------------------------------------------------------------------------------------
class ScienceStore : public SubsystemInterface
{
friend class ScienceInfo;
public:
void init();
void reset();
void update() { }
Bool isValidScience(ScienceType st) const;
Bool isScienceGrantable(ScienceType st) const;
Bool getNameAndDescription(ScienceType st, UnicodeString& name, UnicodeString& description) const;
Bool playerHasPrereqsForScience(const Player* player, ScienceType st) const;
/**
this is a subtle call, and should ALMOST NEVER be called by external code...
this is used to determine if you have the "root" requirements for a given science,
and thus could *potentially* obtain it if you got extra prereqs.
Generally, you should call getPurchasableSciences() instead of this!
*/
Bool playerHasRootPrereqsForScience(const Player* player, ScienceType st) const;
Int getSciencePurchaseCost(ScienceType science) const;
ScienceType getScienceFromInternalName(const AsciiString& name) const;
AsciiString getInternalNameForScience(ScienceType science) const;
/** return a list of the sciences the given player can purchase now, and a list he might be able to purchase in the future,
but currently lacks prereqs or points for. (either might be an empty list) */
void getPurchasableSciences(const Player* player, ScienceVec& purchasable, ScienceVec& potentiallyPurchasable) const;
// this is intended ONLY for use by INI::scanScience.
// Don't use it anywhere else. In particular, never, ever, ever
// call this with a hardcoded science name. (srj)
ScienceType friend_lookupScience(const char* scienceName) const;
static void friend_parseScienceDefinition(INI* ini);
// return a vector of all the currently-known science names
// NOTE: this is really only for use by WorldBuilder! Please
// do not use it in RTS!
std::vector<AsciiString> friend_getScienceNames() const;
private:
const ScienceInfo* findScienceInfo(ScienceType st) const;
typedef std::vector<ScienceInfo*> ScienceInfoVec;
ScienceInfoVec m_sciences;
};
extern ScienceStore* TheScienceStore;
#endif // __SCIENCE_H_

View File

@ -0,0 +1,46 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// FILE: ScopedMutex.h ////////////////////////////////////////////////////////////////////////////
// Author: John McDonald, November 2002
// Desc: A scoped mutex class to easily lock a scope with a pre-existing mutex object.
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __SCOPEDMUTEX_H__
#define __SCOPEDMUTEX_H__
class ScopedMutex
{
private:
HANDLE m_mutex;
public:
ScopedMutex(HANDLE mutex) : m_mutex(mutex)
{
WaitForSingleObject(m_mutex, INFINITE);
}
~ScopedMutex()
{
ReleaseMutex(m_mutex);
}
};
#endif /* __SCOPEDMUTEX_H__ */

View File

@ -0,0 +1,145 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
// FILE: ScoreKeeper.h /////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// Electronic Arts Pacific.
//
// Confidential Information
// Copyright (C) 2002 - All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// created: Jun 2002
//
// Filename: ScoreKeeper.h
//
// author: Chris Huybregts
//
// purpose: Header file for the scorekeeper class
//
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __SCOREKEEPER_H_
#define __SCOREKEEPER_H_
//-----------------------------------------------------------------------------
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "Common/Snapshot.h"
//-----------------------------------------------------------------------------
// FORWARD REFERENCES /////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
class Object;
class ThingTemplate;
//-----------------------------------------------------------------------------
// TYPE DEFINES ///////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
class ScoreKeeper : public Snapshot
{
public:
ScoreKeeper( void );
~ScoreKeeper( void );
void reset( Int playerIdx ); ///< Zero out the variables
Int calculateScore( void ); ///< Performs the equation to calculate the score
void addMoneySpent( Int money ); ///< Adds money to the amount spent
void addMoneyEarned( Int money ); ///< Adds money to the earned amount
void addObjectBuilt( const Object *o );
void addObjectDestroyed( const Object *o );
void addObjectLost( const Object *o );
void addObjectCaptured( const Object *o );
void removeObjectBuilt( const Object *o );
Int getTotalMoneyEarned( void ) { return m_totalMoneyEarned; }
Int getTotalMoneySpent( void ) { return m_totalMoneySpent; }
Int getTotalUnitsDestroyed( void );
Int getTotalUnitsBuilt( void ) { return m_totalUnitsBuilt; }
Int getTotalUnitsLost( void ) { return m_totalUnitsLost; }
Int getTotalBuildingsDestroyed( void );
Int getTotalBuildingsBuilt( void ) { return m_totalBuildingsBuilt; }
Int getTotalBuildingsLost( void ) { return m_totalBuildingsLost; }
Int getTotalTechBuildingsCaptured( void ) { return m_totalTechBuildingsCaptured; }
Int getTotalFactionBuildingsCaptured( void ) { return m_totalFactionBuildingsCaptured; }
Int getTotalObjectsBuilt( const ThingTemplate *pTemplate ); // get a count of objects built matching a specific thing template
// for battle honor calculation. done once at the end of each online game
Int getTotalUnitsBuilt( KindOfMaskType validMask, KindOfMaskType invalidMask );
protected:
// snapshot methods
virtual void crc( Xfer *xfer );
virtual void xfer( Xfer *xfer );
virtual void loadPostProcess( void );
private:
Int m_totalMoneyEarned; ///< The total money that was harvested, refined, received in crates
Int m_totalMoneySpent; ///< The total money spent on units, buildings, repairs
Int m_totalUnitsDestroyed[MAX_PLAYER_COUNT]; ///< The total number of enimies that we've killed
Int m_totalUnitsBuilt; ///< The total number of units we've created (created meaning that we built from a building)
Int m_totalUnitsLost; ///< The total number of our units lost
Int m_totalBuildingsDestroyed[MAX_PLAYER_COUNT]; ///< The total number of Buildings we've destroyed
Int m_totalBuildingsBuilt; ///< The total number of buildings we've constructed
Int m_totalBuildingsLost; ///< The total number of our buildings lost
Int m_totalTechBuildingsCaptured; ///< The total number of tech buildings captured
Int m_totalFactionBuildingsCaptured; ///< The total number of faction buildings captured
Int m_currentScore; ///< Based off the stats, this is the current score
Int m_myPlayerIdx; ///< We need to not score kills on ourselves... so we need to know who we are
typedef std::map<const ThingTemplate *, Int> ObjectCountMap;
typedef ObjectCountMap::iterator ObjectCountMapIt;
ObjectCountMap m_objectsBuilt; ///< How many and what kinds of objects did we build
ObjectCountMap m_objectsDestroyed[MAX_PLAYER_COUNT]; ///< How many and what kinds and who's did we kill
ObjectCountMap m_objectsLost; ///< how many and what kinds of objects did we loose
ObjectCountMap m_objectsCaptured;
void xferObjectCountMap( Xfer *xfer, ObjectCountMap *map );
};
//-----------------------------------------------------------------------------
// INLINING ///////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
inline void ScoreKeeper::addMoneySpent( Int money ) { m_totalMoneySpent += money; }
inline void ScoreKeeper::addMoneyEarned( Int money ) { m_totalMoneyEarned += money; }
//-----------------------------------------------------------------------------
// EXTERNALS //////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#endif // __SCOREKEEPER_H_

View File

@ -0,0 +1,98 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (c) 2001-2003 Electronic Arts Inc. //
// //
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// FILE: SkirmishBattleHonors.h
// Author: Matthew D. Campbell, November 2002
// Description: Saving/Loading of skirmish battle honors info
///////////////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef __SKIRMISHBATTLEHONORS_H__
#define __SKIRMISHBATTLEHONORS_H__
//-----------------------------------------------------------------------------
// USER INCLUDES //////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include "Common/UnicodeString.h"
#include "Common/UserPreferences.h"
class Image;
class GameWindow;
class WinInstanceData;
//-----------------------------------------------------------------------------
// CustomMatchPreferences base class
//-----------------------------------------------------------------------------
class SkirmishBattleHonors : public UserPreferences
{
public:
SkirmishBattleHonors();
virtual ~SkirmishBattleHonors();
void setWins(Int val);
Int getWins(void) const;
void setLosses(Int val);
Int getLosses(void) const;
void setWinStreak(Int val);
Int getWinStreak(void) const;
void setBestWinStreak(Int val);
Int getBestWinStreak(void) const;
void setChallengeMedals(Int val);
Int getChallengeMedals(void) const;
void setBuiltSCUD(void);
Bool builtSCUD(void) const;
void setBuiltParticleCannon(void);
Bool builtParticleCannon(void) const;
void setBuiltNuke(void);
Bool builtNuke(void) const;
void setHonors(Int mask);
Int getHonors(void) const;
void setEnduranceMedal(AsciiString mapName, Int difficulty, int numAIs);
Int getEnduranceMedal(AsciiString mapName, Int difficulty) const;
void setLastGeneral(AsciiString val);
AsciiString getLastGeneral(void) const;
void setNumGamesLoyal(Int val);
Int getNumGamesLoyal(void) const;
};
void ResetBattleHonorInsertion(void);
void InsertBattleHonor(GameWindow *list, const Image *image, Bool enabled, Int itemData, Int& row, Int& column, UnicodeString text = UnicodeString::TheEmptyString);
void BattleHonorTooltip(GameWindow *window,
WinInstanceData *instData,
UnsignedInt mouse);
#endif // __SKIRMISHBATTLEHONORS_H__

Some files were not shown because too many files have changed in this diff Show More