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

View file

@ -0,0 +1,196 @@
/*
** 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: CaveSystem.cpp /////////////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood July 2002
// Desc: System responsible for keeping track of all cave systems on the map
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
#include "Common/GameState.h"
#include "Common/TunnelTracker.h"
#include "Common/Xfer.h"
#include "GameLogic/CaveSystem.h"
CaveSystem *TheCaveSystem = NULL;
CaveSystem::CaveSystem()
{
}
CaveSystem::~CaveSystem()
{
}
void CaveSystem::init()
{
}
void CaveSystem::reset()
{
for( std::vector<TunnelTracker*>::iterator iter = m_tunnelTrackerVector.begin(); iter != m_tunnelTrackerVector.end(); iter++ )
{
TunnelTracker *currentTracker = *iter;
if( currentTracker )// could be NULL, since we don't slide back to fill deleted entries so offsets don't shift
{
currentTracker->deleteInstance();
}
}
m_tunnelTrackerVector.clear();
}
void CaveSystem::update()
{
}
Bool CaveSystem::canSwitchIndexToIndex( Int oldIndex, Int newIndex )
{
// When I grant permission, you need to do it. ie call Unregister and then re-register with the new number
TunnelTracker *oldTracker = NULL;
TunnelTracker *newTracker = NULL;
if( m_tunnelTrackerVector.size() > oldIndex )
{
oldTracker = m_tunnelTrackerVector[oldIndex];
if( oldTracker && oldTracker->getContainCount() > 0 )
return FALSE;// You can't switch a connection if one of the two is non empty
}
if( m_tunnelTrackerVector.size() > newIndex )
{
newTracker = m_tunnelTrackerVector[newIndex];
if( newTracker && newTracker->getContainCount() > 0 )
return FALSE;// You can't switch a connection if one of the two is non empty
}
// Both are either empty or non-existent, so go ahead.
// (Remember non-exist is only a valid case because you are going to do the switch now.)
return TRUE;
}
void CaveSystem::registerNewCave( Int theIndex )
{
Bool needToCreate = FALSE;
if( theIndex >= m_tunnelTrackerVector.size() )
{
// You are new and off the edge, so I will fill NULLs up to you and then make a newTracker at that spot
while( theIndex >= m_tunnelTrackerVector.size() )
m_tunnelTrackerVector.push_back( NULL );
needToCreate = TRUE;
}
else
{
// else you either exist or have existed, so I will either let things be or re-create that slot
if( m_tunnelTrackerVector[theIndex] == NULL )
needToCreate = TRUE;
}
if( needToCreate )// if true, we new theIndex is the index of a NULL to be filled
m_tunnelTrackerVector[theIndex] = newInstance(TunnelTracker);
}
void CaveSystem::unregisterCave( Int theIndex )
{
// Doesn't need to do a thing. ContainModule logic knows how to say goodbye, and a TunnelTracker
// knows how to exist while having no entry points.
theIndex;
}
TunnelTracker *CaveSystem::getTunnelTrackerForCaveIndex( Int theIndex )
{
TunnelTracker *theTracker = NULL;
if( theIndex < m_tunnelTrackerVector.size() )
{
theTracker = m_tunnelTrackerVector[theIndex];
}
DEBUG_ASSERTCRASH( theTracker != NULL, ("No one should be interested in a sub-cave that doesn't exist.") );
return theTracker;
}
// ------------------------------------------------------------------------------------------------
/** Xfer Method
* Version Info
* 1: Initial version */
// ------------------------------------------------------------------------------------------------
void CaveSystem::xfer( Xfer *xfer )
{
// version
XferVersion currentVersion = 1;
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
// tunnel tracker size and data
UnsignedShort count = m_tunnelTrackerVector.size();
xfer->xferUnsignedShort( &count );
TunnelTracker *tracker;
if( xfer->getXferMode() == XFER_SAVE )
{
std::vector< TunnelTracker* >::iterator it;
for( it = m_tunnelTrackerVector.begin(); it != m_tunnelTrackerVector.end(); ++it )
{
// xfer data
tracker = *it;
xfer->xferSnapshot( tracker );
} // end
} // end if, save
else
{
// the list must be empty now
if( m_tunnelTrackerVector.empty() == FALSE )
{
DEBUG_CRASH(( "CaveSystem::xfer - m_tunnelTrackerVector should be empty but is not\n" ));
throw SC_INVALID_DATA;
} // end if
// read each item
for( UnsignedShort i = 0; i < count; ++i )
{
// allocate new tracker
tracker = newInstance( TunnelTracker );
// read data
xfer->xferSnapshot( tracker );
// put in vector
m_tunnelTrackerVector.push_back( tracker );
} // end for, i
} // end else, laod
} // end xfer

