Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
75
Generals/Code/GameEngine/Source/Common/Thing/DrawModule.cpp
Normal file
75
Generals/Code/GameEngine/Source/Common/Thing/DrawModule.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
** 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.cpp ///////////////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, September 2002
|
||||
// Desc: Draw module base class
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h"
|
||||
#include "Common/DrawModule.h"
|
||||
#include "Common/Xfer.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** CRC */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DrawModule::crc( Xfer *xfer )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
DrawableModule::crc( xfer );
|
||||
|
||||
} // end crc
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer method
|
||||
* Version Info;
|
||||
* 1: Initial version */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DrawModule::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
// extend base class
|
||||
DrawableModule::xfer( xfer );
|
||||
|
||||
} // end xfer
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Load post process */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DrawModule::loadPostProcess( void )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
DrawableModule::loadPostProcess();
|
||||
|
||||
} // end loadPostProcess
|
||||
|
285
Generals/Code/GameEngine/Source/Common/Thing/Module.cpp
Normal file
285
Generals/Code/GameEngine/Source/Common/Thing/Module.cpp
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
** 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.cpp ///////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "Common/Module.h"
|
||||
#include "Common/Thing.h"
|
||||
#include "Common/INI.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/Upgrade.h"
|
||||
#include "Common/Xfer.h"
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/Module/BodyModule.h"
|
||||
#include "GameLogic/Module/CollideModule.h"
|
||||
#include "GameLogic/Module/ContainModule.h"
|
||||
#include "GameLogic/Module/DamageModule.h"
|
||||
#include "GameLogic/Module/DieModule.h"
|
||||
#include "GameLogic/Module/UpdateModule.h"
|
||||
#include "GameLogic/Module/UpgradeModule.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// 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* Module::friend_newModuleData(INI* ini)
|
||||
{
|
||||
ModuleData* data = MSGNEW("Module::friend_newModuleData") ModuleData; // no need to memorypool these since we never allocate more than one of each
|
||||
if (ini)
|
||||
ini->initFromINI(data, 0); // this is just so that an "end" token is required
|
||||
return data;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Module::~Module()
|
||||
{
|
||||
|
||||
} // end ~Module
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** CRC */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Module::crc( Xfer *xfer )
|
||||
{
|
||||
|
||||
} // end crc
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer method
|
||||
* Version Info:
|
||||
* 1: Initial version */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Module::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
} // end xfer
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** load post process */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Module::loadPostProcess( void )
|
||||
{
|
||||
|
||||
} // end loadPostProcess
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ObjectModule::ObjectModule( Thing *thing, const ModuleData* moduleData ) : Module(moduleData)
|
||||
{
|
||||
if (!moduleData)
|
||||
{
|
||||
DEBUG_CRASH(("module data may not be null\n"));
|
||||
throw INI_INVALID_DATA;
|
||||
}
|
||||
|
||||
DEBUG_ASSERTCRASH( thing, ("Thing passed to ObjectModule is NULL!\n") );
|
||||
m_object = AsObject(thing);
|
||||
DEBUG_ASSERTCRASH( m_object, ("Thing passed to ObjectModule is not an Object!\n") );
|
||||
|
||||
} // end ObjectModule
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ObjectModule::~ObjectModule( void )
|
||||
{
|
||||
|
||||
} // end ~ObjectModule
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** CRC */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjectModule::crc( Xfer *xfer )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
Module::crc( xfer );
|
||||
|
||||
} // end crc
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer method
|
||||
* Version Info:
|
||||
* 1: Initial version */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjectModule::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
// extend base class
|
||||
Module::xfer( xfer );
|
||||
|
||||
} // end xfer
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** load post process */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjectModule::loadPostProcess( void )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
Module::loadPostProcess();
|
||||
|
||||
} // end loadPostProcess
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DrawableModule::DrawableModule( Thing *thing, const ModuleData* moduleData ) : Module(moduleData)
|
||||
{
|
||||
if (!moduleData)
|
||||
{
|
||||
DEBUG_CRASH(("module data may not be null\n"));
|
||||
throw INI_INVALID_DATA;
|
||||
}
|
||||
|
||||
DEBUG_ASSERTCRASH( thing, ("Thing passed to DrawableModule is NULL!\n") );
|
||||
m_drawable = AsDrawable(thing);
|
||||
DEBUG_ASSERTCRASH( m_drawable, ("Thing passed to DrawableModule is not a Drawable!\n") );
|
||||
|
||||
} // end ~DrawableModule
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DrawableModule::~DrawableModule( void )
|
||||
{
|
||||
|
||||
} // end ~DrawableModule
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** CRC */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DrawableModule::crc( Xfer *xfer )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
Module::crc( xfer );
|
||||
|
||||
} // end crc
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer method
|
||||
* Version Info:
|
||||
* 1: Initial version */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DrawableModule::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
// extend base class
|
||||
Module::xfer( xfer );
|
||||
|
||||
} // end xfer
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** load post process */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void DrawableModule::loadPostProcess( void )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
Module::loadPostProcess();
|
||||
|
||||
} // end loadPostProcess
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void UpgradeMuxData::performUpgradeFX(Object* obj) const
|
||||
{
|
||||
if (m_fxListUpgrade)
|
||||
{
|
||||
FXList::doFXObj(m_fxListUpgrade, obj);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void UpgradeMuxData::getUpgradeActivationMasks(Int64& activation, Int64& conflicting) const
|
||||
{
|
||||
// already computed.
|
||||
if (!m_activationUpgradeNames.empty() || !m_conflictingUpgradeNames.empty())
|
||||
{
|
||||
m_activationMask = 0;
|
||||
m_conflictingMask = 0;
|
||||
|
||||
std::vector<AsciiString>::const_iterator it;
|
||||
for( it = m_activationUpgradeNames.begin();
|
||||
it != m_activationUpgradeNames.end();
|
||||
it++)
|
||||
{
|
||||
const UpgradeTemplate* theTemplate = TheUpgradeCenter->findUpgrade( *it );
|
||||
if( !theTemplate && !it->isEmpty() && !it->isNone())
|
||||
{
|
||||
DEBUG_CRASH(("An upgrade module references %s, which is not an Upgrade", it->str()));
|
||||
throw INI_INVALID_DATA;
|
||||
}
|
||||
|
||||
m_activationMask |= theTemplate->getUpgradeMask();
|
||||
}
|
||||
|
||||
for( it = m_conflictingUpgradeNames.begin();
|
||||
it != m_conflictingUpgradeNames.end();
|
||||
it++)
|
||||
{
|
||||
const UpgradeTemplate* theTemplate = TheUpgradeCenter->findUpgrade( *it );
|
||||
if( !theTemplate && !it->isEmpty() && !it->isNone())
|
||||
{
|
||||
DEBUG_CRASH(("An upgrade module references %s, which is not an Upgrade", it->str()));
|
||||
throw INI_INVALID_DATA;
|
||||
}
|
||||
m_conflictingMask |= theTemplate->getUpgradeMask();
|
||||
}
|
||||
|
||||
m_activationUpgradeNames.clear();
|
||||
m_conflictingUpgradeNames.clear();
|
||||
}
|
||||
activation = m_activationMask;
|
||||
conflicting = m_conflictingMask;
|
||||
}
|
676
Generals/Code/GameEngine/Source/Common/Thing/ModuleFactory.cpp
Normal file
676
Generals/Code/GameEngine/Source/Common/Thing/ModuleFactory.cpp
Normal file
|
@ -0,0 +1,676 @@
|
|||
/*
|
||||
** 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.cpp ////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/Module.h"
|
||||
#include "Common/ModuleFactory.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
|
||||
// behavior includes
|
||||
#include "GameLogic/Module/AutoHealBehavior.h"
|
||||
#include "GameLogic/Module/BehaviorModule.h"
|
||||
#include "GameLogic/Module/BridgeBehavior.h"
|
||||
#include "GameLogic/Module/BridgeScaffoldBehavior.h"
|
||||
#include "GameLogic/Module/BridgeTowerBehavior.h"
|
||||
#include "GameLogic/Module/DumbProjectileBehavior.h"
|
||||
#include "GameLogic/Module/InstantDeathBehavior.h"
|
||||
#include "GameLogic/Module/SlowDeathBehavior.h"
|
||||
#include "GameLogic/Module/HelicopterSlowDeathUpdate.h"
|
||||
#include "GameLogic/Module/NeutronMissileSlowDeathUpdate.h"
|
||||
#include "GameLogic/Module/CaveContain.h"
|
||||
#include "GameLogic/Module/OpenContain.h"
|
||||
#include "GameLogic/Module/OverchargeBehavior.h"
|
||||
#include "GameLogic/Module/HealContain.h"
|
||||
#include "GameLogic/Module/GarrisonContain.h"
|
||||
#include "GameLogic/Module/TransportContain.h"
|
||||
#include "GameLogic/Module/RailedTransportContain.h"
|
||||
#include "GameLogic/Module/MobNexusContain.h"
|
||||
#include "GameLogic/Module/TunnelContain.h"
|
||||
#include "GameLogic/Module/OverlordContain.h"
|
||||
#include "GameLogic/Module/ParachuteContain.h"
|
||||
#ifdef ALLOW_SURRENDER
|
||||
#include "GameLogic/Module/POWTruckBehavior.h"
|
||||
#include "GameLogic/Module/PrisonBehavior.h"
|
||||
#include "GameLogic/Module/PropagandaCenterBehavior.h"
|
||||
#endif
|
||||
#include "GameLogic/Module/PropagandaTowerBehavior.h"
|
||||
#include "GameLogic/Module/FireWeaponWhenDamagedBehavior.h"
|
||||
#include "GameLogic/Module/FireWeaponWhenDeadBehavior.h"
|
||||
#include "GameLogic/Module/GenerateMinefieldBehavior.h"
|
||||
#include "GameLogic/Module/ParkingPlaceBehavior.h"
|
||||
#include "GameLogic/Module/PoisonedBehavior.h"
|
||||
#include "GameLogic/Module/RebuildHoleBehavior.h"
|
||||
#include "GameLogic/Module/SupplyWarehouseCripplingBehavior.h"
|
||||
#include "GameLogic/Module/TechBuildingBehavior.h"
|
||||
#include "GameLogic/Module/MinefieldBehavior.h"
|
||||
#include "GameLogic/Module/JetSlowDeathBehavior.h"
|
||||
|
||||
// die includes
|
||||
#include "GameLogic/Module/CreateCrateDie.h"
|
||||
#include "GameLogic/Module/CreateObjectDie.h"
|
||||
#include "GameLogic/Module/CrushDie.h"
|
||||
#include "GameLogic/Module/DamDie.h"
|
||||
#include "GameLogic/Module/DestroyDie.h"
|
||||
#include "GameLogic/Module/EjectPilotDie.h"
|
||||
#include "GameLogic/Module/FXListDie.h"
|
||||
#include "GameLogic/Module/RebuildHoleExposeDie.h"
|
||||
#include "GameLogic/Module/SpecialPowerCompletionDie.h"
|
||||
#include "GameLogic/Module/UpgradeDie.h"
|
||||
#include "GameLogic/Module/KeepObjectDie.h"
|
||||
|
||||
// logic update includes
|
||||
#include "GameLogic/Module/AIUpdate.h"
|
||||
#include "GameLogic/Module/AssistedTargetingUpdate.h"
|
||||
#include "GameLogic/Module/BaseRegenerateUpdate.h"
|
||||
#include "GameLogic/Module/BoneFXUpdate.h"
|
||||
#include "GameLogic/Module/ChinookAIUpdate.h"
|
||||
#include "GameLogic/Module/DefaultProductionExitUpdate.h"
|
||||
#include "GameLogic/Module/DelayedWeaponSetUpgradeUpdate.h"
|
||||
#include "GameLogic/Module/DeletionUpdate.h"
|
||||
#include "GameLogic/Module/DeliverPayloadAIUpdate.h"
|
||||
#include "GameLogic/Module/DozerAIUpdate.h"
|
||||
#include "GameLogic/Module/DynamicGeometryInfoUpdate.h"
|
||||
#include "GameLogic/Module/DynamicShroudClearingRangeUpdate.h"
|
||||
#include "GameLogic/Module/EnemyNearUpdate.h"
|
||||
#include "GameLogic/Module/FireSpreadUpdate.h"
|
||||
#include "GameLogic/Module/FirestormDynamicGeometryInfoUpdate.h"
|
||||
#include "GameLogic/Module/FireWeaponUpdate.h"
|
||||
#include "GameLogic/Module/FlammableUpdate.h"
|
||||
#include "GameLogic/Module/FloatUpdate.h"
|
||||
#include "GameLogic/Module/TensileFormationUpdate.h"
|
||||
#include "GameLogic/Module/HackInternetAIUpdate.h"
|
||||
#include "GameLogic/Module/DeployStyleAIUpdate.h"
|
||||
#include "GameLogic/Module/AssaultTransportAIUpdate.h"
|
||||
#include "GameLogic/Module/HeightDieUpdate.h"
|
||||
#include "GameLogic/Module/HordeUpdate.h"
|
||||
#include "GameLogic/Module/JetAIUpdate.h"
|
||||
#include "GameLogic/Module/LaserUpdate.h"
|
||||
#include "GameLogic/Module/PointDefenseLaserUpdate.h"
|
||||
#include "GameLogic/Module/CleanupHazardUpdate.h"
|
||||
#include "GameLogic/Module/AutoFindHealingUpdate.h"
|
||||
#include "GameLogic/Module/CommandButtonHuntUpdate.h"
|
||||
#include "GameLogic/Module/PilotFindVehicleUpdate.h"
|
||||
#include "GameLogic/Module/DemoTrapUpdate.h"
|
||||
#include "GameLogic/Module/ParticleUplinkCannonUpdate.h"
|
||||
#include "GameLogic/Module/BaikonurLaunchPower.h"
|
||||
#include "GameLogic/Module/BattlePlanUpdate.h"
|
||||
#include "GameLogic/Module/LifetimeUpdate.h"
|
||||
#include "GameLogic/Module/RadiusDecalUpdate.h"
|
||||
#include "GameLogic/Module/AutoDepositUpdate.h"
|
||||
#include "GameLogic/Module/MissileAIUpdate.h"
|
||||
#include "GameLogic/Module/NeutronMissileUpdate.h"
|
||||
#include "GameLogic/Module/OCLUpdate.h"
|
||||
#include "GameLogic/Module/PhysicsUpdate.h"
|
||||
#ifdef ALLOW_SURRENDER
|
||||
#include "GameLogic/Module/POWTruckAIUpdate.h"
|
||||
#endif
|
||||
#include "GameLogic/Module/ProductionUpdate.h"
|
||||
#include "GameLogic/Module/ProjectileStreamUpdate.h"
|
||||
#include "GameLogic/Module/ProneUpdate.h"
|
||||
#include "GameLogic/Module/QueueProductionExitUpdate.h"
|
||||
#include "GameLogic/Module/RadarUpdate.h"
|
||||
#include "GameLogic/Module/RepairDockUpdate.h"
|
||||
#ifdef ALLOW_SURRENDER
|
||||
#include "GameLogic/Module/PrisonDockUpdate.h"
|
||||
#endif
|
||||
#include "GameLogic/Module/RailedTransportDockUpdate.h"
|
||||
#include "GameLogic/Module/RailedTransportAIUpdate.h"
|
||||
#include "GameLogic/Module/RailroadGuideAIUpdate.h"
|
||||
#include "GameLogic/Module/SlavedUpdate.h"
|
||||
#include "GameLogic/Module/MobMemberSlavedUpdate.h"
|
||||
#include "GameLogic/Module/SpecialAbilityUpdate.h"
|
||||
#include "GameLogic/Module/MissileLauncherBuildingUpdate.h"
|
||||
#include "GameLogic/Module/StealthDetectorUpdate.h"
|
||||
#include "GameLogic/Module/StealthUpdate.h"
|
||||
#include "GameLogic/Module/SpawnPointProductionExitUpdate.h"
|
||||
#include "GameLogic/Module/SpawnBehavior.h"
|
||||
#include "GameLogic/Module/SpyVisionUpdate.h"
|
||||
#include "GameLogic/Module/StickyBombUpdate.h"
|
||||
#include "GameLogic/Module/FireOCLAfterWeaponCooldownUpdate.h"
|
||||
#include "GameLogic/Module/HijackerUpdate.h"
|
||||
#include "GameLogic/Module/StructureCollapseUpdate.h"
|
||||
#include "GameLogic/Module/StructureToppleUpdate.h"
|
||||
#include "GameLogic/Module/SupplyCenterDockUpdate.h"
|
||||
#include "GameLogic/Module/SupplyCenterProductionExitUpdate.h"
|
||||
#include "GameLogic/Module/SupplyTruckAIUpdate.h"
|
||||
#include "GameLogic/Module/SupplyWarehouseDockUpdate.h"
|
||||
#include "GameLogic/Module/ToppleUpdate.h"
|
||||
#include "GameLogic/Module/TransportAIUpdate.h"
|
||||
#include "GameLogic/Module/WanderAIUpdate.h"
|
||||
#include "GameLogic/Module/WaveGuideUpdate.h"
|
||||
#include "GameLogic/Module/WorkerAIUpdate.h"
|
||||
#include "GameLogic/Module/PowerPlantUpdate.h"
|
||||
#include "GameLogic/Module/CheckpointUpdate.h"
|
||||
#include "GameLogic/Module/EMPUpdate.h"
|
||||
|
||||
// upgrade includes
|
||||
#include "GameLogic/Module/ActiveShroudUpgrade.h"
|
||||
#include "GameLogic/Module/ArmorUpgrade.h"
|
||||
#include "GameLogic/Module/CommandSetUpgrade.h"
|
||||
#include "GameLogic/Module/DelayedUpgrade.h"
|
||||
#include "GameLogic/Module/LocomotorSetUpgrade.h"
|
||||
#include "GameLogic/Module/ObjectCreationUpgrade.h"
|
||||
#include "GameLogic/Module/RadarUpgrade.h"
|
||||
#include "GameLogic/Module/PowerPlantUpgrade.h"
|
||||
#include "GameLogic/Module/StatusBitsUpgrade.h"
|
||||
#include "GameLogic/Module/SubObjectsUpgrade.h"
|
||||
#include "GameLogic/Module/StealthUpgrade.h"
|
||||
#include "GameLogic/Module/UnpauseSpecialPowerUpgrade.h"
|
||||
#include "GameLogic/Module/WeaponBonusUpgrade.h"
|
||||
#include "GameLogic/Module/WeaponSetUpgrade.h"
|
||||
#include "GameLogic/Module/WeaponBonusUpgrade.h"
|
||||
#include "GameLogic/Module/CostModifierUpgrade.h"
|
||||
#include "GameLogic/Module/ExperienceScalarUpgrade.h"
|
||||
#include "GameLogic/Module/MaxHealthUpgrade.h"
|
||||
|
||||
// create includes
|
||||
#include "GameLogic/Module/SupplyCenterCreate.h"
|
||||
#include "GameLogic/Module/SupplyWarehouseCreate.h"
|
||||
#include "GameLogic/Module/GrantUpgradeCreate.h"
|
||||
#include "GameLogic/Module/PreorderCreate.h"
|
||||
#include "GameLogic/Module/SpecialPowerCreate.h"
|
||||
#include "GameLogic/Module/VeterancyGainCreate.h"
|
||||
|
||||
// damage includes
|
||||
#include "GameLogic/Module/BoneFXDamage.h"
|
||||
#include "GameLogic/Module/TransitionDamageFX.h"
|
||||
|
||||
// collide includes
|
||||
#include "GameLogic/Module/FireWeaponCollide.h"
|
||||
#include "GameLogic/Module/SquishCollide.h"
|
||||
|
||||
#include "GameLogic/Module/HealCrateCollide.h"
|
||||
#include "GameLogic/Module/MoneyCrateCollide.h"
|
||||
#include "GameLogic/Module/ShroudCrateCollide.h"
|
||||
#include "GameLogic/Module/UnitCrateCollide.h"
|
||||
#include "GameLogic/Module/VeterancyCrateCollide.h"
|
||||
#include "GameLogic/Module/ConvertToCarBombCrateCollide.h"
|
||||
#include "GameLogic/Module/ConvertToHijackedVehicleCrateCollide.h"
|
||||
#include "GameLogic/Module/SalvageCrateCollide.h"
|
||||
|
||||
// body includes
|
||||
#include "GameLogic/Module/InactiveBody.h"
|
||||
#include "GameLogic/Module/ActiveBody.h"
|
||||
#include "GameLogic/Module/HighlanderBody.h"
|
||||
#include "GameLogic/Module/ImmortalBody.h"
|
||||
#include "GameLogic/Module/StructureBody.h"
|
||||
#include "GameLogic/Module/HiveStructureBody.h"
|
||||
|
||||
// contain includes
|
||||
// (none)
|
||||
|
||||
// special power modules
|
||||
#include "GameLogic/Module/CashHackSpecialPower.h"
|
||||
#include "GameLogic/Module/DefectorSpecialPower.h"
|
||||
#ifdef ALLOW_DEMORALIZE
|
||||
#include "GameLogic/Module/DemoralizeSpecialPower.h"
|
||||
#endif
|
||||
#include "GameLogic/Module/OCLSpecialPower.h"
|
||||
#include "GameLogic/Module/SpecialAbility.h"
|
||||
#include "GameLogic/Module/SpyVisionSpecialPower.h"
|
||||
#include "GameLogic/Module/CashBountyPower.h"
|
||||
#include "GameLogic/Module/CleanupAreaPower.h"
|
||||
|
||||
// destroy includes
|
||||
// (none)
|
||||
|
||||
// client update includes
|
||||
#include "GameClient/Module/AnimatedParticleSysBoneClientUpdate.h"
|
||||
#include "GameClient/Module/SwayClientUpdate.h"
|
||||
#include "GameClient/Module/BeaconClientUpdate.h"
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
|
||||
ModuleFactory *TheModuleFactory = NULL; ///< the module factory singleton
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ModuleFactory::ModuleFactory( void )
|
||||
{
|
||||
m_moduleTemplateMap.clear();
|
||||
m_moduleDataList.clear();
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ModuleFactory::~ModuleFactory( void )
|
||||
{
|
||||
m_moduleTemplateMap.clear();
|
||||
|
||||
for (ModuleDataList::iterator i = m_moduleDataList.begin(); i != m_moduleDataList.end(); ++i)
|
||||
{
|
||||
const ModuleData* data = *i;
|
||||
delete data;
|
||||
}
|
||||
m_moduleDataList.clear();
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the module factory. Any class that needs to be attached
|
||||
* to objects or drawables as modules needs to add a template
|
||||
* for that class here */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ModuleFactory::init( void )
|
||||
{
|
||||
|
||||
// behavior modules
|
||||
addModule( AutoHealBehavior );
|
||||
addModule( BridgeBehavior );
|
||||
addModule( BridgeScaffoldBehavior );
|
||||
addModule( BridgeTowerBehavior );
|
||||
addModule( DumbProjectileBehavior );
|
||||
addModule( PhysicsBehavior );
|
||||
addModule( InstantDeathBehavior );
|
||||
addModule( SlowDeathBehavior );
|
||||
addModule( HelicopterSlowDeathBehavior );
|
||||
addModule( NeutronMissileSlowDeathBehavior );
|
||||
addModule( CaveContain );
|
||||
addModule( OpenContain );
|
||||
addModule( OverchargeBehavior );
|
||||
addModule( HealContain );
|
||||
addModule( GarrisonContain );
|
||||
addModule( TransportContain );
|
||||
addModule( RailedTransportContain );
|
||||
addModule( MobNexusContain );
|
||||
addModule( TunnelContain );
|
||||
addModule( OverlordContain );
|
||||
addModule( ParachuteContain );
|
||||
#ifdef ALLOW_SURRENDER
|
||||
addModule( POWTruckBehavior );
|
||||
addModule( PrisonBehavior );
|
||||
addModule( PropagandaCenterBehavior );
|
||||
#endif
|
||||
addModule( PropagandaTowerBehavior );
|
||||
addModule( FireWeaponWhenDamagedBehavior );
|
||||
addModule( FireWeaponWhenDeadBehavior );
|
||||
addModule( GenerateMinefieldBehavior );
|
||||
addModule( ParkingPlaceBehavior );
|
||||
addModule( PoisonedBehavior );
|
||||
addModule( RebuildHoleBehavior );
|
||||
addModule( SupplyWarehouseCripplingBehavior );
|
||||
addModule( TechBuildingBehavior );
|
||||
addModule( MinefieldBehavior );
|
||||
addModule( JetSlowDeathBehavior );
|
||||
addModule( RailroadBehavior );
|
||||
addModule( SpawnBehavior );
|
||||
|
||||
// die modules
|
||||
addModule( DestroyDie );
|
||||
addModule( FXListDie );
|
||||
addModule( CrushDie );
|
||||
addModule( DamDie );
|
||||
addModule( CreateCrateDie );
|
||||
addModule( CreateObjectDie );
|
||||
addModule( EjectPilotDie );
|
||||
addModule( SpecialPowerCompletionDie );
|
||||
addModule( RebuildHoleExposeDie );
|
||||
addModule( UpgradeDie );
|
||||
addModule( KeepObjectDie );
|
||||
|
||||
// update modules
|
||||
addModule( AssistedTargetingUpdate );
|
||||
addModule( AutoFindHealingUpdate );
|
||||
addModule( BaseRegenerateUpdate );
|
||||
addModule( StealthDetectorUpdate );
|
||||
addModule( StealthUpdate );
|
||||
addModule( DelayedWeaponSetUpgradeUpdate );
|
||||
addModule( DeletionUpdate );
|
||||
addModule( DynamicShroudClearingRangeUpdate );
|
||||
addModule( DeployStyleAIUpdate );
|
||||
addModule( AssaultTransportAIUpdate );
|
||||
addModule( HordeUpdate );
|
||||
addModule( ToppleUpdate );
|
||||
addModule( EnemyNearUpdate );
|
||||
addModule( LifetimeUpdate );
|
||||
addModule( RadiusDecalUpdate );
|
||||
addModule( EMPUpdate );
|
||||
addModule( AutoDepositUpdate );
|
||||
addModule( MissileAIUpdate );
|
||||
addModule( NeutronMissileUpdate );
|
||||
addModule( FireSpreadUpdate );
|
||||
addModule( FireWeaponUpdate );
|
||||
addModule( FlammableUpdate );
|
||||
addModule( FloatUpdate );
|
||||
addModule( TensileFormationUpdate );
|
||||
addModule( HeightDieUpdate );
|
||||
addModule( ChinookAIUpdate );
|
||||
addModule( JetAIUpdate );
|
||||
addModule( AIUpdateInterface );
|
||||
addModule( SupplyTruckAIUpdate );
|
||||
addModule( DeliverPayloadAIUpdate );
|
||||
addModule( HackInternetAIUpdate );
|
||||
addModule( DynamicGeometryInfoUpdate );
|
||||
addModule( FirestormDynamicGeometryInfoUpdate );
|
||||
addModule( LaserUpdate );
|
||||
addModule( PointDefenseLaserUpdate );
|
||||
addModule( CleanupHazardUpdate );
|
||||
addModule( CommandButtonHuntUpdate );
|
||||
addModule( PilotFindVehicleUpdate );
|
||||
addModule( DemoTrapUpdate );
|
||||
addModule( ParticleUplinkCannonUpdate );
|
||||
addModule( BaikonurLaunchPower );
|
||||
addModule( BattlePlanUpdate );
|
||||
addModule( ProjectileStreamUpdate );
|
||||
addModule( QueueProductionExitUpdate );
|
||||
addModule( RepairDockUpdate );
|
||||
#ifdef ALLOW_SURRENDER
|
||||
addModule( PrisonDockUpdate );
|
||||
#endif
|
||||
addModule( RailedTransportDockUpdate );
|
||||
addModule( DefaultProductionExitUpdate );
|
||||
addModule( SpawnPointProductionExitUpdate );
|
||||
addModule( SpyVisionUpdate );
|
||||
addModule( SlavedUpdate );
|
||||
addModule( MobMemberSlavedUpdate );
|
||||
addModule( OCLUpdate );
|
||||
addModule( SpecialAbilityUpdate );
|
||||
addModule( MissileLauncherBuildingUpdate );
|
||||
addModule( SupplyCenterProductionExitUpdate );
|
||||
addModule( SupplyCenterDockUpdate );
|
||||
addModule( SupplyWarehouseDockUpdate );
|
||||
addModule( DozerAIUpdate );
|
||||
#ifdef ALLOW_SURRENDER
|
||||
addModule( POWTruckAIUpdate );
|
||||
#endif
|
||||
addModule( RailedTransportAIUpdate );
|
||||
addModule( ProductionUpdate );
|
||||
addModule( ProneUpdate );
|
||||
addModule( StickyBombUpdate );
|
||||
addModule( FireOCLAfterWeaponCooldownUpdate );
|
||||
addModule( HijackerUpdate );
|
||||
addModule( StructureToppleUpdate );
|
||||
addModule( StructureCollapseUpdate );
|
||||
addModule( BoneFXUpdate );
|
||||
addModule( RadarUpdate );
|
||||
addModule( TransportAIUpdate );
|
||||
addModule( WanderAIUpdate );
|
||||
addModule( WaveGuideUpdate );
|
||||
addModule( WorkerAIUpdate );
|
||||
addModule( PowerPlantUpdate );
|
||||
addModule( CheckpointUpdate );
|
||||
|
||||
// upgrade modules
|
||||
addModule( CostModifierUpgrade );
|
||||
addModule( ActiveShroudUpgrade );
|
||||
addModule( ArmorUpgrade );
|
||||
addModule( CommandSetUpgrade );
|
||||
addModule( DelayedUpgrade );
|
||||
addModule( StatusBitsUpgrade );
|
||||
addModule( SubObjectsUpgrade );
|
||||
addModule( StealthUpgrade );
|
||||
addModule( RadarUpgrade );
|
||||
addModule( PowerPlantUpgrade );
|
||||
addModule( LocomotorSetUpgrade );
|
||||
addModule( ObjectCreationUpgrade );
|
||||
addModule( UnpauseSpecialPowerUpgrade );
|
||||
addModule( WeaponBonusUpgrade );
|
||||
addModule( WeaponSetUpgrade );
|
||||
addModule( WeaponBonusUpgrade );
|
||||
addModule( ExperienceScalarUpgrade );
|
||||
addModule( MaxHealthUpgrade );
|
||||
|
||||
// create modules
|
||||
addModule( PreorderCreate );
|
||||
addModule( SupplyCenterCreate );
|
||||
addModule( SupplyWarehouseCreate );
|
||||
addModule( SpecialPowerCreate );
|
||||
addModule( GrantUpgradeCreate );
|
||||
addModule( VeterancyGainCreate );
|
||||
|
||||
// damage modules
|
||||
addModule( BoneFXDamage );
|
||||
addModule( TransitionDamageFX );
|
||||
|
||||
// collide modules
|
||||
addModule( FireWeaponCollide );
|
||||
addModule( SquishCollide );
|
||||
|
||||
addModule( HealCrateCollide );
|
||||
addModule( MoneyCrateCollide );
|
||||
addModule( ShroudCrateCollide );
|
||||
addModule( UnitCrateCollide );
|
||||
addModule( VeterancyCrateCollide );
|
||||
addModule( ConvertToCarBombCrateCollide );
|
||||
addModule( ConvertToHijackedVehicleCrateCollide );
|
||||
addModule( SalvageCrateCollide );
|
||||
|
||||
// body modules
|
||||
addModule( InactiveBody );
|
||||
addModule( ActiveBody );
|
||||
addModule( HighlanderBody );
|
||||
addModule( ImmortalBody );
|
||||
addModule( StructureBody );
|
||||
addModule( HiveStructureBody );
|
||||
|
||||
// contain modules
|
||||
// (none)
|
||||
|
||||
// special power modules
|
||||
addModule( CashHackSpecialPower );
|
||||
addModule( DefectorSpecialPower );
|
||||
#ifdef ALLOW_DEMORALIZE
|
||||
addModule( DemoralizeSpecialPower );
|
||||
#endif
|
||||
addModule( OCLSpecialPower );
|
||||
addModule( SpecialAbility );
|
||||
addModule( SpyVisionSpecialPower );
|
||||
addModule( CashBountyPower );
|
||||
addModule( CleanupAreaPower );
|
||||
|
||||
// destroy modules
|
||||
// (none)
|
||||
|
||||
// client update modules
|
||||
addModule( AnimatedParticleSysBoneClientUpdate );
|
||||
addModule( SwayClientUpdate );
|
||||
addModule( BeaconClientUpdate );
|
||||
|
||||
} // end init
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Int ModuleFactory::findModuleInterfaceMask(const AsciiString& name, ModuleType type)
|
||||
{
|
||||
if (name.isEmpty())
|
||||
return 0;
|
||||
|
||||
const ModuleTemplate* moduleTemplate = findModuleTemplate(name, type);
|
||||
if (moduleTemplate)
|
||||
{
|
||||
return moduleTemplate->m_whichInterfaces;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ModuleData* ModuleFactory::newModuleDataFromINI(INI* ini, const AsciiString& name, ModuleType type,
|
||||
const AsciiString& moduleTag)
|
||||
{
|
||||
if (name.isEmpty())
|
||||
return NULL;
|
||||
|
||||
const ModuleTemplate* moduleTemplate = findModuleTemplate(name, type);
|
||||
if (moduleTemplate)
|
||||
{
|
||||
ModuleData* md = (*moduleTemplate->m_createDataProc)(ini);
|
||||
md->setModuleTagNameKey( NAMEKEY( moduleTag ) );
|
||||
m_moduleDataList.push_back(md);
|
||||
return md;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/*static*/ NameKeyType ModuleFactory::makeDecoratedNameKey(const AsciiString& name, ModuleType type)
|
||||
{
|
||||
char tmp[256];
|
||||
tmp[0] = '0' + (int)type;
|
||||
strcpy(&tmp[1], name.str());
|
||||
return TheNameKeyGenerator->nameToKey(tmp);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const ModuleFactory::ModuleTemplate* ModuleFactory::findModuleTemplate(const AsciiString& name, ModuleType type)
|
||||
{
|
||||
NameKeyType namekey = makeDecoratedNameKey(name, type);
|
||||
|
||||
ModuleTemplateMap::const_iterator it = m_moduleTemplateMap.find(namekey);
|
||||
if (it == m_moduleTemplateMap.end())
|
||||
{
|
||||
DEBUG_CRASH(( "Module name '%s' not found\n", name.str() ));
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &(*it).second;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Allocate a new acton class istance given the name */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Module *ModuleFactory::newModule( Thing *thing, const AsciiString& name, const ModuleData* moduleData, ModuleType type )
|
||||
{
|
||||
// sanity
|
||||
if( name.isEmpty() )
|
||||
{
|
||||
DEBUG_CRASH(("attempting to create module with empty name\n"));
|
||||
return NULL;
|
||||
}
|
||||
const ModuleTemplate* mt = findModuleTemplate(name, type);
|
||||
if (mt)
|
||||
{
|
||||
Module* mod = (*mt->m_createProc)( thing, moduleData );
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (type == MODULETYPE_BEHAVIOR)
|
||||
{
|
||||
BehaviorModule* bm = (BehaviorModule*)mod;
|
||||
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_BODY)) != 0) == (bm->getBody() != NULL),
|
||||
("getInterfaceMask bad for MODULE_BODY (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_COLLIDE)) != 0) == (bm->getCollide() != NULL),
|
||||
("getInterfaceMask bad for MODULE_COLLIDE (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_CONTAIN)) != 0) == (bm->getContain() != NULL),
|
||||
("getInterfaceMask bad for MODULE_CONTAIN (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_CREATE)) != 0) == (bm->getCreate() != NULL),
|
||||
("getInterfaceMask bad for MODULE_CREATE (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_DAMAGE)) != 0) == (bm->getDamage() != NULL),
|
||||
("getInterfaceMask bad for MODULE_DAMAGE (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_DESTROY)) != 0) == (bm->getDestroy() != NULL),
|
||||
("getInterfaceMask bad for MODULE_DESTROY (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_DIE)) != 0) == (bm->getDie() != NULL),
|
||||
("getInterfaceMask bad for MODULE_DIE (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_SPECIAL_POWER)) != 0) == (bm->getSpecialPower() != NULL),
|
||||
("getInterfaceMask bad for MODULE_SPECIAL_POWER (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_UPDATE)) != 0) == (bm->getUpdate() != NULL),
|
||||
("getInterfaceMask bad for MODULE_UPDATE (%s)\n",name.str()));
|
||||
DEBUG_ASSERTCRASH(
|
||||
((mt->m_whichInterfaces & (MODULEINTERFACE_UPGRADE)) != 0) == (bm->getUpgrade() != NULL),
|
||||
("getInterfaceMask bad for MODULE_UPGRADE (%s)\n",name.str()));
|
||||
}
|
||||
#endif
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
} // end newModule
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Add a module template to our list of templates */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ModuleFactory::addModuleInternal( NewModuleProc proc, NewModuleDataProc dataproc, ModuleType type, const AsciiString& name, Int whichIntf )
|
||||
{
|
||||
NameKeyType namekey = makeDecoratedNameKey(name, type);
|
||||
ModuleTemplate& mtm = m_moduleTemplateMap[namekey]; // this creates it if it does not exist already
|
||||
mtm.m_createProc = proc;
|
||||
mtm.m_createDataProc = dataproc;
|
||||
mtm.m_whichInterfaces = whichIntf;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ModuleFactory::crc( Xfer *xfer )
|
||||
{
|
||||
for (ModuleDataList::iterator mdIt = m_moduleDataList.begin(); mdIt != m_moduleDataList.end(); ++mdIt)
|
||||
{
|
||||
((ModuleData *)(*mdIt))->crc(xfer);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ModuleFactory::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
for (ModuleDataList::iterator mdIt = m_moduleDataList.begin(); mdIt != m_moduleDataList.end(); ++mdIt)
|
||||
{
|
||||
((ModuleData *)(*mdIt))->xfer(xfer);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ModuleFactory::loadPostProcess( void )
|
||||
{
|
||||
}
|
392
Generals/Code/GameEngine/Source/Common/Thing/Thing.cpp
Normal file
392
Generals/Code/GameEngine/Source/Common/Thing/Thing.cpp
Normal file
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
** 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: Thing.cpp ////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, May 2001
|
||||
//
|
||||
// Desc: Things are the base class for objects and drawables, objects
|
||||
// are logic side representations while drawables are client
|
||||
// side. Common data will be held in the Thing defined here
|
||||
// and systems that need to work with both of them will work with
|
||||
// "Things"
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/PerfTimer.h"
|
||||
#include "Common/Thing.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/ThingFactory.h"
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/Team.h"
|
||||
#include "Lib/Trig.h"
|
||||
#include "GameLogic/TerrainLogic.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
/** Constructor */
|
||||
//=============================================================================
|
||||
Thing::Thing( const ThingTemplate *thingTemplate )
|
||||
{
|
||||
// sanity
|
||||
if( thingTemplate == NULL )
|
||||
{
|
||||
|
||||
// cannot create thing without template
|
||||
DEBUG_CRASH(( "no template" ));
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
m_template = thingTemplate;
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
m_templateName = thingTemplate->getName();
|
||||
#endif
|
||||
m_transform.Make_Identity();
|
||||
m_cachedPos.zero();
|
||||
m_cachedAngle = 0.0f;
|
||||
m_cachedDirVector.zero();
|
||||
m_cachedAltitudeAboveTerrain = 0;
|
||||
m_cachedAltitudeAboveTerrainOrWater = 0;
|
||||
m_cacheFlags = 0;
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
/** Destructor */
|
||||
//=============================================================================
|
||||
Thing::~Thing()
|
||||
{
|
||||
}
|
||||
|
||||
//DECLARE_PERF_TIMER(ThingMatrixStuff)
|
||||
|
||||
//=============================================================================
|
||||
const ThingTemplate *Thing::getTemplate() const
|
||||
{
|
||||
return m_template;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
const Coord3D* Thing::getUnitDirectionVector2D() const
|
||||
{
|
||||
//USE_PERF_TIMER(ThingMatrixStuff)
|
||||
if (!(m_cacheFlags & VALID_DIRVECTOR))
|
||||
{
|
||||
Real angle = getOrientation();
|
||||
m_cachedDirVector.x = Cos( angle );
|
||||
m_cachedDirVector.y = Sin( angle );
|
||||
m_cachedDirVector.z = 0;
|
||||
m_cacheFlags |= VALID_DIRVECTOR;
|
||||
}
|
||||
|
||||
return &m_cachedDirVector;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Thing::getUnitDirectionVector2D(Coord3D& dir) const
|
||||
{
|
||||
dir = *getUnitDirectionVector2D();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Thing::getUnitDirectionVector3D(Coord3D& dir) const
|
||||
{
|
||||
Vector3 vdir = m_transform.Get_X_Vector();
|
||||
vdir.Normalize();
|
||||
dir.x = vdir.X;
|
||||
dir.y = vdir.Y;
|
||||
dir.z = vdir.Z;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// the nice thing about this is that we don't have to recalc out cached terrain stuff.
|
||||
void Thing::setPositionZ( Real z )
|
||||
{
|
||||
//USE_PERF_TIMER(ThingMatrixStuff)
|
||||
if( !m_template->isKindOf( KINDOF_STICK_TO_TERRAIN_SLOPE) )
|
||||
{
|
||||
Real oldAngle = m_cachedAngle;
|
||||
Coord3D oldPos = m_cachedPos;
|
||||
Matrix3D oldMtx = m_transform;
|
||||
|
||||
m_transform.Set_Z_Translation( z );
|
||||
m_cachedPos.z = z;
|
||||
|
||||
if (m_cacheFlags & VALID_ALTITUDE_TERRAIN)
|
||||
{
|
||||
m_cachedAltitudeAboveTerrain += (z - oldPos.z);
|
||||
}
|
||||
if (m_cacheFlags & VALID_ALTITUDE_SEALEVEL)
|
||||
{
|
||||
m_cachedAltitudeAboveTerrainOrWater += (z - oldPos.z);
|
||||
}
|
||||
|
||||
reactToTransformChange(&oldMtx, &oldPos, oldAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix3D mtx;
|
||||
const Bool stickToGround = true; // yes, set the "z" pos
|
||||
Coord3D pos = m_cachedPos;
|
||||
pos.z = z;
|
||||
TheTerrainLogic->alignOnTerrain(getOrientation(), pos, stickToGround, mtx );
|
||||
setTransformMatrix(&mtx);
|
||||
}
|
||||
DEBUG_ASSERTCRASH(!(_isnan(getPosition()->x) || _isnan(getPosition()->y) || _isnan(getPosition()->z)), ("Drawable/Object position NAN! '%s'\n", m_template->getName().str() ));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Thing::setPosition( const Coord3D *pos )
|
||||
{
|
||||
//USE_PERF_TIMER(ThingMatrixStuff)
|
||||
if( !m_template->isKindOf( KINDOF_STICK_TO_TERRAIN_SLOPE) )
|
||||
{
|
||||
Real oldAngle = m_cachedAngle;
|
||||
Coord3D oldPos = m_cachedPos;
|
||||
Matrix3D oldMtx = m_transform;
|
||||
|
||||
//DEBUG_ASSERTCRASH(!(_isnan(pos->x) || _isnan(pos->y) || _isnan(pos->z)), ("Drawable/Object position NAN! '%s'\n", m_template->getName().str() ));
|
||||
m_transform.Set_X_Translation( pos->x );
|
||||
m_transform.Set_Y_Translation( pos->y );
|
||||
m_transform.Set_Z_Translation( pos->z );
|
||||
m_cachedPos = *pos;
|
||||
m_cacheFlags &= ~(VALID_ALTITUDE_TERRAIN | VALID_ALTITUDE_SEALEVEL); // but don't clear the dir flags.
|
||||
|
||||
reactToTransformChange(&oldMtx, &oldPos, oldAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix3D mtx;
|
||||
const Bool stickToGround = true; // yes, set the "z" pos
|
||||
TheTerrainLogic->alignOnTerrain(getOrientation(), *pos, stickToGround, mtx );
|
||||
setTransformMatrix(&mtx);
|
||||
}
|
||||
DEBUG_ASSERTCRASH(!(_isnan(getPosition()->x) || _isnan(getPosition()->y) || _isnan(getPosition()->z)), ("Drawable/Object position NAN! '%s'\n", m_template->getName().str() ));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Thing::setOrientation( Real angle )
|
||||
{
|
||||
//USE_PERF_TIMER(ThingMatrixStuff)
|
||||
Coord3D u, x, y, z, pos;
|
||||
|
||||
// setOrientation always forces us straight up in the Z axis,
|
||||
// or aligned with the terrain if we have the magic flag set.
|
||||
// don't want this? call setTransformMatrix instead.
|
||||
|
||||
Real oldAngle = m_cachedAngle;
|
||||
Coord3D oldPos = m_cachedPos;
|
||||
Matrix3D oldMtx = m_transform;
|
||||
|
||||
pos.x = m_transform.Get_X_Translation();
|
||||
pos.y = m_transform.Get_Y_Translation();
|
||||
pos.z = m_transform.Get_Z_Translation();
|
||||
if( m_template->isKindOf( KINDOF_STICK_TO_TERRAIN_SLOPE) )
|
||||
{
|
||||
Matrix3D mtx;
|
||||
const Bool stickToGround = true; // yes, set the "z" pos
|
||||
TheTerrainLogic->alignOnTerrain(angle, pos, stickToGround, m_transform );
|
||||
}
|
||||
else
|
||||
{
|
||||
z.x = 0.0f;
|
||||
z.y = 0.0f;
|
||||
z.z = 1.0f;
|
||||
|
||||
u.x = Cos(angle);
|
||||
u.y = Sin(angle);
|
||||
u.z = 0.0f;
|
||||
|
||||
y.crossProduct( &z, &u, &y );
|
||||
x.crossProduct( &y, &z, &x );
|
||||
|
||||
m_transform.Set( x.x, y.x, z.x, pos.x,
|
||||
x.y, y.y, z.y, pos.y,
|
||||
x.z, y.z, z.z, pos.z );
|
||||
}
|
||||
|
||||
//DEBUG_ASSERTCRASH(-PI <= angle && angle <= PI, ("Please pass only normalized (-PI..PI) angles to setOrientation (%f).\n", angle));
|
||||
m_cachedAngle = normalizeAngle(angle);
|
||||
m_cachedPos = pos;
|
||||
m_cacheFlags &= ~VALID_DIRVECTOR; // but don't clear the altitude flags.
|
||||
|
||||
reactToTransformChange(&oldMtx, &oldPos, oldAngle);
|
||||
DEBUG_ASSERTCRASH(!(_isnan(getPosition()->x) || _isnan(getPosition()->y) || _isnan(getPosition()->z)), ("Drawable/Object position NAN! '%s'\n", m_template->getName().str() ));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
/** Set the world transformation matrix */
|
||||
//=============================================================================
|
||||
void Thing::setTransformMatrix( const Matrix3D *mx )
|
||||
{
|
||||
//USE_PERF_TIMER(ThingMatrixStuff)
|
||||
Real oldAngle = m_cachedAngle;
|
||||
Coord3D oldPos = m_cachedPos;
|
||||
Matrix3D oldMtx = m_transform;
|
||||
|
||||
m_transform = *mx;
|
||||
m_cachedPos.x = m_transform.Get_X_Translation();
|
||||
m_cachedPos.y = m_transform.Get_Y_Translation();
|
||||
m_cachedPos.z = m_transform.Get_Z_Translation();
|
||||
m_cachedAngle = m_transform.Get_Z_Rotation();
|
||||
m_cacheFlags = 0;
|
||||
|
||||
reactToTransformChange(&oldMtx, &oldPos, oldAngle);
|
||||
DEBUG_ASSERTCRASH(!(_isnan(getPosition()->x) || _isnan(getPosition()->y) || _isnan(getPosition()->z)), ("Drawable/Object position NAN! '%s'\n", m_template->getName().str() ));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Bool Thing::isKindOf(KindOfType t) const
|
||||
{
|
||||
return getTemplate()->isKindOf(t);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Bool Thing::isKindOfMulti(const KindOfMaskType& mustBeSet, const KindOfMaskType& mustBeClear) const
|
||||
{
|
||||
return getTemplate()->isKindOfMulti(mustBeSet, mustBeClear);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Bool Thing::isAnyKindOf( const KindOfMaskType& anyKindOf ) const
|
||||
{
|
||||
return getTemplate()->isAnyKindOf( anyKindOf );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Real Thing::calculateHeightAboveTerrain() const
|
||||
{
|
||||
//USE_PERF_TIMER(ThingMatrixStuff)
|
||||
const Coord3D* pos = getPosition();
|
||||
Real terrainZ = TheTerrainLogic->getGroundHeight( pos->x, pos->y );
|
||||
Real myZ = pos->z;
|
||||
return myZ - terrainZ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Real Thing::getHeightAboveTerrain() const
|
||||
{
|
||||
if (!(m_cacheFlags & VALID_ALTITUDE_TERRAIN))
|
||||
{
|
||||
m_cachedAltitudeAboveTerrain = calculateHeightAboveTerrain();
|
||||
m_cacheFlags |= VALID_ALTITUDE_TERRAIN;
|
||||
}
|
||||
return m_cachedAltitudeAboveTerrain;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Real Thing::getHeightAboveTerrainOrWater() const
|
||||
{
|
||||
//USE_PERF_TIMER(ThingMatrixStuff)
|
||||
if (!(m_cacheFlags & VALID_ALTITUDE_SEALEVEL))
|
||||
{
|
||||
const Coord3D* pos = getPosition();
|
||||
Real waterZ;
|
||||
if (TheTerrainLogic->isUnderwater(pos->x, pos->y, &waterZ))
|
||||
{
|
||||
m_cachedAltitudeAboveTerrainOrWater = pos->z - waterZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cachedAltitudeAboveTerrainOrWater = getHeightAboveTerrain();
|
||||
}
|
||||
m_cacheFlags |= VALID_ALTITUDE_SEALEVEL;
|
||||
}
|
||||
return m_cachedAltitudeAboveTerrainOrWater;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
/** If we treat this as airborne, then they slide down slopes. This checks whether
|
||||
they are high enough that we should let them act like they're flying. jba. */
|
||||
//=============================================================================
|
||||
Bool Thing::isSignificantlyAboveTerrain() const
|
||||
{
|
||||
// If it's high enough that it will take more than 3 frames to return to the ground,
|
||||
// then it's significantly airborne. jba
|
||||
return (getHeightAboveTerrain() > -(3*3)*TheGlobalData->m_gravity);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Thing::convertBonePosToWorldPos(const Coord3D* bonePos, const Matrix3D* boneTransform, Coord3D* worldPos, Matrix3D* worldTransform) const
|
||||
{
|
||||
if (worldTransform)
|
||||
{
|
||||
#ifdef ALLOW_TEMPORARIES
|
||||
*worldTransform = m_transform * (*boneTransform);
|
||||
#else
|
||||
worldTransform->mul(m_transform, *boneTransform);
|
||||
#endif
|
||||
}
|
||||
if (worldPos)
|
||||
{
|
||||
Vector3 vector;
|
||||
vector.X = bonePos->x;
|
||||
vector.Y = bonePos->y;
|
||||
vector.Z = bonePos->z;
|
||||
m_transform.Transform_Vector(m_transform, vector, &vector);
|
||||
worldPos->x = vector.X;
|
||||
worldPos->y = vector.Y;
|
||||
worldPos->z = vector.Z;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Push the 'in' parameter through our transformation matrix and store in 'out' */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Thing::transformPoint( const Coord3D *in, Coord3D *out )
|
||||
{
|
||||
|
||||
// santiy
|
||||
if( in == NULL || out == NULL )
|
||||
return;
|
||||
|
||||
// for conversion
|
||||
Vector3 vectorIn;
|
||||
Vector3 vectorOut;
|
||||
|
||||
///@ todo this is dumb and we should not have to convert types
|
||||
// convert to Vector3 datatypes
|
||||
vectorIn.X = in->x;
|
||||
vectorIn.Y = in->y;
|
||||
vectorIn.Z = in->z;
|
||||
|
||||
// do the transform
|
||||
m_transform.Transform_Vector( m_transform, vectorIn, &vectorOut );
|
||||
|
||||
// store converted vector in 'out'
|
||||
out->x = vectorOut.X;
|
||||
out->y = vectorOut.Y;
|
||||
out->z = vectorOut.Z;
|
||||
|
||||
} // end transformPoint
|
542
Generals/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp
Normal file
542
Generals/Code/GameEngine/Source/Common/Thing/ThingFactory.cpp
Normal file
|
@ -0,0 +1,542 @@
|
|||
/*
|
||||
** 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: ThingFactory.cpp /////////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, April 2001
|
||||
// Desc: This is how we go and make our things, we make our things, we make our things!
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/ThingFactory.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/FileSystem.h"
|
||||
#include "Common/GameAudio.h"
|
||||
#include "Common/MapObject.h"
|
||||
#include "Common/ModuleFactory.h"
|
||||
#include "Common/RandomValue.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/Object.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "GameLogic/PartitionManager.h"
|
||||
#include "GameLogic/Module/CreateModule.h"
|
||||
#include "Common/ProductionPrerequisite.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "Common/INI.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
///#pragma optimize("", off)
|
||||
///#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
enum { TEMPLATE_HASH_SIZE = 12288 };
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
|
||||
ThingFactory *TheThingFactory = NULL; ///< Thing manager singleton declaration
|
||||
|
||||
// STATIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE METHODS
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Free all data loaded into this template database */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ThingFactory::freeDatabase( void )
|
||||
{
|
||||
while (m_firstTemplate)
|
||||
{
|
||||
ThingTemplate* tmpl = m_firstTemplate;
|
||||
m_firstTemplate = m_firstTemplate->friend_getNextTemplate();
|
||||
tmpl->deleteInstance();
|
||||
}
|
||||
|
||||
m_templateHashMap.clear();
|
||||
|
||||
} // end freeDatabase
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** add the thing template passed in, into the databse */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ThingFactory::addTemplate( ThingTemplate *tmplate )
|
||||
{
|
||||
ThingTemplateHashMapIt tIt = m_templateHashMap.find(tmplate->getName());
|
||||
|
||||
if (tIt != m_templateHashMap.end()) {
|
||||
DEBUG_CRASH(("Duplicate Thing Template name found: %s\n", tmplate->getName().str()));
|
||||
}
|
||||
|
||||
// Link it to the list
|
||||
tmplate->friend_setNextTemplate(m_firstTemplate);
|
||||
m_firstTemplate = tmplate;
|
||||
|
||||
// Add it to the hash table.
|
||||
m_templateHashMap[tmplate->getName()] = tmplate;
|
||||
} // end addTemplate
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC METHODS
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ThingFactory::ThingFactory()
|
||||
{
|
||||
m_firstTemplate = NULL;
|
||||
m_nextTemplateID = 1; // not zero!
|
||||
|
||||
m_templateHashMap.resize( TEMPLATE_HASH_SIZE );
|
||||
} // end ThingFactory
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ThingFactory::~ThingFactory()
|
||||
{
|
||||
|
||||
// free all the template data
|
||||
freeDatabase();
|
||||
|
||||
} // end ~ThingFactory
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Create a new template with name 'name' and add to our template list */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ThingTemplate *ThingFactory::newTemplate( const AsciiString& name )
|
||||
{
|
||||
ThingTemplate *newTemplate;
|
||||
|
||||
// allocate template
|
||||
newTemplate = newInstance(ThingTemplate);
|
||||
|
||||
// if the default template is present, get it and copy over any data to the new template
|
||||
const ThingTemplate *defaultT = findTemplate( AsciiString( "DefaultThingTemplate" ) );
|
||||
if( defaultT )
|
||||
{
|
||||
|
||||
// copy over static data
|
||||
*newTemplate = *defaultT;
|
||||
newTemplate->setCopiedFromDefault();
|
||||
|
||||
} // end if
|
||||
|
||||
// give template a unique identifier
|
||||
newTemplate->friend_setTemplateID( m_nextTemplateID++ );
|
||||
DEBUG_ASSERTCRASH( m_nextTemplateID != 0, ("m_nextTemplateID wrapped to zero") );
|
||||
|
||||
// assign name
|
||||
newTemplate->friend_setTemplateName( name );
|
||||
|
||||
// add to list
|
||||
addTemplate( newTemplate );
|
||||
|
||||
// return the newly created template
|
||||
return newTemplate;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Create newTemplate, copy data from final override of 'thingTemplate' to the newly created one,
|
||||
* and add newTemplate as the m_override of that final override. NOTE that newTemplate
|
||||
* is *NOT* added to master template list, it is a hidden place to store
|
||||
* override values for 'thingTemplate' */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ThingTemplate* ThingFactory::newOverride( ThingTemplate *thingTemplate )
|
||||
{
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( thingTemplate, ("newOverride(): NULL 'parent' thing template\n") );
|
||||
|
||||
// sanity just for debuging, the weapon must be in the master list to do overrides
|
||||
DEBUG_ASSERTCRASH( findTemplate( thingTemplate->getName() ) != NULL,
|
||||
("newOverride(): Thing template '%s' not in master list\n",
|
||||
thingTemplate->getName().str()) );
|
||||
|
||||
// find final override of the 'parent' template
|
||||
ThingTemplate *child = (ThingTemplate*) thingTemplate->friend_getFinalOverride();
|
||||
|
||||
// allocate new template
|
||||
ThingTemplate *newTemplate = newInstance(ThingTemplate);
|
||||
|
||||
// copy data from final override to 'newTemplate' as a set of initial default values
|
||||
*newTemplate = *child;
|
||||
newTemplate->setCopiedFromDefault();
|
||||
|
||||
newTemplate->markAsOverride();
|
||||
child->setNextOverride(newTemplate);
|
||||
|
||||
// return the newly created override for us to set values with etc
|
||||
return newTemplate;
|
||||
|
||||
} // end newOverride
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Init */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ThingFactory::init( void )
|
||||
{
|
||||
|
||||
} // end init
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Reset */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ThingFactory::reset( void )
|
||||
{
|
||||
ThingTemplate *t;
|
||||
// go through all templates and delete any overrides
|
||||
for( t = m_firstTemplate; t; /* empty */ )
|
||||
{
|
||||
Bool possibleAdjustment = FALSE;
|
||||
// t itself can be deleted if it is something created for this map only. Therefore,
|
||||
// we need to store what the next item is so that we don't orphan a bunch of templates.
|
||||
ThingTemplate *nextT = t->friend_getNextTemplate();
|
||||
if (t == m_firstTemplate) {
|
||||
possibleAdjustment = TRUE;
|
||||
}
|
||||
|
||||
// if stillValid is NULL after we delete the overrides, then this template was created for
|
||||
// this map only. If it also happens to be m_firstTemplate, then we need to update m_firstTemplate
|
||||
// as well. Finally, if it was only created for this map, we need to remove the name from the
|
||||
// hash map, to prevent any crashes.
|
||||
|
||||
AsciiString templateName = t->getName();
|
||||
|
||||
Overridable *stillValid = t->deleteOverrides();
|
||||
if (stillValid == NULL && possibleAdjustment) {
|
||||
m_firstTemplate = nextT;
|
||||
}
|
||||
|
||||
if (stillValid == NULL) {
|
||||
// Also needs to be removed from the Hash map.
|
||||
m_templateHashMap.erase(templateName);
|
||||
}
|
||||
|
||||
t = nextT;
|
||||
}
|
||||
} // end reset
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Update */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ThingFactory::update( void )
|
||||
{
|
||||
|
||||
} // end update
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Return the template with the matching database name */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const ThingTemplate *ThingFactory::findByTemplateID( UnsignedShort id )
|
||||
{
|
||||
for (ThingTemplate *tmpl = m_firstTemplate; tmpl; tmpl = tmpl->friend_getNextTemplate())
|
||||
{
|
||||
if (tmpl->getTemplateID() == id)
|
||||
return tmpl;
|
||||
}
|
||||
DEBUG_CRASH(("template %d not found\n",(Int)id));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Return the template with the matching database name */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ThingTemplate *ThingFactory::findTemplateInternal( const AsciiString& name )
|
||||
{
|
||||
ThingTemplateHashMapIt tIt = m_templateHashMap.find(name);
|
||||
|
||||
if (tIt != m_templateHashMap.end()) {
|
||||
return tIt->second;
|
||||
}
|
||||
|
||||
#ifdef LOAD_TEST_ASSETS
|
||||
if (!strncmp(name.str(), TEST_STRING, strlen(TEST_STRING)))
|
||||
{
|
||||
ThingTemplate *tmplate = newTemplate( AsciiString( "Un-namedTemplate" ) );
|
||||
|
||||
// load the values
|
||||
tmplate->initForLTA( name );
|
||||
|
||||
// Kinda lame, but necessary.
|
||||
m_templateHashMap.erase("Un-namedTemplate");
|
||||
m_templateHashMap[name] = tmplate;
|
||||
|
||||
// add tmplate template to the database
|
||||
return findTemplateInternal( name );
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//DEBUG_LOG(("*** Object template %s not found\n",name.str()));
|
||||
return NULL;
|
||||
|
||||
} // end getTemplate
|
||||
|
||||
//=============================================================================
|
||||
Object *ThingFactory::newObject( const ThingTemplate *tmplate, Team *team, ObjectStatusBits statusBits )
|
||||
{
|
||||
if (tmplate == NULL)
|
||||
throw ERROR_BAD_ARG;
|
||||
|
||||
const std::vector<AsciiString>& asv = tmplate->getBuildVariations();
|
||||
if (!asv.empty())
|
||||
{
|
||||
Int which = GameLogicRandomValue(0, asv.size()-1);
|
||||
const ThingTemplate* tmp = findTemplate( asv[which] );
|
||||
if (tmp != NULL)
|
||||
tmplate = tmp;
|
||||
}
|
||||
|
||||
DEBUG_ASSERTCRASH(!tmplate->isKindOf(KINDOF_DRAWABLE_ONLY), ("You may not create Objects with the template %s, only Drawables\n",tmplate->getName().str()));
|
||||
|
||||
// have the game logic create an object of the correct type.
|
||||
// (this will throw an exception on failure.)
|
||||
//Added ability to pass in optional statusBits. This is needed to be set prior to
|
||||
//the onCreate() calls... in the case of constructing.
|
||||
Object *obj = TheGameLogic->friend_createObject( tmplate, statusBits, team );
|
||||
|
||||
// run the create function for the thing
|
||||
for (BehaviorModule** m = obj->getBehaviorModules(); *m; ++m)
|
||||
{
|
||||
CreateModuleInterface* create = (*m)->getCreate();
|
||||
if (!create)
|
||||
continue;
|
||||
|
||||
create->onCreate();
|
||||
}
|
||||
|
||||
//
|
||||
// all objects are part of the partition manager system, add it to that
|
||||
// system now
|
||||
//
|
||||
ThePartitionManager->registerObject( obj );
|
||||
|
||||
obj->initObject();
|
||||
|
||||
return obj;
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
Drawable *ThingFactory::newDrawable(const ThingTemplate *tmplate, DrawableStatus statusBits)
|
||||
{
|
||||
if (tmplate == NULL)
|
||||
throw ERROR_BAD_ARG;
|
||||
|
||||
Drawable *draw = TheGameClient->friend_createDrawable( tmplate, statusBits );
|
||||
|
||||
/** @todo we should keep track of all the drawables we've allocated here
|
||||
but we'll wait until we have an drawable storage to do that cause it will
|
||||
all be tied together */
|
||||
|
||||
return draw;
|
||||
|
||||
} // end newDrawableByType
|
||||
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
AsciiString TheThingTemplateBeingParsedName;
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Parse Object entry */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/*static*/ void ThingFactory::parseObjectDefinition( INI* ini, const AsciiString& name, const AsciiString& reskinFrom )
|
||||
{
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
TheThingTemplateBeingParsedName = name;
|
||||
#endif
|
||||
|
||||
// find existing item if present
|
||||
ThingTemplate *thingTemplate = TheThingFactory->findTemplateInternal( name );
|
||||
if( !thingTemplate )
|
||||
{
|
||||
// no item is present, create a new one
|
||||
thingTemplate = TheThingFactory->newTemplate( name );
|
||||
if ( ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES )
|
||||
{
|
||||
// This ThingTemplate is actually an override, so we will mark it as such so that it properly
|
||||
// gets deleted on ::reset().
|
||||
thingTemplate->markAsOverride();
|
||||
}
|
||||
}
|
||||
else if( ini->getLoadType() != INI_LOAD_CREATE_OVERRIDES )
|
||||
{
|
||||
//Holy crap, this sucks to debug!!!
|
||||
//If you have two different objects, the previous code would simply
|
||||
//allow you to define multiple objects with the same name, and just
|
||||
//nuke the old one with the new one. So, I (KM) have added this
|
||||
//assert to notify in case of two same-name objects.
|
||||
DEBUG_CRASH(( "[LINE: %d in '%s'] Duplicate factionunit %s found!", ini->getLineNum(), ini->getFilename().str(), name.str() ));
|
||||
}
|
||||
else
|
||||
{
|
||||
thingTemplate = TheThingFactory->newOverride( thingTemplate );
|
||||
}
|
||||
|
||||
if (reskinFrom.isNotEmpty())
|
||||
{
|
||||
const ThingTemplate* reskinTmpl = TheThingFactory->findTemplate(reskinFrom);
|
||||
if (reskinTmpl)
|
||||
{
|
||||
thingTemplate->copyFrom(reskinTmpl);
|
||||
thingTemplate->setCopiedFromDefault();
|
||||
thingTemplate->setReskinnedFrom(reskinTmpl);
|
||||
ini->initFromINI( thingTemplate, thingTemplate->getReskinFieldParse() );
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("ObjectReskin must come after the original Object (%s, %s).\n",reskinFrom.str(),name.str()));
|
||||
throw INI_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ini->initFromINI( thingTemplate, thingTemplate->getFieldParse() );
|
||||
}
|
||||
|
||||
thingTemplate->validate();
|
||||
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
TheThingTemplateBeingParsedName.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
//#define CHECK_THING_NAMES
|
||||
#ifdef CHECK_THING_NAMES
|
||||
|
||||
#include "Common/STLTypedefs.h"
|
||||
|
||||
const char *outFilenameINI = "thing.txt";
|
||||
const char *outFilenameStringFile = "thingString.txt";
|
||||
|
||||
void resetReportFile( void )
|
||||
{
|
||||
FILE *fp = fopen(outFilenameINI, "w");
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, "-- ThingTemplate INI Report --\n\n");
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
fp = fopen(outFilenameStringFile, "w");
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, "-- ThingTemplate String File Report --\n\n");
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
AsciiStringList missingStrings;
|
||||
void reportMissingNameInStringFile( AsciiString templateName )
|
||||
{
|
||||
// see if we've seen it before
|
||||
AsciiStringListConstIterator cit = std::find(missingStrings.begin(), missingStrings.end(), templateName);
|
||||
if (cit != missingStrings.end())
|
||||
return;
|
||||
|
||||
missingStrings.push_back(templateName);
|
||||
}
|
||||
|
||||
void dumpMissingStringNames( void )
|
||||
{
|
||||
missingStrings.sort();
|
||||
FILE *fp = fopen(outFilenameStringFile, "w");
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, "-- ThingTemplate String File Report --\n\n");
|
||||
for (AsciiStringListConstIterator cit = missingStrings.begin(); cit!=missingStrings.end(); cit++)
|
||||
{
|
||||
fprintf(fp, "OBJECT:%s\n\"%s\"\nEND\n\n", cit->str(), cit->str());
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
AsciiStringList missingNames;
|
||||
void reportMissingNameInTemplate( AsciiString templateName )
|
||||
{
|
||||
// see if we've seen it before
|
||||
AsciiStringListConstIterator cit = std::find(missingNames.begin(), missingNames.end(), templateName);
|
||||
if (cit != missingNames.end())
|
||||
return;
|
||||
|
||||
missingNames.push_back(templateName);
|
||||
|
||||
FILE *fp = fopen(outFilenameINI, "a+");
|
||||
if (fp)
|
||||
{
|
||||
fprintf(fp, " DisplayName = OBJECT:%s\n", templateName.str());
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
//reportMissingNameInStringFile( templateName );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Post process phase after loading the database files */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ThingFactory::postProcessLoad()
|
||||
{
|
||||
#ifdef CHECK_THING_NAMES
|
||||
//resetReportFile();
|
||||
#endif
|
||||
|
||||
// go through all thing templates
|
||||
for( ThingTemplate *thingTemplate = m_firstTemplate;
|
||||
thingTemplate;
|
||||
thingTemplate = thingTemplate->friend_getNextTemplate() )
|
||||
{
|
||||
|
||||
// resolve the prerequisite names
|
||||
thingTemplate->resolveNames();
|
||||
|
||||
#ifdef CHECK_THING_NAMES
|
||||
if (thingTemplate->getDisplayName().isEmpty())
|
||||
{
|
||||
reportMissingNameInTemplate( thingTemplate->getName() );
|
||||
}
|
||||
else if (wcsstr(thingTemplate->getDisplayName().str(), L"MISSING:"))
|
||||
{
|
||||
AsciiString asciiName;
|
||||
asciiName.translate(thingTemplate->getDisplayName());
|
||||
asciiName.removeLastChar();
|
||||
asciiName = asciiName.str() + 17;
|
||||
reportMissingNameInStringFile( asciiName );
|
||||
}
|
||||
#endif
|
||||
|
||||
} // end for
|
||||
|
||||
#ifdef CHECK_THING_NAMES
|
||||
dumpMissingStringNames();
|
||||
exit(0);
|
||||
#endif
|
||||
} // end postProcess
|
1444
Generals/Code/GameEngine/Source/Common/Thing/ThingTemplate.cpp
Normal file
1444
Generals/Code/GameEngine/Source/Common/Thing/ThingTemplate.cpp
Normal file
File diff suppressed because it is too large
Load diff
Reference in a new issue