View file

@ -0,0 +1,229 @@
/*
** 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: CrateSystem.cpp /////////////////////////////////////////////////////////////////////////////////
// Author: Graham Smallwood Feb 2002
// Desc: System responsible for Crates as code objects - ini, new/delete etc
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
#define DEFINE_VETERANCY_NAMES // for TheVeterancyNames[]
#include "GameLogic/CrateSystem.h"
#include "Common/BitFlagsIO.h"
CrateSystem *TheCrateSystem = NULL;
CrateSystem::CrateSystem()
{
m_crateTemplateVector.clear();
}
CrateSystem::~CrateSystem()
{
Int count = m_crateTemplateVector.size();
for( Int templateIndex = 0; templateIndex < count; templateIndex ++ )
{
CrateTemplate *currentTemplate = m_crateTemplateVector[templateIndex];
if( currentTemplate )
{
currentTemplate->deleteInstance();
}
}
m_crateTemplateVector.clear();
}
void CrateSystem::init( void )
{
reset();
}
void CrateSystem::reset( void )
{
// clean up overrides
std::vector<CrateTemplate *>::iterator it;
for( it = m_crateTemplateVector.begin(); it != m_crateTemplateVector.end(); )
{
CrateTemplate *currentTemplate = *it;
if( currentTemplate )
{
Overridable *tempCrateTemplate = currentTemplate->deleteOverrides();
if (!tempCrateTemplate)
{
// base dude was an override - kill it from the vector
it = m_crateTemplateVector.erase(it);
}
else
{
++it;
}
}
else
{
it = m_crateTemplateVector.erase(it);
}
}
}
void CrateSystem::parseCrateTemplateDefinition(INI* ini)
{
AsciiString name;
// read the crateTemplate name
const char* c = ini->getNextToken();
name.set(c);
CrateTemplate *crateTemplate = TheCrateSystem->friend_findCrateTemplate(name);
if (crateTemplate == NULL) {
crateTemplate = TheCrateSystem->newCrateTemplate(name);
if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES) {
crateTemplate->markAsOverride();
}
} else if( ini->getLoadType() != INI_LOAD_CREATE_OVERRIDES ) {
DEBUG_CRASH(( "[LINE: %d in '%s'] Duplicate crate %s found!", ini->getLineNum(), ini->getFilename().str(), name.str() ));
} else {
crateTemplate = TheCrateSystem->newCrateTemplateOverride(crateTemplate);
}
// parse the ini weapon definition
ini->initFromINI(crateTemplate, crateTemplate->getFieldParse());
}
CrateTemplate *CrateSystem::newCrateTemplate( AsciiString name )
{
// sanity
if(name.isEmpty())
return NULL;
// allocate a new weapon
CrateTemplate *ct = newInstance(CrateTemplate);
// if the default template is present, get it and copy over any data to the new template
const CrateTemplate *defaultCT = findCrateTemplate(AsciiString("DefaultCrate"));
if(defaultCT)
{
*ct = *defaultCT;
}
ct->setName( name );
m_crateTemplateVector.push_back(ct);
return ct;
}
CrateTemplate *CrateSystem::newCrateTemplateOverride( CrateTemplate *crateToOverride )
{
if (!crateToOverride) {
return NULL;
}
CrateTemplate *newOverride = newInstance(CrateTemplate);
*newOverride = *crateToOverride;
newOverride->markAsOverride();
crateToOverride->setNextOverride(newOverride);
return newOverride;
}
const CrateTemplate *CrateSystem::findCrateTemplate(AsciiString name) const
{
// search weapon list for name
for (Int i = 0; i < m_crateTemplateVector.size(); i++)
if(m_crateTemplateVector[i]->getName() == name) {
CrateTemplateOverride overridable(m_crateTemplateVector[i]);
return overridable;
}
return NULL;
}
CrateTemplate *CrateSystem::friend_findCrateTemplate(AsciiString name)
{
// search weapon list for name
for (Int i = 0; i < m_crateTemplateVector.size(); i++)
if(m_crateTemplateVector[i]->getName() == name) {
CrateTemplateOverride overridable(m_crateTemplateVector[i]);
return const_cast<CrateTemplate*>((const CrateTemplate *)overridable);
}
return NULL;
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
const FieldParse CrateTemplate::TheCrateTemplateFieldParseTable[] =
{
{ "CreationChance", INI::parseReal, NULL, offsetof( CrateTemplate, m_creationChance ) },
{ "VeterancyLevel", INI::parseIndexList, TheVeterancyNames, offsetof( CrateTemplate, m_veterancyLevel ) },
{ "KilledByType", KindOfMaskType::parseFromINI, NULL, offsetof( CrateTemplate, m_killedByTypeKindof) },
{ "CrateObject", CrateTemplate::parseCrateCreationEntry, NULL, NULL },
{ "KillerScience", INI::parseScience, NULL, offsetof( CrateTemplate, m_killerScience) },
{ "OwnedByMaker", INI::parseBool, NULL, offsetof( CrateTemplate, m_isOwnedByMaker) },
{ NULL, NULL, NULL, NULL }, // keep this last!
};
CrateTemplate::CrateTemplate()
{
m_name = "";
m_creationChance = 0;
CLEAR_KINDOFMASK(m_killedByTypeKindof);
m_veterancyLevel = LEVEL_INVALID;
m_killerScience = SCIENCE_INVALID;
m_possibleCrates.clear();
m_isOwnedByMaker = FALSE;
}
CrateTemplate::~CrateTemplate()
{
m_possibleCrates.clear();
}
void CrateTemplate::parseCrateCreationEntry( INI* ini, void *instance, void *, const void* )
{
CrateTemplate *self = (CrateTemplate *)instance;
const char *token = ini->getNextToken();
AsciiString crateName = token;
token = ini->getNextToken();
Real crateValue;
if (sscanf( token, "%f", &crateValue ) != 1)
throw INI_INVALID_DATA;
crateCreationEntry newEntry;
newEntry.crateName = crateName;
newEntry.crateChance = crateValue;
self->m_possibleCrates.push_back( newEntry );
}

View file

@ -0,0 +1,113 @@
/*
** 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: Damage.cpp ///////////////////////////////////////////////////////////////////////////////
// Author: Colin Day, September 2002
// Desc: Basic structures for the damage process
///////////////////////////////////////////////////////////////////////////////////////////////////
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
#include "PreRTS.h"
#include "Common/Xfer.h"
#include "GameLogic/Damage.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------------------------------
/** Xfer method
* Version Info:
* 1: Initial version */
// ------------------------------------------------------------------------------------------------
void DamageInfo::xfer( Xfer *xfer )
{
// version
XferVersion currentVersion = 1;
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
// xfer input
xfer->xferSnapshot( &in );
// xfer output
xfer->xferSnapshot( &out );
} // end xfer
// ------------------------------------------------------------------------------------------------
/** Xfer method
* Version Info:
* 1: Initial version */
// ------------------------------------------------------------------------------------------------
void DamageInfoInput::xfer( Xfer *xfer )
{
// version
XferVersion currentVersion = 1;
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
// source id
xfer->xferObjectID( &m_sourceID );
// source player mask
xfer->xferUser( &m_sourcePlayerMask, sizeof( PlayerMaskType ) );
// damage type
xfer->xferUser( &m_damageType, sizeof( DamageType ) );
// death type
xfer->xferUser( &m_deathType, sizeof( DeathType ) );
// amount
xfer->xferReal( &m_amount );
} // end xfer
// ------------------------------------------------------------------------------------------------
/** Xfer method
* Version Info:
* 1: Initial version */
// ------------------------------------------------------------------------------------------------
void DamageInfoOutput::xfer( Xfer *xfer )
{
// version
XferVersion currentVersion = 1;
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );
// actual damage
xfer->xferReal( &m_actualDamageDealt );
// damage clipped
xfer->xferReal( &m_actualDamageClipped );
// no effect
xfer->xferBool( &m_noEffect );
} // end xfer

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,161 @@
/*
** 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: RankInfo.cpp /////////////////////////////////////////////////////////
// Created: Steven Johnson, Sep 2002
// Desc:
//-----------------------------------------------------------------------------
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
#include "Common/INI.h"
#include "Common/Player.h"
#include "GameLogic/RankInfo.h"
RankInfoStore* TheRankInfoStore = NULL;
#ifdef _INTERNAL
// for occasional debugging...
//#pragma optimize("", off)
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
#endif
//-----------------------------------------------------------------------------
void RankInfoStore::init()
{
DEBUG_ASSERTCRASH(m_rankInfos.empty(), ("Hmm"));
m_rankInfos.clear();
}
//-----------------------------------------------------------------------------
void RankInfoStore::reset()
{
// nope.
//m_rankInfos.clear();
for (RankInfoVec::iterator it = m_rankInfos.begin(); it != m_rankInfos.end(); /*++it*/)
{
RankInfo* ri = *it;
if (ri)
{
Overridable* temp = ri->deleteOverrides();
if (!temp)
{
DEBUG_CRASH(("hmm, should not be possible for RankInfo"));
it = m_rankInfos.erase(it);
}
else
{
++it;
}
}
}
}
//-----------------------------------------------------------------------------
Int RankInfoStore::getRankLevelCount() const
{
return m_rankInfos.size();
}
//-----------------------------------------------------------------------------
// note that level is 1...n, NOT 0...n-1
const RankInfo* RankInfoStore::getRankInfo(Int level) const
{
if (level >= 1 && level <= getRankLevelCount())
{
const RankInfo* ri = m_rankInfos[level-1];
if (ri)
{
return (const RankInfo*)ri->getFinalOverride();
}
}
return NULL;
}
//-----------------------------------------------------------------------------
void RankInfoStore::friend_parseRankDefinition( INI* ini )
{
if (TheRankInfoStore)
{
Int rank = INI::scanInt(ini->getNextToken());
static const FieldParse myFieldParse[] =
{
{ "RankName", INI::parseAndTranslateLabel, NULL, offsetof( RankInfo, m_rankName ) },
{ "SkillPointsNeeded", INI::parseInt, NULL, offsetof( RankInfo, m_skillPointsNeeded ) },
{ "SciencesGranted", INI::parseScienceVector, NULL, offsetof( RankInfo, m_sciencesGranted ) },
{ "SciencePurchasePointsGranted", INI::parseUnsignedInt, NULL, offsetof( RankInfo, m_sciencePurchasePointsGranted ) },
{ 0, 0, 0, 0 }
};
if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES)
{
// we aren't allowed to add ranks in overrides, only to override existing ones.
if (rank < 1 || rank > TheRankInfoStore->m_rankInfos.size())
{
DEBUG_CRASH(("Rank not found in map.ini"));
throw INI_INVALID_DATA;
}
RankInfo* info = TheRankInfoStore->m_rankInfos[rank-1];
if (!info)
{
DEBUG_CRASH(("Rank not found in map.ini"));
throw INI_INVALID_DATA;
}
RankInfo* newInfo = newInstance(RankInfo);
// copy data from final override to 'newInfo' as a set of initial default values
info = (RankInfo*)(info->friend_getFinalOverride());
*newInfo = *info;
info->setNextOverride(newInfo);
newInfo->markAsOverride(); // must do AFTER the copy
ini->initFromINI(newInfo, myFieldParse);
//TheRankInfoStore->m_rankInfos.push_back(newInfo); // NO, BAD, WRONG -- don't add in this case.
}
else
{
if (rank != TheRankInfoStore->m_rankInfos.size() + 1)
{
DEBUG_CRASH(("Ranks must increase monotonically"));
throw INI_INVALID_DATA;
}
RankInfo* info = newInstance(RankInfo);
ini->initFromINI(info, myFieldParse);
TheRankInfoStore->m_rankInfos.push_back(info);
}
}
}
//-----------------------------------------------------------------------------
void INI::parseRankDefinition( INI* ini )
{
RankInfoStore::friend_parseRankDefinition(ini);
}