Initial commit of Command & Conquer Renegade source code.

This commit is contained in:
LFeenanEA
2025-02-27 16:39:46 +00:00
parent 74ab8fa5e0
commit 58ed459113
4918 changed files with 1366710 additions and 0 deletions

View File

@@ -0,0 +1,582 @@
/*
** Command & Conquer Renegade(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/>.
*/
#include "CNCModeSettings.h"
#include "CombatChunkID.h"
#include "PersistFactory.h"
#include "DefinitionFactory.h"
#include "SimpleDefinitionFactory.h"
#include "PlayerType.h"
#include "WWHack.h"
#include "Debug.h"
DECLARE_FORCE_LINK(CNCModeSettings)
CNCModeSettingsDef* CNCModeSettingsDef::_mInstance = NULL;
// Factories
SimplePersistFactoryClass<CNCModeSettingsDef, CHUNKID_GLOBAL_SETTINGS_DEF_CNCMODE> _CNCModeSettingsDefPersistFactory;
DECLARE_DEFINITION_FACTORY(CNCModeSettingsDef, CLASSID_GLOBAL_SETTINGS_DEF_CNCMODE, "C&C Mode Settings") _CNCModeSettingsDefDefFactory;
CNCModeSettingsDef::CNCModeSettingsDef(void) :
AnnouncementInterval(30)
{
//WWASSERT(_mInstance == NULL);
_mInstance = this;
for (int team = 0; team < NUM_TEAMS; ++team)
{
mPowerOfflineID[team] = 0;
mPurchaseCanceledID[team] = 0;
mInsufficientFundsID[team] = 0;
mConstructingID[team] = 0;
mUnitReadyID[team] = 0;
mIonBeaconDeployedID[team] = 0;
mIonBeaconDisarmedID[team] = 0;
mIonBeaconWarningID[team] = 0;
mNukeBeaconDeployedID[team] = 0;
mNukeBeaconDisarmedID[team] = 0;
mNukeBeaconWarningID[team] = 0;
}
memset(mRadioCmds, 0, sizeof(mRadioCmds));
EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_INT, AnnouncementInterval);
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mPowerOfflineID[0], "Nod power offline");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mPowerOfflineID[1], "GDI power offline");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mPurchaseCanceledID[0], "Nod purchase canceled");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mPurchaseCanceledID[1], "GDI purchase canceled");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mInsufficientFundsID[0], "Nod inssufficient funds");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mInsufficientFundsID[1], "GDI inssufficient funds");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mUnitReadyID[0], "Nod unit ready");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mUnitReadyID[1], "GDI unit ready");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mIonBeaconDeployedID[0], "Nod Ion Cannon Deployed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mIonBeaconDeployedID[1], "GDI Ion Cannon Deployed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mIonBeaconDisarmedID[0], "Nod Ion Cannon Disarmed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mIonBeaconDisarmedID[1], "GDI Ion Cannon Disarmed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mIonBeaconWarningID[0], "Nod Ion Cannon Warning");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mIonBeaconWarningID[1], "GDI Ion Cannon Disarmed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mNukeBeaconDeployedID[0], "Nod Nuke Deployed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mNukeBeaconDeployedID[1], "GDI Nuke Deployed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mNukeBeaconDisarmedID[0], "Nod Nuke Disarmed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mNukeBeaconDisarmedID[1], "GDI Nuke Disarmed");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mNukeBeaconWarningID[0], "Nod Nuke Warning");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mNukeBeaconWarningID[1], "GDI Nuke Warning");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[0], "Radio Command 1 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[1], "Radio Command 2 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[2], "Radio Command 3 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[3], "Radio Command 4 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[4], "Radio Command 5 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[5], "Radio Command 6 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[6], "Radio Command 7 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[7], "Radio Command 8 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[8], "Radio Command 9 (CTRL");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[9], "Radio Command 10 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[10], "Radio Command 11 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[11], "Radio Command 12 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[12], "Radio Command 13 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[13], "Radio Command 14 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[14], "Radio Command 15 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[15], "Radio Command 16 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[16], "Radio Command 17 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[17], "Radio Command 18 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[18], "Radio Command 19 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[19], "Radio Command 20 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[20], "Radio Command 21 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[21], "Radio Command 22 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[22], "Radio Command 23 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[23], "Radio Command 24 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[24], "Radio Command 25 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[25], "Radio Command 26 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[26], "Radio Command 27 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[27], "Radio Command 28 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[28], "Radio Command 29 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_STRINGSDB_ID, mRadioCmds[29], "Radio Command 30 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[0], "Radio EmotIcon 1 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[1], "Radio EmotIcon 2 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[2], "Radio EmotIcon 3 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[3], "Radio EmotIcon 4 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[4], "Radio EmotIcon 5 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[5], "Radio EmotIcon 6 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[6], "Radio EmotIcon 7 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[7], "Radio EmotIcon 8 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[8], "Radio EmotIcon 9 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[9], "Radio EmotIcon 10 (CTRL)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[10], "Radio EmotIcon 11 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[11], "Radio EmotIcon 12 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[12], "Radio EmotIcon 13 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[13], "Radio EmotIcon 14 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[14], "Radio EmotIcon 15 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[15], "Radio EmotIcon 16 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[16], "Radio EmotIcon 17 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[17], "Radio EmotIcon 18 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[18], "Radio EmotIcon 19 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[19], "Radio EmotIcon 20 (ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[20], "Radio EmotIcon 21 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[21], "Radio EmotIcon 22 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[22], "Radio EmotIcon 23 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[23], "Radio EmotIcon 24 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[24], "Radio EmotIcon 25 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[25], "Radio EmotIcon 26 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[26], "Radio EmotIcon 27 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[27], "Radio EmotIcon 28 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[28], "Radio EmotIcon 29 (CTRL + ALT)");
NAMED_EDITABLE_PARAM(CNCModeSettingsDef, ParameterClass::TYPE_FILENAME, mRadioCmdIcons[29], "Radio EmotIcon 30 (CTRL + ALT)");
}
CNCModeSettingsDef::~CNCModeSettingsDef(void)
{
_mInstance = NULL;
}
uint32 CNCModeSettingsDef::Get_Class_ID(void) const
{
return CLASSID_GLOBAL_SETTINGS_DEF_CNCMODE;
}
const PersistFactoryClass& CNCModeSettingsDef::Get_Factory(void) const
{
return _CNCModeSettingsDefPersistFactory;
}
PersistClass* CNCModeSettingsDef::Create(void) const
{
WWASSERT (0);
return NULL;
}
// Save/load constants
enum
{
CHUNKID_PARENT = 803001812,
CHUNKID_VARIABLES,
VARID_DEF_ANNOUNCEMENT_INTERVAL = 1,
VARID_DEF_NOD_POWER_OFFLINE_ID,
VARID_DEF_GDI_POWER_OFFLINE_ID,
VARID_DEF_NOD_PURCHASE_CANCELED_ID,
VARID_DEF_GDI_PURCHASE_CANCELED_ID,
VARID_DEF_NOD_INSUFFICIENT_FUNDS_ID,
VARID_DEF_GDI_INSUFFICIENT_FUNDS_ID,
VARID_DEF_NOD_UNIT_READY_ID,
VARID_DEF_GDI_UNIT_READY_ID,
VARID_DEF_RADIO_CMD_01,
VARID_DEF_RADIO_CMD_02,
VARID_DEF_RADIO_CMD_03,
VARID_DEF_RADIO_CMD_04,
VARID_DEF_RADIO_CMD_05,
VARID_DEF_RADIO_CMD_06,
VARID_DEF_RADIO_CMD_07,
VARID_DEF_RADIO_CMD_08,
VARID_DEF_RADIO_CMD_09,
VARID_DEF_RADIO_CMD_10,
VARID_DEF_RADIO_CMD_11,
VARID_DEF_RADIO_CMD_12,
VARID_DEF_RADIO_CMD_13,
VARID_DEF_RADIO_CMD_14,
VARID_DEF_RADIO_CMD_15,
VARID_DEF_RADIO_CMD_16,
VARID_DEF_RADIO_CMD_17,
VARID_DEF_RADIO_CMD_18,
VARID_DEF_RADIO_CMD_19,
VARID_DEF_RADIO_CMD_20,
VARID_DEF_RADIO_CMD_21,
VARID_DEF_RADIO_CMD_22,
VARID_DEF_RADIO_CMD_23,
VARID_DEF_RADIO_CMD_24,
VARID_DEF_RADIO_CMD_25,
VARID_DEF_RADIO_CMD_26,
VARID_DEF_RADIO_CMD_27,
VARID_DEF_RADIO_CMD_28,
VARID_DEF_RADIO_CMD_29,
VARID_DEF_RADIO_CMD_30,
VARID_DEF_NOD_ION_BEACON_DEPLOYED_ID,
VARID_DEF_GDI_ION_BEACON_DEPLOYED_ID,
VARID_DEF_NOD_ION_BEACON_DISARMED_ID,
VARID_DEF_GDI_ION_BEACON_DISARMED_ID,
VARID_DEF_NOD_ION_BEACON_WARNING_ID,
VARID_DEF_GDI_ION_BEACON_WARNING_ID,
VARID_DEF_NOD_NUKE_BEACON_DEPLOYED_ID,
VARID_DEF_GDI_NUKE_BEACON_DEPLOYED_ID,
VARID_DEF_NOD_NUKE_BEACON_DISARMED_ID,
VARID_DEF_GDI_NUKE_BEACON_DISARMED_ID,
VARID_DEF_NOD_NUKE_BEACON_WARNING_ID,
VARID_DEF_GDI_NUKE_BEACON_WARNING_ID,
VARID_DEF_RADIO_ICON_01,
VARID_DEF_RADIO_ICON_02,
VARID_DEF_RADIO_ICON_03,
VARID_DEF_RADIO_ICON_04,
VARID_DEF_RADIO_ICON_05,
VARID_DEF_RADIO_ICON_06,
VARID_DEF_RADIO_ICON_07,
VARID_DEF_RADIO_ICON_08,
VARID_DEF_RADIO_ICON_09,
VARID_DEF_RADIO_ICON_10,
VARID_DEF_RADIO_ICON_11,
VARID_DEF_RADIO_ICON_12,
VARID_DEF_RADIO_ICON_13,
VARID_DEF_RADIO_ICON_14,
VARID_DEF_RADIO_ICON_15,
VARID_DEF_RADIO_ICON_16,
VARID_DEF_RADIO_ICON_17,
VARID_DEF_RADIO_ICON_18,
VARID_DEF_RADIO_ICON_19,
VARID_DEF_RADIO_ICON_20,
VARID_DEF_RADIO_ICON_21,
VARID_DEF_RADIO_ICON_22,
VARID_DEF_RADIO_ICON_23,
VARID_DEF_RADIO_ICON_24,
VARID_DEF_RADIO_ICON_25,
VARID_DEF_RADIO_ICON_26,
VARID_DEF_RADIO_ICON_27,
VARID_DEF_RADIO_ICON_28,
VARID_DEF_RADIO_ICON_29,
VARID_DEF_RADIO_ICON_30,
};
bool CNCModeSettingsDef::Save(ChunkSaveClass& csave)
{
csave.Begin_Chunk(CHUNKID_PARENT);
DefinitionClass::Save(csave);
csave.End_Chunk();
csave.Begin_Chunk(CHUNKID_VARIABLES);
WRITE_MICRO_CHUNK(csave, VARID_DEF_ANNOUNCEMENT_INTERVAL, AnnouncementInterval);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_POWER_OFFLINE_ID, mPowerOfflineID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_POWER_OFFLINE_ID, mPowerOfflineID[1]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_PURCHASE_CANCELED_ID, mPurchaseCanceledID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_PURCHASE_CANCELED_ID, mPurchaseCanceledID[1]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_INSUFFICIENT_FUNDS_ID, mInsufficientFundsID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_INSUFFICIENT_FUNDS_ID, mInsufficientFundsID[1]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_UNIT_READY_ID, mUnitReadyID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_UNIT_READY_ID, mUnitReadyID[1]);
for (int radioIndex = 0; radioIndex < 30; ++radioIndex)
{
WRITE_MICRO_CHUNK(csave, VARID_DEF_RADIO_CMD_01 + radioIndex, mRadioCmds[radioIndex]);
WRITE_MICRO_CHUNK_WWSTRING(csave, VARID_DEF_RADIO_ICON_01 + radioIndex, mRadioCmdIcons[radioIndex]);
}
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_ION_BEACON_DEPLOYED_ID, mIonBeaconDeployedID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_ION_BEACON_DEPLOYED_ID, mIonBeaconDeployedID[1]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_ION_BEACON_DISARMED_ID, mIonBeaconDisarmedID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_ION_BEACON_DISARMED_ID, mIonBeaconDisarmedID[1]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_ION_BEACON_WARNING_ID, mIonBeaconWarningID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_ION_BEACON_WARNING_ID, mIonBeaconWarningID[1]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_NUKE_BEACON_DEPLOYED_ID, mNukeBeaconDeployedID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_NUKE_BEACON_DEPLOYED_ID, mNukeBeaconDeployedID[1]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_NUKE_BEACON_DISARMED_ID, mNukeBeaconDisarmedID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_NUKE_BEACON_DISARMED_ID, mNukeBeaconDisarmedID[1]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_NOD_NUKE_BEACON_WARNING_ID, mNukeBeaconWarningID[0]);
WRITE_MICRO_CHUNK(csave, VARID_DEF_GDI_NUKE_BEACON_WARNING_ID, mNukeBeaconWarningID[1]);
csave.End_Chunk();
return true;
}
bool CNCModeSettingsDef::Load(ChunkLoadClass& cload)
{
while (cload.Open_Chunk())
{
switch (cload.Cur_Chunk_ID())
{
case CHUNKID_PARENT:
DefinitionClass::Load(cload);
break;
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk())
{
switch (cload.Cur_Micro_Chunk_ID())
{
READ_MICRO_CHUNK(cload, VARID_DEF_ANNOUNCEMENT_INTERVAL, AnnouncementInterval);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_POWER_OFFLINE_ID, mPowerOfflineID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_POWER_OFFLINE_ID, mPowerOfflineID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_PURCHASE_CANCELED_ID, mPurchaseCanceledID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_PURCHASE_CANCELED_ID, mPurchaseCanceledID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_INSUFFICIENT_FUNDS_ID, mInsufficientFundsID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_INSUFFICIENT_FUNDS_ID, mInsufficientFundsID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_UNIT_READY_ID, mUnitReadyID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_UNIT_READY_ID, mUnitReadyID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_01, mRadioCmds[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_02, mRadioCmds[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_03, mRadioCmds[2]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_04, mRadioCmds[3]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_05, mRadioCmds[4]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_06, mRadioCmds[5]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_07, mRadioCmds[6]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_08, mRadioCmds[7]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_09, mRadioCmds[8]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_10, mRadioCmds[9]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_11, mRadioCmds[10]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_12, mRadioCmds[11]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_13, mRadioCmds[12]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_14, mRadioCmds[13]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_15, mRadioCmds[14]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_16, mRadioCmds[15]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_17, mRadioCmds[16]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_18, mRadioCmds[17]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_19, mRadioCmds[18]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_20, mRadioCmds[19]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_21, mRadioCmds[20]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_22, mRadioCmds[21]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_23, mRadioCmds[22]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_24, mRadioCmds[23]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_25, mRadioCmds[24]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_26, mRadioCmds[25]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_27, mRadioCmds[26]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_28, mRadioCmds[27]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_29, mRadioCmds[28]);
READ_MICRO_CHUNK(cload, VARID_DEF_RADIO_CMD_30, mRadioCmds[29]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_01, mRadioCmdIcons[0]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_02, mRadioCmdIcons[1]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_03, mRadioCmdIcons[2]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_04, mRadioCmdIcons[3]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_05, mRadioCmdIcons[4]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_06, mRadioCmdIcons[5]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_07, mRadioCmdIcons[6]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_08, mRadioCmdIcons[7]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_09, mRadioCmdIcons[8]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_10, mRadioCmdIcons[9]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_11, mRadioCmdIcons[10]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_12, mRadioCmdIcons[11]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_13, mRadioCmdIcons[12]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_14, mRadioCmdIcons[13]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_15, mRadioCmdIcons[14]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_16, mRadioCmdIcons[15]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_17, mRadioCmdIcons[16]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_18, mRadioCmdIcons[17]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_19, mRadioCmdIcons[18]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_20, mRadioCmdIcons[19]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_21, mRadioCmdIcons[20]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_22, mRadioCmdIcons[21]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_23, mRadioCmdIcons[22]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_24, mRadioCmdIcons[23]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_25, mRadioCmdIcons[24]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_26, mRadioCmdIcons[25]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_27, mRadioCmdIcons[26]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_28, mRadioCmdIcons[27]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_29, mRadioCmdIcons[28]);
READ_MICRO_CHUNK_WWSTRING(cload, VARID_DEF_RADIO_ICON_30, mRadioCmdIcons[29]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_ION_BEACON_DEPLOYED_ID, mIonBeaconDeployedID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_ION_BEACON_DEPLOYED_ID, mIonBeaconDeployedID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_ION_BEACON_DISARMED_ID, mIonBeaconDisarmedID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_ION_BEACON_DISARMED_ID, mIonBeaconDisarmedID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_ION_BEACON_WARNING_ID, mIonBeaconWarningID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_ION_BEACON_WARNING_ID, mIonBeaconWarningID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_NUKE_BEACON_DEPLOYED_ID, mNukeBeaconDeployedID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_NUKE_BEACON_DEPLOYED_ID, mNukeBeaconDeployedID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_NUKE_BEACON_DISARMED_ID, mNukeBeaconDisarmedID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_NUKE_BEACON_DISARMED_ID, mNukeBeaconDisarmedID[1]);
READ_MICRO_CHUNK(cload, VARID_DEF_NOD_NUKE_BEACON_WARNING_ID, mNukeBeaconWarningID[0]);
READ_MICRO_CHUNK(cload, VARID_DEF_GDI_NUKE_BEACON_WARNING_ID, mNukeBeaconWarningID[1]);
default:
Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID (),__FILE__,__LINE__));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
return true;
}
int CNCModeSettingsDef::Get_Power_Offline_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mPowerOfflineID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Purchase_Canceled_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mPurchaseCanceledID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Insufficient_Funds_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mInsufficientFundsID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Constructing_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mConstructingID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Unit_Ready_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mUnitReadyID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Ion_Beacon_Deployed_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mIonBeaconDeployedID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Ion_Beacon_Disarmed_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mIonBeaconDisarmedID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Ion_Beacon_Warning_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mIonBeaconWarningID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Nuke_Beacon_Deployed_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mNukeBeaconDeployedID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Nuke_Beacon_Disarmed_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mNukeBeaconDisarmedID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Nuke_Beacon_Warning_Report(int team) const
{
if (team >= 0 && team < NUM_TEAMS)
{
return mNukeBeaconWarningID[team];
}
return 0;
}
int CNCModeSettingsDef::Get_Radio_Command(int num) const
{
return mRadioCmds[num];
}
const char *CNCModeSettingsDef::Get_Radio_Command_Emot_Icon(int num) const
{
const char *retval = NULL;
if (num >= 0 && num < 30)
{
retval = mRadioCmdIcons[num];
}
return retval;
}

View File

@@ -0,0 +1,110 @@
/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/******************************************************************************
*
* FILE
* $Archive: /Commando/Code/Combat/CNCModeSettings.h $
*
* DESCRIPTION
* Settings for CNC Multiplayer mode.
*
* PROGRAMMER
* Denzil E. Long, Jr.
* $Author: Patrick $
*
* VERSION INFO
* $Revision: 5 $
* $Modtime: 11/28/01 2:22p $
*
******************************************************************************/
#ifndef __CNCMODESETTINGS_H__
#define __CNCMODESETTINGS_H__
#include "Always.h"
#include "Definition.h"
class CNCModeSettingsDef :
public DefinitionClass
{
public:
enum {NUM_TEAMS = 2};
CNCModeSettingsDef(void);
virtual ~CNCModeSettingsDef(void);
virtual uint32 Get_Class_ID(void) const;
virtual PersistClass* Create(void) const;
virtual bool Save(ChunkSaveClass& csave);
virtual bool Load(ChunkLoadClass& cload);
virtual const PersistFactoryClass& Get_Factory(void) const;
static CNCModeSettingsDef* Get_Instance(void)
{return _mInstance;}
int Get_Announcement_Interval(void) const
{return AnnouncementInterval;}
int Get_Power_Offline_Report(int team) const;
int Get_Purchase_Canceled_Report(int team) const;
int Get_Insufficient_Funds_Report(int team) const;
int Get_Constructing_Report(int team) const;
int Get_Unit_Ready_Report(int team) const;
int Get_Ion_Beacon_Deployed_Report(int team) const;
int Get_Ion_Beacon_Disarmed_Report(int team) const;
int Get_Ion_Beacon_Warning_Report(int team) const;
int Get_Nuke_Beacon_Deployed_Report(int team) const;
int Get_Nuke_Beacon_Disarmed_Report(int team) const;
int Get_Nuke_Beacon_Warning_Report(int team) const;
int Get_Radio_Command(int num) const;
const char *Get_Radio_Command_Emot_Icon(int num) const;
// Editable support
DECLARE_EDITABLE(CNCModeSettingsDef, DefinitionClass);
protected:
static CNCModeSettingsDef* _mInstance;
int AnnouncementInterval;
int mPowerOfflineID[NUM_TEAMS];
int mPurchaseCanceledID[NUM_TEAMS];
int mInsufficientFundsID[NUM_TEAMS];
int mConstructingID[NUM_TEAMS];
int mUnitReadyID[NUM_TEAMS];
int mIonBeaconDeployedID[NUM_TEAMS];
int mIonBeaconDisarmedID[NUM_TEAMS];
int mIonBeaconWarningID[NUM_TEAMS];
int mNukeBeaconDeployedID[NUM_TEAMS];
int mNukeBeaconDisarmedID[NUM_TEAMS];
int mNukeBeaconWarningID[NUM_TEAMS];
int mRadioCmds[30];
StringClass mRadioCmdIcons[30];
};
#endif // __CNCMODESETTINGS_H__

1259
Code/Combat/Combat.dsp Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,170 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/SoundEnvironment.cpp $*
* *
* Author:: Ian Leslie *
* *
* $Modtime:: 5/21/01 2:16p $*
* *
* $Revision:: 7 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
// Includes.
#include "soundenvironment.h"
#include "camera.h"
#include "combat.h"
#include "gameobjmanager.h"
#include "phys.h"
#include "physcoltest.h"
#include "pscene.h"
/***********************************************************************************************
* SoundEnvironmentClass::SoundEnvironmentClass -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/16/01 IML : Created. *
*=============================================================================================*/
SoundEnvironmentClass::SoundEnvironmentClass()
: UserCount (0)
{
// Initialize the amplitude mixing buffer.
AmplitudeBuffer = new float [AMPLITUDE_BUFFER_SIZE];
WWASSERT (AmplitudeBuffer != NULL);
Reset();
}
/***********************************************************************************************
* SoundEnvironmentClass::Reset -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/16/01 IML : Created. *
*=============================================================================================*/
void SoundEnvironmentClass::Reset()
{
// Clear the amplitude buffer.
AmplitudeIndex = 0;
AmplitudeSum = 0.0f;
for (unsigned i = 0; i < AMPLITUDE_BUFFER_SIZE; i++) {
AmplitudeBuffer [i] = 0.0f;
}
}
/***********************************************************************************************
* SoundEnvironmentClass::~SoundEnvironmentClass -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/20/01 PDS : Created. *
*=============================================================================================*/
SoundEnvironmentClass::~SoundEnvironmentClass()
{
delete [] AmplitudeBuffer;
}
/***********************************************************************************************
* SoundEnvironmentClass::Update -- *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 04/16/01 IML : Created. *
*=============================================================================================*/
void SoundEnvironmentClass::Update (PhysicsSceneClass *scene, CameraClass *camera)
{
// Optimization: only update if this object is being used.
if (UserCount > 0) {
Vector3 cameraposition;
Vector3 scenemin, scenemax;
float amplitude;
cameraposition = camera->Get_Position();
// Get the highest point in the scene.
scene->Get_Level_Extents (scenemin, scenemax);
// Expand the bounding box by a small amount so that we can distinguish between collisions with geometry and
// collisions with the bounding box.
scenemin.Z -= 1.0f;
scenemax.Z += 1.0f;
// Cast a ray from the camera position upwards.
{
Vector3 raycastendpoint (cameraposition.X, cameraposition.Y, scenemax.Z);
LineSegClass raycast (cameraposition, raycastendpoint);
CastResultStruct rayresult;
PhysRayCollisionTestClass raytest (raycast, &rayresult, TERRAIN_ONLY_COLLISION_GROUP, COLLISION_TYPE_PROJECTILE);
scene->Cast_Ray (raytest);
// Did the ray hit an object?
if (raytest.Result->Fraction < 1.0f) {
// Is the camera in an environment zone (in which case environmental sounds should not be heard)?
if (GameObjManager::Is_In_Environment_Zone (cameraposition)) {
amplitude = 0.0f;
} else {
amplitude = 0.5f;
}
} else {
amplitude = 1.0f;
}
}
AmplitudeSum -= AmplitudeBuffer [AmplitudeIndex];
AmplitudeBuffer [AmplitudeIndex] = amplitude;
AmplitudeSum += amplitude;
AmplitudeIndex++;
if (AmplitudeIndex >= AMPLITUDE_BUFFER_SIZE) AmplitudeIndex = 0;
}
}

View File

@@ -0,0 +1,81 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/SoundEnvironment.h $*
* *
* Author:: Ian Leslie *
* *
* $Modtime:: 4/20/01 7:01p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef SOUNDENVIRONMENT_H
#define SOUNDENVIRONMENT_H
// Includes.
#include "refcount.h"
// Class declarations.
class CameraClass;
class PhysicsSceneClass;
// A simple class that, upon each update, will determine of there is an object vertically
// above the camera (at any height). If so then an amplitude value is attenuated. If, the
// camera is also in an environment zone, then the amplitude is attenuated further. Amplitude
// values are in the range 0..1. This class also uses a small mixing buffer so that amplitude
// changes occur smoothly over time.
class SoundEnvironmentClass : public RefCountClass
{
public:
SoundEnvironmentClass();
~SoundEnvironmentClass();
void Reset();
void Update (PhysicsSceneClass *scene, CameraClass *camera);
float Get_Amplitude() {return (AmplitudeSum / AMPLITUDE_BUFFER_SIZE);}
void Add_User() {UserCount++;} // Call to indicate that you want to start using this object.
void Remove_User() {UserCount--;} // Call to indicate that you no longer need this object.
protected:
enum {
AMPLITUDE_BUFFER_SIZE = 8
};
unsigned UserCount;
unsigned AmplitudeIndex;
float AmplitudeSum;
float *AmplitudeBuffer;
};
#endif // SOUNDENVIRONMENT_H

2378
Code/Combat/WeatherMgr.cpp Normal file

File diff suppressed because it is too large Load Diff

452
Code/Combat/WeatherMgr.h Normal file
View File

@@ -0,0 +1,452 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/WeatherMgr.h $*
* *
* Author:: Ian Leslie *
* *
* $Modtime:: 1/15/02 7:26p $*
* *
* $Revision:: 16 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WEATHERMGR_H
#define WEATHERMGR_H
// Code controlling defines.
#define WEATHER_PARTICLE_SORT 0
// Includes.
#include "combatchunkid.h"
#include "pointgr.h"
#include "mempool.h"
#include "networkobject.h"
#include "random.h"
#include "rendobj.h"
#include "saveloadsubsystem.h"
#include "soundenvironment.h"
#include "texture.h"
#include "vector.h"
#include "vector2.h"
#include "vector3.h"
#include "wwdebug.h"
// Class declarations.
class ChunkLoadClass;
class ChunkSaveClass;
class PhysicsSceneClass;
#if WEATHER_PARTICLE_SORT
class SortingIndexBufferClass;
#else
class DX8IndexBufferClass;
#endif
class AudibleSoundClass;
class WindClass
{
public:
WindClass (float heading, float speed, float variability, SoundEnvironmentClass *soundenvironment);
~WindClass();
Vector2 Get_Velocity() {return (Velocity);}
void Set (float heading, float speed, float variability);
bool Update();
protected:
enum {
OCTAVE_COUNT = 2
};
SoundEnvironmentClass *SoundEnvironment;
float Heading;
float Speed;
float Variability;
double Theta [OCTAVE_COUNT];
Vector2 Velocity;
AudibleSoundClass *Sound;
};
class WeatherSystemClass : public RenderObjClass
{
public:
enum {
GROWTH_STEP = 256
};
enum RenderModeEnum {
RENDER_MODE_AXIS_ALIGNED, // Render particle oriented about the particle's velocity vector (suitable for rain, for example).
RENDER_MODE_CAMERA_ALIGNED, // Render particle aligned with the camera direction (suitable for snow, for example).
RENDER_MODE_SURFACE_ALIGNED // Render particle such that it looks attached to the surface of an object.
};
WeatherSystemClass (PhysicsSceneClass *scene,
float emittersize,
float emitterheight,
float particledensity,
float particlesperunitlength,
float particlewidth,
float particleheight,
float particlespeed,
const Vector2 &pageoffset,
const Vector2 &pagesize,
unsigned pagecount,
bool staticpageexists,
float minstatictime,
float maxstatictime,
RenderModeEnum rendermode,
bool decayaftercollision,
bool prime);
~WeatherSystemClass();
RenderObjClass *Clone() const
{
WWASSERT (false);
return (0);
}
void Set_Density (float density);
void Render (RenderInfoClass &rinfo);
void Get_Obj_Space_Bounding_Sphere (SphereClass &sphere) const;
void Get_Obj_Space_Bounding_Box (AABoxClass &box) const;
virtual bool Update (WindClass *wind, const Vector3 &cameraposition);
protected:
enum {
VERTICES_PER_TRIANGLE = 3,
MAX_IB_PARTICLE_COUNT = 2048,
MAX_AGE = 1000000
};
struct RayStruct : public AutoPoolClass <RayStruct, GROWTH_STEP>
{
public:
RayStruct *Next; // Next ray in list.
bool Initialized; // Has the ray been defined?
bool RayCast; // Does this ray need to be relocated in the emitter (and therefore needs to be raycast).
Vector3 ParticleVelocity; // Velocity of all particles spawned by this ray.
Vector2 StartPosition; // Start position of ray inside emitter.
Vector3 EndPosition; // Point of collision of ray with environment.
bool ValidSurfaceNormal; // Does the ray intersect a phyical object?
Vector3 SurfaceNormal; // Normal of surface ray intersects (if any).
};
struct ParticleStruct : public AutoPoolClass <ParticleStruct, GROWTH_STEP>
{
public:
ParticleStruct *Prev; // Previous particle in list.
ParticleStruct *Next; // Next particle in list.
float CollisionTime; // Time when particle hits something (in seconds).
float LifeTime; // Lifetime of particle (in seconds).
float ElapsedTime; // Time elapsed since birth of particle (in seconds).
Vector3 Velocity; // Velocity of particle (in metres per second).
Vector2 UnitZVelocity; // Velocity / Velocity.Z (precomputed for optimization purposes).
Vector3 CollisionPosition; // Position of collision.
Vector3 CurrentPosition; // Current position of particle (in world space).
Vector3 SurfaceNormal; // Normal of surface particle collides with (if any).
unsigned char Page; // Texture page for this particle.
unsigned char RenderMode;
unsigned char Pad [2]; // Pad structure to 4-byte multiple.
};
// Utility functions.
float Spawn_Count (float time) {return (ParticleDensity * EmitterSize * EmitterSize * time);}
bool Can_Spawn (const RayStruct *rayptr) {return (rayptr->EndPosition.Z < EmitterPosition.Z);}
bool Spawn (RayStruct *suppliedrayptr = NULL);
void Kill (ParticleStruct *particleptr);
PhysicsSceneClass *Scene; // The scene that contains the weather system.
float Age; // Age of this weather system (in seconds).
float EmitterSize; // Size of square emitter (area of emitter = size * size).
float EmitterHeight; // Height of emitter (relative to camera).
Vector3 EmitterPosition; // Centroid of emitter (in world space).
float ParticleDensity; // Density of particles (over area of emitter).
float ParticlesPerUnitLength;
float ParticleSpeed;
Vector3 ParticleVelocity; // Dominant velocity vector of particles.
float HalfParticleWidth;
float HalfParticleHeight;
RayStruct *RayHead;
unsigned RayCount;
RayStruct *RaySpawnPtr;
RayStruct *RayUpdatePtr;
float MinRayEndZ; // Current lowest Z-value of end of any ray (used to determine a bounding box around this render object).
float SpawnCountFraction; // Cumulative fractional spawn counts (for improved accuracy).
Vector3 SceneMin, SceneMax; // Bounding box around the scene that the particle system lives in.
Vector3 ObjectMin, ObjectMax; // Bounding box around this render object (for culling purposes).
ParticleStruct *ParticleHead; // Head of list of particles in system.
unsigned ParticleCount; // No. of particles in system.
#if WEATHER_PARTICLE_SORT
SortingIndexBufferClass *IndexBuffer;
#else
DX8IndexBufferClass *IndexBuffer;
#endif
VertexMaterialClass *Material;
ShaderClass Shader;
TextureClass *Texture;
Vector2 *TextureArray;
RenderModeEnum RenderMode;
bool DecayAfterCollision;
unsigned PageCount;
bool StaticPageExists;
float MinStaticTime;
float MaxStaticTime;
Vector3 CameraPosition;
bool CameraPositionValid;
static Random2Class _RandomNumber; // Random no. generator.
static unsigned _GlobalParticleCount; // Total no. of particles over all weather systems.
};
class RainSystemClass : public WeatherSystemClass
{
public:
RainSystemClass (PhysicsSceneClass *scene, float particledensity, WindClass *wind, SoundEnvironmentClass *soundenvironment, bool prime);
virtual ~RainSystemClass();
bool Update (WindClass *wind, const Vector3 &cameraposition);
protected:
enum {
PAGE_COUNT = 4
};
AudibleSoundClass *Sound; // Sound effect for rainfall.
SoundEnvironmentClass *SoundEnvironment;
};
class SnowSystemClass : public WeatherSystemClass
{
public:
SnowSystemClass (PhysicsSceneClass *scene, float particledensity, WindClass *wind, bool prime);
bool Update (WindClass *wind, const Vector3 &cameraposition);
protected:
enum {
PAGE_COUNT = 4
};
};
class AshSystemClass : public WeatherSystemClass
{
public:
AshSystemClass (PhysicsSceneClass *scene, float particledensity, WindClass *wind, bool prime);
bool Update (WindClass *wind, const Vector3 &cameraposition);
protected:
enum {
PAGE_COUNT = 4
};
};
class WeatherParameterClass
{
public:
void Initialize();
void Set (float targetvalue, float ramptime, bool override);
void Set (float overrideramptime) {OverrideDuration = overrideramptime;}
float Value() {return (CurrentValue);}
bool Update (float time, bool override);
void Update (float &value, float &target, float &duration, float time);
private:
float CurrentValue;
float NormalValue;
float NormalTarget;
float NormalDuration;
float OverrideTarget;
float OverrideDuration;
friend class WeatherMgrClass;
};
class WeatherMgrClass : public SaveLoadSubSystemClass, public NetworkObjectClass
{
public:
enum PrecipitationEnum {
PRECIPITATION_FIRST,
PRECIPITATION_RAIN = PRECIPITATION_FIRST,
PRECIPITATION_SNOW,
PRECIPITATION_ASH,
PRECIPITATION_COUNT
};
WeatherMgrClass();
~WeatherMgrClass() {}
uint32 Chunk_ID() const {return (CHUNKID_WEATHER_MGR);}
const char *Name() const {return ("WeatherMgrClass");}
void Delete (void) {}
virtual void Set_Delete_Pending (void) {};
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
bool Load_Micro_Chunks (ChunkLoadClass &cload);
void Export_Rare (BitStreamClass &packet);
void Import_Rare (BitStreamClass &packet);
static void Init (SoundEnvironmentClass *soundenvironment);
static void Reset();
static void Shutdown();
static bool Save_Dynamic (ChunkSaveClass &csave);
static bool Load_Dynamic (ChunkLoadClass &cload);
static bool Load_Dynamic_Micro_Chunks (ChunkLoadClass &cload);
static bool Set_Wind (float heading, float speed, float variability, float ramptime = 0.0f);
static bool Override_Wind (float heading, float speed, float variability, float ramptime = 0.0f);
static void Get_Wind (float &heading, float &speed, float &variability);
static void Restore_Wind (float ramptime);
static bool Set_Precipitation (PrecipitationEnum precipitation, float density, float ramptime = 0.0f);
static bool Override_Precipitation (PrecipitationEnum precipitation, float density, float ramptime = 0.0f);
static void Get_Precipitation (PrecipitationEnum precipitation, float &density);
static void Restore_Precipitation (float ramptime);
static void Set_Fog_Enable (bool enabled)
{
_FogEnabled = enabled;
Set_Dirty();
}
static bool Get_Fog_Enable()
{
return (_FogEnabled);
}
static bool Set_Fog_Range (float startdistance, float enddistance, float ramptime = 0.0f);
static void Get_Fog_Range (float &startdistance, float &enddistance);
static void Update (PhysicsSceneClass *scene, CameraClass *camera);
static void Render (const CameraClass *camera);
private:
#define VARID_PARAMETER(varname) \
VARID_ ## varname ## _CURRENT_VALUE, \
VARID_ ## varname ## _NORMAL_VALUE, \
VARID_ ## varname ## _NORMAL_TARGET, \
VARID_ ## varname ## _NORMAL_DURATION, \
VARID_ ## varname ## _OVERRIDE_TARGET, \
VARID_ ## varname ## _OVERRIDE_DURATION
// Constants.
enum {
CHUNKID_MICRO_CHUNKS = 0x03020113,
CHUNKID_DYNAMIC_MICRO_CHUNKS = 0x11020245
};
enum {
VARID_DUMMY = 0x09,
VARID_PARAMETER (WIND_HEADING),
VARID_PARAMETER (WIND_SPEED),
VARID_PARAMETER (WIND_VARIABILITY),
VARID_PARAMETER (RAIN_DENSITY),
VARID_PARAMETER (SNOW_DENSITY),
VARID_PARAMETER (ASH_DENSITY),
VARID_WIND_OVERRIDE_COUNT,
VARID_PRECIPITATION_OVERRIDE_COUNT,
VARID_FOG_ENABLED,
VARID_PARAMETER (FOG_START_DISTANCE),
VARID_PARAMETER (FOG_END_DISTANCE)
};
#undef VARID_PARAMETER
enum {
PARAMETER_WIND_HEADING,
PARAMETER_WIND_SPEED,
PARAMETER_WIND_VARIABILITY,
PARAMETER_RAIN_DENSITY,
PARAMETER_SNOW_DENSITY,
PARAMETER_ASH_DENSITY,
PARAMETER_FOG_START_DISTANCE,
PARAMETER_FOG_END_DISTANCE,
PARAMETER_COUNT
};
static bool Set_Wind (float heading, float speed, float variability, float ramptime, bool override);
static bool Set_Precipitation (PrecipitationEnum precipitation, float density, float ramptime, bool override);
static bool Is_Dirty() {return (_Dirty);}
static void Set_Dirty (bool dirty = true) {_Dirty = dirty;}
static SoundEnvironmentClass *_SoundEnvironment;
static WeatherParameterClass _Parameters [PARAMETER_COUNT];
static bool _Prime;
static bool _Imported;
static unsigned _WindOverrideCount;
static unsigned _PrecipitationOverrideCount;
static WindClass *_Wind;
static WeatherSystemClass *_Precipitation [PRECIPITATION_COUNT];
static bool _FogEnabled;
static bool _Dirty;
};
// Externals.
extern WeatherMgrClass _TheWeatherMgr;
#endif // WEATHERMGR_H

3389
Code/Combat/action.cpp Normal file

File diff suppressed because it is too large Load Diff

147
Code/Combat/action.h Normal file
View File

@@ -0,0 +1,147 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/action.h $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 10/09/01 2:15p $*
* *
* $Revision:: 47 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef ACTION_H
#define ACTION_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef VECTOR3_H
#include "vector3.h"
#endif
#ifndef GAMEOBJREF_H
#include "gameobjref.h"
#endif
#ifndef WWSTRING_H
#include "wwstring.h"
#endif
#ifndef ACTIONPARAMS_H
#include "actionparams.h"
#endif
/*
**
*/
class ActionCodeClass;
class SmartGameObj;
/*
**
*/
class SafeActionParamsStruct : public ActionParamsStruct {
public:
SafeActionParamsStruct & operator = (const ActionParamsStruct & src); // Assignment operator.
bool Save( ChunkSaveClass & csave );
bool Load( ChunkLoadClass & cload );
GameObjReference MoveObjectRef;
GameObjReference AttackObjectRef;
GameObjReference LookObjectRef;
StringClass SafeAnimationName;
StringClass SafeConversationName;
};
/*
**
*/
class ActionClass {
public:
ActionClass( SmartGameObj *obj );
virtual ~ActionClass( void );
bool Save( ChunkSaveClass & csave );
bool Load( ChunkLoadClass & cload );
SmartGameObj * Get_Action_Obj( void ) { return ActionObj; }
SafeActionParamsStruct & Get_Parameters( void ) { return Parameters; }
bool Is_Acting( void );
bool Is_Animating( void );
void Begin_Hibernation( void );
void End_Hibernation( void );
bool Reset( float priority );
bool Follow_Input( const ActionParamsStruct & parameters );
bool Stand( const ActionParamsStruct & parameters );
bool Play_Animation( const ActionParamsStruct & parameters );
bool Goto( const ActionParamsStruct & parameters );
bool Enter_Exit( const ActionParamsStruct & parameters );
bool Dive( const ActionParamsStruct & parameters );
bool Attack( const ActionParamsStruct & parameters );
bool Face_Location( const ActionParamsStruct & parameters );
bool Have_Conversation( const ActionParamsStruct & parameters );
bool Dock_Vehicle( const ActionParamsStruct & parameters );
bool Modify( const ActionParamsStruct & parameters, bool modify_move, bool modify_attack );
void Act( void );
unsigned int Get_Act_Count( void ) { return ActCount; }
bool Is_Active( void );
bool Is_Busy( void );
bool Is_Paused( void ) const { return IsPaused; }
void Pause( bool onoff) { IsPaused = onoff; }
void Done( int reason ); // Notify the obserever
protected:
void Notify_Completed( int observer_id, int action_id, int reason ); // Notify the obserever
bool Request_Action( ActionCodeClass * action, const ActionParamsStruct & parameters );
SmartGameObj * ActionObj;
ActionCodeClass * ActionCode;
SafeActionParamsStruct Parameters;
bool IsPaused;
unsigned int ActCount; // TSS - diagnostic
void Set_Action_Code( ActionCodeClass * code );
};
// Debugging
void Toggle_Display_Findpaths( void );
#endif // ACTION_H

228
Code/Combat/actionparams.h Normal file
View File

@@ -0,0 +1,228 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/actionparams.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 3/19/02 11:31a $*
* *
* $Revision:: 30 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef ACTIONPARAMS_H
#define ACTIONPARAMS_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef VECTOR3_H
#include "vector3.h"
#endif
#ifndef GAMEOBJOBSERVER_H
#include "gameobjobserver.h"
#endif
/*
**
*/
class ScriptableGameObj;
typedef ScriptableGameObj GameObject;
/*
**
*/
typedef enum {
NO_AI_STATE_CHANGE = -1,
AI_STATE_IDLE = 0,
AI_STATE_SECONDARY_IDLE,
AI_STATE_SEARCH,
AI_STATE_COMBAT
} SoldierAIState;
/*
**
*/
const float DONT_MOVE_ARRIVED_DIST = 1000.0F;
/*
**
*/
class ActionParamsStruct {
public:
ActionParamsStruct( void );
void Set_Basic( GameObjObserverClass * script, float priority, int action_id, SoldierAIState ai_state = NO_AI_STATE_CHANGE ) { ObserverID = script->Get_ID(); Priority = priority; ActionID = action_id; AIState = ai_state; }
void Set_Basic( long observer_id, float priority, int action_id, SoldierAIState ai_state = NO_AI_STATE_CHANGE ) { ObserverID = observer_id; Priority = priority; ActionID = action_id; AIState = ai_state; }
void Set_Look( const Vector3 & location, float duration ) { LookLocation = location; LookDuration = duration; }
void Set_Look( GameObject * object, float duration ) { LookObject = object; LookDuration = duration; }
void Set_Look( const Vector3 & obj_pos, float angle, float duration );
void Set_Movement( const Vector3 & location, float speed, float arrived_distance, bool crouched = false ) { MoveLocation = location; MoveSpeed = speed; MoveArrivedDistance = arrived_distance; MoveCrouched = crouched; }
void Set_Movement( GameObject * object, float speed, float arrived_distance, bool crouched = false ) { MoveObject = object; MoveSpeed = speed; MoveArrivedDistance = arrived_distance; MoveCrouched = crouched; }
void Set_Attack( const Vector3 & location, float range, float error, bool primary_fire ) { AttackLocation = location; AttackRange = range; AttackError = error; AttackPrimaryFire = primary_fire; }
void Set_Attack( GameObject * object, float range, float error, bool primary_fire ) { AttackObject = object; AttackRange = range; AttackError = error; AttackPrimaryFire = primary_fire; }
void Set_Animation( const char * name, bool looping ) { AnimationName = name; AnimationLooping = looping; }
void Set_Face_Location( const Vector3 &location, float duration ) { FaceLocation = location; FaceDuration = duration; }
void Set_Face_Location( const Vector3 & obj_pos, float angle, float duration );
void Join_Conversation( int active_conversation_id ) { ActiveConversationID = active_conversation_id; }
void Start_Conversation( const char * name ) { ConversationName = name; }
void Dock_Vehicle( const Vector3 &dock_location, const Vector3 &dock_entrance ) { DockLocation = dock_location; DockEntrance = dock_entrance; }
//protected:
// Note: all of these must be saved in SafeActionParamsStruct::Save
int Priority;
int ActionID;
long ObserverID;
Vector3 LookLocation;
GameObject * LookObject;
float LookDuration;
Vector3 MoveLocation;
GameObject * MoveObject;
Vector3 MoveObjectOffset;
float MoveSpeed;
float MoveArrivedDistance;
bool MoveBackup;
bool MoveFollow;
bool MoveCrouched;
bool MovePathfind;
bool ShutdownEngineOnArrival;
float AttackRange;
float AttackError;
bool AttackErrorOverride;
GameObject * AttackObject;
bool AttackPrimaryFire;
bool AttackCrouched;
Vector3 AttackLocation;
bool AttackCheckBlocked;
bool AttackActive;
bool AttackWanderAllowed;
bool AttackFaceTarget; // (gth) control over whether VTOL vehicles face their target when attacking
bool AttackForceFire;
bool ForceFacing;
Vector3 FaceLocation;
float FaceDuration;
bool IgnoreFacing;
int WaypathID;
int WaypointStartID;
int WaypointEndID;
bool WaypathSplined;
const char * AnimationName;
bool AnimationLooping;
int ActiveConversationID;
const char * ConversationName;
SoldierAIState AIState;
Vector3 DockLocation;
Vector3 DockEntrance;
};
inline ActionParamsStruct::ActionParamsStruct( void ) :
Priority( 0 ),
ActionID( 0 ),
ObserverID( 0 ),
LookLocation( 0,0,0 ),
LookObject( NULL ),
LookDuration( 0 ),
MoveLocation( 0,0,0 ),
MoveObject( NULL ),
MoveObjectOffset( 0,0,0 ),
MoveSpeed( 1 ),
MoveArrivedDistance( DONT_MOVE_ARRIVED_DIST ),
MoveBackup( false ),
MoveFollow( false ),
MoveCrouched( false ),
MovePathfind( true ),
ShutdownEngineOnArrival( false ),
AttackRange( 20 ),
AttackError( 0 ),
AttackErrorOverride( false ),
AttackObject( NULL ),
AttackPrimaryFire( true ),
AttackCrouched( false ),
AttackLocation( 0,0,0 ),
AttackCheckBlocked( true ),
AttackActive( true ),
AttackWanderAllowed( false ),
AttackFaceTarget( true ),
AttackForceFire( false ),
ForceFacing( false ),
IgnoreFacing( false ),
FaceLocation( 0, 0, 0 ),
FaceDuration( 2.0F ),
WaypathID( 0 ),
WaypointStartID( 0 ),
WaypointEndID( 0 ),
WaypathSplined( false ),
AnimationName( NULL ),
AnimationLooping( false ),
ActiveConversationID( 0 ),
ConversationName( NULL ),
AIState( NO_AI_STATE_CHANGE ),
DockLocation( 0,0,0 ),
DockEntrance( 0,0,0 )
{
}
void inline ActionParamsStruct::Set_Face_Location( const Vector3 &obj_pos, float angle, float duration )
{
FaceLocation = obj_pos;
FaceLocation.X += ::cos( angle );
FaceLocation.Y += ::sin( angle );
FaceDuration = duration;
return ;
}
void inline ActionParamsStruct::Set_Look( const Vector3 &obj_pos, float angle, float duration )
{
LookLocation = obj_pos;
LookLocation.X += ::cos( angle );
LookLocation.Y += ::sin( angle );
LookDuration = duration;
return ;
}
#endif // ACTIONPARAMS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,210 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/activeconversation.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 12/05/01 1:46p $*
* *
* $Revision:: 14 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __ACTIVE_CONVERSATION_H
#define __ACTIVE_CONVERSATION_H
#include "refcount.h"
#include "conversation.h"
#include "vector.h"
#include "vector3.h"
#include "gameobjref.h"
////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////
class ChunkSaveClass;
class ChunkLoadClass;
class PhysicalGameObj;
class OratorClass;
////////////////////////////////////////////////////////////////
//
// ActiveConversationClass
//
////////////////////////////////////////////////////////////////
class ActiveConversationClass : public RefCountClass
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
ActiveConversationClass (void);
virtual ~ActiveConversationClass (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
//
// Save/load methods
//
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
//
// Identification
//
int Get_ID (void) const { return ID; }
void Set_ID (int id) { ID = id; }
//
// Conversation methods
//
ConversationClass * Peek_Conversation (void) const;
void Set_Conversation (ConversationClass *conversation);
//
// Conversation flow control
//
void Start_Conversation (void);
void Stop_Conversation (ActionCompleteReason reason = ACTION_COMPLETE_CONVERSATION_ENDED);
void Think (void);
bool Is_Finished (void) { return bool(State == STATE_FINISHED); }
//
// State evaluation methods
//
bool Get_Orator_Location (PhysicalGameObj *orator, Vector3 *position);
bool Get_Current_Orator_Location (Vector3 *position);
PhysicalGameObj * Get_Current_Orator (void);
void Get_Conversation_Center (Vector3 *position);
void Set_Orator_Arrived (PhysicalGameObj *orator, bool has_arrived);
void Control_Orator (SoldierGameObj *orator);
//
// Orator methods
//
OratorClass * Add_Orator (PhysicalGameObj *orator);
OratorClass * Get_Orator_Information (PhysicalGameObj *orator);
//
// Monitor support
//
void Register_Monitor (ScriptableGameObj *game_obj);
void Unregister_Monitor (ScriptableGameObj *game_obj);
void Set_Action_ID (int id) { ActionID = id; }
//
// Misc accessors
//
int Get_Priority (void) const { return Priority; }
void Set_Priority (int priority) { Priority = priority; }
float Get_Max_Dist (void) const { return MaxDist; }
void Set_Max_Dist (float max_dist) { MaxDist = max_dist; }
bool Is_Interruptable (void) const { return IsInterruptable; }
void Set_Is_Interruptable (bool onoff) { IsInterruptable = onoff; }
//
// Time estimation
//
float Get_Conversation_Time (void);
protected:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
void Free_Orator_List (void);
bool Is_Audience_In_Place (void);
void Check_For_Audience (void);
void Say_Next_Remark (void);
void Stop_Current_Sound (void);
void Notify_Monitors_On_End (ActionCompleteReason id);
void Notify_Monitors (int custom_event_id, int param);
////////////////////////////////////////////////////////////////
// Protected data types
////////////////////////////////////////////////////////////////
enum
{
STATE_INITIALIZING = 0,
STATE_WAITING_FOR_AUDIENCE,
STATE_TALKING,
STATE_FINISHED,
STATE_INTERRUPTED = STATE_FINISHED
};
enum
{
MAX_MONITORS = 10,
};
////////////////////////////////////////////////////////////////
// Protected member data
////////////////////////////////////////////////////////////////
int ID;
ConversationClass * Conversation;
int CurrentRemark;
float NextRemarkTimer;
DynamicVectorClass<OratorClass *> OratorList;
int ActionID;
int OratorSpokenBitmask;
Vector3 CentralPos;
GameObjReference MonitorArray[MAX_MONITORS];
AudibleSoundClass * CurrentSound;
int State;
float InitializingTimeLeft;
int Priority;
float MaxDist;
bool IsInterruptable;
};
////////////////////////////////////////////////////////////////
// Peek_Conversation
////////////////////////////////////////////////////////////////
inline ConversationClass *
ActiveConversationClass::Peek_Conversation (void) const
{
return Conversation;
}
#endif //__ACTIVE_CONVERSATION_H

View File

@@ -0,0 +1,572 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/airstripgameobj.cpp $Author:: Patrick $*
* *
* $Modtime:: 2/24/02 2:06p $*
* *
* $Revision:: 19 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "airstripgameobj.h"
#include "basecontroller.h"
#include "vehicle.h"
#include "wwhack.h"
#include "simpledefinitionfactory.h"
#include "persistfactory.h"
#include "definitionmgr.h"
#include "combatchunkid.h"
#include "debug.h"
#include "scriptzone.h"
#include "wwprofile.h"
#include "basecontroller.h"
#include "combatchunkid.h"
#include "objlibrary.h"
#include "cinematicgameobj.h"
#include "combat.h"
////////////////////////////////////////////////////////////////
// Hacks
////////////////////////////////////////////////////////////////
DECLARE_FORCE_LINK (AirStrip)
////////////////////////////////////////////////////////////////
// Editable and persist factories
////////////////////////////////////////////////////////////////
SimplePersistFactoryClass <AirStripGameObjDef, CHUNKID_GAME_OBJECT_DEF_AIRSTRIP> _AirStripGameObjDefPersistFactory;
SimplePersistFactoryClass <AirStripGameObj, CHUNKID_GAME_OBJECT_AIRSTRIP> _AirStripGameObjPersistFactory;
DECLARE_DEFINITION_FACTORY (AirStripGameObjDef, CLASSID_GAME_OBJECT_DEF_AIRSTRIP, "Airstrip") _AirStripGameObjDefDefFactory;
////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////
static const float UNITIALIZED_TIMER = -100.0F;
static const float VEHICLE_LOCK_TIME = 30.0f;
////////////////////////////////////////////////////////////////
// Save/Load constants
////////////////////////////////////////////////////////////////
enum
{
CHUNKID_DEF_PARENT = 0x02200638,
CHUNKID_DEF_VARIABLES,
MICROCHUNKID_DEF_CINEMATIC_DEFID = 1,
MICROCHUNKID_DEF_CINEMATIC_LENGTH_TO_DROPOFF,
MICROCHUNKID_DEF_CINEMATIC_SLOT_INDEX,
MICROCHUNKID_DEF_DISPLAY_VEHICLE_TIME
};
enum
{
CHUNKID_PARENT = 0x0219043,
CHUNKID_VARIABLES,
MICROCHUNKID_UNUSED = 1,
};
////////////////////////////////////////////////////////////////
//
// AirStripGameObjDef
//
////////////////////////////////////////////////////////////////
AirStripGameObjDef::AirStripGameObjDef (void) :
CinematicLengthToDropOff (0),
CinematicLengthToVehicleDisplay (0),
CinematicDefID (0),
CinematicSlotIndex (0)
{
//
// Editable support
//
EDITABLE_PARAM (AirStripGameObjDef, ParameterClass::TYPE_FLOAT, CinematicLengthToDropOff);
EDITABLE_PARAM (AirStripGameObjDef, ParameterClass::TYPE_INT, CinematicSlotIndex);
EDITABLE_PARAM (AirStripGameObjDef, ParameterClass::TYPE_FLOAT, CinematicLengthToVehicleDisplay);
#ifdef PARAM_EDITING_ON
GenericDefParameterClass *param = new GenericDefParameterClass (&CinematicDefID);
param->Set_Class_ID (CLASSID_GAME_OBJECT_DEF_SIMPLE);
param->Set_Name ("Drop-Off Cinematic");
GENERIC_EDITABLE_PARAM (AirStripGameObjDef, param)
#endif //PARAM_EDITING_ON
return ;
}
////////////////////////////////////////////////////////////////
//
// ~AirStripGameObjDef
//
////////////////////////////////////////////////////////////////
AirStripGameObjDef::~AirStripGameObjDef (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Class_ID
//
////////////////////////////////////////////////////////////////
uint32
AirStripGameObjDef::Get_Class_ID (void) const
{
return CLASSID_GAME_OBJECT_DEF_AIRSTRIP;
}
////////////////////////////////////////////////////////////////
//
// Create
//
////////////////////////////////////////////////////////////////
PersistClass *
AirStripGameObjDef::Create (void) const
{
AirStripGameObj *building = new AirStripGameObj;
building->Init (*this);
return building;
}
////////////////////////////////////////////////////////////////
//
// Create
//
////////////////////////////////////////////////////////////////
bool
AirStripGameObjDef::Save (ChunkSaveClass &csave)
{
csave.Begin_Chunk (CHUNKID_DEF_PARENT);
VehicleFactoryGameObjDef::Save (csave);
csave.End_Chunk ();
csave.Begin_Chunk (CHUNKID_DEF_VARIABLES);
WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_CINEMATIC_LENGTH_TO_DROPOFF, CinematicLengthToDropOff);
WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_CINEMATIC_DEFID, CinematicDefID);
WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_CINEMATIC_SLOT_INDEX, CinematicSlotIndex);
WRITE_MICRO_CHUNK (csave, MICROCHUNKID_DEF_DISPLAY_VEHICLE_TIME, CinematicLengthToVehicleDisplay);
csave.End_Chunk ();
return true;
}
////////////////////////////////////////////////////////////////
//
// Load
//
////////////////////////////////////////////////////////////////
bool
AirStripGameObjDef::Load (ChunkLoadClass &cload)
{
while (cload.Open_Chunk ())
{
switch (cload.Cur_Chunk_ID ())
{
case CHUNKID_DEF_PARENT:
VehicleFactoryGameObjDef::Load (cload);
break;
case CHUNKID_DEF_VARIABLES:
Load_Variables (cload);
break;
default:
Debug_Say (("Unrecognized AirStrip Def chunkID\n"));
break;
}
cload.Close_Chunk ();
}
return true;
}
////////////////////////////////////////////////////////////////
//
// Load_Variables
//
////////////////////////////////////////////////////////////////
void
AirStripGameObjDef::Load_Variables (ChunkLoadClass &cload)
{
while (cload.Open_Micro_Chunk ()) {
switch (cload.Cur_Micro_Chunk_ID ())
{
READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_CINEMATIC_LENGTH_TO_DROPOFF, CinematicLengthToDropOff);
READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_CINEMATIC_DEFID, CinematicDefID);
READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_CINEMATIC_SLOT_INDEX, CinematicSlotIndex);
READ_MICRO_CHUNK (cload, MICROCHUNKID_DEF_DISPLAY_VEHICLE_TIME, CinematicLengthToVehicleDisplay);
default:
Debug_Say (("Unrecognized AirStrip Def Variable chunkID\n"));
break;
}
cload.Close_Micro_Chunk();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Factory
//
////////////////////////////////////////////////////////////////
const PersistFactoryClass &
AirStripGameObjDef::Get_Factory (void) const
{
return _AirStripGameObjDefPersistFactory;
}
////////////////////////////////////////////////////////////////
//
// AirStripGameObj
//
////////////////////////////////////////////////////////////////
AirStripGameObj::AirStripGameObj (void) :
CinematicStartTimer (0),
ClearDropoffZoneTimer (UNITIALIZED_TIMER),
DisplayVehicleTimer (UNITIALIZED_TIMER),
IsCinematicStarted (false),
CinematicObject (NULL)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// ~AirStripGameObj
//
////////////////////////////////////////////////////////////////
AirStripGameObj::~AirStripGameObj (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Factory
//
////////////////////////////////////////////////////////////////
const PersistFactoryClass &
AirStripGameObj::Get_Factory (void) const
{
return _AirStripGameObjPersistFactory;
}
////////////////////////////////////////////////////////////////
//
// Init
//
////////////////////////////////////////////////////////////////
void AirStripGameObj::Init( void )
{
Init( Get_Definition() );
}
////////////////////////////////////////////////////////////////
//
// Init
//
////////////////////////////////////////////////////////////////
void
AirStripGameObj::Init (const AirStripGameObjDef &definition)
{
VehicleFactoryGameObj::Init (definition);
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Definition
//
////////////////////////////////////////////////////////////////
const AirStripGameObjDef &
AirStripGameObj::Get_Definition (void) const
{
return (const AirStripGameObjDef &)BaseGameObj::Get_Definition ();
}
////////////////////////////////////////////////////////////////
//
// Save
//
////////////////////////////////////////////////////////////////
bool
AirStripGameObj::Save (ChunkSaveClass &csave)
{
csave.Begin_Chunk (CHUNKID_PARENT);
VehicleFactoryGameObj::Save (csave);
csave.End_Chunk ();
csave.Begin_Chunk (CHUNKID_VARIABLES);
csave.End_Chunk ();
return true;
}
////////////////////////////////////////////////////////////////
//
// Load
//
////////////////////////////////////////////////////////////////
bool
AirStripGameObj::Load (ChunkLoadClass &cload)
{
while (cload.Open_Chunk ()) {
switch (cload.Cur_Chunk_ID ()) {
case CHUNKID_PARENT:
VehicleFactoryGameObj::Load (cload);
break;
case CHUNKID_VARIABLES:
Load_Variables (cload);
break;
default:
Debug_Say (("Unrecognized AirStrip chunkID\n"));
break;
}
cload.Close_Chunk();
}
return true;
}
////////////////////////////////////////////////////////////////
//
// Load_Variables
//
////////////////////////////////////////////////////////////////
void
AirStripGameObj::Load_Variables (ChunkLoadClass &cload)
{
while (cload.Open_Micro_Chunk ()) {
/*switch (cload.Cur_Micro_Chunk_ID ())
{
default:
Debug_Say (("Unrecognized AirStrip Variable chunkID\n"));
break;
}*/
cload.Close_Micro_Chunk();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// CnC_Initialize
//
////////////////////////////////////////////////////////////////
void
AirStripGameObj::CnC_Initialize (BaseControllerClass *base)
{
VehicleFactoryGameObj::CnC_Initialize (base);
return ;
}
////////////////////////////////////////////////////////////////
//
// Think
//
////////////////////////////////////////////////////////////////
void
AirStripGameObj::Think (void)
{
WWPROFILE ("AirStrip Think");
//
// Begin the cinematic if necessary
//
if (IsDestroyed == false && GeneratingVehicleID != 0) {
//
// Start the cinematic (if necessary)
//
if (IsCinematicStarted == false) {
CinematicStartTimer -= TimeManager::Get_Frame_Seconds ();
if (CinematicStartTimer <= 0) {
Start_Cinematic ();
ClearDropoffZoneTimer = 0.8f * Get_Definition().CinematicLengthToDropOff;
}
}
}
if ((GeneratingVehicleID != 0) && (IsCinematicStarted)) {
//
// Check to see if its time to display the object or not
//
if (DisplayVehicleTimer > UNITIALIZED_TIMER) {
DisplayVehicleTimer -= TimeManager::Get_Frame_Seconds ();
if (DisplayVehicleTimer < 0) {
//
// Display the vehicle
//
if (Vehicle != NULL) {
PhysicalGameObj *physical_obj = Vehicle.Get_Ptr ()->As_PhysicalGameObj ();
physical_obj->Peek_Model ()->Set_Hidden (false);
physical_obj->Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
}
DisplayVehicleTimer = UNITIALIZED_TIMER;
// Tell the vehicle to drive to one of the delivery points
Deliver_Vehicle();
}
}
//
// Check if we need to clear the dropoff zone
//
if (ClearDropoffZoneTimer > UNITIALIZED_TIMER) {
ClearDropoffZoneTimer -= TimeManager::Get_Frame_Seconds ();
if (ClearDropoffZoneTimer < 0) {
Destroy_Blocking_Objects ();
ClearDropoffZoneTimer = UNITIALIZED_TIMER;
}
}
}
VehicleFactoryGameObj::Think ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Begin_Generation
//
////////////////////////////////////////////////////////////////
void
AirStripGameObj::Begin_Generation (void)
{
CinematicStartTimer = GenerationTime - Get_Definition ().CinematicLengthToDropOff;
IsCinematicStarted = false;
return ;
}
////////////////////////////////////////////////////////////////
//
// Start_Cinematic
//
////////////////////////////////////////////////////////////////
void
AirStripGameObj::Start_Cinematic (void)
{
if (CombatManager::I_Am_Server () == false) {
return ;
}
//
// Create the vehicle
//
VehicleGameObj *vehicle = Create_Vehicle ();
if (vehicle != NULL) {
//
// Hide the vehicle until later
//
if (vehicle->Peek_Model () != NULL) {
vehicle->Peek_Model ()->Set_Hidden (true);
vehicle->Set_Object_Dirty_Bit (NetworkObjectClass::BIT_RARE, true);
}
//
// Lock the vehicle
//
if (Purchaser != NULL) {
vehicle->Lock_Vehicle(Purchaser,VEHICLE_LOCK_TIME);
}
//
// Create the cinematic controller
//
CinematicObject = ObjectLibraryManager::Create_Object (Get_Definition ().CinematicDefID);
if (CinematicObject != NULL) {
CinematicObject->Start_Observers ();
//
// Position the cinematic controller in the world
//
Matrix3D test_tm = CreationTM;
CinematicObject->Set_Transform (test_tm);
//
// Try to find the script parser so we can communicate with it
//
const GameObjObserverList &script_list = CinematicObject->Get_Observers ();
for (int index = 0; index < script_list.Count (); index ++) {
GameObjObserverClass *script = script_list[index];
if (::lstrcmpi (script->Get_Name (), "Test_Cinematic") == 0) {
//
// Attach the vehicle to the given slot in the cinematic
//
int slot = 10000 + Get_Definition ().CinematicSlotIndex;
script->Custom (this, slot, vehicle->Get_ID (), this);
break;
}
}
}
}
IsCinematicStarted = true;
DisplayVehicleTimer = Get_Definition ().CinematicLengthToVehicleDisplay;
return ;
}

View File

@@ -0,0 +1,174 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/airstripgameobj.h $Author:: Patrick $*
* *
* $Modtime:: 10/01/01 3:44p $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __AIRSTRIPGAMEOBJ_H
#define __AIRSTRIPGAMEOBJ_H
#include "always.h"
#include "vehiclefactorygameobj.h"
////////////////////////////////////////////////////////////////
// Forward delcarations
////////////////////////////////////////////////////////////////
class BaseControllerClass;
////////////////////////////////////////////////////////////////
//
// AirStripGameObjDef
//
////////////////////////////////////////////////////////////////
class AirStripGameObjDef : public VehicleFactoryGameObjDef
{
public:
////////////////////////////////////////////////////////////////
// Friends
////////////////////////////////////////////////////////////////
friend class AirStripGameObj;
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
AirStripGameObjDef (void);
~AirStripGameObjDef (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
uint32 Get_Class_ID (void) const;
PersistClass * Create (void) const;
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
const PersistFactoryClass & Get_Factory (void) const;
////////////////////////////////////////////////////////////////
// Editable support
////////////////////////////////////////////////////////////////
DECLARE_EDITABLE (AirStripGameObjDef, VehicleFactoryGameObjDef);
protected:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
////////////////////////////////////////////////////////////////
// Protected member data
////////////////////////////////////////////////////////////////
int CinematicDefID;
int CinematicSlotIndex;
float CinematicLengthToDropOff;
float CinematicLengthToVehicleDisplay;
};
////////////////////////////////////////////////////////////////
//
// AirStripGameObj
//
////////////////////////////////////////////////////////////////
class AirStripGameObj : public VehicleFactoryGameObj
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
AirStripGameObj (void);
~AirStripGameObj (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
//
// Definition support
//
virtual void Init( void );
void Init (const AirStripGameObjDef & definition);
const AirStripGameObjDef & Get_Definition (void) const;
//
// RTTI
//
AirStripGameObj * As_AirStripGameObj (void) { return this; }
//
// Persist support
//
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
const PersistFactoryClass & Get_Factory (void) const;
//
// From BuildingGameObj
//
void CnC_Initialize (BaseControllerClass *base);
//
// GameObj methods
//
void Think (void);
protected:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
void Begin_Generation (void);
void Start_Cinematic (void);
void Attach_Vehicle (void);
////////////////////////////////////////////////////////////////
// Protected member data
////////////////////////////////////////////////////////////////
float CinematicStartTimer;
float EndTimer;
float DisplayVehicleTimer;
float ClearDropoffZoneTimer;
bool IsCinematicStarted;
PhysicalGameObj * CinematicObject;
};
#endif // __AIRSTRIPGAMEOBJ_H

921
Code/Combat/animcontrol.cpp Normal file
View File

@@ -0,0 +1,921 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/animcontrol.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 1/04/02 10:26a $*
* *
* $Revision:: 53 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "animcontrol.h"
#include "assets.h"
#include "debug.h"
#include "rendobj.h"
#include "chunkio.h"
#include "saveload.h"
#include "htree.h"
/*
**
*/
enum {
XXXCHUNKID_LEGS = 910991512,
XXXCHUNKID_TORSO,
CHUNKID_CHANNEL,
CHUNKID_VARIABLES,
CHUNKID_OLD,
CHUNKID_NEW,
CHUNKID_PARENT,
CHUNKID_CHANNEL1,
CHUNKID_CHANNEL2,
MICROCHUNKID_BLEND_TIMER = 1,
MICROCHUNKID_BLEND_TOTAL,
MICROCHUNKID_FRAME,
XXXMICROCHUNKID_WEIGHT,
MICROCHUNKID_MODE,
MICROCHUNKID_ANIMATION_NAME,
MICROCHUNKID_MODEL_PTR,
MICROCHUNKID_CHANNEL2_RATIO,
MICROCHUNKID_TARGET_FRAME,
MICROCHUNKID_SKELETON,
};
/*
** AnimChannelClass
*/
AnimChannelClass::AnimChannelClass( void ) :
Animation( NULL ),
Frame( 0.0f ),
NumFrames( 1 ),
TargetFrame( 0.0f ),
Mode( ANIM_MODE_ONCE )
{
}
AnimChannelClass::~AnimChannelClass( void )
{
if ( Animation ) {
Animation->Release_Ref();
Animation = NULL;
}
}
AnimChannelClass & AnimChannelClass::operator = (const AnimChannelClass & src)
{
if (Animation != NULL) {
Animation->Release_Ref();
}
Animation = src.Animation;
if (Animation != NULL) {
Animation->Add_Ref();
}
Frame = src.Frame;
NumFrames = src.NumFrames;
Mode = src.Mode;
TargetFrame = src.TargetFrame;
return *this;
}
bool AnimChannelClass::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_VARIABLES );
// save the anim first, because the load will stomp the frame & weight
if ( Animation ) {
csave.Begin_Micro_Chunk( MICROCHUNKID_ANIMATION_NAME );
const char * anim_name = Animation->Get_Name();
csave.Write( anim_name, strlen( anim_name ) + 1);
csave.End_Micro_Chunk();
}
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_FRAME, Frame );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_MODE, Mode );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TARGET_FRAME, TargetFrame );
csave.End_Chunk();
return true;
}
bool AnimChannelClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_FRAME, Frame );
READ_MICRO_CHUNK( cload, MICROCHUNKID_MODE, Mode );
READ_MICRO_CHUNK( cload, MICROCHUNKID_TARGET_FRAME, TargetFrame );
case MICROCHUNKID_ANIMATION_NAME:
{
char anim_name[80];
cload.Read( anim_name, cload.Cur_Micro_Chunk_Length() );
Set_Animation( anim_name );
break;
}
default:
Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
return true;
}
void AnimChannelClass::Set_Animation( const char *name )
{
// If this is our current anim, bail
if ( ( Animation != NULL ) && ( name != NULL ) ) {
if ( stricmp( Animation->Get_Name(), name ) == 0 ) {
return;
}
}
if ( ( Animation == NULL ) && ( name == NULL ) ) {
return;
}
// Release the old anim
if ( Animation ) {
Animation->Release_Ref();
Animation = NULL;
}
// we need to switch anims
if (( name != NULL ) && ( name[0] != 0 ) ) {
Animation = WW3DAssetManager::Get_Instance()->Get_HAnim( name );
}
if ( Animation ) {
SET_REF_OWNER( Animation );
NumFrames = Animation->Get_Num_Frames();
Mode = ANIM_MODE_ONCE;
Frame = 0;
TargetFrame = 0;
}
}
void AnimChannelClass::Set_Animation( const HAnimClass *anim )
{
// If this is our current anim, bail
if ( Animation == anim ) {
return;
}
// Release the old anim
if ( Animation ) {
Animation->Release_Ref();
Animation = NULL;
}
// we need to switch anims
Animation = (HAnimClass *)anim;
if ( Animation ) {
Animation->Add_Ref();
NumFrames = Animation->Get_Num_Frames();
Mode = ANIM_MODE_ONCE;
Frame = 0;
TargetFrame = 0;
}
}
void AnimChannelClass::Set_Mode( AnimMode mode, float frame )
{
Mode = mode;
if ( frame >= 0 ) {
Frame = frame;
}
}
void AnimChannelClass::Update( float dtime )
{
if ( Mode == ANIM_MODE_STOP ) {
return;
}
if ( Animation != NULL ) {
switch ( Mode )
{
case ANIM_MODE_LOOP:
//
// Increment the frame based on the current timeslice
//
Frame += dtime * Animation->Get_Frame_Rate();
//
// Handle wrapping
//
if ( Frame >= NumFrames-1 ) {
Frame -= NumFrames-1;
}
if ( Frame >= NumFrames ) {
Frame = 0;
}
break;
case ANIM_MODE_TARGET:
//
// Which direction are we animating?
//
if ( Frame < TargetFrame ) {
Frame += dtime * Animation->Get_Frame_Rate();
//
// If we overshoot targetframe, snap to targetframe
//
if (Frame >= TargetFrame) {
Frame = TargetFrame;
}
} else if ( Frame > TargetFrame ) {
Frame -= dtime * Animation->Get_Frame_Rate();
//
// If we overshoot targetframe, snap to targetframe
//
if ( Frame <= TargetFrame ) {
Frame = TargetFrame;
}
}
break;
case ANIM_MODE_ONCE:
//
// Increment the frame based on the current timeslice
//
Frame += dtime * Animation->Get_Frame_Rate();
//
// Make sure we don't go past the end
//
if ( Frame > NumFrames-1 ) {
Frame = NumFrames-1;
}
break;
}
#if 0
if ( dtime != 0 ) {
Debug_Say(( "Anim %s frame %1.3f\n", Animation->Get_Name(), Frame ));
}
#endif
}
}
void AnimChannelClass::Get_Animation_Data( AnimationDataList & list, float weight )
{
if ( Animation != NULL && weight > 0 ) {
AnimationDataRecord * record = list.Uninitialized_Add();
WWASSERT( record != NULL );
record->Animation = Animation;
record->Frame = Frame;
record->Weight = weight;
}
}
void AnimChannelClass::Update_Model( RenderObjClass *anim_model )
{
if ( Animation ) {
anim_model->Set_Animation( Animation, Frame );
} else {
anim_model->Set_Animation();
}
}
/*
** BlendableAnimChannelClass
*/
BlendableAnimChannelClass::BlendableAnimChannelClass( void ) :
BlendTimer( 0 ),
BlendTotal( 0 )
{
}
bool BlendableAnimChannelClass::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_NEW );
NewChannel.Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_OLD );
OldChannel.Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_BLEND_TIMER, BlendTimer );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_BLEND_TOTAL, BlendTotal );
csave.End_Chunk();
return true;
}
bool BlendableAnimChannelClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_NEW:
NewChannel.Load( cload );
break;
case CHUNKID_OLD:
OldChannel.Load( cload );
break;
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_BLEND_TIMER, BlendTimer );
READ_MICRO_CHUNK( cload, MICROCHUNKID_BLEND_TOTAL, BlendTotal );
default:
Debug_Say(( "Unrecognized BlendableAnimChannel Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(( "Unrecognized BlendableAnimChannel chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
void BlendableAnimChannelClass::Set_Animation( const char *name, float blendtime, float start_frame )
{
// if setting to our current anim, bail
if ( ( NewChannel.Peek_Animation() == NULL ) && ( name == NULL ) ) {
return;
}
if ( ( NewChannel.Peek_Animation() != NULL ) && ( name != NULL ) ) {
if ( stricmp( NewChannel.Peek_Animation()->Get_Name(), name ) == 0 ) {
return;
}
}
// if no current channel, or no blend, or no new name, don't blend
if ( (NewChannel.Peek_Animation() == NULL) || (blendtime == 0) || (name == NULL) ) {
BlendTotal = 0.0f;
BlendTimer = 0.0f;
} else if ( BlendTotal == 0.0 ) { //if not currently blending
OldChannel = NewChannel;
BlendTimer = 0.0f;
BlendTotal = blendtime;
#if 0
} else if ( OldChannel.Peek_Animation() == new_anim.Peek_Animation() ) { // if old anim is the new one
OldChannel.Copy_From( NewChannel );
BlendTimer = (1.0f - (BlendTimer / BlendTotal)) * blendtime;
BlendTotal = blendtime;
#endif
} else if ( (BlendTimer / BlendTotal) > 0.5 ) { // if more than halfway through the old blend
OldChannel = NewChannel;
BlendTimer = (1.0f - (BlendTimer / BlendTotal)) * blendtime;
BlendTotal = blendtime;
} else {
BlendTimer = (BlendTimer / BlendTotal) * blendtime;
BlendTotal = blendtime;
}
NewChannel.Set_Animation( name );
if ( NewChannel.Peek_Animation() != NULL ) {
NewChannel.Set_Frame( start_frame );
}
if ( name == NULL ) {
OldChannel.Set_Animation( (const char *)NULL );
}
}
void BlendableAnimChannelClass::Set_Animation( const HAnimClass * anim, float blendtime, float start_frame )
{
// if setting to our current anim, bail
if ( ( NewChannel.Peek_Animation() == NULL ) && ( anim == NULL ) ) {
return;
}
if ( ( NewChannel.Peek_Animation() != NULL ) && ( anim != NULL ) ) {
if ( NewChannel.Peek_Animation() == anim ) {
return;
}
}
// if no current channel, or no blend, or no new name, don't blend
if ( (NewChannel.Peek_Animation() == NULL) || (blendtime == 0) || (anim == NULL) ) {
BlendTotal = 0.0f;
BlendTimer = 0.0f;
} else if ( BlendTotal == 0.0 ) { //if not currently blending
OldChannel = NewChannel;
BlendTimer = 0.0f;
BlendTotal = blendtime;
#if 0
} else if ( OldChannel.Peek_Animation() == new_anim.Peek_Animation() ) { // if old anim is the new one
OldChannel.Copy_From( NewChannel );
BlendTimer = (1.0f - (BlendTimer / BlendTotal)) * blendtime;
BlendTotal = blendtime;
#endif
} else if ( (BlendTimer / BlendTotal) > 0.5 ) { // if more than halfway through the old blend
OldChannel = NewChannel;
BlendTimer = (1.0f - (BlendTimer / BlendTotal)) * blendtime;
BlendTotal = blendtime;
} else {
BlendTimer = (BlendTimer / BlendTotal) * blendtime;
BlendTotal = blendtime;
}
NewChannel.Set_Animation( anim );
if ( NewChannel.Peek_Animation() != NULL ) {
NewChannel.Set_Frame( start_frame );
}
if ( anim == NULL ) {
OldChannel.Set_Animation( (const HAnimClass *)NULL );
}
}
void BlendableAnimChannelClass::Update( float dtime )
{
if ( BlendTotal != 0.0f ) { // if blending between two animations
BlendTimer += dtime; // Bump blend timer forward
if ( BlendTimer >= BlendTotal ) // blend complete, remove oldanim
{
BlendTotal = 0.0f;
BlendTimer = 0.0f;
OldChannel.Set_Animation( (const char *)NULL );
}
}
// Calculate which frame we are on in each of the animations
NewChannel.Update( dtime );
OldChannel.Update( dtime );
}
void BlendableAnimChannelClass::Get_Animation_Data( AnimationDataList & list, float weight )
{
float blend_ratio = 1.0f; // assume no blending
if ( BlendTotal != 0.0f ) { // if blending between two animations
// Calculate the blend percentage between the two animations.
// This starts at 0.0 (all OldAnimation) and proceeds to 1.0 (all Animation)
blend_ratio = WWMath::Clamp( BlendTimer / BlendTotal, 0, 1 );
}
NewChannel.Get_Animation_Data( list, weight * blend_ratio );
OldChannel.Get_Animation_Data( list, weight * ( 1 - blend_ratio ) );
}
void BlendableAnimChannelClass::Update_Model( RenderObjClass *anim_model )
{
float blend_ratio = 1.0f; // assume no blending
if ( BlendTotal != 0.0f ) { // if blending between two animations
// Calculate the blend percentage between the two animations.
// This starts at 0.0 (all OldAnimation) and proceeds to 1.0 (all Animation)
blend_ratio = WWMath::Clamp( BlendTimer / BlendTotal, 0, 1 );
}
if ( OldChannel.Peek_Animation() ) {
anim_model->Set_Animation( OldChannel.Peek_Animation(), OldChannel.Get_Frame(),
NewChannel.Peek_Animation(), NewChannel.Get_Frame(),
blend_ratio );
} else if ( NewChannel.Peek_Animation() ) {
anim_model->Set_Animation( NewChannel.Peek_Animation(), NewChannel.Get_Frame() );
} else {
anim_model->Set_Animation();
}
}
/*
** AnimControlClass
*/
AnimControlClass::AnimControlClass( void ) :
Model( NULL )
{
}
AnimControlClass::~AnimControlClass( void )
{
REF_PTR_RELEASE( Model );
}
bool AnimControlClass::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_MODEL_PTR, Model );
csave.End_Chunk();
return true;
}
bool AnimControlClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_VARIABLES:
WWASSERT( Model == NULL );
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_MODEL_PTR, Model );
default:
Debug_Say(( "Unrecognized AnimControl Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
if ( Model != NULL ) {
REQUEST_REF_COUNTED_POINTER_REMAP( (RefCountClass **)&Model );
} else {
Debug_Say(( "Loaded NULL model\n" ));
}
break;
default:
Debug_Say(( "Unrecognized AnimControl chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
void AnimControlClass::Set_Model( RenderObjClass *anim_model )
{
REF_PTR_SET( Model, anim_model );
}
/*
** SimpleAnimControlClass
*/
SimpleAnimControlClass::SimpleAnimControlClass( void )
{
}
SimpleAnimControlClass::~SimpleAnimControlClass( void )
{
}
bool SimpleAnimControlClass::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_PARENT );
AnimControlClass::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_CHANNEL );
Channel.Save( csave );
csave.End_Chunk();
return true;
}
bool SimpleAnimControlClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_PARENT:
AnimControlClass::Load( cload );
break;
case CHUNKID_CHANNEL:
Channel.Load( cload );
break;
default:
Debug_Say(( "Unrecognized HumanAnimControl chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
void SimpleAnimControlClass::Set_Animation( const char *name, float blendtime, float start_frame )
{
Channel.Set_Animation( name, blendtime, start_frame );
}
void SimpleAnimControlClass::Set_Animation( const HAnimClass * anim, float blendtime, float start_frame )
{
Channel.Set_Animation( anim, blendtime, start_frame );
}
void SimpleAnimControlClass::Update( float dtime )
{
Channel.Update( dtime );
// Setup the model for the current frame(s)
assert( Model != NULL );
Channel.Update_Model( Model );
}
/*
** HumanAnimControlClass
*/
HumanAnimControlClass::HumanAnimControlClass( void ) :
AnimCombo( 2 ),
Channel2Ratio( 0 ),
Skeleton( 'A' ),
AnimSpeedScale( 1 )
{
}
HumanAnimControlClass::~HumanAnimControlClass( void )
{
}
bool HumanAnimControlClass::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_PARENT );
AnimControlClass::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_CHANNEL2_RATIO, Channel2Ratio );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_SKELETON, Skeleton );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_CHANNEL1 );
Channel1.Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_CHANNEL2 );
Channel2.Save( csave );
csave.End_Chunk();
// Don't need to save the animcombo
return true;
}
bool HumanAnimControlClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_PARENT:
AnimControlClass::Load( cload );
break;
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_CHANNEL2_RATIO, Channel2Ratio );
READ_MICRO_CHUNK( cload, MICROCHUNKID_SKELETON, Skeleton );
default:
Debug_Say(( "Unrecognized HumanAnimControl Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
case CHUNKID_CHANNEL1:
Channel1.Load( cload );
break;
case CHUNKID_CHANNEL2:
Channel2.Load( cload );
break;
default:
Debug_Say(( "Unrecognized HumanAnimControl chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
void HumanAnimControlClass::Build_Skeleton_Anim_Name( StringClass& new_name, const char * name )
{
if (name == NULL) return;
if (*name == NULL) {
Debug_Say(( "No name in Build_Skeleton_Anim_Name\n" ));
return;
}
new_name = name;
if ( Skeleton == 'V' ) { // Special case for visceroids
return;
}
// If the anim doesn't start with "S_A_HUMAN.", add it
if ( ::strnicmp( name, "S_", 2 ) != 0 ) {
new_name.Format( "S_%c_HUMAN.%s", Skeleton, name );
}
// If the anim name is "S_A_HUMAN.H_A_*", and the Skeleton is not 'A', use
// the other skeleton anim, if found
if ( new_name.Get_Length() > 14 && Skeleton != 'A' && ::strnicmp( new_name, "S_A_HUMAN.H_A_", 14 ) == 0 ) {
StringClass mod_name(new_name,true);
mod_name[2] = Skeleton;
mod_name[12] = Skeleton;
// can we find the anim name?
HAnimClass * anim = WW3DAssetManager::Get_Instance()->Get_HAnim( mod_name );
if ( anim != NULL ) {
anim->Release_Ref();
new_name=mod_name;
}
}
}
void HumanAnimControlClass::Set_Animation( const char *name, float blendtime, float start_frame )
{
StringClass new_name(0,true);
Build_Skeleton_Anim_Name( new_name, name );
Channel1.Set_Animation( new_name, blendtime, start_frame );
Channel2.Set_Animation( (const char *)NULL );
Channel2Ratio = 0;
}
void HumanAnimControlClass::Set_Animation( const HAnimClass * anim, float blendtime, float start_frame )
{
if ( anim != NULL ) {
Set_Animation( anim->Get_Name(), blendtime, start_frame );
} else {
Set_Animation( (const char *)NULL, blendtime, start_frame );
}
}
void HumanAnimControlClass::Set_Animation( const char *name1, const char * name2, float ratio, float blendtime )
{
StringClass new_name1(0,true);
Build_Skeleton_Anim_Name( new_name1, name1 );
StringClass new_name2(0,true);
Build_Skeleton_Anim_Name( new_name2, name2 );
if ( ratio == 0 ) {
Set_Animation( new_name1, blendtime );
return;
}
if ( Channel2Ratio == 0 ) {
Channel2 = Channel1;
}
Channel1.Set_Animation( new_name1, blendtime );
Channel2.Set_Animation( new_name2, blendtime );
Channel2Ratio = ratio;
}
void HumanAnimControlClass::Set_Mode( AnimMode mode, float frame )
{
Channel1.Set_Mode( mode, frame );
Channel2.Set_Mode( mode, frame );
}
void HumanAnimControlClass::Set_Model( RenderObjClass *anim_model )
{
AnimControlClass::Set_Model( anim_model );
// Update the skeleton
if( anim_model != NULL ) {
const HTreeClass * tree = anim_model->Get_HTree();
if ( tree != NULL ) {
const char * name = tree->Get_Name();
Skeleton = name[2];
}
}
}
/*
**
*/
StringClass _MonitorAnimDescription;
HumanAnimControlClass * _Monitor = NULL;
void HumanAnimControlClass::Update( float dtime )
{
// Update channels
Channel1.Update( dtime * AnimSpeedScale );
Channel2.Update( dtime * AnimSpeedScale );
if ( Model != NULL ) {
// Get Animation data
DataList.Reset_Active();
Channel1.Get_Animation_Data( DataList, (1 - Channel2Ratio) );
Channel2.Get_Animation_Data( DataList, Channel2Ratio );
// Use the cheapest anim method possible
int total_animations = DataList.Count();
if ( total_animations == 0 ) {
// Debug_Say(( "No animations to display!\n" ));
Model->Set_Animation();
} else if ( total_animations == 1 ) {
// Debug_Say(( "1 animation to display!\n" ));
Model->Set_Animation( DataList[0].Animation, DataList[0].Frame );
} else if ( total_animations == 2 ) {
// Debug_Say(( "2 animation to display!\n" ));
float percent = DataList[1].Weight / (DataList[0].Weight + DataList[1].Weight);
Model->Set_Animation( DataList[0].Animation, DataList[0].Frame,
DataList[1].Animation, DataList[1].Frame, percent );
} else {
// Debug_Say(( ">2 animation to display!\n" ));
// set up anim combo
AnimCombo.Reset();
for ( int i = 0; i < total_animations; i++ ) {
HAnimComboDataClass * anim_data = new HAnimComboDataClass();
anim_data->Set_HAnim( DataList[i].Animation );
anim_data->Set_Frame( DataList[i].Frame );
anim_data->Set_Weight( DataList[i].Weight );
AnimCombo.Append_Anim_Combo_Data( anim_data );
}
// Setup the model for the current frame(s)
Model->Set_Animation( &AnimCombo );
}
if ( _Monitor == this ) {
for ( int i = 0; i < total_animations; i++ ) {
if ( i == 0 ) {
_MonitorAnimDescription = "";
}
StringClass a(0,true);
a.Format( "%s %1.0f%% %1.0f\n", DataList[i].Animation->Get_Name()+10, DataList[i].Weight*100, DataList[i].Frame );
_MonitorAnimDescription += a;
}
}
}
}
/*
**
*/
void HumanAnimControlClass::Get_Information( StringClass & string )
{
_Monitor = this;
string += _MonitorAnimDescription;
}

310
Code/Combat/animcontrol.h Normal file
View File

@@ -0,0 +1,310 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/animcontrol.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 1/04/02 10:33a $*
* *
* $Revision:: 36 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef ANIMCONTROL_H
#define ANIMCONTROL_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef HANIM_H
#include "hanim.h"
#endif
#ifndef VECTOR_H
#include "vector.h"
#endif
#include "wwstring.h"
/*
**
*/
class RenderObjClass;
typedef enum {
ANIM_MODE_ONCE,
ANIM_MODE_LOOP,
ANIM_MODE_STOP,
ANIM_MODE_TARGET
} AnimMode;
/*
** AnimationDataRecord
*/
struct AnimationDataRecord {
HAnimClass *Animation;
float Frame;
float Weight;
bool operator == (AnimationDataRecord const & rec) const { return false; }
bool operator != (AnimationDataRecord const & rec) const { return true; }
};
typedef DynamicVectorClass<AnimationDataRecord> AnimationDataList;
/*
** AnimChannelClass
*/
class AnimChannelClass {
public:
// Constructor and Destructor
AnimChannelClass( void );
AnimChannelClass(const AnimChannelClass &);
AnimChannelClass & operator = (const AnimChannelClass &);
~AnimChannelClass(void);
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
// Set Animation
void Set_Animation( const char *name );
void Set_Animation( const HAnimClass *anim );
HAnimClass *Peek_Animation( void ) { return Animation; }
// Set Mode
void Set_Mode( AnimMode mode, float frame = -1 );
AnimMode Get_Mode( void ) { return Mode; }
bool Is_Complete( void ) { return (Animation == NULL) || ((Mode == ANIM_MODE_ONCE) && (Frame == NumFrames-1)) || ((Mode == ANIM_MODE_TARGET) && (Frame == TargetFrame)); }
const char *Get_Animation_Name( void ) { return Animation ? Animation->Get_Name() : ""; }
// Frame
void Set_Frame( float frame ) { Frame = frame; }
float Get_Frame( void ) { return Frame; }
float Get_Progress( void ) { return NumFrames ? Frame / NumFrames : 0; }
void Set_Target_Frame( float frame ) { TargetFrame = frame; }
float Get_Target_Frame( void ) { return TargetFrame; }
// Update the animation
void Update( float dtime );
// Get Animation Data
void Get_Animation_Data( AnimationDataList & list, float weight = 1.0f );
// Update Model
void Update_Model( RenderObjClass *anim_model );
private:
HAnimClass * Animation;
float Frame;
float NumFrames;
float TargetFrame;
AnimMode Mode;
};
/*
** BlendableAnimChannelClass
*/
class BlendableAnimChannelClass {
public:
// Constructor
BlendableAnimChannelClass( void );
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
// Set Animation
void Set_Animation( const char *name, float blendtime = 0.0f, float start_frame = 0.0f );
void Set_Animation( const HAnimClass * anim, float blendtime = 0.0f, float start_frame = 0.0f );
void Set_Mode( AnimMode mode, float frame = -1 ) { NewChannel.Set_Mode( mode, frame ); }
AnimMode Get_Mode( void ) { return NewChannel.Get_Mode(); }
bool Is_Complete( void ) { return NewChannel.Is_Complete(); }
const char *Get_Animation_Name( void ) { return NewChannel.Get_Animation_Name(); }
void Set_Target_Frame( float frame ) { NewChannel.Set_Target_Frame ( frame ); }
float Get_Target_Frame( void ) { return NewChannel.Get_Target_Frame(); }
HAnimClass *Peek_Animation( void ) { return NewChannel.Peek_Animation (); }
// Update the animation
void Update( float dtime );
// Get Animation Data
void Get_Animation_Data( AnimationDataList & list, float weight = 1.0f );
// Update Model
void Update_Model( RenderObjClass *anim_model );
// Data Access
float Get_Frame( void ) { return NewChannel.Get_Frame(); }
float Get_Progress( void ) { return NewChannel.Get_Progress(); }
private:
AnimChannelClass NewChannel;
AnimChannelClass OldChannel;
float BlendTimer; // in seconds
float BlendTotal; // in seconds
};
/*
** AnimControlClass
*/
class AnimControlClass {
public:
// Constructor and Destructor
AnimControlClass( void );
virtual ~AnimControlClass( void );
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
// Set Model
virtual void Set_Model( RenderObjClass *anim_model );
virtual RenderObjClass *Peek_Model( void ) { return Model; }
// Set Animation
virtual void Set_Animation( const char *name, float blendtime = 0.0f, float start_frame = 0.0f ) = 0;
virtual void Set_Animation( const HAnimClass * anim, float blendtime = 0.0f, float start_frame = 0.0f ) = 0;
virtual void Set_Mode( AnimMode mode, float frame = -1 ) = 0;
virtual AnimMode Get_Mode( void ) = 0;
virtual bool Is_Complete( void ) = 0;
virtual const char *Get_Animation_Name( void ) = 0;
virtual void Set_Target_Frame( float frame ) = 0;
virtual float Get_Target_Frame( void ) = 0;
virtual float Get_Current_Frame( void ) = 0;
virtual HAnimClass * Peek_Animation( void ) { return NULL; }
// Update the animation
virtual void Update( float dtime ) = 0;
protected:
RenderObjClass *Model;
};
/*
** SimpleAnimControlClass
*/
class SimpleAnimControlClass : public AnimControlClass {
public:
// Constructor and Destructor
SimpleAnimControlClass( void );
~SimpleAnimControlClass( void );
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
// Set Animation
virtual void Set_Animation( const char *name, float blendtime = 0.0f, float start_frame = 0.0f );
virtual void Set_Animation( const HAnimClass * anim, float blendtime = 0.0f, float start_frame = 0.0f );
virtual void Set_Mode( AnimMode mode, float frame = -1 ) { Channel.Set_Mode( mode, frame ); }
virtual AnimMode Get_Mode( void ) { return Channel.Get_Mode(); }
virtual bool Is_Complete( void ) { return Channel.Is_Complete(); }
virtual const char *Get_Animation_Name( void ) { return Channel.Get_Animation_Name(); }
virtual void Set_Target_Frame( float frame ) { Channel.Set_Target_Frame( frame ); }
virtual float Get_Target_Frame( void ) { return Channel.Get_Target_Frame(); }
virtual float Get_Current_Frame( void ) { return Channel.Get_Frame(); }
// Update the animation
virtual void Update( float dtime );
private:
BlendableAnimChannelClass Channel;
};
/*
** HumanAnimControlClass
*/
class HumanAnimControlClass : public AnimControlClass {
public:
// Constructor and Destructor
HumanAnimControlClass( void );
~HumanAnimControlClass( void );
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
virtual void Set_Model( RenderObjClass *anim_model );
// Set Animation
virtual void Set_Animation( const char *name, float blendtime = 0.0f, float start_frame = 0.0f );
virtual void Set_Animation( const HAnimClass * anim, float blendtime = 0.0f, float start_frame = 0.0f );
virtual void Set_Animation( const char *name1, const char * name2, float ratio, float blendtime = 0.0f );
virtual void Set_Mode( AnimMode mode, float frame = -1 );
virtual AnimMode Get_Mode( void ) { return Channel1.Get_Mode(); }
virtual bool Is_Complete( void ) { return Channel1.Is_Complete(); }
virtual const char *Get_Animation_Name( void ) { return Channel1.Get_Animation_Name(); }
virtual float Get_Frame( void ) { return Channel1.Get_Frame(); }
virtual float Get_Progress( void ) { return Channel1.Get_Progress(); }
virtual void Set_Target_Frame( float frame ) { Channel1.Set_Target_Frame( frame ); }
virtual float Get_Target_Frame( void ) { return Channel1.Get_Target_Frame(); }
virtual float Get_Current_Frame( void ) { return Channel1.Get_Frame(); }
virtual void Set_Anim_Speed_Scale( float speed ) { AnimSpeedScale = speed; }
virtual void Update( float dtime );
virtual HAnimClass * Peek_Animation( void ) { return Channel1.Peek_Animation(); }
void Get_Information( StringClass & string );
char Get_Skeleton( void ) { return Skeleton; }
private:
BlendableAnimChannelClass Channel1;
BlendableAnimChannelClass Channel2;
float Channel2Ratio;
float AnimSpeedScale;
AnimationDataList DataList;
HAnimComboClass AnimCombo;
char Skeleton;
void Build_Skeleton_Anim_Name( StringClass& new_name, const char * name );
};
#endif // ANIMCONTROL_H

View File

@@ -0,0 +1,138 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/apppackettypes.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 2/21/02 3:01p $*
* *
* $Revision:: 21 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __APPPACKETTYPES_H__
#define __APPPACKETTYPES_H__
//-----------------------------------------------------------------------------
//
// Leaf node net object types
// N.B. If you add to this list you must also add in cAppPacketStats::Interpret_Type.
//
enum
{
//
// S->C
//
APPPACKETTYPE_UNKNOWN,
APPPACKETTYPE_SIMPLE,
APPPACKETTYPE_SOLDIER,
APPPACKETTYPE_VEHICLE,
APPPACKETTYPE_TURRET,
APPPACKETTYPE_BUILDING,
APPPACKETTYPE_PLAYER,
APPPACKETTYPE_TEAM,
APPPACKETTYPE_GAMEOPTIONSEVENT,
APPPACKETTYPE_PLAYERKILLEVENT,
APPPACKETTYPE_PURCHASERESPONSEEVENT,
APPPACKETTYPE_SCTEXTOBJ,
APPPACKETTYPE_SVRGOODBYEEVENT,
APPPACKETTYPE_WINEVENT,
APPPACKETTYPE_POWERUP,
APPPACKETTYPE_STATIC,
APPPACKETTYPE_DOOR,
APPPACKETTYPE_ELEVATOR,
APPPACKETTYPE_DSAPO,
APPPACKETTYPE_SERVERFPS,
APPPACKETTYPE_CONSOLECOMMANDEVENT,
APPPACKETTYPE_RESETWINSEVENT,
APPPACKETTYPE_EVICTIONEVENT,
APPPACKETTYPE_NETWEATHER,
APPPACKETTYPE_GAMEDATAUPDATEEVENT,
APPPACKETTYPE_SCPINGRESPONSEEVENT,
APPPACKETTYPE_BASECONTROLLER,
APPPACKETTYPE_CINEMATIC,
APPPACKETTYPE_C4,
APPPACKETTYPE_BEACON,
APPPACKETTYPE_SCEXPLOSIONEVENT,
APPPACKETTYPE_SCOBELISKEVENT,
APPPACKETTYPE_SCANNOUNCEMENT,
APPPACKETTYPE_NETBACKGROUND,
APPPACKETTYPE_GAMESPYSCCHALLENGEEVENT,
//
// C->S
//
APPPACKETTYPE_CLIENTCONTROL,
APPPACKETTYPE_CSTEXTOBJ,
APPPACKETTYPE_SUICIDEEVENT,
APPPACKETTYPE_CHANGETEAMEVENT,
APPPACKETTYPE_MONEYEVENT,
APPPACKETTYPE_WARPEVENT,
APPPACKETTYPE_PURCHASEREQUESTEVENT,
APPPACKETTYPE_CLIENTGOODBYEEVENT,
APPPACKETTYPE_BIOEVENT,
APPPACKETTYPE_LOADINGEVENT,
APPPACKETTYPE_GODMODEEVENT,
APPPACKETTYPE_VIPMODEEVENT,
APPPACKETTYPE_SCOREEVENT,
APPPACKETTYPE_CLIENTBBOEVENT,
APPPACKETTYPE_CLIENTFPS,
APPPACKETTYPE_CSPINGREQUESTEVENT,
APPPACKETTYPE_CSDAMAGEEVENT,
APPPACKETTYPE_REQUESTKILLEVENT,
APPPACKETTYPE_CSCONSOLECOMMANDEVENT,
APPPACKETTYPE_CSHINT,
APPPACKETTYPE_CSANNOUNCEMENT,
APPPACKETTYPE_DONATEEVENT,
APPPACKETTYPE_GAMESPYCSCHALLENGERESPONSEEVENT,
//
// Summation
//
APPPACKETTYPE_ALL,
APPPACKETTYPE_COUNT,
};
//-----------------------------------------------------------------------------
#endif //__APPPACKETTYPES_H__
//APPPACKETTYPE_FLAGCAPEVENT,
//APPPACKETTYPE_STEALTHEVENT,

View File

@@ -0,0 +1,530 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/armedgameobj.cpp $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 12/20/01 7:10p $*
* *
* $Revision:: 38 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
** Includes
*/
#include "armedgameobj.h"
#include "debug.h"
#include "weaponbag.h"
#include "weapons.h"
#include "rendobj.h"
#include "bitpackids.h"
#include "wwprofile.h"
#include "smartgameobj.h"
/*
** ArmedGameObjDef
*/
ArmedGameObjDef::ArmedGameObjDef( void ) :
WeaponTiltRate( 1.0f ),
WeaponTiltMin( -10000.0f ),
WeaponTiltMax( 10000.0f ),
WeaponTurnRate( 1.0f ),
WeaponTurnMin( -10000.0f ),
WeaponTurnMax( 10000.0f ),
WeaponError( 0 ),
WeaponDefID( 0 ),
SecondaryWeaponDefID( 0 ),
WeaponRounds( -1 )
{
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_ANGLE, WeaponTiltRate );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_ANGLE, WeaponTiltMin );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_ANGLE, WeaponTiltMax );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_ANGLE, WeaponTurnRate );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_ANGLE, WeaponTurnMin );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_ANGLE, WeaponTurnMax );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_ANGLE, WeaponError );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_WEAPONOBJDEFINITIONID, WeaponDefID );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_INT, WeaponRounds );
EDITABLE_PARAM( ArmedGameObjDef, ParameterClass::TYPE_WEAPONOBJDEFINITIONID, SecondaryWeaponDefID );
}
enum {
CHUNKID_DEF_PARENT = 418001829,
CHUNKID_DEF_VARIABLES,
MICROCHUNKID_DEF_WEAPON_TILT_RATE = 1,
MICROCHUNKID_DEF_WEAPON_TILT_MIN,
MICROCHUNKID_DEF_WEAPON_TILT_MAX,
MICROCHUNKID_DEF_WEAPON_TURN_RATE,
MICROCHUNKID_DEF_WEAPON_TURN_MIN,
MICROCHUNKID_DEF_WEAPON_TURN_MAX,
XXXMICROCHUNKID_DEF_PRIMARY_ROUNDS,
XXXMICROCHUNKID_DEF_PRIMARY_AMMO_WEAPON_DEF_ID,
XXXMICROCHUNKID_DEF_SECONDARY_AMMO_WEAPON_DEF_ID,
XXXMICROCHUNKID_DEF_SECONDARY_ROUNDS,
MICROCHUNKID_DEF_WEAPON_DEF_ID,
MICROCHUNKID_DEF_WEAPON_ROUNDS,
MICROCHUNKID_DEF_WEAPON_ERROR,
MICROCHUNKID_DEF_SECONDARY_WEAPON_DEF_ID,
};
bool ArmedGameObjDef::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_DEF_PARENT );
PhysicalGameObjDef::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_TILT_RATE, WeaponTiltRate );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_TILT_MIN, WeaponTiltMin );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_TILT_MAX, WeaponTiltMax );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_TURN_RATE, WeaponTurnRate );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_TURN_MIN, WeaponTurnMin );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_TURN_MAX, WeaponTurnMax );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_DEF_ID, WeaponDefID );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_SECONDARY_WEAPON_DEF_ID, SecondaryWeaponDefID );
WRITE_SAFE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_ROUNDS, WeaponRounds, int );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_WEAPON_ERROR, WeaponError );
csave.End_Chunk();
return true;
}
bool ArmedGameObjDef::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_DEF_PARENT:
PhysicalGameObjDef::Load( cload );
break;
case CHUNKID_DEF_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_TILT_RATE, WeaponTiltRate );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_TILT_MIN, WeaponTiltMin );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_TILT_MAX, WeaponTiltMax );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_TURN_RATE, WeaponTurnRate );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_TURN_MIN, WeaponTurnMin );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_TURN_MAX, WeaponTurnMax );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_DEF_ID, WeaponDefID );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_SECONDARY_WEAPON_DEF_ID, SecondaryWeaponDefID );
READ_SAFE_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_ROUNDS, WeaponRounds, int );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_WEAPON_ERROR, WeaponError );
default:
Debug_Say(( "Unrecognized ArmedDef Variable chunkID %d\n", cload.Cur_Micro_Chunk_ID() ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(( "Unrecognized ArmedDef chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
/*
** ArmedGameObj
*/
ArmedGameObj::ArmedGameObj( void ) :
MuzzleA0Bone( 0 ),
MuzzleA1Bone( 0 ),
MuzzleB0Bone( 0 ),
MuzzleB1Bone( 0 ),
TargetingPos(0,0,0)
{
WeaponBag = new WeaponBagClass( this );
}
ArmedGameObj::~ArmedGameObj( void )
{
delete WeaponBag;
}
/*
**
*/
void ArmedGameObj::Init( const ArmedGameObjDef & definition )
{
PhysicalGameObj::Init( definition );
Copy_Settings( definition );
return ;
}
/*
**
*/
void ArmedGameObj::Copy_Settings( const ArmedGameObjDef & definition )
{
WeaponClass * weapon = NULL;
if ( definition.WeaponDefID != 0 ) {
weapon = WeaponBag->Add_Weapon( definition.WeaponDefID, definition.WeaponRounds );
}
if ( definition.SecondaryWeaponDefID != 0 ) {
WeaponClass * s_weapon = WeaponBag->Add_Weapon( definition.SecondaryWeaponDefID, definition.WeaponRounds );
if ( weapon == NULL ) {
weapon = s_weapon;
}
}
if ( weapon != NULL ) {
WeaponBag->Select_Weapon( weapon );
}
Init_Muzzle_Bones();
return ;
}
/*
**
*/
void ArmedGameObj::Re_Init( const ArmedGameObjDef & definition )
{
PhysicalGameObj::Re_Init( definition );
//
// Remove all non-beacon entries from the weapon bag...
//
WeaponBagClass *old_bag = WeaponBag;
if ( WeaponBag != NULL ) {
//
// Loop over all the weapons in the bag
//
int weapon_index = WeaponBag->Get_Count();
while (weapon_index --) {
WeaponClass *weapon = WeaponBag->Peek_Weapon( weapon_index );
//
// If this isn't a beacon, then remove it
//
if (weapon != NULL && weapon->Get_Definition ()->Style != WEAPON_HOLD_STYLE_BEACON) {
WeaponBag->Remove_Weapon( weapon_index );
}
}
WeaponBag = NULL;
}
//
// Re-initialize the weapon bag
//
WeaponBag = new WeaponBagClass( this );
//
// Copy any internal settings from the definition
//
Copy_Settings( definition );
//
// Now add any beacons back into the weapon bag
//
if ( old_bag != NULL ) {
WeaponBag->Move_Contents( old_bag );
delete old_bag;
}
return ;
}
const ArmedGameObjDef & ArmedGameObj::Get_Definition( void ) const
{
return (const ArmedGameObjDef &)BaseGameObj::Get_Definition();
}
/*
** ArmedGameObj Save and Load
*/
enum {
CHUNKID_PARENT = 418001841,
CHUNKID_VARIABLES,
CHUNKID_WEAPONBAG,
MICROCHUNKID_TARGETING_POS = 1,
};
bool ArmedGameObj::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_PARENT );
PhysicalGameObj::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TARGETING_POS, TargetingPos );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_WEAPONBAG );
WeaponBag->Save( csave );
csave.End_Chunk();
return true;
}
bool ArmedGameObj::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_PARENT:
PhysicalGameObj::Load( cload );
break;
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_TARGETING_POS, TargetingPos );
default:
Debug_Say(( "Unrecognized ArmedGameObj Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
case CHUNKID_WEAPONBAG:
WeaponBag->Load( cload );
break;
default:
Debug_Say(( "Unrecognized ArmedGameObj chunkID\n" ));
break;
}
cload.Close_Chunk();
}
SaveLoadSystemClass::Register_Post_Load_Callback(this);
return true;
}
void ArmedGameObj::On_Post_Load( void )
{
PhysicalGameObj::On_Post_Load();
Init_Muzzle_Bones();
}
//-----------------------------------------------------------------------------
void ArmedGameObj::Import_Frequent(BitStreamClass & packet)
{
PhysicalGameObj::Import_Frequent( packet );
Vector3 targeting_pos;
packet.Get(targeting_pos.X, BITPACK_WORLD_POSITION_X);
packet.Get(targeting_pos.Y, BITPACK_WORLD_POSITION_Y);
packet.Get(targeting_pos.Z, BITPACK_WORLD_POSITION_Z);
//
// Don't force the targetting if the object is controlled
// by this player
//
SmartGameObj *smart_game_obj = As_SmartGameObj ();
if (smart_game_obj == NULL || smart_game_obj->Is_Controlled_By_Me() == false) {
Set_Targeting(targeting_pos);
}
return ;
}
//-----------------------------------------------------------------------------
void ArmedGameObj::Export_Frequent(BitStreamClass & packet)
{
PhysicalGameObj::Export_Frequent( packet );
packet.Add(TargetingPos.X, BITPACK_WORLD_POSITION_X);
packet.Add(TargetingPos.Y, BITPACK_WORLD_POSITION_Y);
packet.Add(TargetingPos.Z, BITPACK_WORLD_POSITION_Z);
}
//-----------------------------------------------------------------------------
void ArmedGameObj::Export_State_Cs(BitStreamClass & packet)
{
#if 1
Vector3 my_pos;
Get_Position( &my_pos );
Vector3 rel_target = TargetingPos - my_pos;
packet.Add(rel_target.X, BITPACK_WORLD_POSITION_X);
packet.Add(rel_target.Y, BITPACK_WORLD_POSITION_Y);
packet.Add(rel_target.Z, BITPACK_WORLD_POSITION_Z);
#else
packet.Add(TargetingPos.X, BITPACK_WORLD_POSITION_X);
packet.Add(TargetingPos.Y, BITPACK_WORLD_POSITION_Y);
packet.Add(TargetingPos.Z, BITPACK_WORLD_POSITION_Z);
#endif
}
//-----------------------------------------------------------------------------
void ArmedGameObj::Import_State_Cs(BitStreamClass & packet)
{
#if 1
Vector3 rel_target;
packet.Get(rel_target.X, BITPACK_WORLD_POSITION_X);
packet.Get(rel_target.Y, BITPACK_WORLD_POSITION_Y);
packet.Get(rel_target.Z, BITPACK_WORLD_POSITION_Z);
Vector3 my_pos;
Get_Position( &my_pos );
Vector3 targeting_pos = rel_target + my_pos;
Set_Targeting(targeting_pos);
#else
Vector3 targeting_pos;
packet.Get(targeting_pos.X, BITPACK_WORLD_POSITION_X);
packet.Get(targeting_pos.Y, BITPACK_WORLD_POSITION_Y);
packet.Get(targeting_pos.Z, BITPACK_WORLD_POSITION_Z);
Set_Targeting(targeting_pos);
#endif
}
void ArmedGameObj::Post_Think( void )
{
PhysicalGameObj::Post_Think();
WWPROFILE( "Armed PostThink" );
if ( Is_Delete_Pending() ) { // don't update if destroying... (so we don't create a new laser!)
return;
}
if ( Get_Weapon() != NULL ) { // Update the weapon after the commands and update_human_animation
Get_Weapon()->Update();
}
// allow any recoil animation to progress
if (Peek_Model() != NULL) {
for (int i=0; i<MAX_MUZZLES; i++) {
MuzzleRecoilController[i].Update(Peek_Model());
}
}
}
/*
** Weapons
*/
WeaponClass * ArmedGameObj::Get_Weapon( void )
{
return WeaponBag->Get_Weapon();
}
void ArmedGameObj::Init_Muzzle_Bones( void )
{
MuzzleA0Bone = Peek_Model()->Get_Bone_Index( "muzzlea0" );
MuzzleA1Bone = Peek_Model()->Get_Bone_Index( "muzzlea1" );
MuzzleB0Bone = Peek_Model()->Get_Bone_Index( "muzzleb0" );
MuzzleB1Bone = Peek_Model()->Get_Bone_Index( "muzzleb1" );
if (MuzzleA1Bone == 0) {
MuzzleA1Bone = MuzzleA0Bone;
}
if (MuzzleB0Bone == 0) {
MuzzleB0Bone = MuzzleA0Bone;
}
if (MuzzleB1Bone == 0) {
MuzzleB1Bone = MuzzleB0Bone;
}
MuzzleRecoilController[0].Init(MuzzleA0Bone);
MuzzleRecoilController[1].Init(MuzzleA1Bone);
MuzzleRecoilController[2].Init(MuzzleB0Bone);
MuzzleRecoilController[3].Init(MuzzleB1Bone);
// Let the weapon learn about muzzle flashes
if ( Get_Weapon() ) {
Get_Weapon()->Set_Model( Peek_Model() );
}
}
bool ArmedGameObj::Set_Targeting( const Vector3 & pos, bool do_tilt )
{
TargetingPos = pos;
// Move the turret to match the target
return true;
}
const Matrix3D & ArmedGameObj::Get_Muzzle( int index )
{
RenderObjClass * model = Peek_Model();
if ( index == 3 && MuzzleB1Bone != 0 ) {
return model->Get_Bone_Transform( MuzzleB1Bone );
}
if ( index >= 2 && MuzzleB0Bone != 0 ) {
return model->Get_Bone_Transform( MuzzleB0Bone );
}
if ( index == 1 && MuzzleA1Bone != 0 ) {
return model->Get_Bone_Transform( MuzzleA1Bone );
}
if ( MuzzleA0Bone != 0 ) {
return model->Get_Bone_Transform( MuzzleA0Bone );
}
return Get_Transform();
}
bool ArmedGameObj::Muzzle_Exists( int index )
{
if ( index == 0 ) {
return MuzzleA0Bone != 0;
}
if ( index == 1 ) {
return MuzzleA1Bone != 0;
}
if ( index == 2 ) {
return MuzzleB0Bone != 0;
}
if ( index == 3 ) {
return MuzzleB1Bone != 0;
}
return false;
}
void ArmedGameObj::Start_Recoil( int muzzle_index,float recoil_scale,float recoil_time )
{
WWASSERT(muzzle_index >= 0);
WWASSERT(muzzle_index < MAX_MUZZLES);
MuzzleRecoilController[muzzle_index].Start_Recoil(recoil_scale,recoil_time);
}

157
Code/Combat/armedgameobj.h Normal file
View File

@@ -0,0 +1,157 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/armedgameobj.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/17/01 4:18p $*
* *
* $Revision:: 23 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef ARMEDGAMEOBJ_H
#define ARMEDGAMEOBJ_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef PHYSICALGAMEOBJ_H
#include "physicalgameobj.h"
#endif
#ifndef MUZZLERECOIL_H
#include "muzzlerecoil.h"
#endif
/*
**
*/
class WeaponClass;
class WeaponBagClass;
/*
** ArmedGameObjDef - Defintion class for a ArmedGameObj
*/
class ArmedGameObjDef : public PhysicalGameObjDef
{
public:
ArmedGameObjDef( void );
// virtual uint32 Get_Class_ID( void ) const;
// virtual PersistClass * Create( void ) const ;
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
// virtual const PersistFactoryClass & Get_Factory( void ) const;
DECLARE_EDITABLE( ArmedGameObjDef, PhysicalGameObjDef );
protected:
float WeaponTiltRate;
float WeaponTiltMin;
float WeaponTiltMax;
float WeaponTurnRate;
float WeaponTurnMin;
float WeaponTurnMax;
float WeaponError;
int WeaponDefID;
int SecondaryWeaponDefID;
safe_int WeaponRounds;
friend class ArmedGameObj;
};
/*
**
*/
class ArmedGameObj : public PhysicalGameObj {
public:
// Constructor and Destructor
ArmedGameObj( void );
virtual ~ArmedGameObj( void );
// Definitions
void Init( const ArmedGameObjDef & definition );
void Copy_Settings( const ArmedGameObjDef & definition );
void Re_Init( const ArmedGameObjDef & definition );
const ArmedGameObjDef & Get_Definition( void ) const ;
// Save / Load
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
virtual void On_Post_Load( void );
// State import/export
virtual void Import_Frequent( BitStreamClass & packet );
virtual void Export_Frequent( BitStreamClass & packet );
virtual void Import_State_Cs( BitStreamClass & packet );
virtual void Export_State_Cs( BitStreamClass & packet );
// Thinking
virtual void Post_Think();
// Weapon
WeaponClass * Get_Weapon( void );
WeaponBagClass * Get_Weapon_Bag( void ) { return WeaponBag; }
bool Muzzle_Exists( int index = 0 );
virtual const Matrix3D &Get_Muzzle( int index = 0 );
void Start_Recoil( int muzzle_index,float recoil_scale,float recoil_time );
float Get_Weapon_Error( void ) { return Get_Definition().WeaponError; }
// Targeting
Vector3 Get_Targeting_Pos( void ) { return TargetingPos; }
virtual bool Set_Targeting( const Vector3 & pos, bool do_tilt = true );
// Type identification
virtual ArmedGameObj *As_ArmedGameObj( void ) { return this; }
protected:
WeaponBagClass * WeaponBag; // Weapon & Ammo collection
private:
Vector3 TargetingPos;
int MuzzleA0Bone; // YUCK!!!
int MuzzleA1Bone;
int MuzzleB0Bone;
int MuzzleB1Bone;
enum { MAX_MUZZLES = 4 };
MuzzleRecoilClass MuzzleRecoilController[MAX_MUZZLES];
void Init_Muzzle_Bones( void );
};
#endif // ARMEDGAMEOBJ_H

341
Code/Combat/assetdep.cpp Normal file
View File

@@ -0,0 +1,341 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/assetdep.cpp $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 11/29/01 9:48p $*
* *
* $Revision:: 12 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "assetdep.h"
#include "chunkio.h"
#include "wwstring.h"
#include "assetmgr.h"
#include "ffactory.h"
#include "saveloadstatus.h"
#include "wwprofile.h"
///////////////////////////////////////////////////////////////////////
// Local prototypes
///////////////////////////////////////////////////////////////////////
static void Asset_Name_From_Filename (StringClass& new_name, const char *filename);
static void Get_Filename_From_Path (StringClass& new_name, const char *filename);
///////////////////////////////////////////////////////////////////////
// Constants
///////////////////////////////////////////////////////////////////////
static const char * ALWAYS_FILENAME = "always.dep";
static const char * DEP_EXTENSION = ".dep";
enum
{
CHUNKID_FILE_LIST = 0x04020527,
VARID_ASSET_FILENAME = 0x01,
};
///////////////////////////////////////////////////////////////////////
//
// Save_Always_Dependencies
//
///////////////////////////////////////////////////////////////////////
void
AssetDependencyManager::Save_Always_Dependencies (const char *path, ASSET_LIST &asset_list)
{
//
// Get a pointer to the file object
//
StringClass filename(path + StringClass ("\\") + StringClass (ALWAYS_FILENAME),true);
FileClass * file = _TheWritingFileFactory->Get_File (filename);
if (file != NULL) {
//
// Open or create the file
//
file->Open (FileClass::WRITE);
//
// Save the asset list to the file
//
ChunkSaveClass csave (file);
Save_Dependencies (csave, asset_list);
//
// Close the file
//
file->Close ();
_TheWritingFileFactory->Return_File (file);
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Save_Level_Dependencies
//
///////////////////////////////////////////////////////////////////////
void
AssetDependencyManager::Save_Level_Dependencies (const char *full_path, ASSET_LIST &asset_list)
{
//
// Get a pointer to the file object
//
FileClass * file = _TheWritingFileFactory->Get_File (full_path);
if (file != NULL) {
//
// Open or create the file
//
file->Open (FileClass::WRITE);
//
// Save the asset list to the file
//
ChunkSaveClass csave (file);
Save_Dependencies (csave, asset_list);
//
// Close the file
//
file->Close ();
_TheWritingFileFactory->Return_File (file);
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Save_Dependencies
//
///////////////////////////////////////////////////////////////////////
void
AssetDependencyManager::Save_Dependencies (ChunkSaveClass &csave, ASSET_LIST &asset_list)
{
csave.Begin_Chunk (CHUNKID_FILE_LIST);
//
// Write each filename dependency to a chunk
//
for (int index = 0; index < asset_list.Count (); index ++) {
StringClass &filename = asset_list[index];
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_ASSET_FILENAME, filename);
}
csave.End_Chunk ();
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Load_Level_Assets
//
///////////////////////////////////////////////////////////////////////
void
AssetDependencyManager::Load_Level_Assets (const char *level_name)
{
//
// Strip the extension (if necessary)
//
StringClass base_name(level_name,true);
const char *extension = ::strrchr (base_name, '.');
if (extension != NULL && base_name.Get_Length () > 4) {
base_name.Erase (base_name.Get_Length () - 4, 4);
}
//
// Build a filename from the level name, and load the assets from it.
//
StringClass filename(base_name + StringClass (DEP_EXTENSION),true);
Load_Assets (filename);
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Load_Always_Assets
//
///////////////////////////////////////////////////////////////////////
void
AssetDependencyManager::Load_Always_Assets (void)
{
//
// Load the assets from the always file
//
Load_Assets (ALWAYS_FILENAME);
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Load_Assets
//
///////////////////////////////////////////////////////////////////////
void
AssetDependencyManager::Load_Assets (const char *filename)
{
//
// Get a pointer to the file object
//
FileClass * file = _TheFileFactory->Get_File (filename);
if (file != NULL) {
if ( file->Is_Available() ) {
//
// Open the file
//
file->Open (FileClass::READ);
//
// Load the asset dependencies from the file
//
ChunkLoadClass cload (file);
Load_Assets (cload);
//
// Close the file
//
file->Close ();
} else {
WWDEBUG_SAY(( "Failed to find %s\n", filename ));
}
_TheFileFactory->Return_File (file);
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Load_Assets
//
///////////////////////////////////////////////////////////////////////
void
AssetDependencyManager::Load_Assets (ChunkLoadClass &cload)
{
WWLOG_PREPARE_TIME_AND_MEMORY("AssetDependencyManager::Load_Assets (ChunkLoadClass &cload)");
cload.Open_Chunk ();
WWASSERT (cload.Cur_Chunk_ID () == CHUNKID_FILE_LIST);
if (cload.Cur_Chunk_ID () == CHUNKID_FILE_LIST) {
//
// Read the filename of each asset from the chunk and
// load its assets into the asset manager.
//
while (cload.Open_Micro_Chunk ()) {
switch (cload.Cur_Micro_Chunk_ID ())
{
case VARID_ASSET_FILENAME:
{
//
// Read the filename from the chunk
//
StringClass filename(0,true);
int size = cload.Cur_Micro_Chunk_Length ();
cload.Read (filename.Get_Buffer (size), size);
//
// Determine what the render object name should be from
// the filename.
//
StringClass render_obj_name(0,true);
::Asset_Name_From_Filename (render_obj_name,filename);
INIT_SUB_STATUS(filename);
//
// Load the assets from this file into the asset manager
//
if (WW3DAssetManager::Get_Instance ()->Render_Obj_Exists (render_obj_name) == false) {
WW3DAssetManager::Get_Instance ()->Load_3D_Assets (filename);
}
// WWLOG_INTERMEDIATE(filename);
}
break;
default:
WWDEBUG_SAY (("Unexpected chunk id %d found while preloading assets.\r\n", cload.Cur_Micro_Chunk_ID));
break;
}
cload.Close_Micro_Chunk ();
}
}
cload.Close_Chunk ();
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Filename_From_Path
//
////////////////////////////////////////////////////////////////////////////
void Get_Filename_From_Path (StringClass& new_filename, const char *path)
{
// Find the last occurance of the directory deliminator
const char *filename = ::strrchr (path, '\\');
if (filename != NULL) {
// Increment past the directory deliminator
filename ++;
} else {
filename = path;
}
new_filename=filename;
}
////////////////////////////////////////////////////////////////////////////
//
// Asset_Name_From_Filename
//
////////////////////////////////////////////////////////////////////////////
void Asset_Name_From_Filename (StringClass& asset_name, const char *filename)
{
// Get the filename from this path
::Get_Filename_From_Path (asset_name, filename);
// Find and strip off the extension (if it exists)
char *extension = ::strrchr (asset_name, '.');
if (extension != NULL) {
extension[0] = 0;
}
}

85
Code/Combat/assetdep.h Normal file
View File

@@ -0,0 +1,85 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/assetdep.h $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 4/20/00 5:59p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __ASSET_DEP_H
#define __ASSET_DEP_H
#include "vector.h"
///////////////////////////////////////////////////////////////////////
// Forward declarations
///////////////////////////////////////////////////////////////////////
class ChunkSaveClass;
class ChunkLoadClass;
class StringClass;
///////////////////////////////////////////////////////////////////////
//
// AssetDependencyManager
//
///////////////////////////////////////////////////////////////////////
class AssetDependencyManager
{
public:
////////////////////////////////////////////////////////////////////
// Public data types
////////////////////////////////////////////////////////////////////
typedef DynamicVectorClass<StringClass> ASSET_LIST;
////////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////////
static void Save_Always_Dependencies (const char *path, ASSET_LIST &asset_list);
static void Save_Level_Dependencies (const char *full_path, ASSET_LIST &asset_list);
static void Save_Dependencies (ChunkSaveClass &csave, ASSET_LIST &asset_list);
static void Load_Level_Assets (const char *level_name);
static void Load_Always_Assets (void);
static void Load_Assets (const char *filename);
static void Load_Assets (ChunkLoadClass &cload);
};
#endif //__ASSET_DEP_H

143
Code/Combat/assets.cpp Normal file
View File

@@ -0,0 +1,143 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/assets.cpp $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 8/31/01 8:03p $*
* *
* $Revision:: 49 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "assets.h"
#include "wwfile.h"
#include "debug.h"
#include "ffactory.h"
/*
**
*/
INIClass * Get_INI( const char * filename )
{
INIClass * ini = NULL;
FileClass * INIfile = _TheFileFactory->Get_File( filename );
if ( INIfile ) {
if ( INIfile->Is_Available() ) {
ini = new INIClass( *INIfile );
}
_TheFileFactory->Return_File( INIfile );
}
return ini;
}
void Save_INI( INIClass * p_ini, const char * filename )
{
WWASSERT(p_ini != NULL);
WWASSERT(filename != NULL);
FileClass * p_INIfile = _TheWritingFileFactory->Get_File(filename);
if (p_INIfile != NULL && p_INIfile->Is_Available()) {
p_ini->Save(*p_INIfile);
_TheWritingFileFactory->Return_File(p_INIfile);
}
}
void Release_INI( INIClass * ini )
{
WWASSERT( ini );
delete ini;
}
/*
**
*/
void Strip_Path_From_Filename( StringClass& new_name, const char * filename )
{
if ( ::strchr( filename, '\\' ) != 0 ) {
new_name = ::strrchr( filename, '\\' ) + 1;
}
else new_name=filename;
}
/*
** Asset access
*/
void Get_Render_Obj_Name_From_Filename( StringClass& new_name, const char * filename )
{
Strip_Path_From_Filename( new_name, filename );
if ( new_name.Get_Length() > 4 ) {
new_name.Erase( new_name.Get_Length() - 4, 4 );
}
}
RenderObjClass * Create_Render_Obj_From_Filename( const char * filename )
{
StringClass render_obj_name(true);
Strip_Path_From_Filename( render_obj_name, filename );
render_obj_name.Erase( render_obj_name.Get_Length() - 4, 4 );
RenderObjClass *model = WW3DAssetManager::Get_Instance()->Create_Render_Obj( render_obj_name );
if ( model == NULL ) {
Debug_Say(( "Failed to create \"%s\" from \"%s\"\n", (const char *)render_obj_name, filename ));
}
return model;
}
TextureClass * Get_Texture_From_Filename
(
const char * filename,
TextureClass::MipCountType mip_level_count
)
{
StringClass tex_name(true);
Strip_Path_From_Filename( tex_name, filename );
return WW3DAssetManager::Get_Instance()->Get_Texture( tex_name, mip_level_count );
}
/*
** Filenames
*/
void Create_Animation_Name( StringClass& anim_name, const char * anim_filename, const char * model_name )
{
anim_name=anim_filename;
if ( ::strrchr( anim_name, '\\' ) != 0 ) {
StringClass temp(::strrchr( anim_name, '\\' ) + 1,true);
anim_name = temp;
anim_name.Erase( anim_name.Get_Length() - 4, 4 ); // Strip off ".w3d"
}
if ( ::strchr( anim_name, '.' ) == 0 ) { // Add model name
StringClass temp(true);
temp.Format( "%s.%s", model_name, anim_name );
anim_name = temp;
}
}

80
Code/Combat/assets.h Normal file
View File

@@ -0,0 +1,80 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/assets.h $*
* *
* $Author:: Jani_p $*
* *
* $Modtime:: 8/31/01 8:03p $*
* *
* $Revision:: 31 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef ASSETS_H
#define ASSETS_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef ASSETMGR_H
#include "assetmgr.h"
#endif
#ifndef INI_H
#include "ini.h"
#endif
/*
** INI File Access
*/
void Set_INI_Path( const char * path );
INIClass * Get_INI( const char * filename );
void Save_INI( INIClass * p_ini, const char * filename );
void Release_INI( INIClass * ini );
/*
** Path Striping
*/
void Strip_Path_From_Filename( StringClass& new_name, const char * filename );
void Get_Render_Obj_Name_From_Filename( StringClass& new_name, const char * filename );
/*
** Asset access - these functions strips the path off of the filenames; for use
** with filenames that come from preset definitions.
*/
RenderObjClass * Create_Render_Obj_From_Filename( const char * filename );
TextureClass * Get_Texture_From_Filename( const char * filename,
TextureClass::MipCountType mip_level_count=TextureClass::MIP_LEVELS_ALL );
/*
** Filenames
*/
void Create_Animation_Name( StringClass& anim_name, const char * anim_filename, const char * model_name );
#endif // ASSETS_H

File diff suppressed because it is too large Load Diff

651
Code/Combat/backgroundmgr.h Normal file
View File

@@ -0,0 +1,651 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/backgroundmgr.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/15/02 7:26p $*
* *
* $Revision:: 25 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __BACKGROUNDMGR_H
#define __BACKGROUNDMGR_H
// Includes.
#include "combat.h"
#include "combatchunkid.h"
#include "dx8indexbuffer.h"
#include "networkobject.h"
#include "rendobj.h"
#include "saveloadsubsystem.h"
#include "segline.h"
#include "shader.h"
#include "vector3.h"
#include "vector3i.h"
#include "vertmaterial.h"
#include "wwdebug.h"
// Forward declarations.
class CameraClass;
class DazzleRenderObjClass;
class SimpleSceneClass;
class TextureClass;
class SoundEnvironmentClass;
// Classes.
class VisibilityClass {
public:
VisibilityClass() {Visible = true;}
bool Is_Visible() {return (Visible);}
void Set_Visibility (bool visible) {Visible = visible;}
private :
bool Visible;
};
class HazeClass : public VisibilityClass
{
public:
HazeClass (float radius);
~HazeClass();
void Configure (const Vector3 &blendcolor, const Vector3 &horizoncolor, float intensity);
void Configure (const Vector3 &blendcolor, const Vector3 &horizoncolor);
void Configure (const Vector3 &blendcolor, float intensity);
void Configure (const Vector3 &blendcolor);
Vector3 Get_Horizon_Color() {return (HorizonColor * Intensity);}
void Render();
protected:
enum {
ROW_COUNT = 3,
VERTICES_PER_TRIANGLE = 3
};
void Configure();
Vector3 BlendColor;
Vector3 HorizonColor;
float Intensity;
unsigned RowCount;
unsigned VertexCount;
Vector3 *VertexArray;
unsigned TriangleCount;
DX8IndexBufferClass *IndexBuffer;
unsigned *DiffuseArray;
VertexMaterialClass *Material;
ShaderClass Shader;
};
class StarfieldClass : public VisibilityClass
{
public:
StarfieldClass (float radius, unsigned starcount);
~StarfieldClass();
void Configure (const Vector3 &orientation, float length, float radius, const Vector3 &color0, const Vector3 &color1, float alpha);
void Configure (const Vector3 &orientation, float length, float radius);
void Configure (const Vector3 &color0, const Vector3 &color1, float alpha);
void Render();
protected:
void Configure();
enum {
VERTICES_PER_TRIANGLE = 3
};
Vector3 Orientation;
float Length;
float Radius;
Vector3 Color0, Color1;
float Alpha;
unsigned VertexCount;
Vector3 *VertexArray;
unsigned TriangleCount;
DX8IndexBufferClass *IndexBuffer;
VertexMaterialClass *Material;
ShaderClass Shader;
TextureClass *Texture;
unsigned *DiffuseArray;
unsigned ActiveVertexCount;
unsigned ActiveTriangleCount;
};
class SkyObjectClass : public VisibilityClass
{
public:
SkyObjectClass (ShaderClass shader);
~SkyObjectClass();
void Configure (const Vector3 &direction, float length, float radius, const Vector3 &color);
void Configure (const Vector3 &direction, float length, float width, float height);
void Configure (const Vector3 &direction, float length, float radius);
void Configure (const Vector3 &color);
void Set_Texture (const char *texturename);
Vector3 Get_Color() {return (Color);}
void Render();
protected:
enum {
VERTICES_PER_TRIANGLE = 3
};
void Configure();
Vector3 Direction;
float Length;
float Width;
float Height;
Vector3 Color;
unsigned VertexCount;
Vector3 *VertexArray;
unsigned TriangleCount;
DX8IndexBufferClass *IndexBuffer;
VertexMaterialClass *Material;
ShaderClass Shader;
TextureClass *Texture;
Vector2 *TexCoordArray;
unsigned *DiffuseArray;
};
class CloudLayerClass : public VisibilityClass
{
public:
CloudLayerClass (float maxdistance, const char *texturename, const Vector2 &velocity, float tilefactor, bool rotate);
~CloudLayerClass();
void Configure (const Vector3 &warmcolor, const Vector3 &coldcolor);
void Configure (const Vector3 &warmdirection);
void Configure (const Vector3 &warmcolor, const Vector3 &coldcolor, const Vector3 &warmdirection);
void Configure (float alpha, float cloudintensity, float horizonintensity);
void Render();
protected:
enum {
VERTICES_PER_TRIANGLE = 3
};
void Configure();
Vector3 WarmColor;
Vector3 ColdColor;
Vector3 WarmDirection;
float Alpha;
float CloudIntensity;
float HorizonIntensity;
unsigned RowCount;
unsigned VertexCount;
Vector3 *VertexArray;
unsigned TriangleCount;
DX8IndexBufferClass *IndexBuffer;
VertexMaterialClass *Material;
ShaderClass Shader;
TextureClass *Texture;
Vector2 *TexCoordArray;
Vector2 Velocity;
unsigned *DiffuseArray;
};
class SkyGlowClass : public VisibilityClass
{
public:
SkyGlowClass (float radius);
~SkyGlowClass();
void Configure (const Vector2 &hotdirection, const Vector3 &horizoncolor, float coldintensity);
void Render();
protected:
enum {
ROW_COUNT = 5,
VERTICES_PER_TRIANGLE = 3
};
void Configure();
Vector2 HotDirection;
Vector3 HorizonColor;
float ColdIntensity;
unsigned RowCount;
float Radius;
float MinZ, MaxZ;
unsigned VertexCount;
Vector3 *VertexArray;
unsigned TriangleCount;
DX8IndexBufferClass *IndexBuffer;
unsigned *DiffuseArray;
VertexMaterialClass *Material;
ShaderClass Shader;
};
class LightningBoltClass : public VisibilityClass, public SegmentedLineClass
{
public:
LightningBoltClass::LightningBoltClass (int branchcount, Matrix3D &m, float length, float childlength, float width, float amplitude);
~LightningBoltClass ();
void Configure (Vector3 &color);
virtual void Set_Transform (Matrix3D &t);
virtual void Render (RenderInfoClass &rinfo);
void Set_Visibility (bool visible, bool recurse);
private:
struct BranchStruct {
LightningBoltClass *LightningBolt;
};
BranchStruct *Branches;
int BranchCount;
};
class LightningClass
{
public:
LightningClass (float extent, float startdistance, float enddistance, float heading, float distribution);
~LightningClass();
bool Update (Matrix3D &t, Vector3 &additivecolor, SoundEnvironmentClass *soundenvironment);
void Render (RenderInfoClass &rinfo);
private:
SkyGlowClass *LightningGlow;
LightningBoltClass *LightningBolt;
SkyObjectClass *LightningSource;
Vector2 Direction;
float Distance;
unsigned Time;
unsigned ThunderDelayTime;
Vector3 ThunderPosition;
const char *ThunderSampleName;
bool PlayedThunder;
};
class WarBlitzClass
{
public:
WarBlitzClass (float extent, float startdistance, float enddistance, float heading, float distribution);
~WarBlitzClass();
bool Update (Matrix3D &t, Vector3 &additivecolor);
void Render (RenderInfoClass &rinfo);
private:
SkyGlowClass *WarBlitzGlow;
Vector2 Direction;
float Distance;
unsigned Time;
unsigned SampleDelayTime;
Vector3 SamplePosition;
bool PlayedSample;
};
class SkyClass : public RenderObjClass
{
public:
enum MoonTypeEnum {
MOON_TYPE_FULL,
MOON_TYPE_PART,
MOON_TYPE_COUNT
};
SkyClass (SoundEnvironmentClass *soundenvironment);
~SkyClass();
RenderObjClass *Clone() const
{
WWASSERT (false);
return (0);
}
void Set_Color();
Vector3 Get_Color() {return (Color);}
SkyObjectClass *Get_Sun() {return (Sun);}
void Set_Light_Direction (const Vector3 &sundirection, const Vector3 &moondirection);
void Set_Time_Of_Day (unsigned hours, unsigned minutes);
void Set_Moon_Type (MoonTypeEnum moontype);
void Set_Clouds (float cloudcover, float gloominess);
void Set_Tint_Factor (float tintfactor);
void Set_Lightning (float intensity, float startdistance, float enddistance, float heading, float distribution)
{
LightningIntensity = intensity;
LightningStartDistance = startdistance;
LightningEndDistance = enddistance;
LightningHeading = DEG_TO_RADF (heading);
LightningDistribution = distribution;
}
void Set_War_Blitz (float intensity, float startdistance, float enddistance, float heading, float distribution)
{
WarBlitzIntensity = intensity;
WarBlitzStartDistance = startdistance;
WarBlitzEndDistance = enddistance;
WarBlitzHeading = DEG_TO_RADF (heading);
WarBlitzDistribution = distribution;
}
void Update (SceneClass *mainscene, const Vector3 &cameraposition);
void Render (RenderInfoClass &rinfo);
void Get_Obj_Space_Bounding_Sphere (SphereClass &sphere) const;
void Get_Obj_Space_Bounding_Box (AABoxClass &box) const;
protected:
enum {
LIGHTNING_COUNT = 2
};
Vector3 Interpolate_Color (const unsigned char colortable [][3], unsigned colorcount, float interpolant);
float Interpolate_Scalar (const unsigned char scalartable [], unsigned scalarcount, float interpolant);
unsigned Lightning_Delay();
unsigned War_Blitz_Delay();
float Extent; // Radius of sphere (and half cube width) which contains all sky objects (for clipping purposes).
Vector3 Color;
unsigned Hours, Minutes;
float Gloominess;
float TintFactor;
HazeClass *Haze;
StarfieldClass *Starfield;
SkyObjectClass *Sun;
SkyObjectClass *SunHalo;
SkyObjectClass *Moon;
SkyObjectClass *MoonHalo;
CloudLayerClass *CloudLayer0;
CloudLayerClass *CloudLayer1;
LightningClass *Lightning [LIGHTNING_COUNT];
int LightningCountdown [LIGHTNING_COUNT];
float LightningIntensity;
float LightningStartDistance;
float LightningEndDistance;
float LightningHeading;
float LightningDistribution;
SoundEnvironmentClass *SoundEnvironment;
WarBlitzClass *WarBlitz;
int WarBlitzCountdown;
float WarBlitzIntensity;
float WarBlitzStartDistance;
float WarBlitzEndDistance;
float WarBlitzHeading;
float WarBlitzDistribution;
};
class BackgroundParameterClass
{
public:
void Initialize();
void Set (float targetvalue, float ramptime, bool override);
void Set (float overrideramptime) {OverrideDuration = overrideramptime;}
float Value() {return (CurrentValue);}
bool Update (float time, bool override);
void Update (float &value, float &target, float &duration, float time);
private:
float CurrentValue;
float NormalValue;
float NormalTarget;
float NormalDuration;
float OverrideTarget;
float OverrideDuration;
friend class BackgroundMgrClass;
};
class BackgroundMgrClass : public SaveLoadSubSystemClass, public NetworkObjectClass
{
public:
enum LightSourceTypeEnum {
LIGHT_SOURCE_TYPE_SUN,
LIGHT_SOURCE_TYPE_MOON
};
BackgroundMgrClass();
~BackgroundMgrClass() {}
uint32 Chunk_ID() const {return (CHUNKID_BACKGROUND_MGR);}
const char *Name() const {return ("BackgroundMgrClass");}
void Delete (void) {}
virtual void Set_Delete_Pending (void) {};
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
bool Load_Micro_Chunks (ChunkLoadClass &cload);
void Export_Rare (BitStreamClass &packet);
void Import_Rare (BitStreamClass &packet);
static void Init (SimpleSceneClass *renderscene, SoundEnvironmentClass *soundenvironment, bool render_available = true);
static void Reset();
static void Shutdown();
static bool Save_Dynamic (ChunkSaveClass &csave);
static bool Load_Dynamic (ChunkLoadClass &cload);
static bool Load_Dynamic_Micro_Chunks (ChunkLoadClass &cload);
static Vector3 Get_Clear_Color()
{
if (_Sky != NULL) {
return (_Sky->Get_Color());
} else {
return (Vector3 (0.0f, 0.0f, 0.0f));
}
}
static bool Set_Time_Of_Day (unsigned hours, unsigned minutes)
{
if ((hours >= 0) && (hours <= 23) && (minutes >= 0) && (minutes <= 59)) {
_Hours = hours;
_Minutes = minutes;
Set_Dirty();
return (true);
} else {
return (false);
}
}
static void Get_Time_Of_Day (unsigned &hours, unsigned &minutes)
{
hours = _Hours;
minutes = _Minutes;
}
static void Set_Light_Source_Type (LightSourceTypeEnum lightsourcetype)
{
_LightSourceType = lightsourcetype;
Set_Dirty();
}
static LightSourceTypeEnum Get_Light_Source_Type() {return (_LightSourceType);}
static void Set_Moon_Type (SkyClass::MoonTypeEnum moontype)
{
_MoonType = moontype;
Set_Dirty();
}
static SkyClass::MoonTypeEnum Get_Moon_Type()
{
return (_MoonType);
}
static bool Set_Clouds (float cloudcover, float cloudgloominess, float ramptime = 0.0f);
static bool Override_Clouds (float cloudcover, float cloudgloominess, float ramptime = 0.0f);
static void Get_Clouds (float &cloudcover, float &gloominess);
static void Restore_Clouds (float ramptime);
static bool Set_Sky_Tint (float skytintfactor, float ramptime = 0.0f);
static bool Override_Sky_Tint (float skytintfactor, float ramptime = 0.0f);
static void Restore_Sky_Tint (float ramptime);
static bool Set_Lightning_Intensity (float intensity, float ramptime = 0.0f);
static bool Set_Lightning (float intensity, float startdistance, float enddistance, float heading, float distribution, float ramptime = 0.0f);
static bool Override_Lightning (float intensity, float startdistance, float enddistance, float heading, float distribution, float ramptime = 0.0f);
static void Get_Lightning (float &intensity, float &startdistance, float &enddistance, float &heading, float &distribution);
static void Restore_Lightning (float ramptime);
static bool Set_War_Blitz (float intensity, float ramptime = 0.0f);
static bool Set_War_Blitz (float intensity, float startdistance, float enddistance, float heading, float distribution, float ramptime = 0.0f, bool override = false);
static void Get_War_Blitz (float &intensity, float &startdistance, float &enddistance, float &heading, float &distribution);
static void Update (PhysicsSceneClass *mainscene, CameraClass *camera);
private:
#define VARID_PARAMETER(varname) \
VARID_ ## varname ## _CURRENT_VALUE, \
VARID_ ## varname ## _NORMAL_VALUE, \
VARID_ ## varname ## _NORMAL_TARGET, \
VARID_ ## varname ## _NORMAL_DURATION, \
VARID_ ## varname ## _OVERRIDE_TARGET, \
VARID_ ## varname ## _OVERRIDE_DURATION
// Constants.
enum
{
CHUNKID_MICRO_CHUNKS = 0x11080732,
CHUNKID_DYNAMIC_MICRO_CHUNKS = 0x11020216
};
enum {
VARID_TIME_HOURS = 0x14,
VARID_TIME_MINUTES,
VARID_LIGHT_SOURCE_TYPE,
VARID_MOON_TYPE,
VARID_PARAMETER (CLOUD_COVER),
VARID_PARAMETER (CLOUD_GLOOMINESS),
VARID_PARAMETER (SKY_TINT_FACTOR),
VARID_PARAMETER (LIGHTNING_INTENSITY),
VARID_PARAMETER (LIGHTNING_START_DISTANCE),
VARID_PARAMETER (LIGHTNING_END_DISTANCE),
VARID_PARAMETER (LIGHTNING_HEADING),
VARID_PARAMETER (LIGHTNING_DISTRIBUTION),
VARID_CLOUD_OVERRIDE_COUNT,
VARID_LIGHTNING_OVERRIDE_COUNT,
VARID_PARAMETER (WAR_BLITZ_INTENSITY),
VARID_PARAMETER (WAR_BLITZ_START_DISTANCE),
VARID_PARAMETER (WAR_BLITZ_END_DISTANCE),
VARID_PARAMETER (WAR_BLITZ_HEADING),
VARID_PARAMETER (WAR_BLITZ_DISTRIBUTION),
VARID_SKY_TINT_OVERRIDE_COUNT
};
#undef VARID_PARAMETER
enum {
PARAMETER_CLOUD_COVER,
PARAMETER_CLOUD_GLOOMINESS,
PARAMETER_SKY_TINT_FACTOR,
PARAMETER_LIGHTNING_INTENSITY,
PARAMETER_LIGHTNING_START_DISTANCE,
PARAMETER_LIGHTNING_END_DISTANCE,
PARAMETER_LIGHTNING_HEADING,
PARAMETER_LIGHTNING_DISTRIBUTION,
PARAMETER_WAR_BLITZ_INTENSITY,
PARAMETER_WAR_BLITZ_START_DISTANCE,
PARAMETER_WAR_BLITZ_END_DISTANCE,
PARAMETER_WAR_BLITZ_HEADING,
PARAMETER_WAR_BLITZ_DISTRIBUTION,
PARAMETER_COUNT
};
static bool Set_Clouds (float cloudcover, float cloudgloominess, float ramptime, bool override);
static bool Set_Sky_Tint (float skytintfactor, float ramptime, bool override);
static bool Set_Lightning_Intensity (float intensity, float ramptime, bool override);
static bool Set_Lightning (float intensity, float startdistance, float enddistance, float heading, float distribution, float ramptime, bool override);
static bool Is_Dirty() {return (_Dirty);}
static void Set_Dirty (bool dirty = true) {_Dirty = dirty;}
static unsigned _Hours;
static unsigned _Minutes;
static LightSourceTypeEnum _LightSourceType;
static SkyClass::MoonTypeEnum _MoonType;
static BackgroundParameterClass _Parameters [PARAMETER_COUNT];
static Vector3 _LightVector;
static Vector3 _UnitLightVector;
static unsigned _CloudOverrideCount;
static unsigned _LightningOverrideCount;
static unsigned _SkyTintOverrideCount;
static bool _Dirty;
static bool _FogEnabled;
static SkyClass *_Sky;
static DazzleRenderObjClass *_Dazzle;
};
// Externals.
extern BackgroundMgrClass _TheBackgroundMgr;
#endif // BACKGROUNDMGR_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,255 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/basecontroller.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/15/02 7:18p $*
* *
* $Revision:: 19 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __BASE_CONTROLLER_H
#define __BASE_CONTROLLER_H
#include "building.h"
#include "obbox.h"
#include "vector.h"
#include "characterclasssettings.h"
#include "networkobject.h"
////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////
class ChunkSaveClass;
class ChunkLoadClass;
class ConversationClass;
class ActiveConversationClass;
class SoldierGameObj;
class BuildingGameObj;
class VehicleGameObj;
class BeaconGameObj;
////////////////////////////////////////////////////////////////
//
// BaseControllerClass
//
////////////////////////////////////////////////////////////////
class BaseControllerClass : public NetworkObjectClass
{
public:
////////////////////////////////////////////////////////////////
// Friends
////////////////////////////////////////////////////////////////
friend class BuildingMonitorClass;
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
BaseControllerClass (void);
virtual ~BaseControllerClass (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
//
// Initialization
//
void Initialize ( int player_type );
void Shutdown (void);
void Delete (void) {};
//
// Networking.
//
// Set_Delete_Pending -
//
// The base controllers persist between levels so they should never be marked for deletion. They will be deleted
// when needed by their owner, the game mode
//
virtual void Set_Delete_Pending (void) {};
//
// Building access
//
void Add_Building (BuildingGameObj *building);
//
// Timestep
//
void Think (void);
//
// Power related methods
//
void Set_Base_Powered (bool onoff);
bool Is_Base_Powered (void) const { return BasePowered; }
void Check_Base_Power (void);
void Power_Base (bool onoff);
void Set_Operation_Time_Factor (float factor);
float Get_Operation_Time_Factor (void) { return OperationTimeFactor; }
//
// Harvester support
//
void Request_Harvester (int def_id);
VehicleGameObj * Get_Harvester_Vehicle (void);
//
// State accessors
//
bool Can_Generate_Soldiers (void) const { return CanGenerateSoldiers; }
bool Can_Generate_Vehicles (void) const { return CanGenerateVehicles; }
void Set_Can_Generate_Soldiers (bool onoff);
void Set_Can_Generate_Vehicles (bool onoff);
//
// Data accessors
//
int Get_Player_Type (void) const { return PlayerType; }
//
// Base destruction
//
void Set_Base_Destroyed ( bool onoff );
bool Is_Base_Destroyed (void) const { return IsBaseDestroyed; }
void Destroy_Base (void);
void Set_Beacon_Destroyed_Base ( bool onoff );
bool Did_Beacon_Destroy_Base ( void ) const { return DidBeaconDestroyBase; }
//
// Beacon zone access
//
const OBBoxClass & Get_Beacon_Zone (void) { return BeaconZone; }
//
// Radar support
//
void Check_Radar (void);
bool Is_Radar_Enabled (void) const { return IsRadarEnabled; }
void Play_Announcement(int text_id);
//
// Notifications
//
void On_Building_Damaged (BuildingGameObj *building);
void On_Building_Destroyed (BuildingGameObj *building);
void On_Vehicle_Generated(VehicleGameObj *vehicle);
void On_Vehicle_Delivered(VehicleGameObj *vehicle);
void On_Vehicle_Damaged(VehicleGameObj* vehicle);
void On_Vehicle_Destroyed(VehicleGameObj* vehicle);
void On_Beacon_Armed(BeaconGameObj* beacon);
void On_Beacon_Disarmed(BeaconGameObj* beacon);
void On_Beacon_Warning(BeaconGameObj* beacon);
//
// Fund support
//
//void Deposit_Funds (int funds);
void Distribute_Funds_To_Each_Teammate (int funds);
//
// Network support
//
void Import_Occasional (BitStreamClass &packet);
void Export_Occasional (BitStreamClass &packet);
//
// Component lookup
//
static BaseControllerClass * Find_Base ( int playertype );
static BaseControllerClass * Find_Base_For_Star (void);
BuildingGameObj * Find_Building (BuildingConstants::BuildingType type);
protected:
////////////////////////////////////////////////////////////////
// Protected constants
////////////////////////////////////////////////////////////////
typedef enum
{
BASE_UNDER_ATTACK = 0,
BUILDING_DESTROYED
} Notification;
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Initialize_Building_List (void);
void Reset_Building_List (void);
void Enable_Radar (bool onoff);
//
// Team notification
//
void Notify_Team (Notification event, BuildingConstants::BuildingType type);
private:
////////////////////////////////////////////////////////////////
// Private methods
////////////////////////////////////////////////////////////////
bool Are_All_Buildings_Destroyed (void);
////////////////////////////////////////////////////////////////
// Private member data
////////////////////////////////////////////////////////////////
float OperationTimeFactor;
int PlayerType; // Team
DynamicVectorClass<BuildingGameObj *> BuildingList;
bool BasePowered;
bool CanGenerateSoldiers;
bool CanGenerateVehicles;
bool IsRadarEnabled;
bool IsBaseDestroyed;
bool DidBeaconDestroyBase;
OBBoxClass BeaconZone;
int AnnounceInterval;
float AnnouncedAlliedBldgDamageTime;
float AnnouncedEnemyBldgDamageTime;
float AnnouncedAlliedVehicleDamageTime;
float AnnouncedEnemyVehicleDamageTime;
static BaseControllerClass * CurrentBases[BuildingConstants::BASE_COUNT];
};
#endif //__BASE_CONTROLLER_H

271
Code/Combat/basegameobj.cpp Normal file
View File

@@ -0,0 +1,271 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/basegameobj.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 8/23/01 10:52a $*
* *
* $Revision:: 27 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "basegameobj.h"
#include "combat.h"
#include "pscene.h"
#include "gameobjmanager.h"
#include "phys.h"
#include "timemgr.h"
#include "chunkio.h"
#include "debug.h"
#include "assets.h"
#include "matinfo.h"
#include "definitionclassids.h"
#include "networkobjectfactory.h"
//////////////////////////////////////////////////////////////
// NetworkGameObjectFactoryClass
//////////////////////////////////////////////////////////////
class NetworkGameObjectFactoryClass : public NetworkObjectFactoryClass
{
public:
virtual NetworkObjectClass * Create (cPacket &packet) const;
virtual void Prep_Packet (NetworkObjectClass *object, cPacket &packet) const;
virtual uint32 Get_Class_ID (void) const { return NETCLASSID_GAMEOBJ; }
};
//////////////////////////////////////////////////////////////
// Prep_Packet
//////////////////////////////////////////////////////////////
void
NetworkGameObjectFactoryClass::Prep_Packet (NetworkObjectClass *object, cPacket &packet) const
{
WWASSERT (object != NULL);
BaseGameObj *game_obj = (BaseGameObj *)(object);
//
// Add the definition ID of the object to the packet
//
packet.Add (game_obj->Get_Definition ().Get_ID ());
return ;
}
//////////////////////////////////////////////////////////////
// Create
//////////////////////////////////////////////////////////////
NetworkObjectClass *
NetworkGameObjectFactoryClass::Create (cPacket &packet) const
{
int definition_id = packet.Get (definition_id);
//
// Lookup the definition for this object
//
DefinitionClass *definition = DefinitionMgrClass::Find_Definition (definition_id);
WWASSERT (definition != NULL);
//
// Create the new object
//
BaseGameObj *new_game_obj = (BaseGameObj *)definition->Create();
//
// Convert the game object to a network object
//
return static_cast<NetworkObjectClass *> (new_game_obj);
}
//////////////////////////////////////////////////////////////
// Static data
//////////////////////////////////////////////////////////////
static NetworkGameObjectFactoryClass _NetworkGameObjectFactory;
/*
** BaseGameObjDef
*/
enum {
CHUNKID_DEF_PARENT = 1111991123,
};
bool BaseGameObjDef::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_DEF_PARENT );
DefinitionClass::Save( csave );
csave.End_Chunk();
return true;
}
bool BaseGameObjDef::Load( ChunkLoadClass &cload )
{
cload.Open_Chunk();
WWASSERT( cload.Cur_Chunk_ID() == CHUNKID_DEF_PARENT );
DefinitionClass::Load( cload );
cload.Close_Chunk();
return true;
}
/*
**
*/
BaseGameObj::BaseGameObj( void ) :
Definition( NULL ),
//DestroyType( DESTROY_NONE ),
//ID( 0 ),
IsPostThinkAllowed( false ),
EnableCinematicFreeze( true )
{
GameObjManager::Add( this );
Set_Object_Dirty_Bit (NetworkObjectClass::BIT_CREATION, true);
}
/*
**
*/
BaseGameObj::~BaseGameObj( void )
{
GameObjManager::Remove( this );
}
/*
**
*/
void BaseGameObj::Init( const BaseGameObjDef & definition )
{
Definition = &definition;
}
const BaseGameObjDef & BaseGameObj::Get_Definition( void ) const
{
return *Definition;
};
/*
** BaseGameObj Save and Load
*/
enum {
CHUNKID_VARIABLES = 910991407,
XXX_MICROCHUNKID_DESTROY_TYPE = 1,
MICROCHUNKID_DEFINITION_ID,
MICROCHUNKID_INSTANCE_ID,
MICROCHUNKID_IS_PENDING_DELETE,
MICROCHUNKID_ENABLE_CINEMATIC_FREEZE,
};
bool BaseGameObj::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_VARIABLES );
bool is_delete_pending = Is_Delete_Pending ();
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_IS_PENDING_DELETE, is_delete_pending );
int definition_id = Definition->Get_ID();
WWASSERT( SuperClassID_From_ClassID( Definition->Get_Class_ID () ) == CLASSID_GAME_OBJECTS ||
SuperClassID_From_ClassID( Definition->Get_Class_ID () ) == CLASSID_BUILDINGS );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEFINITION_ID, definition_id );
int id = Get_Network_ID ();
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_INSTANCE_ID, id );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ENABLE_CINEMATIC_FREEZE, EnableCinematicFreeze );
csave.End_Chunk();
return true;
}
bool BaseGameObj::Load( ChunkLoadClass &cload )
{
int id = 0;
cload.Open_Chunk();
WWASSERT( cload.Cur_Chunk_ID() == CHUNKID_VARIABLES );
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
case MICROCHUNKID_IS_PENDING_DELETE:
{
bool is_delete_pending = false;
LOAD_MICRO_CHUNK( cload, is_delete_pending );
if (is_delete_pending) {
Set_Delete_Pending ();
}
break;
}
case MICROCHUNKID_INSTANCE_ID:
{
LOAD_MICRO_CHUNK( cload, id );
//TSS
//Set_Network_ID( id );
break;
}
case MICROCHUNKID_DEFINITION_ID:
int definition_id;
LOAD_MICRO_CHUNK( cload, definition_id );
WWASSERT( Definition == NULL );
Definition = (const BaseGameObjDef*)DefinitionMgrClass::Find_Definition( definition_id );
if ( Definition == NULL ) {
Debug_Say(( "Definition %d not found\n. Re-Export needed\n", definition_id ));
}
//
// 07/30/01 attempting to load a level with temps will presently assert here.
//
WWASSERT( Definition != NULL );
break;
READ_MICRO_CHUNK( cload, MICROCHUNKID_ENABLE_CINEMATIC_FREEZE, EnableCinematicFreeze );
default:
Debug_Say(( "Unrecognized BaseGameObj Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
cload.Close_Chunk();
//
// Set the ID if necessary
//
if (id == 0) {
id = Get_ID ();
if (id == 0) {
Set_Network_ID (NetworkObjectMgrClass::Get_New_Dynamic_ID ());
} else {
WWASSERT(id >= NETID_DYNAMIC_OBJECT_MIN && id <= NETID_DYNAMIC_OBJECT_MAX);
}
} else {
Set_Network_ID (id);
}
return true;
}

149
Code/Combat/basegameobj.h Normal file
View File

@@ -0,0 +1,149 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/basegameobj.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 10/15/01 7:48p $*
* *
* $Revision:: 17 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BASEGAMEOBJ_H
#define BASEGAMEOBJ_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef PERSIST_H
#include "persist.h"
#endif
#ifndef DEFINITION_H
#include "definition.h"
#endif
#ifndef __NETWORKOBJECT_H
#include "networkobject.h"
#endif
#include "netclassids.h"
/*
**
*/
class SmartGameObj;
class PhysicalGameObj;
class ScriptableGameObj;
class VehicleGameObj;
/*
** BaseGameObjDef - Defintion class for a BaseGameObj
*/
class BaseGameObjDef : public DefinitionClass
{
public:
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
};
/*
**
*/
class BaseGameObj : public PersistClass, public NetworkObjectClass {
public:
// Constructor and Destructor
BaseGameObj( void );
virtual ~BaseGameObj( void );
// Definitions
virtual void Init( void ) = 0;
void Init( const BaseGameObjDef & definition );
const BaseGameObjDef & Get_Definition( void ) const ;
// Save / Load
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
// Thinking
virtual void Think() { IsPostThinkAllowed = true; }
virtual void Post_Think() {};
// ID
void Set_ID( int id ) { Set_Network_ID (id); }
int Get_ID( void ) const { return Get_Network_ID (); }
// Hibernation
virtual bool Is_Hibernating( void ) { return false; }
// Termination
//virtual void Destroy(bool damaged = false) { DestroyType = damaged ? DESTROY_DAMAGED : DESTROY_CONTROLLED; }
//bool Is_Destroy() { return (DestroyType != DESTROY_NONE); }
//bool Is_Damage_Destroyed() { return (DestroyType == DESTROY_DAMAGED); }
// Type identification
virtual PhysicalGameObj *As_PhysicalGameObj( void ) { return (PhysicalGameObj*)NULL; };
virtual VehicleGameObj *As_VehicleGameObj( void ) { return (VehicleGameObj *)NULL; }
virtual SmartGameObj *As_SmartGameObj( void ) { return (SmartGameObj*)NULL; };
virtual ScriptableGameObj *As_ScriptableGameObj( void ) { return (ScriptableGameObj*)NULL; };
// Network support
virtual uint32 Get_Network_Class_ID( void ) const { return NETCLASSID_GAMEOBJ; }
virtual void Delete (void) { delete this; }
bool Is_Post_Think_Allowed( void ) { return IsPostThinkAllowed; }
void Enable_Cinematic_Freeze( bool enable ) { EnableCinematicFreeze = enable; }
bool Is_Cinematic_Freeze_Enabled( void ) { return EnableCinematicFreeze; }
private:
// Constants
/*enum
{
DESTROY_NONE = 0,
DESTROY_DAMAGED,
DESTROY_CONTROLLED
};*/
// Member data
const BaseGameObjDef * Definition;
//int DestroyType;
//int ID;
// This is used to prevent postthinking before a think call
bool IsPostThinkAllowed;
// This keeps certain object alive during cinematic freeze
bool EnableCinematicFreeze;
};
#endif // BASEGAMEOBJ_H

File diff suppressed because it is too large Load Diff

251
Code/Combat/beacongameobj.h Normal file
View File

@@ -0,0 +1,251 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/beacongameobj.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 1/04/02 2:58p $*
* *
* $Revision:: 16 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __BEACONGAMEOBJ_H
#define __BEACONGAMEOBJ_H
#include "always.h"
#include "simplegameobj.h"
#include "timemgr.h"
////////////////////////////////////////////////////////////////
// Forward delcarations
////////////////////////////////////////////////////////////////
class BaseControllerClass;
class WeaponDefinitionClass;
class AudibleSoundClass;
////////////////////////////////////////////////////////////////
//
// BeaconGameObjDef
//
////////////////////////////////////////////////////////////////
class BeaconGameObjDef : public SimpleGameObjDef
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
BeaconGameObjDef (void);
~BeaconGameObjDef (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
virtual uint32 Get_Class_ID (void) const;
virtual PersistClass * Create (void) const;
virtual bool Save (ChunkSaveClass &csave);
virtual bool Load (ChunkLoadClass &cload);
virtual const PersistFactoryClass & Get_Factory (void) const;
bool Is_Nuke(void) const {return (IsNuke != 0);}
DECLARE_EDITABLE (BeaconGameObjDef, SimpleGameObjDef);
protected:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
////////////////////////////////////////////////////////////////
// Protected friends
////////////////////////////////////////////////////////////////
friend class BeaconGameObj;
////////////////////////////////////////////////////////////////
// Protected member data
////////////////////////////////////////////////////////////////
float BroadcastToAllTime;
float ArmTime;
float DisarmTime;
float PreDetonateCinematicDelay;
float DetonateTime;
float PostDetonateTime;
int ArmedSoundDefID;
int DisarmingTextID;
int DisarmedTextID;
int ArmingTextID;
int ArmingInterruptedTextID;
int DisarmingInterruptedTextID;
int PreDetonateCinematicDefID;
int PostDetonateCinematicDefID;
int ExplosionDefID;
int IsNuke;
StringClass ArmingAnimationName;
};
////////////////////////////////////////////////////////////////
//
// BeaconGameObj
//
////////////////////////////////////////////////////////////////
class BeaconGameObj : public SimpleGameObj
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
BeaconGameObj (void);
virtual ~BeaconGameObj (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
//
// Definition support
//
virtual void Init( void );
void Init (const BeaconGameObjDef & definition);
const BeaconGameObjDef & Get_Definition (void) const;
//
// RTTI
//
virtual BeaconGameObj * As_BeaconGameObj (void) { return this; }
//
// Save / Load / Construction Factory
//
bool Save (ChunkSaveClass & csave);
bool Load (ChunkLoadClass & cload);
const PersistFactoryClass & Get_Factory (void) const;
//
// GameObj methods
//
void Think (void);
void Get_Information (StringClass &string);
//
// Beacon initialization
//
void Init_Beacon (const WeaponDefinitionClass *definiton, SoldierGameObj *owner, const Vector3 &position);
//
// Beacon stuff
//
bool Can_Place_Here (const Vector3 &position);
void On_Arming_Interrupted (void);
void Begin_Arming (void);
void On_Poked (ScriptableGameObj *poker);
virtual void Completely_Damaged( const OffenseObjectClass & damager );
virtual void Export_Rare( BitStreamClass &packet );
virtual void Import_Rare( BitStreamClass &packet );
SoldierGameObj * Get_Owner (void);
private:
////////////////////////////////////////////////////////////////
// Private methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
void Stop_Armed_Sound (void);
void Stop_Current_Message_Sound (void);
void Display_Message (int text_id);
void Start_Owner_Animation (void);
void Stop_Owner_Animation (void);
bool Was_Owner_Interrupted (void);
void Start_Cinematic (int id);
bool Is_In_Enemy_Base( void );
void Create_Explosion (void);
//
// State support
//
void Set_State (int state);
void Update_State (void);
BaseControllerClass * Get_Enemy_Base (void);
////////////////////////////////////////////////////////////////
// Private constants
////////////////////////////////////////////////////////////////
enum
{
STATE_NULL = 0,
STATE_ARMING,
STATE_ARMED,
STATE_DISARMED,
STATE_DETONATING
};
////////////////////////////////////////////////////////////////
// Private member data
////////////////////////////////////////////////////////////////
GameObjReference Owner;
int State;
float StateTimer;
float PreDetonateTimer;
float DetonateTimer;
float WarningTimer;
AudibleSoundClass * ArmedSound;
AudibleSoundClass * MessageSound;
bool IsArmed;
const WeaponDefinitionClass * WeaponDefinition;
GameObjReference CinematicObject;
void * OwnerBackup;
void Restore_Owner( void );
};
#endif // __BEACONGAMEOBJ_H

139
Code/Combat/bones.cpp Normal file
View File

@@ -0,0 +1,139 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/bones.cpp $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 6/14/02 10:41a $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "bones.h"
#include "debug.h"
#include "assets.h"
#include "wwstring.h"
#include "stl.h"
static bool _BonesMangerInitted = false;
/*
**
*/
class BoneDataClass {
public:
BoneDataClass( const char * screen_name, float damage_scale ) :
ScreenName( screen_name ), DamageScale( damage_scale ) {}
StringClass ScreenName;
float DamageScale;
};
typedef std::map< StringClass , BoneDataClass * > BoneMapper;
BoneMapper BoneMap;
/*
** Database Loading
*/
#define BONES_INI_FILENAME "BONES.INI"
#define SECTION_LIST "Bones_List"
#define ENTRY_NAME "Name"
#define ENTRY_SCREEN_NAME "ScreenName"
#define ENTRY_DAMAGE_SCALE "DamageScale"
void Load_Bones( void )
{
INIClass * bonesINI = Get_INI( BONES_INI_FILENAME );
if (bonesINI != NULL) {
WWASSERT( bonesINI && bonesINI->Section_Count() > 0 );
int count = bonesINI->Entry_Count( SECTION_LIST ); // Load gang list
for ( int entry = 0; entry < count; entry++ ) {
char name[80];
char screen_name[80];
char section_name[80];
bonesINI->Get_String( SECTION_LIST, bonesINI->Get_Entry( SECTION_LIST, entry),
"", section_name, sizeof( section_name ) );
bonesINI->Get_String( section_name, ENTRY_NAME, "", name, sizeof( name ) );
bonesINI->Get_String( section_name, ENTRY_SCREEN_NAME, "", screen_name, sizeof( screen_name ) );
float damage_scale = bonesINI->Get_Float( section_name, ENTRY_DAMAGE_SCALE, 1.0 );
BoneMap[ name ] = new BoneDataClass( screen_name, damage_scale );
// Debug_Say(( "Add bone %s %s %f\n", name, screen_name, damage_scale ));
}
Release_INI( bonesINI );
} else {
Debug_Say(("Load_Bones - Unable to load %s\n", BONES_INI_FILENAME));
}
}
/*
**
*/
void BonesManager::Init( void )
{
if (_BonesMangerInitted) {
Shutdown();
}
Load_Bones();
_BonesMangerInitted = true;
}
void BonesManager::Shutdown( void )
{
for(BoneMapper::iterator it = BoneMap.begin(); it != BoneMap.end(); it++) {
delete it->second;
}
BoneMap.clear();
_BonesMangerInitted = false;
}
const char * BonesManager::Get_Bone_Screen_Name( const char * bone_name )
{
BoneMapper::iterator i = BoneMap.find( bone_name );
if ( i != BoneMap.end() ) {
return i->second->ScreenName;
}
return "???";
}
float BonesManager::Get_Bone_Damage_Scale( const char * bone_name )
{
StringClass bone_name_string(bone_name,true);
BoneMapper::iterator i = BoneMap.find( bone_name_string );
if ( i != BoneMap.end() ) {
return i->second->DamageScale;
}
return 1.0f;
}

59
Code/Combat/bones.h Normal file
View File

@@ -0,0 +1,59 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Commando/bones.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 7/28/99 11:58a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BONES_H
#define BONES_H
#ifndef ALWAYS_H
#include "always.h"
#endif
/*
** BONES MANAGER
*/
class BonesManager {
public:
static void Init( void );
static void Shutdown( void );
static const char * Get_Bone_Screen_Name( const char * bone_name );
static float Get_Bone_Damage_Scale( const char * bone_name );
};
#endif

1635
Code/Combat/building.cpp Normal file

File diff suppressed because it is too large Load Diff

327
Code/Combat/building.h Normal file
View File

@@ -0,0 +1,327 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/building.h $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 1/07/02 3:52p $*
* *
* $Revision:: 42 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef BUILDING_H
#define BUILDING_H
#include "always.h"
#include "damageablegameobj.h"
#include "combatphysobserver.h"
#include "buildingaggregate.h"
#include "lightphys.h"
#include "playertype.h"
/*
** Forward declarations
*/
class AudibleSoundClass;
class BaseControllerClass;
class BuildingMonitorClass;
class PowerPlantGameObj;
class SoldierFactoryGameObj;
class VehicleFactoryGameObj;
class AirStripGameObj;
class WarFactoryGameObj;
class RefineryGameObj;
class ComCenterGameObj;
class RepairBayGameObj;
/**
** BuildingConstants
** Convienent namespace declaration for the constants used with buildings
*/
namespace BuildingConstants
{
typedef enum
{
TYPE_NONE = -1,
TYPE_POWER_PLANT,
TYPE_SOLDIER_FACTORY,
TYPE_VEHICLE_FACTORY,
TYPE_REFINERY,
TYPE_COM_CENTER,
TYPE_REPAIR_BAY,
TYPE_SHRINE,
TYPE_HELIPAD,
TYPE_CONYARD,
TYPE_BASE_DEFENSE,
TYPE_COUNT
} BuildingType;
typedef enum
{
LEGACY_TEAM_GDI = 0,
LEGACY_TEAM_NOD,
} LegacyBuildingTeam;
typedef enum
{
BASE_COUNT = 2,
};
}
/**
** Building Game Obj Def
** This class is an editable definition for a building. It contains all constant data needed to initialize
** a BuildingGameObj.
*/
class BuildingGameObjDef : public DamageableGameObjDef
{
public:
BuildingGameObjDef( void );
virtual uint32 Get_Class_ID( void ) const;
virtual PersistClass * Create( void ) const ;
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
virtual const PersistFactoryClass & Get_Factory( void ) const;
DECLARE_EDITABLE( BuildingGameObjDef, DamageableGameObjDef );
void Set_Type (BuildingConstants::BuildingType type) { Type = type; }
BuildingConstants::BuildingType Get_Type (void) const { return Type; }
const StringClass & Get_Mesh_Prefix (void) const { return MeshPrefix; }
int Get_Damage_Report(int team) const;
int Get_Destroy_Report(int team) const;
protected:
StringClass MeshPrefix;
ArmorType MCTSkin;
BuildingConstants::BuildingType Type;
int GDIDamageReportID;
int NodDamageReportID;
int GDIDestroyReportID;
int NodDestroyReportID;
friend class BuildingGameObj;
};
/*
** Building Game Obj
** This class encapsulates the basic building functionality.
**
** At initialization, the following things need to happen.
** - Collects all of the meshes that are part of the building using proximity, prefix matching
** and the "house" naming convention (# indicates an interior mesh, ^ indicates an exterior mesh).
** - Collect all of the BuildingAggregates that are part of the building using proximity and
** prefix matching.
** - Collect all light sources associated with the building using proximity and prefix matching.
** - Install itself as an observer into each StaticPhysClass (meshes and aggregates) that is part
** of the building.
**
** During gameplay, the building code does the following things:
** - Responds to all bullet collisions and explosions on any of its meshes/aggregates by
** applying damage to the building.
** - When destroyed, applies the alternate materials on its exterior meshes
** - When the power goes out, applies the alternate materials on its interior meshes
** - When the state changes (power on/off, health 100,75,50,25,0) switches the behaviors of
** all aggregates.
**
*/
class BuildingGameObj : public DamageableGameObj, public CombatPhysObserverClass
{
public:
// Constructor and Destructor
BuildingGameObj( void );
virtual ~BuildingGameObj( void );
// Definitions
virtual void Init( void );
void Init( const BuildingGameObjDef & definition );
const BuildingGameObjDef & Get_Definition( void ) const ;
// Save / Load
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
virtual const PersistFactoryClass & Get_Factory( void ) const;
// Type identification
virtual BuildingGameObj * As_BuildingGameObj( void ) { return this; }
virtual DamageableGameObj * As_DamageableGameObj( void ) { return this; }
virtual PowerPlantGameObj * As_PowerPlantGameObj (void) { return NULL; }
virtual SoldierFactoryGameObj * As_SoldierFactoryGameObj (void) { return NULL; }
virtual VehicleFactoryGameObj * As_VehicleFactoryGameObj (void) { return NULL; }
virtual AirStripGameObj * As_AirStripGameObj (void) { return NULL; }
virtual WarFactoryGameObj * As_WarFactoryGameObj (void) { return NULL; }
virtual RefineryGameObj * As_RefineryGameObj (void) { return NULL; }
virtual ComCenterGameObj * As_ComCenterGameObj (void) { return NULL; }
virtual RepairBayGameObj * As_RepairBayGameObj (void) { return NULL; }
/****/
/*
** Position interface, the position of the building controller influences which meshes
** and other components are automatically assigned to this building. When there are two
** BuildingGameObj's that can accept a particular component, the closest one wins.
*/
void Get_Position(Vector3 * pos) const { *pos = Position; }
void Set_Position(const Vector3 & pos) { Position = pos; CollectionSphere.Center = pos; }
/*
** Damage interface, designed to work similarly to a game object
*/
virtual void Apply_Damage( const OffenseObjectClass & damager,
float scale = 1.0f,
int alternate_skin = -1 );
void Apply_Damage_Building( const OffenseObjectClass & offense,
StaticPhysClass * component );
void Apply_Damage_Building( const OffenseObjectClass & offense,
bool mct_damage );
void Set_Normalized_Health (float health);
/*
** Power interface, turn the power on and off
*/
void Enable_Power(bool onoff);
bool Is_Power_Enabled(void) const { return IsPowerOn; }
/*
** Building announcment support
*/
void Play_Announcement( int text_id, bool broadcast );
void Stop_Current_Announcement( void );
/*
** Utility functions for the building mesh naming convention.
** Exterior meshes contain a ^ as the first character following their prefix.
** Interior meshes contain a # as the first character following their prefix.
*/
bool Name_Prefix_Matches_This_Building(const char * name);
static bool Is_Interior_Mesh_Name(const char * name);
static bool Is_Exterior_Mesh_Name(const char * name);
const char * Get_Name_Prefix (void) const { return Get_Definition().MeshPrefix; }
/*
** Building component support
*/
void Collect_Building_Components (void);
void Get_Collection_Sphere (SphereClass *sphere) const { *sphere = CollectionSphere; }
void Set_Collection_Sphere (const SphereClass &sphere) { CollectionSphere = sphere; }
/*
** CnC mode suport
*/
virtual void CnC_Initialize (BaseControllerClass *base);
virtual void On_Destroyed (void);
virtual void On_Damaged (void);
bool Is_Destroyed (void) const { return IsDestroyed; }
/*
** Network support
*/
virtual void Import_Rare (BitStreamClass &packet);
virtual void Export_Rare (BitStreamClass &packet);
virtual void Export_Creation (BitStreamClass &packet);
virtual void Import_Creation (BitStreamClass &packet);
static void Set_Precision (void);
virtual bool Get_World_Position (Vector3 &pos) const { pos = Position; return true; }
//virtual float Compute_Object_Priority (int client_id, const Vector3 &client_pos);
//virtual void Get_Extended_Information( StringClass & description );
virtual void Get_Description( StringClass & description );
virtual bool Is_Tagged(void) { return false; }
/*
**
*/
bool Is_GDI( void ) { return Get_Player_Type() == PLAYERTYPE_GDI; }
bool Is_Nod( void ) { return Get_Player_Type() == PLAYERTYPE_NOD; }
static void Set_Can_Repair_Buildings(bool flag) {CanRepairBuildings = flag;}
static bool Get_Can_Repair_Buildings(void) {return CanRepairBuildings;}
//
// Informational
//
void Find_Closest_Poly (const Vector3 &pos, float *distance2);
protected:
/*
** CnC mode stuff
*/
BuildingMonitorClass * BuildingMonitor;
BaseControllerClass * BaseController;
bool IsDestroyed;
//private:
Vector3 Position;
bool IsPowerOn;
int CurrentState; // derived from the health and IsPowerOn
AudibleSoundClass * CurrentAnnouncement;
SphereClass AnnouncementSphere;
SphereClass CollectionSphere;
RefMultiListClass<StaticPhysClass> InteriorMeshes;
RefMultiListClass<StaticPhysClass> ExteriorMeshes;
RefMultiListClass<BuildingAggregateClass> Aggregates;
RefMultiListClass<LightPhysClass> PowerOnLights;
RefMultiListClass<LightPhysClass> PowerOffLights;
static bool CanRepairBuildings;
void Initialize_Building(void);
void Reset_Components(void);
void Add_Mesh(StaticPhysClass * terrain);
void Remove_Mesh(StaticPhysClass * terrain);
void Add_Aggregate(BuildingAggregateClass * aggregate);
void Remove_Aggregate(BuildingAggregateClass * aggregate);
void Add_Light(LightPhysClass * light);
void Find_Closest_Poly_For_Model (RenderObjClass *model, const Vector3 &pos, float *distance2);
void Update_State(bool force_update = false);
void Enable_Alternate_Materials(RefMultiListClass<StaticPhysClass> & models, bool onoff);
void Enable_Alternate_Materials(RenderObjClass * model,bool onoff);
friend class GameObjManager;
};
#endif // BUILDING_H

View File

@@ -0,0 +1,749 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/buildingaggregate.cpp $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 1/07/03 1:38p $*
* *
* $Revision:: 14 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* BuildingAggregateClass::BuildingAggregateClass -- Constructor *
* BuildingAggregateClass::BuildingAggregateClass -- Constructor *
* BuildingAggregateClass::~BuildingAggregateClass -- Destructor *
* BuildingAggregateClass::Init -- Initialze from a definition *
* BuildingAggregateClass::Get_Current_State -- returns the current state *
* BuildingAggregateClass::Set_Current_State -- Sets the current state *
* BuildingAggregateClass::Is_MCT -- is this aggregate an MCT? *
* BuildingAggregateClass::Save -- Get the persist factory for this clas *
* BuildingAggregateClass::Save -- Save the state of this object *
* BuildingAggregateClass::Load -- Load the state of this object *
* BuildingAggregateClass::On_Post_Load -- post-load processing *
* BuildingAggregateDefClass::BuildingAggregateDefClass -- Constructor *
* BuildingAggregateDefClass::Get_Class_ID -- returns the definition class ID *
* BuildingAggregateDefClass::Create -- creates an instance of a BuildingAggregateClass *
* BuildingAggregateDefClass::Get_Factory -- returns the persist factory *
* BuildingAggregateDefClass::Save -- Saves the contents of this object *
* BuildingAggregateDefClass::Save_State_Animation_Data -- Save the data for one of the buil *
* BuildingAggregateDefClass::Load -- Load the contents of this object *
* BuildingAggregateDefClass::Load_State_Animation_Data -- Load anim data for a building sta *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "buildingaggregate.h"
#include "simpledefinitionfactory.h"
#include "persistfactory.h"
#include "wwphysids.h"
#include "hanim.h"
#include "combat.h"
#include "wwaudio.h"
#include "wwdebug.h"
#include "wwhack.h"
#include "wwprofile.h"
DECLARE_FORCE_LINK( buildingaggregate );
/*************************************************************************************************************
**
** BuildingAggregateClass (BAG) Implementation
**
*************************************************************************************************************/
SimplePersistFactoryClass<BuildingAggregateClass, PHYSICS_CHUNKID_BUILDINGAGGREGATE> _BuildingAggregatePersistFactory;
enum
{
BAG_CHUNK_STATICANIMPHYS = 8281529,
BAG_CHUNK_VARIABLES,
BAG_VARIABLE_CURRENTSTATE = 0,
};
/***********************************************************************************************
* BuildingAggregateClass::BuildingAggregateClass -- Constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
BuildingAggregateClass::BuildingAggregateClass(void) :
CurrentState(BuildingStateClass::HEALTH100_POWERON)
{
}
/***********************************************************************************************
* BuildingAggregateClass::~BuildingAggregateClass -- Destructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
*=============================================================================================*/
BuildingAggregateClass::~BuildingAggregateClass(void)
{
}
/***********************************************************************************************
* BuildingAggregateClass::Init -- Initialze from a definition *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
void BuildingAggregateClass::Init(const BuildingAggregateDefClass & def)
{
StaticAnimPhysClass::Init(def);
AnimCollisionManagerClass & anim_mgr = Get_Animation_Manager();
anim_mgr.Set_Current_Frame(def.Frame0[CurrentState]);
}
/***********************************************************************************************
* BuildingAggregateClass::Get_Current_State -- returns the current state *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/8/2000 gth : Created. *
*=============================================================================================*/
int BuildingAggregateClass::Get_Current_State(void)
{
return CurrentState;
}
/***********************************************************************************************
* BuildingAggregateClass::Set_Current_State -- Sets the current state *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/8/2000 gth : Created. *
*=============================================================================================*/
void BuildingAggregateClass::Set_Current_State(int new_state,bool force_update)
{
if ((new_state != CurrentState) || (force_update == true)) {
AnimCollisionManagerClass & anim_mgr = Get_Animation_Manager();
const BuildingAggregateDefClass * def = Get_BuildingAggregateDef();
WWASSERT(def != NULL);
switch (def->AnimLogicMode)
{
case BuildingAggregateDefClass::ANIM_LOGIC_LOOP:
{
/*
** Calculate the fractional position in our current loop
*/
float normalized_frame = 0.0f;
float cur_loop_len = def->Frame1[CurrentState] - def->Frame0[CurrentState];
if (cur_loop_len > 0.0f) {
normalized_frame = (anim_mgr.Get_Current_Frame() - def->Frame0[CurrentState]) /
(def->Frame1[CurrentState] - def->Frame0[CurrentState]);
}
/*
** Switch the loop start and end
*/
anim_mgr.Set_Loop_Start(def->Frame0[new_state]);
anim_mgr.Set_Loop_End(def->Frame1[new_state]);
/*
** Jump to the same fractional position in the new loop
*/
anim_mgr.Set_Current_Frame(def->Frame0[new_state] + normalized_frame * (def->Frame1[new_state] - def->Frame0[new_state]));
/*
** If animation is disabled, set the animation mode to manual, otherwise set it to loop
*/
if (def->AnimationEnabled[new_state] == true) {
anim_mgr.Set_Animation_Mode(AnimCollisionManagerClass::ANIMATE_LOOP);
} else {
anim_mgr.Set_Animation_Mode(AnimCollisionManagerClass::ANIMATE_MANUAL);
}
break;
}
case BuildingAggregateDefClass::ANIM_LOGIC_LINEAR:
{
/*
** The new target frame is determined by the new state
*/
anim_mgr.Set_Target_Frame(def->Frame0[new_state]);
anim_mgr.Set_Animation_Mode(AnimCollisionManagerClass::ANIMATE_TARGET);
/*
** If we changed power states or animation is disabled, then we need to warp the current frame
*/
if ( (BuildingStateClass::Is_Power_On(new_state) != BuildingStateClass::Is_Power_On(CurrentState)) ||
(def->AnimationEnabled[new_state] == false))
{
anim_mgr.Set_Current_Frame(def->Frame0[new_state]);
}
break;
}
case BuildingAggregateDefClass::ANIM_LOGIC_SEQUENCE:
{
/*
** The current and target frames are determined by the new state. If the new sequence
** is the same as the previous sequence, don't do anything.
*/
if ((def->Frame0[CurrentState] != def->Frame0[new_state]) || (def->Frame1[CurrentState] != def->Frame1[new_state])) {
anim_mgr.Set_Animation_Mode(AnimCollisionManagerClass::ANIMATE_TARGET);
anim_mgr.Set_Current_Frame(def->Frame0[new_state]);
anim_mgr.Set_Target_Frame(def->Frame1[new_state]);
}
break;
}
}
CurrentState = new_state;
}
}
/***********************************************************************************************
* BuildingAggregateClass::Is_MCT -- is this aggregate an MCT? *
* *
* MCT's are weak points for the building. The building will use an alternate skin type *
* when applying damage that was done to the MCT. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/24/2000 gth : Created. *
*=============================================================================================*/
bool BuildingAggregateClass::Is_MCT(void)
{
return Get_BuildingAggregateDef()->IsMCT;
}
/*
** Save and Load
*/
/***********************************************************************************************
* BuildingAggregateClass::Save -- Get the persist factory for this class *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
const PersistFactoryClass & BuildingAggregateClass::Get_Factory(void) const
{
return _BuildingAggregatePersistFactory;
}
/***********************************************************************************************
* BuildingAggregateClass::Save -- Save the state of this object *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
bool BuildingAggregateClass::Save(ChunkSaveClass & csave)
{
csave.Begin_Chunk(BAG_CHUNK_STATICANIMPHYS);
StaticAnimPhysClass::Save(csave);
csave.End_Chunk();
csave.Begin_Chunk(BAG_CHUNK_VARIABLES);
WRITE_MICRO_CHUNK(csave, BAG_VARIABLE_CURRENTSTATE, CurrentState );
csave.End_Chunk();
return true;
}
/***********************************************************************************************
* BuildingAggregateClass::Load -- Load the state of this object *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
bool BuildingAggregateClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case BAG_CHUNK_STATICANIMPHYS:
StaticAnimPhysClass::Load( cload );
break;
case BAG_CHUNK_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK(cload, BAG_VARIABLE_CURRENTSTATE, CurrentState );
default:
WWDEBUG_SAY(( "Unrecognized BuildingAggregate Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
WWDEBUG_SAY(("Unrecognized BuildingAggregate Chunk: 0x%x in file %s, line %d\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
SaveLoadSystemClass::Register_Post_Load_Callback(this);
return true;
}
/***********************************************************************************************
* BuildingAggregateClass::On_Post_Load -- post-load processing *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 9/8/2000 gth : Created. *
*=============================================================================================*/
void BuildingAggregateClass::On_Post_Load(void)
{
StaticAnimPhysClass::On_Post_Load();
Set_Current_State(CurrentState,true);
}
/*
**
*/
void BuildingAggregateClass::Save_State( ChunkSaveClass & csave )
{
csave.Begin_Chunk( BAG_CHUNK_STATICANIMPHYS );
StaticAnimPhysClass::Save_State(csave);
csave.End_Chunk();
csave.Begin_Chunk(BAG_CHUNK_VARIABLES);
WRITE_MICRO_CHUNK(csave, BAG_VARIABLE_CURRENTSTATE, CurrentState );
csave.End_Chunk();
}
/*
**
*/
void BuildingAggregateClass::Load_State( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case BAG_CHUNK_STATICANIMPHYS:
StaticAnimPhysClass::Load_State( cload );
break;
case BAG_CHUNK_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK(cload, BAG_VARIABLE_CURRENTSTATE, CurrentState );
default:
WWDEBUG_SAY(( "Unrecognized BuildingAggregate Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
WWDEBUG_SAY(( "Unrecognized BuildingAggregate chunkID\n" ));
break;
}
cload.Close_Chunk();
}
}
/*************************************************************************************************
**
** BuildingAggregateDefClass Implementation
**
*************************************************************************************************/
/*
** Persist Factory for BuildingAggregateDefClass, this makes them save and load.
*/
SimplePersistFactoryClass<BuildingAggregateDefClass, PHYSICS_CHUNKID_BUILDINGAGGREGATEDEF> _BuildingAggregateDefPersistFactory;
/*
** Definition Factory for BuildingAggregateDefClass, this makes them show up in the editor
*/
DECLARE_DEFINITION_FACTORY(BuildingAggregateDefClass, CLASSID_BUILDINGAGGREGATEDEF, "BuildingAggregate") _BuildingAggregateDefDefFactory;
/*
** Chunk ID's used by BuildingAggregateDefClass
*/
enum
{
BAGDEF_CHUNK_STATICANIMPHYS = 8281441,
BAGDEF_CHUNK_VARIABLES,
BAGDEF_CHUNK_HEALTH100_POWERON_VARIABLES,
BAGDEF_CHUNK_HEALTH75_POWERON_VARIABLES,
BAGDEF_CHUNK_HEALTH50_POWERON_VARIABLES,
BAGDEF_CHUNK_HEALTH25_POWERON_VARIABLES,
BAGDEF_CHUNK_DESTROYED_POWERON_VARIABLES,
BAGDEF_CHUNK_HEALTH100_POWEROFF_VARIABLES,
BAGDEF_CHUNK_HEALTH75_POWEROFF_VARIABLES,
BAGDEF_CHUNK_HEALTH50_POWEROFF_VARIABLES,
BAGDEF_CHUNK_HEALTH25_POWEROFF_VARIABLES,
BAGDEF_CHUNK_DESTROYED_POWEROFF_VARIABLES,
BAGDEF_VARIABLE_ANIMLOGICMODE = 0,
BAGDEF_VARIABLE_FRAME0,
BAGDEF_VARIABLE_FRAME1,
BAGDEF_VARIABLE_ANIMATIONENABLED,
BAGDEF_VARIABLE_ISMCT,
};
/***********************************************************************************************
* BuildingAggregateDefClass::BuildingAggregateDefClass -- Constructor *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
BuildingAggregateDefClass::BuildingAggregateDefClass( void ) :
StaticAnimPhysDefClass(),
AnimLogicMode(ANIM_LOGIC_LOOP),
IsMCT(false)
{
int i;
for (i=0; i<BuildingStateClass::STATE_COUNT; i++) {
Frame0[i] = 0;
Frame1[i] = 0;
AnimationEnabled[i] = true;
}
#ifdef PARAM_EDITING_ON
PARAM_SEPARATOR(BuildingAggregateDefClass, "Building Behavior Settings");
EnumParameterClass * anim_logic_param = new EnumParameterClass(&AnimLogicMode);
anim_logic_param->Set_Name ("AnimLogicMode");
anim_logic_param->Add_Value("ANIM_LOGIC_LINEAR",ANIM_LOGIC_LINEAR);
anim_logic_param->Add_Value("ANIM_LOGIC_LOOP",ANIM_LOGIC_LOOP);
anim_logic_param->Add_Value("ANIM_LOGIC_SEQUENCE",ANIM_LOGIC_SEQUENCE);
GENERIC_EDITABLE_PARAM( BuildingAggregateDefClass, anim_logic_param);
EDITABLE_PARAM(BuildingAggregateDefClass, ParameterClass::TYPE_BOOL, IsMCT);
for (i=0; i<BuildingStateClass::STATE_COUNT; i++) {
PARAM_SEPARATOR(BuildingAggregateDefClass, BuildingStateClass::Get_State_Name(i))
NAMED_EDITABLE_PARAM(BuildingAggregateDefClass, ParameterClass::TYPE_INT, Frame0[i], "Frame0");
NAMED_EDITABLE_PARAM(BuildingAggregateDefClass, ParameterClass::TYPE_INT, Frame1[i], "Frame1");
NAMED_EDITABLE_PARAM(BuildingAggregateDefClass, ParameterClass::TYPE_BOOL, AnimationEnabled[i], "AnimationEnabled");
}
#endif
}
/***********************************************************************************************
* BuildingAggregateDefClass::Get_Class_ID -- returns the definition class ID *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
uint32 BuildingAggregateDefClass::Get_Class_ID(void) const
{
return CLASSID_BUILDINGAGGREGATEDEF;
}
bool BuildingAggregateDefClass::Is_Type(const char * type_name)
{
if (stricmp(type_name,BuildingAggregateDefClass::Get_Type_Name()) == 0) {
return true;
} else {
return StaticAnimPhysDefClass::Is_Type(type_name);
}
}
/***********************************************************************************************
* BuildingAggregateDefClass::Create -- creates an instance of a BuildingAggregateClass *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
PersistClass * BuildingAggregateDefClass::Create(void) const
{
BuildingAggregateClass * obj = new BuildingAggregateClass;
obj->Init( *this );
return obj;
}
/*
** Save and Load
*/
/***********************************************************************************************
* BuildingAggregateDefClass::Get_Factory -- returns the persist factory *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
const PersistFactoryClass & BuildingAggregateDefClass::Get_Factory(void) const
{
return _BuildingAggregateDefPersistFactory;
}
/***********************************************************************************************
* BuildingAggregateDefClass::Save -- Saves the contents of this object *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
bool BuildingAggregateDefClass::Save(ChunkSaveClass & csave)
{
csave.Begin_Chunk( BAGDEF_CHUNK_STATICANIMPHYS );
StaticAnimPhysDefClass::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( BAGDEF_CHUNK_VARIABLES );
WRITE_MICRO_CHUNK( csave, BAGDEF_VARIABLE_ANIMLOGICMODE, AnimLogicMode );
WRITE_MICRO_CHUNK( csave, BAGDEF_VARIABLE_ISMCT, IsMCT );
csave.End_Chunk();
for (int i=0; i<BuildingStateClass::STATE_COUNT; i++) {
Save_State_Animation_Data(csave,i);
}
return true;
}
/***********************************************************************************************
* BuildingAggregateDefClass::Save_State_Animation_Data -- Save the data for one of the buildi *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
bool BuildingAggregateDefClass::Save_State_Animation_Data(ChunkSaveClass & csave,int state_index)
{
WWASSERT(state_index >= 0);
WWASSERT(state_index < BuildingStateClass::STATE_COUNT);
csave.Begin_Chunk(BAGDEF_CHUNK_HEALTH100_POWERON_VARIABLES + state_index);
WRITE_MICRO_CHUNK(csave,BAGDEF_VARIABLE_FRAME0,Frame0[state_index]);
WRITE_MICRO_CHUNK(csave,BAGDEF_VARIABLE_FRAME1,Frame1[state_index]);
WRITE_MICRO_CHUNK(csave,BAGDEF_VARIABLE_ANIMATIONENABLED,AnimationEnabled[state_index]);
csave.End_Chunk();
return true;
}
/***********************************************************************************************
* BuildingAggregateDefClass::Load -- Load the contents of this object *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
bool BuildingAggregateDefClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case BAGDEF_CHUNK_STATICANIMPHYS:
StaticAnimPhysDefClass::Load( cload );
break;
case BAGDEF_CHUNK_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, BAGDEF_VARIABLE_ANIMLOGICMODE,AnimLogicMode );
READ_MICRO_CHUNK( cload, BAGDEF_VARIABLE_ISMCT, IsMCT );
default:
WWDEBUG_SAY(( "Unrecognized BuildingAggregateDef Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
case BAGDEF_CHUNK_HEALTH100_POWERON_VARIABLES:
case BAGDEF_CHUNK_HEALTH75_POWERON_VARIABLES:
case BAGDEF_CHUNK_HEALTH50_POWERON_VARIABLES:
case BAGDEF_CHUNK_HEALTH25_POWERON_VARIABLES:
case BAGDEF_CHUNK_DESTROYED_POWERON_VARIABLES:
case BAGDEF_CHUNK_HEALTH100_POWEROFF_VARIABLES:
case BAGDEF_CHUNK_HEALTH75_POWEROFF_VARIABLES:
case BAGDEF_CHUNK_HEALTH50_POWEROFF_VARIABLES:
case BAGDEF_CHUNK_HEALTH25_POWEROFF_VARIABLES:
case BAGDEF_CHUNK_DESTROYED_POWEROFF_VARIABLES:
Load_State_Animation_Data(cload,cload.Cur_Chunk_ID() - BAGDEF_CHUNK_HEALTH100_POWERON_VARIABLES);
break;
default:
WWDEBUG_SAY(( "Unrecognized BuildingAggregateDef chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
/***********************************************************************************************
* BuildingAggregateDefClass::Load_State_Animation_Data -- Load anim data for a building state *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 8/29/2000 gth : Created. *
*=============================================================================================*/
bool BuildingAggregateDefClass::Load_State_Animation_Data(ChunkLoadClass & cload,int state_index)
{
WWASSERT(state_index >= 0);
WWASSERT(state_index < BuildingStateClass::STATE_COUNT);
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK(cload,BAGDEF_VARIABLE_FRAME0,Frame0[state_index]);
READ_MICRO_CHUNK(cload,BAGDEF_VARIABLE_FRAME1,Frame1[state_index]);
READ_MICRO_CHUNK(cload,BAGDEF_VARIABLE_ANIMATIONENABLED,AnimationEnabled[state_index]);
default:
WWDEBUG_SAY(( "Unrecognized BuildingAggregateDef Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
return true;
}

View File

@@ -0,0 +1,159 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/buildingaggregate.h $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 11/21/01 2:47p $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef BUILDINGAGGREGATE_H
#define BUILDINGAGGREGATE_H
#include "always.h"
#include "staticanimphys.h"
#include "buildingstate.h"
class BuildingAggregateDefClass;
/**
** BuildingAggregateClass (BAG)
** This class implements the behavior of a "building aggregate". Building aggregates are animated
** static objects which display segments of their animation depending on the state of the building.
*/
class BuildingAggregateClass : public StaticAnimPhysClass
{
public:
// Constructor and Destructor
BuildingAggregateClass( void );
virtual ~BuildingAggregateClass( void );
// Definitions
void Init( const BuildingAggregateDefClass & definition );
const BuildingAggregateDefClass * Get_BuildingAggregateDef( void ) const { WWASSERT( Definition ); return (BuildingAggregateDefClass *)Definition; }
// State changing
int Get_Current_State(void);
void Set_Current_State(int new_state,bool force_update = false);
bool Is_MCT(void);
// Save / Load
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
virtual void Save_State( ChunkSaveClass & csave );
virtual void Load_State( ChunkLoadClass & cload );
virtual void On_Post_Load( void );
virtual const PersistFactoryClass & Get_Factory( void ) const;
protected:
bool Is_Power_On(int state);
int CurrentState;
};
/**
** BuildingAggregateDefClass (BAGDef!)
** The data contained in this class defines the behavior of a "building aggregate". Building
** aggregates are animated static objects which display segments of their animation depending
** on the state of the building.
** Obviously, this is a very special case object; designed specifically to provide a set of
** features needed by the building logic in Renegade.
*/
class BuildingAggregateDefClass : public StaticAnimPhysDefClass
{
public:
BuildingAggregateDefClass(void);
virtual uint32 Get_Class_ID( void ) const;
virtual const char * Get_Type_Name(void) { return "BuildingAggregateDef"; }
virtual bool Is_Type(const char *);
virtual PersistClass * Create( void ) const ;
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
virtual const PersistFactoryClass & Get_Factory( void ) const;
DECLARE_EDITABLE( BuildingAggregateDefClass, StaticAnimPhysDefClass );
protected:
bool Save_State_Animation_Data(ChunkSaveClass & csave,int state_index);
bool Load_State_Animation_Data(ChunkLoadClass & cload,int state_index);
/*
** Animation Logic Setting
** ANIM_LOGIC_LINEAR - Frame0 is used for each state, if the damage state changes, the animation
** is played to the new state's Frame0. If the power state changes, we pop to the same relative
** position in the alternate power state.
** ANIM_LOGIC_LOOP - In this mode, each state has a pair of frames which it loops between. Whenever
** the state changes, we pop to the same relative position in the new loop. In addition, certain
** states can have animation disabled; this will cause the object to freeze on the appropriate frame
** right after the state change.
*/
enum
{
ANIM_LOGIC_LINEAR = 0,
ANIM_LOGIC_LOOP,
ANIM_LOGIC_SEQUENCE,
};
int AnimLogicMode;
bool IsMCT;
/*
** Animation controls for each state. In LOOP mode, we use Frame0 and Frame1 to define a loop. In
** Linear mode, only Frame0 is used.
*/
int Frame0[BuildingStateClass::STATE_COUNT];
int Frame1[BuildingStateClass::STATE_COUNT];
bool AnimationEnabled[BuildingStateClass::STATE_COUNT];
friend class BuildingAggregateClass;
};
#endif //BUILDINGAGGREGATE_H

View File

@@ -0,0 +1,115 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/buildingmonitor.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 12/05/01 1:46p $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "buildingmonitor.h"
#include "building.h"
////////////////////////////////////////////////////////////////
//
// Killed
//
////////////////////////////////////////////////////////////////
void
BuildingMonitorClass::Killed (GameObject *game_obj, GameObject *killer)
{
WWASSERT (Building != NULL);
//
// Notify the building
//
Building->On_Destroyed ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Damaged
//
////////////////////////////////////////////////////////////////
void
BuildingMonitorClass::Damaged (GameObject *game_obj, GameObject *killer, float amount )
{
// Only report damage not heal
if (amount > 0.0f) {
WWASSERT (Building != NULL);
// If the building has been damaged to the point of being destroyed
// then do not report the damaged event. A killed event will be sent
// later.
DefenseObjectClass* defense = Building->Get_Defense_Object();
if (defense && (defense->Get_Health() <= 0.0f)) {
return;
}
DamageableGameObj* damager = NULL;
if (killer) {
damager = killer->As_DamageableGameObj();
}
bool friendlyFire = (damager && (damager->Get_Player_Type() == Building->Get_Player_Type()));
// Notify the building
if (!friendlyFire) {
Building->On_Damaged();
}
}
}
////////////////////////////////////////////////////////////////
//
// Custom
//
////////////////////////////////////////////////////////////////
void
BuildingMonitorClass::Custom (GameObject *game_obj, int type, int param, GameObject *sender)
{
WWASSERT (Building != NULL);
//
// Notify the controller
//
if (type == CUSTOM_EVENT_BUILDING_POWER_CHANGED) {
//Building->On_Building_Damaged (game_obj->As_BuldingGameObj ());
}
return ;
}

View File

@@ -0,0 +1,108 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/buildingmonitor.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 11/29/01 11:03a $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __BUILDINGMONITOR_H
#define __BUILDINGMONITOR_H
#include "gameobjobserver.h"
////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////
class BuildingGameObj;
////////////////////////////////////////////////////////////////
//
// BuildingMonitorClass
//
////////////////////////////////////////////////////////////////
class BuildingMonitorClass : public GameObjObserverClass
{
public:
////////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////////
BuildingMonitorClass (void) :
Building (NULL) {}
~BuildingMonitorClass (void) {}
////////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////////
void Set_Building (BuildingGameObj *building) { Building = building; }
//
// From GameObjObeserverClass
//
const char * Get_Name (void) { return "BuildingMonitorClass"; }
void Killed (GameObject *game_obj, GameObject *killer);
void Damaged (GameObject *game_obj, GameObject *damager, float amount );
void Custom (GameObject *game_obj, int type, int param, GameObject *sender);
//
// Unused methods from the base class
//
void Attach (GameObject *) {}
void Detach (GameObject *) {}
void Created (GameObject *) {}
void Destroyed (GameObject *) {}
void Sound_Heard (GameObject *, const CombatSound &) {}
void Enemy_Seen (GameObject *, GameObject *) {}
void Action_Complete (GameObject *, int, ActionCompleteReason) {}
void Timer_Expired (GameObject *, int) {}
void Animation_Complete (GameObject *, const char *) {}
void Poked (GameObject *, GameObject *) {}
void Entered (GameObject *, GameObject *) {}
void Exited (GameObject *, GameObject *) {}
private:
////////////////////////////////////////////////////////////////////
// Private member data
////////////////////////////////////////////////////////////////////
BuildingGameObj * Building;
};
#endif //__BUILDINGMONITOR_H

View File

@@ -0,0 +1,154 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/buildingstate.cpp $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 9/08/00 10:37a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "buildingstate.h"
#include "wwdebug.h"
/*
** Static data used by BuildingStateClass
*/
static int _EquivalentPowerOnState[] =
{
BuildingStateClass::HEALTH100_POWERON,
BuildingStateClass::HEALTH75_POWERON,
BuildingStateClass::HEALTH50_POWERON,
BuildingStateClass::HEALTH25_POWERON,
BuildingStateClass::DESTROYED_POWERON,
BuildingStateClass::HEALTH100_POWERON,
BuildingStateClass::HEALTH75_POWERON,
BuildingStateClass::HEALTH50_POWERON,
BuildingStateClass::HEALTH25_POWERON,
BuildingStateClass::DESTROYED_POWERON,
};
static int _EquivalentPowerOffState[] =
{
BuildingStateClass::HEALTH100_POWEROFF,
BuildingStateClass::HEALTH75_POWEROFF,
BuildingStateClass::HEALTH50_POWEROFF,
BuildingStateClass::HEALTH25_POWEROFF,
BuildingStateClass::DESTROYED_POWEROFF,
BuildingStateClass::HEALTH100_POWEROFF,
BuildingStateClass::HEALTH75_POWEROFF,
BuildingStateClass::HEALTH50_POWEROFF,
BuildingStateClass::HEALTH25_POWEROFF,
BuildingStateClass::DESTROYED_POWEROFF,
};
static const char * _StateNames[] =
{
"Building State: Health 100%, Power ON",
"Building State: Health 75%, Power ON",
"Building State: Health 50%, Power ON",
"Building State: Health 25%, Power ON",
"Building State: Destroyed, Power ON",
"Building State: Health 100%, Power OFF",
"Building State: Health 75%, Power OFF",
"Building State: Health 50%, Power OFF",
"Building State: Health 25%, Power OFF",
"Building State: Destroyed, Power OFF",
};
int BuildingStateClass::Get_Health_State(int building_state)
{
int state = building_state;
if (state >= HEALTH100_POWEROFF) {
state -= HEALTH100_POWEROFF;
}
return state;
}
int BuildingStateClass::Percentage_To_Health_State(float health)
{
if (health <= 0.0f) {
return HEALTH_0;
}
if (health <= 25.0f) {
return HEALTH_25;
}
if (health <= 50.0f) {
return HEALTH_50;
}
if (health <= 75.0f) {
return HEALTH_75;
}
return HEALTH_100;
}
bool BuildingStateClass::Is_Power_On(int building_state)
{
return (building_state < HEALTH100_POWEROFF);
}
int BuildingStateClass::Enable_Power(int input_state,bool onoff)
{
if (onoff) {
return _EquivalentPowerOnState[input_state];
} else {
return _EquivalentPowerOffState[input_state];
}
}
int BuildingStateClass::Compose_State(int health_state,bool power_onoff)
{
int state = health_state;
if (power_onoff == false) {
state += HEALTH100_POWEROFF;
}
return state;
}
const char * BuildingStateClass::Get_State_Name(int state)
{
WWASSERT(state >= 0);
WWASSERT(state < STATE_COUNT);
return _StateNames[state];
}

102
Code/Combat/buildingstate.h Normal file
View File

@@ -0,0 +1,102 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/buildingstate.h $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 2/07/01 6:00p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef BUILDINGSTATES_H
#define BUILDINGSTATES_H
#include "always.h"
/**
** BuildingStateClass
** This 'class' encapsulates some functions which work with the enumerated states that buildings can
** have. These enumerations are used by BuildingGameObj and BuildingAggregateClass...
**
** WARNING: Don't change these enumerations without checking the BuildingGameObj and BuildingAggregateClass
** to see what problems you might cause with save-load and their general operation...
*/
class BuildingStateClass
{
public:
enum
{
HEALTH100_POWERON = 0,
HEALTH75_POWERON,
HEALTH50_POWERON,
HEALTH25_POWERON,
DESTROYED_POWERON,
HEALTH100_POWEROFF,
HEALTH75_POWEROFF,
HEALTH50_POWEROFF,
HEALTH25_POWEROFF,
DESTROYED_POWEROFF,
STATE_COUNT
};
enum
{
HEALTH_100 = 0,
HEALTH_75,
HEALTH_50,
HEALTH_25,
HEALTH_0,
};
static int Get_Health_State(int building_state);
static int Percentage_To_Health_State(float health);
static bool Is_Power_On(int building_state);
static int Enable_Power(int input_state,bool onoff);
static int Compose_State(int health_state,bool power_onoff);
static const char * Get_State_Name(int state);
};
#endif // BUILDINGSTATES_H

1073
Code/Combat/bullet.cpp Normal file

File diff suppressed because it is too large Load Diff

71
Code/Combat/bullet.h Normal file
View File

@@ -0,0 +1,71 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/bullet.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 4/16/01 3:19p $*
* *
* $Revision:: 51 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef BULLET_H
#define BULLET_H
#ifndef ALWAYS_H
#include "always.h"
#endif
class ChunkSaveClass;
class ChunkLoadClass;
class AmmoDefinitionClass;
class Vector3;
class ArmedGameObj;
class DamageableGameObj;
/*
** BulletManager
*/
class BulletManager {
public:
static void Init( void );
static void Shutdown( void );
static void Update( void );
static bool Save( ChunkSaveClass &csave );
static bool Load( ChunkLoadClass &cload );
static void Create_Bullet( const AmmoDefinitionClass * def, const Vector3 & position,
const Vector3 & velocity, const ArmedGameObj * owner, float progress_time, const Vector3 & target, DamageableGameObj * target_object = NULL );
};
#endif // BULLET_H

906
Code/Combat/c4.cpp Normal file
View File

@@ -0,0 +1,906 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/c4.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 2/12/02 10:25a $*
* *
* $Revision:: 72 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "c4.h"
#include "debug.h"
#include "phys.h"
#include "combat.h"
#include "explosion.h"
#include "soldier.h"
#include "persistfactory.h"
#include "combatchunkid.h"
#include "weaponmanager.h"
#include "simpledefinitionfactory.h"
#include "wwhack.h"
#include "decophys.h"
#include "assets.h"
#include "gameobjmanager.h"
#include "wwaudio.h"
#include "wwprofile.h"
#include "projectile.h"
#include "wwphysids.h"
#include "buildingaggregate.h"
#include "rendobj.h"
#include "definitionmgr.h"
#include "apppackettypes.h"
#include "bitpackids.h"
#include "surfaceeffects.h"
#include "gametype.h"
/*
** C4GameObjDef
*/
DECLARE_FORCE_LINK( C4 )
SimplePersistFactoryClass<C4GameObjDef, CHUNKID_GAME_OBJECT_DEF_C4> _C4GameObjDefPersistFactory;
DECLARE_DEFINITION_FACTORY(C4GameObjDef, CLASSID_GAME_OBJECT_DEF_C4, "C4") _C4GameObjDefDefFactory;
C4GameObjDef::C4GameObjDef( void ) :
ThrowVelocity( 5 )
{
EDITABLE_PARAM (C4GameObjDef, ParameterClass::TYPE_FLOAT, ThrowVelocity);
}
uint32 C4GameObjDef::Get_Class_ID (void) const
{
return CLASSID_GAME_OBJECT_DEF_C4;
}
PersistClass * C4GameObjDef::Create( void ) const
{
C4GameObj * obj = new C4GameObj;
obj->Init( *this );
return obj;
}
enum {
CHUNKID_DEF_PARENT = 930991700,
CHUNKID_DEF_VARIABLES,
MICROCHUNKID_DEF_THROW_VELOCITY = 1,
};
bool C4GameObjDef::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_DEF_PARENT );
PhysicalGameObjDef::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_THROW_VELOCITY, ThrowVelocity );
csave.End_Chunk();
return true;
}
bool C4GameObjDef::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_DEF_PARENT:
PhysicalGameObjDef::Load( cload );
break;
case CHUNKID_DEF_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_THROW_VELOCITY, ThrowVelocity );
default:
Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(( "Unrecognized SimpleDef chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
const PersistFactoryClass & C4GameObjDef::Get_Factory (void) const
{
return _C4GameObjDefPersistFactory;
}
/*
**
*/
SimplePersistFactoryClass<C4GameObj, CHUNKID_GAME_OBJECT_C4> _C4GameObjPersistFactory;
const PersistFactoryClass & C4GameObj::Get_Factory (void) const
{
return _C4GameObjPersistFactory;
}
/*
**
*/
C4GameObj::C4GameObj( void ) :
AmmoDefinition( NULL ),
Stuck( false ),
StuckMCT( false ),
StuckToObject( false ),
StuckBone( 0 ),
StuckStaticAnimObj(NULL),
OwnerBackup( NULL ),
Age( 0 )
{
Set_App_Packet_Type(APPPACKETTYPE_C4);
}
C4GameObj::~C4GameObj()
{
REF_PTR_RELEASE(StuckStaticAnimObj);
}
/*
**
*/
void C4GameObj::Init( void )
{
Init( Get_Definition() );
}
/*
**
*/
void C4GameObj::Init( const C4GameObjDef & definition )
{
SimpleGameObj::Init( definition );
Peek_Physical_Object()->Set_Collision_Group( TERRAIN_AND_BULLET_COLLISION_GROUP );
Peek_Physical_Object()->Set_Collision_Group( DEFAULT_COLLISION_GROUP );
}
const C4GameObjDef & C4GameObj::Get_Definition( void ) const
{
return (const C4GameObjDef &)BaseGameObj::Get_Definition();
}
void C4GameObj::Init_C4( const AmmoDefinitionClass * def, SoldierGameObj *owner, int detonation_mode, const Matrix3D & tm )
{
WWASSERT( AmmoDefinition == NULL );
AmmoDefinition = def;
if ( !def->ModelName.Is_Empty() ) {
Peek_Physical_Object()->Set_Model_By_Name( def->ModelName ) ;
}
Owner = owner;
DetonationMode = detonation_mode;
Set_Transform( tm );
Stuck = false;
StuckMCT = false;
StuckToObject = false;
Peek_Physical_Object()->Set_Collision_Group( DEFAULT_COLLISION_GROUP );
OwnerBackup = NULL;
if ( owner ) {
Set_Player_Type( owner->Get_Player_Type() );
OwnerBackup = owner->Get_Player_Data();
if ( CombatManager::I_Am_Server() && !IS_MISSION ) {
Maintain_C4_Limit( Get_Player_Type() );
}
}
int type = AmmoDefinition->AmmoType;
if ( type != AmmoDefinitionClass::AMMO_TYPE_C4_REMOTE ) {
// Setup Arming Timer
float time = def->C4TriggerTime1;
if ( detonation_mode == 2 ) time = def->C4TriggerTime2;
if ( detonation_mode == 3 ) time = def->C4TriggerTime3;
Timer = time;
}
float sound_id = def->C4TimingSound1ID;
if ( detonation_mode == 2 ) sound_id = def->C4TimingSound1ID;
if ( detonation_mode == 3 ) sound_id = def->C4TimingSound1ID;
if ( sound_id ) {
RefCountedGameObjReference *owner_ref = new RefCountedGameObjReference(Owner);
WWAudioClass::Get_Instance()->Create_Instant_Sound( sound_id, Get_Transform(), owner_ref);
REF_PTR_RELEASE(owner_ref);
}
ProjectileClass * po = Peek_Physical_Object()->As_ProjectileClass();
if ( po ) {
po->Set_Velocity( tm.Get_X_Vector() * Get_Definition().ThrowVelocity );
}
//
// "Dirty" the object for networking
//
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_RARE, true );
}
CollisionReactionType C4GameObj::Collision_Occurred( const CollisionEventClass & event )
{
Debug_Say(( "C4 collision\n" ));
// if ( ( !Stuck ) && (CombatManager::I_Am_Server()) )
if (!Stuck)
{
// Figure out who/what/where we hit
PhysicalGameObj * other = NULL;
BuildingGameObj * building = NULL;
bool hit_projectile = event.OtherObj->As_ProjectileClass() != NULL;
if ( event.OtherObj->Get_Observer() != NULL ) {
other = ((CombatPhysObserverClass *)event.OtherObj->Get_Observer())->As_PhysicalGameObj();
building = ((CombatPhysObserverClass *)event.OtherObj->Get_Observer())->As_BuildingGameObj();
}
Restore_Owner();
// Ignore my owner and my owners vehicle
if ( other != NULL && Get_Owner() != NULL ) {
VehicleGameObj * vehicle = other->As_VehicleGameObj();
SoldierGameObj * soldier = Get_Owner()->As_SoldierGameObj();
if ( vehicle != NULL && vehicle == soldier->Get_Vehicle() ) {
return COLLISION_REACTION_NO_BOUNCE;
}
if ( other == Get_Owner() ) {
return COLLISION_REACTION_NO_BOUNCE;
}
// if ( !other->Is_Teammate( Get_Owner() ) )
{
Debug_Say(( "Sticking to game object %p (%p)\n", other, Get_Owner() ));
Stuck = true;
StuckToObject = true;
StuckObject = other;
StuckBone = 0;
RenderObjClass * parent_model = other->Peek_Model();
if ( parent_model ) {
StuckBone = parent_model->Get_Sub_Object_Bone_Index( event.CollidedRenderObj );
}
Vector3 my_pos;
Get_Position(&my_pos);
Matrix3D::Inverse_Transform_Vector( parent_model->Get_Bone_Transform( StuckBone ), my_pos, &StuckOffset );
Peek_Physical_Object()->Enable_User_Control( true );
if (CombatManager::I_Am_Server()) {
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
}
return COLLISION_REACTION_STOP_MOTION;
}
} else if ( building != NULL ) {
// Stick to the building
Stuck = true;
StuckObject = (ScriptableGameObj*)building;
StuckMCT = false;
// Check for MCT collision
if (event.OtherObj->Get_Factory().Chunk_ID() == PHYSICS_CHUNKID_BUILDINGAGGREGATE) {
if (((BuildingAggregateClass *)event.OtherObj)->Is_MCT()) {
StuckMCT = true;
}
}
Peek_Physical_Object()->Enable_User_Control( true );
if (CombatManager::I_Am_Server()) {
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
}
return COLLISION_REACTION_STOP_MOTION;
} else if ( other == NULL && !hit_projectile ) {
// if this is a static anim, then try to stick to it
if (event.OtherObj->As_StaticAnimPhysClass() != NULL) {
Debug_Say(( "Sticking to static anim object %p (%p)\n", event.OtherObj ));
REF_PTR_SET(StuckStaticAnimObj,(StaticAnimPhysClass *)event.OtherObj);
StuckBone = 0;
if ( StuckStaticAnimObj->Peek_Model() ) {
StuckBone = StuckStaticAnimObj->Peek_Model()->Get_Sub_Object_Bone_Index( event.CollidedRenderObj );
Vector3 my_pos;
Get_Position(&my_pos);
Matrix3D::Inverse_Transform_Vector( StuckStaticAnimObj->Peek_Model()->Get_Bone_Transform( StuckBone ), my_pos, &StuckOffset );
}
}
// If we hit permiable, pass through
if ( event.CollisionResult != NULL &&
SurfaceEffectsManager::Is_Surface_Permeable( event.CollisionResult->SurfaceType ) ) {
Debug_Say(( "C4 passes through permeable\n" ));
return COLLISION_REACTION_NO_BOUNCE;
}
// We are hitting a static terrain, just stick
Debug_Say(( "Sticking to terrain\n" ));
Peek_Physical_Object()->Enable_User_Control( true );
Stuck = true;
if (CombatManager::I_Am_Server()) {
Set_Object_Dirty_Bit(NetworkObjectClass::BIT_RARE, true);
}
return COLLISION_REACTION_STOP_MOTION;
}
}
return COLLISION_REACTION_NO_BOUNCE;
}
/*
** C4GameObj Save and Load
*/
enum {
CHUNKID_PARENT = 922991750,
CHUNKID_VARIABLES,
XXXCHUNKID_C4_TIMER,
CHUNKID_OWNER,
CHUNKID_STUCK_OBJECT,
XXXXMICROCHUNKID_PARAMS_NAME = 1,
XXXXXMICROCHUNKID_PARAMS_NAME,
MICROCHUNKID_AMMO_DEF_ID,
MICROCHUNKID_DETONATION_MODE,
MICROCHUNKID_TIMER,
MICROCHUNKID_STUCK,
MICROCHUNKID_STUCK_OFFSET,
MICROCHUNKID_STUCK_MCT,
MICROCHUNKID_STUCK_BONE,
MICROCHUNKID_STUCK_STATIC_ANIM_OBJ_ID,
MICROCHUNKID_STUCK_TO_OBJECT,
MICROCHUNKID_AGE,
};
bool C4GameObj::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_PARENT );
SimpleGameObj::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_VARIABLES );
int ammo_def_id = AmmoDefinition->Get_ID();
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_AMMO_DEF_ID, ammo_def_id );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DETONATION_MODE, DetonationMode );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TIMER, Timer );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK, Stuck );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_OFFSET, StuckOffset );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_MCT, StuckMCT );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_BONE, StuckBone );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_TO_OBJECT, StuckToObject );
if (StuckStaticAnimObj != NULL) {
uint32 id = StuckStaticAnimObj->Get_ID();
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_STUCK_STATIC_ANIM_OBJ_ID, id);
}
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_AGE, Age );
csave.End_Chunk();
if ( Owner != NULL ) {
csave.Begin_Chunk( CHUNKID_OWNER );
Owner.Save( csave );
csave.End_Chunk();
}
if ( StuckObject != NULL ) {
csave.Begin_Chunk( CHUNKID_STUCK_OBJECT );
StuckObject.Save( csave );
csave.End_Chunk();
}
return true;
}
bool C4GameObj::Load( ChunkLoadClass &cload )
{
REF_PTR_RELEASE(StuckStaticAnimObj);
uint32 static_anim_obj_id = 0xFFFFFFFF;
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_PARENT:
SimpleGameObj::Load( cload );
break;
case CHUNKID_VARIABLES:
{
int ammo_def_id = 0;
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_AMMO_DEF_ID, ammo_def_id );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DETONATION_MODE, DetonationMode );
READ_MICRO_CHUNK( cload, MICROCHUNKID_TIMER, Timer );
READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK, Stuck );
READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_OFFSET, StuckOffset );
READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_MCT, StuckMCT );
READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_BONE, StuckBone );
READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_STATIC_ANIM_OBJ_ID, static_anim_obj_id);
READ_MICRO_CHUNK( cload, MICROCHUNKID_STUCK_TO_OBJECT, StuckToObject );
READ_MICRO_CHUNK( cload, MICROCHUNKID_AGE, Age );
default:
Debug_Say(( "Unrecognized C4 Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
WWASSERT( AmmoDefinition == NULL );
AmmoDefinition = WeaponManager::Find_Ammo_Definition( ammo_def_id );
WWASSERT( AmmoDefinition != NULL );
break;
}
case CHUNKID_OWNER:
Owner.Load( cload );
break;
case CHUNKID_STUCK_OBJECT:
StuckObject.Load( cload );
break;
default:
Debug_Say(( "Unrecognized C4 chunkID\n" ));
break;
}
cload.Close_Chunk();
}
if (static_anim_obj_id != 0xFFFFFFFF) {
StaticPhysClass * pobj = PhysicsSceneClass::Get_Instance()->Get_Static_Object_By_ID(static_anim_obj_id);
if (pobj && (pobj->As_StaticAnimPhysClass() != NULL)) {
REF_PTR_SET(StuckStaticAnimObj,(StaticAnimPhysClass *)pobj);
}
REF_PTR_RELEASE(pobj);
}
return true;
}
void C4GameObj::Think( void )
{
SimpleGameObj::Think();
WWPROFILE( "C4 Think" );
if ( !CombatManager::I_Am_Server() ) {
return;
}
Age += TimeManager::Get_Frame_Seconds();
int type = AmmoDefinition->AmmoType;
WWASSERT( type >= AmmoDefinitionClass::AMMO_TYPE_C4_REMOTE );
WWASSERT( type <= AmmoDefinitionClass::AMMO_TYPE_C4_PROXIMITY );
Restore_Owner();
if ( type == AmmoDefinitionClass::AMMO_TYPE_C4_REMOTE ) {
if ( CombatManager::I_Am_Server() ) {
// Check for owner to detonate
SoldierGameObj * owner = Get_Owner();
if ( owner == NULL ) {
Defuse();
} else if ( owner->Detonate_C4() ) {
Detonate();
}
} else {
Set_Delete_Pending();
}
}
if ( type == AmmoDefinitionClass::AMMO_TYPE_C4_TIMED ) {
// Check for time's up
Timer -= TimeManager::Get_Frame_Seconds();
if ( Timer <= 0 ) {
Detonate();
}
}
if ( type == AmmoDefinitionClass::AMMO_TYPE_C4_PROXIMITY ) {
Timer -= TimeManager::Get_Frame_Seconds();
if ( Timer <= 0 ) {
// Reset Timer
// Timer += 1; // Check every second
Timer += 0.25; // Check every 1/4 second
// Check for smart objs in proximity
float trigger_range = AmmoDefinition->C4TriggerRange1;
if ( DetonationMode == 2 ) trigger_range = AmmoDefinition->C4TriggerRange2;
if ( DetonationMode == 3 ) trigger_range = AmmoDefinition->C4TriggerRange3;
Vector3 c4_pos;
Get_Position( &c4_pos );
SLNode<SmartGameObj> * smart_objnode;
for (smart_objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head(); smart_objnode; smart_objnode = smart_objnode->Next()) {
SmartGameObj * obj = smart_objnode->Data();
if ( obj && Is_Enemy( obj ) ) {
Vector3 obj_pos;
obj->Get_Position( &obj_pos );
float range = (obj_pos - c4_pos).Length();
if ( range <= trigger_range ) {
Detonate();
}
}
}
}
}
}
void C4GameObj::Post_Think( void )
{
SimpleGameObj::Post_Think();
WWPROFILE( "C4 Post_Think" );
// Follow your stuck object
if ( Stuck ) {
if ( StuckObject.Get_Ptr() != NULL ) {
PhysicalGameObj * obj = StuckObject.Get_Ptr()->As_PhysicalGameObj();
if ( obj ) {
RenderObjClass * parent_model = obj->Peek_Model();
Vector3 pos;
if ( parent_model ) {
pos = parent_model->Get_Bone_Transform( StuckBone ) * StuckOffset;
} else {
pos = obj->Get_Transform() * StuckOffset;
}
Set_Position( pos );
if (obj->As_SoldierGameObj()) {
bool hide = (obj->As_SoldierGameObj()->Get_Vehicle() != NULL);
if (Peek_Model()) {
Peek_Model()->Set_Hidden(hide);
}
}
}
} else if ( StuckStaticAnimObj != NULL) {
Vector3 pos;
pos = StuckStaticAnimObj->Peek_Model()->Get_Bone_Transform( StuckBone ) * StuckOffset;
Set_Position(pos);
} else {
// Delete without exploding if my object is gone
if ( StuckToObject ) {
Set_Delete_Pending();
}
}
}
}
void C4GameObj::Detonate( void )
{
if ( CombatManager::I_Am_Server() ) {
Restore_Owner();
if ( AmmoDefinition && AmmoDefinition->ExplosionDefID ) {
int owner_id = 0;
if ( Get_Owner() ) {
owner_id = Get_Owner()->Get_ID();
}
DamageableGameObj * force_victim = NULL;
if ( Stuck && StuckToObject ) {
force_victim = (DamageableGameObj *)StuckObject.Get_Ptr();
}
ExplosionManager::Server_Explode( AmmoDefinition->ExplosionDefID, Get_Transform().Get_Translation(), owner_id, force_victim );
}
// If I am stuck to a building, apply damage to that building
if ( Stuck ) {
if ( StuckObject.Get_Ptr() != NULL ) {
BuildingGameObj * building = StuckObject.Get_Ptr()->As_BuildingGameObj();
if ( building ) {
ExplosionManager::Explosion_Damage_Building( AmmoDefinition->ExplosionDefID, building, StuckMCT, Get_Owner() );
}
}
}
}
Set_Delete_Pending();
}
void C4GameObj::Completely_Damaged( const OffenseObjectClass & damager )
{
Defuse();
}
/*
**
*/
void C4GameObj::Get_Information( StringClass & string )
{
SimpleGameObj::Get_Information( string );
int type = AmmoDefinition->AmmoType;
if ( type == AmmoDefinitionClass::AMMO_TYPE_C4_TIMED ) {
StringClass temp(0,true);
temp.Format( "Timer: %1.1f\n", Timer );
string += temp;
}
}
/*
**
*/
void C4GameObj::Export_Rare( BitStreamClass &packet )
{
SimpleGameObj::Export_Rare( packet );
int ammo_def_id = 0;
if ( AmmoDefinition != NULL ) {
ammo_def_id = AmmoDefinition->Get_ID();
}
packet.Add( ammo_def_id );
int owner_id = 0;
if (Get_Owner()) {
owner_id = Get_Owner()->Get_ID();
}
packet.Add(owner_id);
Vector3 pos(0,0,0);
Vector3 vel(0,0,0);
ProjectileClass * po = Peek_Physical_Object()->As_ProjectileClass();
if ( po ) {
po->Get_Velocity(&vel);
po->Get_Position(&pos);
}
packet.Add(vel.X, BITPACK_VEHICLE_VELOCITY);
packet.Add(vel.Y, BITPACK_VEHICLE_VELOCITY);
packet.Add(vel.Z, BITPACK_VEHICLE_VELOCITY);
//
// Synchronize the stuck state of C4
//
packet.Add(Stuck);
if (Stuck) {
packet.Add(pos.X, BITPACK_WORLD_POSITION_X);
packet.Add(pos.Y, BITPACK_WORLD_POSITION_Y);
packet.Add(pos.Z, BITPACK_WORLD_POSITION_Z);
packet.Add(StuckMCT);
packet.Add(StuckToObject);
int stuck_object_id=0;
if (StuckObject.Get_Ptr()) {
stuck_object_id = StuckObject.Get_Ptr()->Get_ID();
}
packet.Add(stuck_object_id);
if (StuckToObject) {
packet.Add(StuckOffset.X, BITPACK_VEHICLE_VELOCITY); // offset, using velocity packing...
packet.Add(StuckOffset.Y, BITPACK_VEHICLE_VELOCITY);
packet.Add(StuckOffset.Z, BITPACK_VEHICLE_VELOCITY);
packet.Add(StuckBone);
}
bool stuck_static_anim = (StuckStaticAnimObj != NULL);
packet.Add(stuck_static_anim);
if (stuck_static_anim) {
packet.Add(StuckStaticAnimObj->Get_ID());
}
}
}
void C4GameObj::Import_Rare( BitStreamClass &packet )
{
SimpleGameObj::Import_Rare( packet );
int ammo_def_id = packet.Get( ammo_def_id );
if ( ammo_def_id != 0 ) {
AmmoDefinition = (AmmoDefinitionClass *)DefinitionMgrClass::Find_Definition( ammo_def_id );
if ( !AmmoDefinition->ModelName.Is_Empty() ) {
Peek_Physical_Object()->Set_Model_By_Name( AmmoDefinition->ModelName ) ;
}
}
int owner_id = packet.Get(owner_id);
if (owner_id != 0) {
Owner = GameObjManager::Find_SmartGameObj(owner_id);
} else {
Owner = NULL;
}
Vector3 vel;
packet.Get(vel.X, BITPACK_VEHICLE_VELOCITY);
packet.Get(vel.Y, BITPACK_VEHICLE_VELOCITY);
packet.Get(vel.Z, BITPACK_VEHICLE_VELOCITY);
ProjectileClass * po = Peek_Physical_Object()->As_ProjectileClass();
if ( po ) {
po->Set_Velocity(vel);
}
//
// Synchronize the stuck state of C4
//
Stuck = packet.Get(Stuck);
if (Stuck) {
Peek_Physical_Object()->Enable_User_Control( true );
// Update the position
Vector3 pos;
packet.Get(pos.X, BITPACK_WORLD_POSITION_X);
packet.Get(pos.Y, BITPACK_WORLD_POSITION_Y);
packet.Get(pos.Z, BITPACK_WORLD_POSITION_Z);
ProjectileClass * po = Peek_Physical_Object()->As_ProjectileClass();
if ( po ) {
Vector3 local_pos;
po->Get_Position(&local_pos);
if ((local_pos - pos).Length2() > 0.5f * 0.5f) {
po->Set_Position(pos);
}
}
WWDEBUG_SAY(("C4 %d is now STUCK, pos= %f, %f, %f",(int)this, pos.X,pos.Y,pos.Z));
packet.Get(StuckMCT);
packet.Get(StuckToObject);
int stuck_object_id;
packet.Get(stuck_object_id);
StuckObject = GameObjManager::Find_ScriptableGameObj(stuck_object_id);
if (StuckToObject) {
packet.Get(StuckOffset.X, BITPACK_VEHICLE_VELOCITY); // offset, using velocity packing...
packet.Get(StuckOffset.Y, BITPACK_VEHICLE_VELOCITY);
packet.Get(StuckOffset.Z, BITPACK_VEHICLE_VELOCITY);
packet.Get(StuckBone);
}
bool stuck_static_anim;
packet.Get(stuck_static_anim);
if (stuck_static_anim) {
uint32 static_anim_obj_id = 0;
packet.Get(static_anim_obj_id);
if (static_anim_obj_id != 0xFFFFFFFF) {
StaticPhysClass * pobj = PhysicsSceneClass::Get_Instance()->Get_Static_Object_By_ID(static_anim_obj_id);
if (pobj && (pobj->As_StaticAnimPhysClass() != NULL)) {
REF_PTR_SET(StuckStaticAnimObj,(StaticAnimPhysClass *)pobj);
}
REF_PTR_RELEASE(pobj);
}
}
}
}
void C4GameObj::Defuse( void )
{
if ( CombatManager::I_Am_Server() ) {
Restore_Owner();
const AmmoDefinitionClass * disarmed_ammo = WeaponManager::Find_Ammo_Definition( "KilledC4" );
if ( disarmed_ammo && disarmed_ammo->ExplosionDefID ) {
int owner_id = 0;
if ( Get_Owner() ) {
owner_id = Get_Owner()->Get_ID();
}
ExplosionManager::Server_Explode( disarmed_ammo->ExplosionDefID, Get_Transform().Get_Translation(), owner_id );
}
}
Set_Delete_Pending();
}
void C4GameObj::Restore_Owner( void )
{
if ( Get_Owner() == NULL && OwnerBackup != NULL &&
AmmoDefinition && (int)AmmoDefinition->AmmoType != (int)AmmoDefinitionClass::AMMO_TYPE_C4_REMOTE ) {
// Try and find a smart game obj with the same playerdata
SLNode<SmartGameObj> * smart_objnode;
for (smart_objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head(); smart_objnode; smart_objnode = smart_objnode->Next()) {
SmartGameObj * obj = smart_objnode->Data();
if ( obj->Get_Player_Data() == OwnerBackup ) {
Owner = obj;
Debug_Say(( "Found C4 owner\n" ));
}
}
if ( Get_Owner() == NULL ) {
OwnerBackup = NULL;
Defuse();
Debug_Say(( "Didn't find C4 owner\n" ));
}
}
}
/*
**
*/
#define C4_LIMIT 30
void C4GameObj::Maintain_C4_Limit( int player_type )
{
if ( !CombatManager::I_Am_Server() || IS_MISSION ) {
return;
}
SLNode<BaseGameObj> *objnode;
C4GameObj * oldest_c4 = NULL;
int count = 0;
for ( objnode = GameObjManager::Get_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
PhysicalGameObj * phys = objnode->Data()->As_PhysicalGameObj();
if ( phys ) {
C4GameObj * c4 = phys->As_C4GameObj();
if ( c4 &&
c4->Get_Player_Type() == player_type &&
c4->AmmoDefinition &&
(int)c4->AmmoDefinition->AmmoType != (int)AmmoDefinitionClass::AMMO_TYPE_C4_TIMED ) {
count++;
if ( (oldest_c4 == NULL) || (c4->Age > oldest_c4->Age) ) {
oldest_c4 = c4;
}
}
}
}
if ( count > C4_LIMIT && oldest_c4 != NULL ) {
oldest_c4->Defuse();
}
}

145
Code/Combat/c4.h Normal file
View File

@@ -0,0 +1,145 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/c4.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 1/08/02 3:05p $*
* *
* $Revision:: 33 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef C4_H
#define C4_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef SIMPLEGAMEOBJ_H
#include "simplegameobj.h"
#endif
#ifndef TIMEMGR_H
#include "timemgr.h"
#endif
class AmmoDefinitionClass;
class StaticAnimPhysClass;
/*
** C4GameObjDef - Defintion class for a C4GameObj
*/
class C4GameObjDef : public SimpleGameObjDef
{
public:
C4GameObjDef( void );
virtual uint32 Get_Class_ID( void ) const;
virtual PersistClass * Create( void ) const ;
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
virtual const PersistFactoryClass & Get_Factory( void ) const;
DECLARE_EDITABLE( C4GameObjDef, SimpleGameObjDef );
float ThrowVelocity;
protected:
friend class C4GameObj;
};
/*
**
*/
class C4GameObj : public SimpleGameObj {
public:
C4GameObj();
virtual ~C4GameObj();
// Definitions
virtual void Init( void );
void Init( const C4GameObjDef & definition );
const C4GameObjDef & Get_Definition( void ) const ;
// Save / Load / Construction Factory
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
virtual const PersistFactoryClass & Get_Factory( void ) const;
virtual C4GameObj * As_C4GameObj( void ) { return this; }
void Init_C4( const AmmoDefinitionClass * def, SoldierGameObj *owner, int detonation_mode, const Matrix3D & tm );
virtual CollisionReactionType Collision_Occurred( const CollisionEventClass & event );
virtual void Think();
virtual void Post_Think();
virtual void Get_Information( StringClass & string );
virtual void Export_Rare( BitStreamClass &packet );
virtual void Import_Rare( BitStreamClass &packet );
ScriptableGameObj * Get_Stuck_Object(void) { return StuckObject.Get_Ptr(); }
virtual void Completely_Damaged( const OffenseObjectClass & damager );
SoldierGameObj *Get_Owner( void ) const { return (SoldierGameObj *)Owner.Get_Ptr(); }
void Defuse( void );
static void Maintain_C4_Limit( int player_type );
private:
float Timer;
GameObjReference Owner;
void * OwnerBackup;
const AmmoDefinitionClass * AmmoDefinition;
int DetonationMode;
bool Stuck;
bool StuckToObject;
GameObjReference StuckObject;
Vector3 StuckOffset;
int StuckBone;
StaticAnimPhysClass * StuckStaticAnimObj;
bool StuckMCT;
float Age;
void Detonate( void );
void Restore_Owner( void );
};
#endif // C4_H

1716
Code/Combat/ccamera.cpp Normal file

File diff suppressed because it is too large Load Diff

201
Code/Combat/ccamera.h Normal file
View File

@@ -0,0 +1,201 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/ccamera.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 12/10/01 2:08p $*
* *
* $Revision:: 62 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef CCAMERA_H
#define CCAMERA_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef CAMERA_H
#include "camera.h"
#endif
#ifndef WWSTRING_H
#include "wwstring.h"
#endif
class CCameraProfileClass;
class Listener3DClass;
/*
** CCameraClass (Commando Camera Class)
*/
class CCameraClass : public CameraClass
{
public:
// Constructor & Destructor
CCameraClass();
virtual ~CCameraClass();
// Get all the profiles loaded
static void Init( void );
static void Shutdown( void );
// Save and Load
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
// Function to update the camera's parameters each frame.
virtual void Update();
bool Is_In_Cinematic( void ) { return HostModel != NULL; }
bool Is_Valid( void ) { return IsValid; }
const Vector2 &Get_Camera_Target_2D_Offset() { return CameraTarget2DOffset; }
void Set_Anchor_Position( Vector3 pos );
void Force_Look( const Vector3 & target );
// Profile access
void Use_Profile( const char * name );
void Use_Default_Profile( void );
void Set_Profile_Height( float height );
void Set_Profile_Distance( float distance );
float Get_Profile_Zoom( void );
void Force_Heading( float heading ) { Heading = heading; }
float Get_Heading( void ) { return Heading; }
void Set_Tilt( float tilt ) { Tilt = tilt; }
float Get_Tilt( void ) { return Tilt; }
void Set_Lerp_Time( float time );
bool Is_Lerping( void ) { return LerpTimeTotal != 0; }
void Set_Host_Model( RenderObjClass * host );
bool Is_Using_Host_Model( void ) { return (HostModel != NULL); }
void Enable_2D_Targeting( bool on_off ) { Enable2DTargeting = on_off; }
bool Is_2D_Targeting( void ) { return Enable2DTargeting; }
void Enable_Weapon_Help( bool on_off ) { EnableWeaponHelp = on_off; }
bool Is_Weapon_Help_Enabled( void ) { return EnableWeaponHelp; }
// Sniper Mode
bool Draw_Sniper( void );
void Cinematic_Sniper_Control( bool enabled, float zoom );
void Set_Is_Star_Sniping( bool yes );
bool Is_Star_Sniping( void ) { return IsStarSniping; }
float Get_Sniper_Zoom( void ) { return SniperZoom; }
void Set_Sniper_Distance( float dist );
float Get_Sniper_Distance( void ) { return SniperDistance; }
Vector3 Get_First_Person_Offset_Tweak( void );
void Reset_First_Person_Offset_Tweak( void );
// Snap Shot Mode
void Set_Snap_Shot_Mode( bool mode ) { SnapShotMode = mode ? SNAPSHOT_ON : SNAPSHOT_OFF; }
bool Is_Snap_Shot_Mode( void ) { return SnapShotMode == SNAPSHOT_ON; }
protected:
// Camera Host Model
RenderObjClass * HostModel;
// Camera Anchor Position
Vector3 AnchorPosition;
bool IsValid;
// Current orientation of the camera
float Tilt;
float Heading;
float DistanceFraction;
bool Enable2DTargeting;
float LagPersistTimer;
bool DisableLag;
// WeaponHelp
bool EnableWeaponHelp;
float WeaponHelpTimer;
int WeaponHelpTargetID; // Should probably be changed to a ObjRef
Vector3 StarTargetingPosition;
Vector2 CameraTarget2DOffset;
// Linear Interpolation
float LerpTimeTotal;
float LerpTimeRemaining;
Vector3 LastAnchorPosition;
float LastHeading;
// Parameter profile
CCameraProfileClass * CurrentProfile;
CCameraProfileClass * LastProfile;
CCameraProfileClass * DefaultProfile;
StringClass CurrentProfileName;
StringClass LastProfileName;
StringClass DefaultProfileName;
float NearClipPlane;
float FarClipPlane;
// Sniper Mode
bool IsStarSniping;
bool WasStarSniping;
float SniperZoom;
float SniperDistance;
Listener3DClass * SniperListener;
bool CinematicSnipingEnabled;
float CinematicSnipingDesiredZoom;
enum {
SNAPSHOT_OFF,
SNAPSHOT_ON,
SNAPSHOT_PROGRESS,
};
int SnapShotMode;
/*
**
*/
Vector3 Get_Camera_Pos( const Vector3 & offset,
float distance, Vector3 * intermediate_pos );
void Use_Host_Model( void );
void Handle_Input();
// Targeting
bool Determine_Targeting_Position( void );
void Apply_Weapon_Help( void );
void Update_Sniper_Listener_Pos( void );
void Handle_Snap_Shot_Mode( void );
};
#endif // CCAMERA_H

View File

@@ -0,0 +1,662 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/characterclasssettings.cpp $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 3/21/01 9:38a $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "characterclasssettings.h"
#include "combatchunkid.h"
#include "wwhack.h"
#include "persistfactory.h"
#include "definitionfactory.h"
#include "simpledefinitionfactory.h"
#include "debug.h"
#include "objectives.h"
DECLARE_FORCE_LINK (CharClassSettings)
///////////////////////////////////////////////////////////////////////////////////////////
// Static member initialization
///////////////////////////////////////////////////////////////////////////////////////////
CharacterClassSettingsDefClass * CharacterClassSettingsDefClass::GlobalInstance = NULL;
///////////////////////////////////////////////////////////////////////////////////////////
// Factories
///////////////////////////////////////////////////////////////////////////////////////////
SimplePersistFactoryClass<CharacterClassSettingsDefClass, CHUNKID_GLOBAL_SETTINGS_DEF_CHAR_CLASS> _CharClassDefPersistFactory;
DECLARE_DEFINITION_FACTORY(CharacterClassSettingsDefClass, CLASSID_GLOBAL_SETTINGS_DEF_CHAR_CLASS, "Character Classes") _CharClassDefDefFactory;
///////////////////////////////////////////////////////////////////////////////////////////
// Constants
///////////////////////////////////////////////////////////////////////////////////////////
static const char * CHAR_CLASS_NAMES[CharacterClassSettingsDefClass::CLASS_COUNT] =
{
"Minigunner",
"Rocket Soldier",
"Grenadier",
"Engineer",
"Flame Thrower",
"Mutant"
};
static const char * CHAR_RANK_NAMES[CharacterClassSettingsDefClass::RANK_COUNT] =
{
"Enlisted",
"Officer",
"Special-Forces",
"Boss"
};
static const char * CHAR_TEAM_NAMES[CharacterClassSettingsDefClass::TEAM_COUNT] =
{
"GDI",
"NOD",
};
///////////////////////////////////////////////////////////////////////////////////////////
// Save/load constants
///////////////////////////////////////////////////////////////////////////////////////////
enum
{
CHUNKID_PARENT = 0x12021027,
CHUNKID_VARIABLES,
VARID_COST_GDI_MINIGUNNER_ENLISTED = 1,
VARID_COST_GDI_MINIGUNNER_OFFICER,
VARID_COST_GDI_MINIGUNNER_SPECIAL_FORCES,
VARID_COST_GDI_MINIGUNNER_BOSS,
VARID_COST_GDI_ROCKET_SOLDIER_ENLISTED,
VARID_COST_GDI_ROCKET_SOLDIER_OFFICER,
VARID_COST_GDI_ROCKET_SOLDIER_SPECIAL_FORCES,
VARID_COST_GDI_ROCKET_SOLDIER_BOSS,
VARID_COST_GDI_GRENADIER_ENLISTED,
VARID_COST_GDI_GRENADIER_OFFICER,
VARID_COST_GDI_GRENADIER_SPECIAL_FORCES,
VARID_COST_GDI_GRENADIER_BOSS,
VARID_COST_GDI_ENGINEER_ENLISTED,
VARID_COST_GDI_ENGINEER_OFFICER,
VARID_COST_GDI_ENGINEER_SPECIAL_FORCES,
VARID_COST_GDI_ENGINEER_BOSS,
VARID_COST_GDI_FLAME_THROWER_ENLISTED,
VARID_COST_GDI_FLAME_THROWER_OFFICER,
VARID_COST_GDI_FLAME_THROWER_SPECIAL_FORCES,
VARID_COST_GDI_FLAME_THROWER_BOSS,
VARID_COST_GDI_MUTANT_ENLISTED,
VARID_COST_GDI_MUTANT_OFFICER,
VARID_COST_GDI_MUTANT_SPECIAL_FORCES,
VARID_COST_GDI_MUTANT_BOSS,
VARID_COST_NOD_MINIGUNNER_ENLISTED,
VARID_COST_NOD_MINIGUNNER_OFFICER,
VARID_COST_NOD_MINIGUNNER_SPECIAL_FORCES,
VARID_COST_NOD_MINIGUNNER_BOSS,
VARID_COST_NOD_ROCKET_SOLDIER_ENLISTED,
VARID_COST_NOD_ROCKET_SOLDIER_OFFICER,
VARID_COST_NOD_ROCKET_SOLDIER_SPECIAL_FORCES,
VARID_COST_NOD_ROCKET_SOLDIER_BOSS,
VARID_COST_NOD_GRENADIER_ENLISTED,
VARID_COST_NOD_GRENADIER_OFFICER,
VARID_COST_NOD_GRENADIER_SPECIAL_FORCES,
VARID_COST_NOD_GRENADIER_BOSS,
VARID_COST_NOD_ENGINEER_ENLISTED,
VARID_COST_NOD_ENGINEER_OFFICER,
VARID_COST_NOD_ENGINEER_SPECIAL_FORCES,
VARID_COST_NOD_ENGINEER_BOSS,
VARID_COST_NOD_FLAME_THROWER_ENLISTED,
VARID_COST_NOD_FLAME_THROWER_OFFICER,
VARID_COST_NOD_FLAME_THROWER_SPECIAL_FORCES,
VARID_COST_NOD_FLAME_THROWER_BOSS,
VARID_COST_NOD_MUTANT_ENLISTED,
VARID_COST_NOD_MUTANT_OFFICER,
VARID_COST_NOD_MUTANT_SPECIAL_FORCES,
VARID_COST_NOD_MUTANT_BOSS,
VARID_DEFID_GDI_MINIGUNNER_ENLISTED,
VARID_DEFID_GDI_MINIGUNNER_OFFICER,
VARID_DEFID_GDI_MINIGUNNER_SPECIAL_FORCES,
VARID_DEFID_GDI_MINIGUNNER_BOSS,
VARID_DEFID_GDI_ROCKET_SOLDIER_ENLISTED,
VARID_DEFID_GDI_ROCKET_SOLDIER_OFFICER,
VARID_DEFID_GDI_ROCKET_SOLDIER_SPECIAL_FORCES,
VARID_DEFID_GDI_ROCKET_SOLDIER_BOSS,
VARID_DEFID_GDI_GRENADIER_ENLISTED,
VARID_DEFID_GDI_GRENADIER_OFFICER,
VARID_DEFID_GDI_GRENADIER_SPECIAL_FORCES,
VARID_DEFID_GDI_GRENADIER_BOSS,
VARID_DEFID_GDI_ENGINEER_ENLISTED,
VARID_DEFID_GDI_ENGINEER_OFFICER,
VARID_DEFID_GDI_ENGINEER_SPECIAL_FORCES,
VARID_DEFID_GDI_ENGINEER_BOSS,
VARID_DEFID_GDI_FLAME_THROWER_ENLISTED,
VARID_DEFID_GDI_FLAME_THROWER_OFFICER,
VARID_DEFID_GDI_FLAME_THROWER_SPECIAL_FORCES,
VARID_DEFID_GDI_FLAME_THROWER_BOSS,
VARID_DEFID_GDI_MUTANT_ENLISTED,
VARID_DEFID_GDI_MUTANT_OFFICER,
VARID_DEFID_GDI_MUTANT_SPECIAL_FORCES,
VARID_DEFID_GDI_MUTANT_BOSS,
VARID_DEFID_NOD_MINIGUNNER_ENLISTED,
VARID_DEFID_NOD_MINIGUNNER_OFFICER,
VARID_DEFID_NOD_MINIGUNNER_SPECIAL_FORCES,
VARID_DEFID_NOD_MINIGUNNER_BOSS,
VARID_DEFID_NOD_ROCKET_SOLDIER_ENLISTED,
VARID_DEFID_NOD_ROCKET_SOLDIER_OFFICER,
VARID_DEFID_NOD_ROCKET_SOLDIER_SPECIAL_FORCES,
VARID_DEFID_NOD_ROCKET_SOLDIER_BOSS,
VARID_DEFID_NOD_GRENADIER_ENLISTED,
VARID_DEFID_NOD_GRENADIER_OFFICER,
VARID_DEFID_NOD_GRENADIER_SPECIAL_FORCES,
VARID_DEFID_NOD_GRENADIER_BOSS,
VARID_DEFID_NOD_ENGINEER_ENLISTED,
VARID_DEFID_NOD_ENGINEER_OFFICER,
VARID_DEFID_NOD_ENGINEER_SPECIAL_FORCES,
VARID_DEFID_NOD_ENGINEER_BOSS,
VARID_DEFID_NOD_FLAME_THROWER_ENLISTED,
VARID_DEFID_NOD_FLAME_THROWER_OFFICER,
VARID_DEFID_NOD_FLAME_THROWER_SPECIAL_FORCES,
VARID_DEFID_NOD_FLAME_THROWER_BOSS,
VARID_DEFID_NOD_MUTANT_ENLISTED,
VARID_DEFID_NOD_MUTANT_OFFICER,
VARID_DEFID_NOD_MUTANT_SPECIAL_FORCES,
VARID_DEFID_NOD_MUTANT_BOSS,
};
///////////////////////////////////////////////////////////////////////////////////////////
//
// CharacterClassSettingsDefClass
//
///////////////////////////////////////////////////////////////////////////////////////////
CharacterClassSettingsDefClass::CharacterClassSettingsDefClass (void)
{
//
// Initialize the cost and definition tables
//
::memset (CostTable, 0, sizeof (CostTable));
::memset (DefinitionTable, 0, sizeof (DefinitionTable));
//
// Configure the editable system
//
for (int class_index = 0; class_index < CLASS_COUNT; class_index ++) {
for (int team_index = 0; team_index < TEAM_COUNT; team_index ++) {
//
// Add a separator for this character class
//
StringClass name;
name.Format ("Class %s (%s)", CHAR_CLASS_NAMES[class_index], CHAR_TEAM_NAMES[team_index]);
PARAM_SEPARATOR (CharacterClassSettingsDefClass, (const char *)name);
//
// Add a pair of parameters for each rank
//
for (int rank_index = 0; rank_index < RANK_COUNT; rank_index ++) {
name.Format ("%s Cost", CHAR_RANK_NAMES[rank_index]);
NAMED_EDITABLE_PARAM (CharacterClassSettingsDefClass, ParameterClass::TYPE_INT, CostTable[class_index][rank_index][team_index], (const char *)name);
name.Format ("%s Object", CHAR_RANK_NAMES[rank_index]);
#ifdef PARAM_EDITING_ON
GenericDefParameterClass *param = new GenericDefParameterClass (&(DefinitionTable[class_index][rank_index][team_index]));
param->Set_Class_ID (CLASSID_GAME_OBJECT_DEF_SOLDIER);
param->Set_Name (name);
GENERIC_EDITABLE_PARAM(CharacterClassSettingsDefClass, param)
#endif //PARAM_EDITING_ON
}
}
}
GlobalInstance = this;
return ;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// ~CharacterClassSettingsDefClass
//
///////////////////////////////////////////////////////////////////////////////////////////
CharacterClassSettingsDefClass::~CharacterClassSettingsDefClass (void)
{
GlobalInstance = NULL;
return ;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// Get_Class_ID
//
///////////////////////////////////////////////////////////////////////////////////////////
uint32
CharacterClassSettingsDefClass::Get_Class_ID (void) const
{
return CLASSID_GLOBAL_SETTINGS_DEF_CHAR_CLASS;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// Get_Factory
//
///////////////////////////////////////////////////////////////////////////////////////////
const PersistFactoryClass &
CharacterClassSettingsDefClass::Get_Factory (void) const
{
return _CharClassDefPersistFactory;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// Create
//
///////////////////////////////////////////////////////////////////////////////////////////
PersistClass *
CharacterClassSettingsDefClass::Create (void) const
{
WWASSERT (0);
return NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// Save
//
///////////////////////////////////////////////////////////////////////////////////////////
bool
CharacterClassSettingsDefClass::Save (ChunkSaveClass &csave)
{
csave.Begin_Chunk (CHUNKID_PARENT);
DefinitionClass::Save (csave);
csave.End_Chunk ();
//
// Save the cost and definition tables...
// Note: We save each with its own specific ID because the format (rows/cols)
// of this table is likely to change...
//
csave.Begin_Chunk (CHUNKID_VARIABLES);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_MINIGUNNER_ENLISTED, CostTable[CLASS_MINIGUNNER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_MINIGUNNER_OFFICER, CostTable[CLASS_MINIGUNNER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_MINIGUNNER_SPECIAL_FORCES, CostTable[CLASS_MINIGUNNER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_MINIGUNNER_BOSS, CostTable[CLASS_MINIGUNNER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_ROCKET_SOLDIER_ENLISTED, CostTable[CLASS_ROCKET_SOLDIER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_ROCKET_SOLDIER_OFFICER, CostTable[CLASS_ROCKET_SOLDIER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_ROCKET_SOLDIER_SPECIAL_FORCES, CostTable[CLASS_ROCKET_SOLDIER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_ROCKET_SOLDIER_BOSS, CostTable[CLASS_ROCKET_SOLDIER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_GRENADIER_ENLISTED, CostTable[CLASS_GRENADIER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_GRENADIER_OFFICER, CostTable[CLASS_GRENADIER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_GRENADIER_SPECIAL_FORCES, CostTable[CLASS_GRENADIER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_GRENADIER_BOSS, CostTable[CLASS_GRENADIER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_ENGINEER_ENLISTED, CostTable[CLASS_ENGINEER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_ENGINEER_OFFICER, CostTable[CLASS_ENGINEER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_ENGINEER_SPECIAL_FORCES, CostTable[CLASS_ENGINEER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_ENGINEER_BOSS, CostTable[CLASS_ENGINEER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_FLAME_THROWER_ENLISTED, CostTable[CLASS_FLAME_THROWER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_FLAME_THROWER_OFFICER, CostTable[CLASS_FLAME_THROWER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_FLAME_THROWER_SPECIAL_FORCES, CostTable[CLASS_FLAME_THROWER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_FLAME_THROWER_BOSS, CostTable[CLASS_FLAME_THROWER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_MUTANT_ENLISTED, CostTable[CLASS_MUTANT][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_MUTANT_OFFICER, CostTable[CLASS_MUTANT][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_MUTANT_SPECIAL_FORCES, CostTable[CLASS_MUTANT][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_GDI_MUTANT_BOSS, CostTable[CLASS_MUTANT][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_MINIGUNNER_ENLISTED, DefinitionTable[CLASS_MINIGUNNER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_MINIGUNNER_OFFICER, DefinitionTable[CLASS_MINIGUNNER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_MINIGUNNER_SPECIAL_FORCES, DefinitionTable[CLASS_MINIGUNNER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_MINIGUNNER_BOSS, DefinitionTable[CLASS_MINIGUNNER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_ROCKET_SOLDIER_ENLISTED, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_ROCKET_SOLDIER_OFFICER, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_ROCKET_SOLDIER_SPECIAL_FORCES, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_ROCKET_SOLDIER_BOSS, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_GRENADIER_ENLISTED, DefinitionTable[CLASS_GRENADIER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_GRENADIER_OFFICER, DefinitionTable[CLASS_GRENADIER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_GRENADIER_SPECIAL_FORCES, DefinitionTable[CLASS_GRENADIER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_GRENADIER_BOSS, DefinitionTable[CLASS_GRENADIER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_ENGINEER_ENLISTED, DefinitionTable[CLASS_ENGINEER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_ENGINEER_OFFICER, DefinitionTable[CLASS_ENGINEER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_ENGINEER_SPECIAL_FORCES, DefinitionTable[CLASS_ENGINEER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_ENGINEER_BOSS, DefinitionTable[CLASS_ENGINEER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_FLAME_THROWER_ENLISTED, DefinitionTable[CLASS_FLAME_THROWER][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_FLAME_THROWER_OFFICER, DefinitionTable[CLASS_FLAME_THROWER][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_FLAME_THROWER_SPECIAL_FORCES, DefinitionTable[CLASS_FLAME_THROWER][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_FLAME_THROWER_BOSS, DefinitionTable[CLASS_FLAME_THROWER][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_MUTANT_ENLISTED, DefinitionTable[CLASS_MUTANT][RANK_ENLISTED][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_MUTANT_OFFICER, DefinitionTable[CLASS_MUTANT][RANK_OFFICER][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_MUTANT_SPECIAL_FORCES, DefinitionTable[CLASS_MUTANT][RANK_SPECIAL_FORCES][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_GDI_MUTANT_BOSS, DefinitionTable[CLASS_MUTANT][RANK_BOSS][TEAM_GDI]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_MINIGUNNER_ENLISTED, CostTable[CLASS_MINIGUNNER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_MINIGUNNER_OFFICER, CostTable[CLASS_MINIGUNNER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_MINIGUNNER_SPECIAL_FORCES, CostTable[CLASS_MINIGUNNER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_MINIGUNNER_BOSS, CostTable[CLASS_MINIGUNNER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_ROCKET_SOLDIER_ENLISTED, CostTable[CLASS_ROCKET_SOLDIER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_ROCKET_SOLDIER_OFFICER, CostTable[CLASS_ROCKET_SOLDIER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_ROCKET_SOLDIER_SPECIAL_FORCES, CostTable[CLASS_ROCKET_SOLDIER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_ROCKET_SOLDIER_BOSS, CostTable[CLASS_ROCKET_SOLDIER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_GRENADIER_ENLISTED, CostTable[CLASS_GRENADIER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_GRENADIER_OFFICER, CostTable[CLASS_GRENADIER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_GRENADIER_SPECIAL_FORCES, CostTable[CLASS_GRENADIER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_GRENADIER_BOSS, CostTable[CLASS_GRENADIER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_ENGINEER_ENLISTED, CostTable[CLASS_ENGINEER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_ENGINEER_OFFICER, CostTable[CLASS_ENGINEER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_ENGINEER_SPECIAL_FORCES, CostTable[CLASS_ENGINEER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_ENGINEER_BOSS, CostTable[CLASS_ENGINEER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_FLAME_THROWER_ENLISTED, CostTable[CLASS_FLAME_THROWER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_FLAME_THROWER_OFFICER, CostTable[CLASS_FLAME_THROWER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_FLAME_THROWER_SPECIAL_FORCES, CostTable[CLASS_FLAME_THROWER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_FLAME_THROWER_BOSS, CostTable[CLASS_FLAME_THROWER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_MUTANT_ENLISTED, CostTable[CLASS_MUTANT][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_MUTANT_OFFICER, CostTable[CLASS_MUTANT][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_MUTANT_SPECIAL_FORCES, CostTable[CLASS_MUTANT][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_COST_NOD_MUTANT_BOSS, CostTable[CLASS_MUTANT][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_MINIGUNNER_ENLISTED, DefinitionTable[CLASS_MINIGUNNER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_MINIGUNNER_OFFICER, DefinitionTable[CLASS_MINIGUNNER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_MINIGUNNER_SPECIAL_FORCES, DefinitionTable[CLASS_MINIGUNNER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_MINIGUNNER_BOSS, DefinitionTable[CLASS_MINIGUNNER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_ROCKET_SOLDIER_ENLISTED, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_ROCKET_SOLDIER_OFFICER, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_ROCKET_SOLDIER_SPECIAL_FORCES, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_ROCKET_SOLDIER_BOSS, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_GRENADIER_ENLISTED, DefinitionTable[CLASS_GRENADIER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_GRENADIER_OFFICER, DefinitionTable[CLASS_GRENADIER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_GRENADIER_SPECIAL_FORCES, DefinitionTable[CLASS_GRENADIER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_GRENADIER_BOSS, DefinitionTable[CLASS_GRENADIER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_ENGINEER_ENLISTED, DefinitionTable[CLASS_ENGINEER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_ENGINEER_OFFICER, DefinitionTable[CLASS_ENGINEER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_ENGINEER_SPECIAL_FORCES, DefinitionTable[CLASS_ENGINEER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_ENGINEER_BOSS, DefinitionTable[CLASS_ENGINEER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_FLAME_THROWER_ENLISTED, DefinitionTable[CLASS_FLAME_THROWER][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_FLAME_THROWER_OFFICER, DefinitionTable[CLASS_FLAME_THROWER][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_FLAME_THROWER_SPECIAL_FORCES, DefinitionTable[CLASS_FLAME_THROWER][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_FLAME_THROWER_BOSS, DefinitionTable[CLASS_FLAME_THROWER][RANK_BOSS][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_MUTANT_ENLISTED, DefinitionTable[CLASS_MUTANT][RANK_ENLISTED][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_MUTANT_OFFICER, DefinitionTable[CLASS_MUTANT][RANK_OFFICER][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_MUTANT_SPECIAL_FORCES, DefinitionTable[CLASS_MUTANT][RANK_SPECIAL_FORCES][TEAM_NOD]);
WRITE_MICRO_CHUNK (csave, VARID_DEFID_NOD_MUTANT_BOSS, DefinitionTable[CLASS_MUTANT][RANK_BOSS][TEAM_NOD]);
csave.End_Chunk();
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// Load
//
///////////////////////////////////////////////////////////////////////////////////////////
bool
CharacterClassSettingsDefClass::Load (ChunkLoadClass &cload)
{
while (cload.Open_Chunk ()) {
switch(cload.Cur_Chunk_ID ()) {
case CHUNKID_PARENT:
DefinitionClass::Load (cload);
break;
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk ()) {
switch(cload.Cur_Micro_Chunk_ID ()) {
READ_MICRO_CHUNK (cload, VARID_COST_GDI_MINIGUNNER_ENLISTED, CostTable[CLASS_MINIGUNNER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_MINIGUNNER_OFFICER, CostTable[CLASS_MINIGUNNER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_MINIGUNNER_SPECIAL_FORCES, CostTable[CLASS_MINIGUNNER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_MINIGUNNER_BOSS, CostTable[CLASS_MINIGUNNER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_ROCKET_SOLDIER_ENLISTED, CostTable[CLASS_ROCKET_SOLDIER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_ROCKET_SOLDIER_OFFICER, CostTable[CLASS_ROCKET_SOLDIER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_ROCKET_SOLDIER_SPECIAL_FORCES, CostTable[CLASS_ROCKET_SOLDIER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_ROCKET_SOLDIER_BOSS, CostTable[CLASS_ROCKET_SOLDIER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_GRENADIER_ENLISTED, CostTable[CLASS_GRENADIER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_GRENADIER_OFFICER, CostTable[CLASS_GRENADIER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_GRENADIER_SPECIAL_FORCES, CostTable[CLASS_GRENADIER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_GRENADIER_BOSS, CostTable[CLASS_GRENADIER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_ENGINEER_ENLISTED, CostTable[CLASS_ENGINEER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_ENGINEER_OFFICER, CostTable[CLASS_ENGINEER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_ENGINEER_SPECIAL_FORCES, CostTable[CLASS_ENGINEER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_ENGINEER_BOSS, CostTable[CLASS_ENGINEER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_FLAME_THROWER_ENLISTED, CostTable[CLASS_FLAME_THROWER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_FLAME_THROWER_OFFICER, CostTable[CLASS_FLAME_THROWER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_FLAME_THROWER_SPECIAL_FORCES, CostTable[CLASS_FLAME_THROWER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_FLAME_THROWER_BOSS, CostTable[CLASS_FLAME_THROWER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_MUTANT_ENLISTED, CostTable[CLASS_MUTANT][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_MUTANT_OFFICER, CostTable[CLASS_MUTANT][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_MUTANT_SPECIAL_FORCES, CostTable[CLASS_MUTANT][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_GDI_MUTANT_BOSS, CostTable[CLASS_MUTANT][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_MINIGUNNER_ENLISTED, DefinitionTable[CLASS_MINIGUNNER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_MINIGUNNER_OFFICER, DefinitionTable[CLASS_MINIGUNNER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_MINIGUNNER_SPECIAL_FORCES, DefinitionTable[CLASS_MINIGUNNER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_MINIGUNNER_BOSS, DefinitionTable[CLASS_MINIGUNNER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_ROCKET_SOLDIER_ENLISTED, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_ROCKET_SOLDIER_OFFICER, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_ROCKET_SOLDIER_SPECIAL_FORCES, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_ROCKET_SOLDIER_BOSS, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_GRENADIER_ENLISTED, DefinitionTable[CLASS_GRENADIER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_GRENADIER_OFFICER, DefinitionTable[CLASS_GRENADIER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_GRENADIER_SPECIAL_FORCES, DefinitionTable[CLASS_GRENADIER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_GRENADIER_BOSS, DefinitionTable[CLASS_GRENADIER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_ENGINEER_ENLISTED, DefinitionTable[CLASS_ENGINEER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_ENGINEER_OFFICER, DefinitionTable[CLASS_ENGINEER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_ENGINEER_SPECIAL_FORCES, DefinitionTable[CLASS_ENGINEER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_ENGINEER_BOSS, DefinitionTable[CLASS_ENGINEER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_FLAME_THROWER_ENLISTED, DefinitionTable[CLASS_FLAME_THROWER][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_FLAME_THROWER_OFFICER, DefinitionTable[CLASS_FLAME_THROWER][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_FLAME_THROWER_SPECIAL_FORCES, DefinitionTable[CLASS_FLAME_THROWER][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_FLAME_THROWER_BOSS, DefinitionTable[CLASS_FLAME_THROWER][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_MUTANT_ENLISTED, DefinitionTable[CLASS_MUTANT][RANK_ENLISTED][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_MUTANT_OFFICER, DefinitionTable[CLASS_MUTANT][RANK_OFFICER][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_MUTANT_SPECIAL_FORCES, DefinitionTable[CLASS_MUTANT][RANK_SPECIAL_FORCES][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_DEFID_GDI_MUTANT_BOSS, DefinitionTable[CLASS_MUTANT][RANK_BOSS][TEAM_GDI]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_MINIGUNNER_ENLISTED, CostTable[CLASS_MINIGUNNER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_MINIGUNNER_OFFICER, CostTable[CLASS_MINIGUNNER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_MINIGUNNER_SPECIAL_FORCES, CostTable[CLASS_MINIGUNNER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_MINIGUNNER_BOSS, CostTable[CLASS_MINIGUNNER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_ROCKET_SOLDIER_ENLISTED, CostTable[CLASS_ROCKET_SOLDIER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_ROCKET_SOLDIER_OFFICER, CostTable[CLASS_ROCKET_SOLDIER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_ROCKET_SOLDIER_SPECIAL_FORCES, CostTable[CLASS_ROCKET_SOLDIER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_ROCKET_SOLDIER_BOSS, CostTable[CLASS_ROCKET_SOLDIER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_GRENADIER_ENLISTED, CostTable[CLASS_GRENADIER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_GRENADIER_OFFICER, CostTable[CLASS_GRENADIER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_GRENADIER_SPECIAL_FORCES, CostTable[CLASS_GRENADIER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_GRENADIER_BOSS, CostTable[CLASS_GRENADIER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_ENGINEER_ENLISTED, CostTable[CLASS_ENGINEER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_ENGINEER_OFFICER, CostTable[CLASS_ENGINEER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_ENGINEER_SPECIAL_FORCES, CostTable[CLASS_ENGINEER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_ENGINEER_BOSS, CostTable[CLASS_ENGINEER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_FLAME_THROWER_ENLISTED, CostTable[CLASS_FLAME_THROWER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_FLAME_THROWER_OFFICER, CostTable[CLASS_FLAME_THROWER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_FLAME_THROWER_SPECIAL_FORCES, CostTable[CLASS_FLAME_THROWER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_FLAME_THROWER_BOSS, CostTable[CLASS_FLAME_THROWER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_MUTANT_ENLISTED, CostTable[CLASS_MUTANT][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_MUTANT_OFFICER, CostTable[CLASS_MUTANT][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_MUTANT_SPECIAL_FORCES, CostTable[CLASS_MUTANT][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_COST_NOD_MUTANT_BOSS, CostTable[CLASS_MUTANT][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_MINIGUNNER_ENLISTED, DefinitionTable[CLASS_MINIGUNNER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_MINIGUNNER_OFFICER, DefinitionTable[CLASS_MINIGUNNER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_MINIGUNNER_SPECIAL_FORCES, DefinitionTable[CLASS_MINIGUNNER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_MINIGUNNER_BOSS, DefinitionTable[CLASS_MINIGUNNER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_ROCKET_SOLDIER_ENLISTED, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_ROCKET_SOLDIER_OFFICER, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_ROCKET_SOLDIER_SPECIAL_FORCES, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_ROCKET_SOLDIER_BOSS, DefinitionTable[CLASS_ROCKET_SOLDIER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_GRENADIER_ENLISTED, DefinitionTable[CLASS_GRENADIER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_GRENADIER_OFFICER, DefinitionTable[CLASS_GRENADIER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_GRENADIER_SPECIAL_FORCES, DefinitionTable[CLASS_GRENADIER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_GRENADIER_BOSS, DefinitionTable[CLASS_GRENADIER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_ENGINEER_ENLISTED, DefinitionTable[CLASS_ENGINEER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_ENGINEER_OFFICER, DefinitionTable[CLASS_ENGINEER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_ENGINEER_SPECIAL_FORCES, DefinitionTable[CLASS_ENGINEER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_ENGINEER_BOSS, DefinitionTable[CLASS_ENGINEER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_FLAME_THROWER_ENLISTED, DefinitionTable[CLASS_FLAME_THROWER][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_FLAME_THROWER_OFFICER, DefinitionTable[CLASS_FLAME_THROWER][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_FLAME_THROWER_SPECIAL_FORCES, DefinitionTable[CLASS_FLAME_THROWER][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_FLAME_THROWER_BOSS, DefinitionTable[CLASS_FLAME_THROWER][RANK_BOSS][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_MUTANT_ENLISTED, DefinitionTable[CLASS_MUTANT][RANK_ENLISTED][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_MUTANT_OFFICER, DefinitionTable[CLASS_MUTANT][RANK_OFFICER][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_MUTANT_SPECIAL_FORCES, DefinitionTable[CLASS_MUTANT][RANK_SPECIAL_FORCES][TEAM_NOD]);
READ_MICRO_CHUNK (cload, VARID_DEFID_NOD_MUTANT_BOSS, DefinitionTable[CLASS_MUTANT][RANK_BOSS][TEAM_NOD]);
default:
Debug_Say(("Unhandled Micro Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID (),__FILE__,__LINE__));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// Get_Cost
//
///////////////////////////////////////////////////////////////////////////////////////////
int
CharacterClassSettingsDefClass::Get_Cost
(
CLASS char_class,
RANK char_rank,
TEAM char_team
)
{
int cost = -1;
//
// Lookup the cost if we have an entry for the given coords
//
if ( char_class >= 0 && char_class < CLASS_COUNT &&
char_rank >= 0 && char_rank < RANK_COUNT &&
char_team >= 0 && char_team < TEAM_COUNT)
{
cost = CostTable[char_class][char_rank][char_team];
}
return cost;
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// Get_Definition
//
///////////////////////////////////////////////////////////////////////////////////////////
int
CharacterClassSettingsDefClass::Get_Definition
(
CLASS char_class,
RANK char_rank,
TEAM char_team
)
{
int definition_id = -1;
//
// Lookup the definition if we have an entry for the given coords
//
if ( char_class >= 0 && char_class < CLASS_COUNT &&
char_rank >= 0 && char_rank < RANK_COUNT &&
char_team >= 0 && char_team < TEAM_COUNT)
{
definition_id = DefinitionTable[char_class][char_rank][char_team];
}
return definition_id;
}

View File

@@ -0,0 +1,131 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/characterclasssettings.h $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 2/12/01 11:20a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CHARACTER_CLASS_SETTINGS_H
#define __CHARACTER_CLASS_SETTINGS_H
#include "always.h"
#include "definition.h"
///////////////////////////////////////////////////////////////////////////////////////////
//
// CharacterClassSettingsDefClass
//
///////////////////////////////////////////////////////////////////////////////////////////
class CharacterClassSettingsDefClass : public DefinitionClass
{
public:
//////////////////////////////////////////////////////////////////////////
// Public constants
//////////////////////////////////////////////////////////////////////////
typedef enum
{
CLASS_MINIGUNNER = 0,
CLASS_ROCKET_SOLDIER,
CLASS_GRENADIER,
CLASS_ENGINEER,
CLASS_FLAME_THROWER,
CLASS_MUTANT,
CLASS_COUNT
} CLASS;
typedef enum
{
RANK_ENLISTED = 0,
RANK_OFFICER,
RANK_SPECIAL_FORCES,
RANK_BOSS,
RANK_COUNT
} RANK;
typedef enum
{
TEAM_GDI = 0,
TEAM_NOD,
TEAM_COUNT
} TEAM;
//////////////////////////////////////////////////////////////////////////
// Public constructors/destructors
//////////////////////////////////////////////////////////////////////////
CharacterClassSettingsDefClass (void);
~CharacterClassSettingsDefClass (void);
//////////////////////////////////////////////////////////////////////////
// Public methods
//////////////////////////////////////////////////////////////////////////
//
// From DefinitionClass
//
virtual uint32 Get_Class_ID (void) const;
virtual PersistClass * Create (void) const ;
virtual bool Save (ChunkSaveClass &csave);
virtual bool Load (ChunkLoadClass &cload);
virtual const PersistFactoryClass & Get_Factory (void) const;
static CharacterClassSettingsDefClass * Get_Instance (void) { return GlobalInstance; }
//
// Accessors
//
int Get_Cost (CLASS char_class, RANK char_rank, TEAM char_team);
int Get_Definition (CLASS char_class, RANK char_rank, TEAM char_team);
//
// Editable support
//
DECLARE_EDITABLE (CharacterClassSettingsDefClass, DefinitionClass);
protected:
//////////////////////////////////////////////////////////////////////////
// Protected member data
//////////////////////////////////////////////////////////////////////////
int CostTable[CLASS_COUNT][RANK_COUNT][TEAM_COUNT];
int DefinitionTable[CLASS_COUNT][RANK_COUNT][TEAM_COUNT];
static CharacterClassSettingsDefClass * GlobalInstance;
};
#endif // __CHARACTER_CLASS_SETTINGS_H

73
Code/Combat/cheatmgr.cpp Normal file
View File

@@ -0,0 +1,73 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : combat *
* *
* $Archive:: /Commando/Code/Combat/cheatmgr.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 10/23/01 3:38p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "cheatmgr.h"
#include "always.h"
//////////////////////////////////////////////////////////////////////
// Static member initialization
//////////////////////////////////////////////////////////////////////
CheatMgrClass * CheatMgrClass::_TheInstance = NULL;
//////////////////////////////////////////////////////////////////////
//
// CheatMgrClass
//
//////////////////////////////////////////////////////////////////////
CheatMgrClass::CheatMgrClass (void) :
Flags (0),
HistoryFlags (0)
{
_TheInstance = this;
return ;
}
//////////////////////////////////////////////////////////////////////
//
// ~CheatMgrClass
//
//////////////////////////////////////////////////////////////////////
CheatMgrClass::~CheatMgrClass (void)
{
_TheInstance = NULL;
return ;
}

121
Code/Combat/cheatmgr.h Normal file
View File

@@ -0,0 +1,121 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : combat *
* *
* $Archive:: /Commando/Code/Combat/cheatmgr.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 12/06/01 11:35a $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __CHEATMGR_H
#define __CHEATMGR_H
#include "gametype.h"
//////////////////////////////////////////////////////////////////////
//
// CheatMgrClass
//
//////////////////////////////////////////////////////////////////////
class CheatMgrClass
{
public:
///////////////////////////////////////////////////////////////////
// Public flags
///////////////////////////////////////////////////////////////////
enum
{
CHEAT_INVULNERABILITY = 1,
CHEAT_INFINITE_AMMO = 2,
CHEAT_ALL_WEAPONS = 4,
ALL_CHEATS = 0x07,
};
///////////////////////////////////////////////////////////////////
// Public constructors/destructors
///////////////////////////////////////////////////////////////////
CheatMgrClass (void);
virtual ~CheatMgrClass (void);
///////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////
//
// Singleton access
//
static CheatMgrClass * Get_Instance (void) { return _TheInstance; }
//
// Cheat control
//
virtual void Enable_Cheat (int cheat, bool onoff) { if (onoff) Flags |= cheat; else Flags &= (~cheat); HistoryFlags |= Flags; }
virtual bool Is_Cheat_Enabled (int /*cheat*/) const { return false; }
virtual bool Is_Cheat_Set (int /*cheat*/) const { return false; }
virtual bool Was_Cheat_Used (int /*cheat*/) const { return false; }
virtual void Update_History (void) { HistoryFlags |= Flags; }
virtual void Reset_History (void) { HistoryFlags = Flags; }
virtual int Get_History (void) const { return HistoryFlags; }
virtual void Set_History (int flags) { HistoryFlags = flags; }
//
// Notifications
//
virtual void Apply_Cheats (void) {}
protected:
///////////////////////////////////////////////////////////////////
// Protected methods
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// Protected member data
///////////////////////////////////////////////////////////////////
int Flags;
int HistoryFlags;
//
// Static member data
//
static CheatMgrClass *_TheInstance;
};
#endif //__CHEATMGR_H

View File

@@ -0,0 +1,515 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/cinematicgameobj.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 10/10/01 11:37a $*
* *
* $Revision:: 32 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
** Includes
*/
#include "cinematicgameobj.h"
#include "debug.h"
#include "animcontrol.h"
#include "Sound3D.H"
#include "combat.h"
#include "pscene.h"
#include "persistfactory.h"
#include "combatchunkid.h"
#include "simpledefinitionfactory.h"
#include "wwhack.h"
#include "weapons.h"
#include "gameobjmanager.h"
#include "assets.h"
#include "ccamera.h"
#include "explosion.h"
#include "damage.h"
#include "dynamicanimphys.h"
#include "wwprofile.h"
#include "apppackettypes.h"
/*
** CinematicGameObjDef
*/
DECLARE_FORCE_LINK( Cinematic )
SimplePersistFactoryClass<CinematicGameObjDef, CHUNKID_GAME_OBJECT_DEF_CINEMATIC> _CinematicGameObjDefPersistFactory;
DECLARE_DEFINITION_FACTORY(CinematicGameObjDef, CLASSID_GAME_OBJECT_DEF_CINEMATIC, "Cinematic") _CinematicGameObjDefDefFactory;
CinematicGameObjDef::CinematicGameObjDef( void ) :
SoundDefID( 0 ),
AutoFireWeapon( false ),
DestroyAfterAnimation( true ),
CameraRelative( false )
{
MODEL_DEF_PARAM( CinematicGameObjDef, PhysDefID, "DynamicAnimPhysDef" );
EDITABLE_PARAM( CinematicGameObjDef, ParameterClass::TYPE_SOUNDDEFINITIONID, SoundDefID );
EDITABLE_PARAM( CinematicGameObjDef, ParameterClass::TYPE_STRING, SoundBoneName );
FILENAME_PARAM( CinematicGameObjDef, AnimationName, "Animation", ".W3D" );
EDITABLE_PARAM( CinematicGameObjDef, ParameterClass::TYPE_BOOL, AutoFireWeapon );
EDITABLE_PARAM( CinematicGameObjDef, ParameterClass::TYPE_BOOL, DestroyAfterAnimation );
EDITABLE_PARAM( CinematicGameObjDef, ParameterClass::TYPE_BOOL, CameraRelative );
}
uint32 CinematicGameObjDef::Get_Class_ID (void) const
{
return CLASSID_GAME_OBJECT_DEF_CINEMATIC;
}
const PersistFactoryClass & CinematicGameObjDef::Get_Factory (void) const
{
return _CinematicGameObjDefPersistFactory;
}
PersistClass * CinematicGameObjDef::Create( void ) const
{
CinematicGameObj * obj = new CinematicGameObj;
obj->Init( *this );
return obj;
}
enum {
CHUNKID_DEF_PARENT = 418001957,
CHUNKID_DEF_VARIABLES,
MICROCHUNKID_DEF_SOUND_DEF_ID = 1,
MICROCHUNKID_DEF_SOUND_BONE_NAME,
XXX_MICROCHUNKID_DEF_ANIMATION_NAME,
MICROCHUNKID_DEF_AUTO_FIRE_WEAPON,
MICROCHUNKID_DEF_DESTROY_AFTER_ANIMATION,
MICROCHUNKID_DEF_CAMERA_RELATIVE,
};
bool CinematicGameObjDef::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_DEF_PARENT );
ArmedGameObjDef::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_SOUND_DEF_ID, SoundDefID );
WRITE_MICRO_CHUNK_WWSTRING( csave, MICROCHUNKID_DEF_SOUND_BONE_NAME, SoundBoneName );
WRITE_MICRO_CHUNK_WWSTRING( csave, XXX_MICROCHUNKID_DEF_ANIMATION_NAME, AnimationName );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_AUTO_FIRE_WEAPON,AutoFireWeapon );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_DESTROY_AFTER_ANIMATION, DestroyAfterAnimation );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_CAMERA_RELATIVE, CameraRelative );
csave.End_Chunk();
return true;
}
bool CinematicGameObjDef::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_DEF_PARENT:
ArmedGameObjDef::Load( cload );
break;
case CHUNKID_DEF_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_SOUND_DEF_ID, SoundDefID );
READ_MICRO_CHUNK_WWSTRING( cload, MICROCHUNKID_DEF_SOUND_BONE_NAME, SoundBoneName );
READ_MICRO_CHUNK_WWSTRING( cload, XXX_MICROCHUNKID_DEF_ANIMATION_NAME, AnimationName );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_AUTO_FIRE_WEAPON,AutoFireWeapon );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_DESTROY_AFTER_ANIMATION, DestroyAfterAnimation );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_CAMERA_RELATIVE, CameraRelative );
default:
Debug_Say(( "Unrecognized CinematicDef Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(( "Unrecognized CinematicDef chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
/*
** CinematicGameObj
*/
SimplePersistFactoryClass<CinematicGameObj, CHUNKID_GAME_OBJECT_CINEMATIC> _CinematicGameObjPersistFactory;
const PersistFactoryClass & CinematicGameObj::Get_Factory (void) const
{
return _CinematicGameObjPersistFactory;
}
CinematicGameObj::CinematicGameObj() :
Sound( NULL )
{
Set_App_Packet_Type(APPPACKETTYPE_CINEMATIC);
}
CinematicGameObj::~CinematicGameObj()
{
Set_Sound( 0 );
COMBAT_SCENE->Remove_From_Dirty_Cull_List( Peek_Physical_Object() );
}
/*
**
*/
void CinematicGameObj::Init( void )
{
Init( Get_Definition() );
}
/*
**
*/
void CinematicGameObj::Init( const CinematicGameObjDef & definition )
{
ArmedGameObj::Init( definition );
Cinematic_Init();
}
void CinematicGameObj::Cinematic_Init( void )
{
/*
** (gth) cinematic game objects behave like animated terrain so they are in the
** terrain collision group
*/
Peek_Physical_Object()->Set_Collision_Group( PhysicsSceneClass::COLLISION_GROUP_WORLD );
// COMBAT_SCENE->Add_To_Dirty_Cull_List( Peek_Physical_Object() );
Set_Sound( Get_Definition().SoundDefID, Get_Definition().SoundBoneName );
}
const CinematicGameObjDef & CinematicGameObj::Get_Definition( void ) const
{
return (const CinematicGameObjDef &)BaseGameObj::Get_Definition();
}
/*
** CinematicGameObj Save and Load
*/
enum {
CHUNKID_PARENT = 418002008,
XXXCHUNKID_VARIABLES,
XXXCHUNKID_ANIM_CONTROL,
XXXMICROCHUNKID_PHYSICAL_OBJECT = 1,
};
bool CinematicGameObj::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_PARENT );
ArmedGameObj::Save( csave );
csave.End_Chunk();
// We don't need to save the sound
return true;
}
bool CinematicGameObj::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_PARENT:
ArmedGameObj::Load( cload );
break;
default:
Debug_Say(( "Unrecognized Cinematic chunkID\n" ));
break;
}
cload.Close_Chunk();
}
SaveLoadSystemClass::Register_Post_Load_Callback(this);
return true;
}
void CinematicGameObj::On_Post_Load( void )
{
ArmedGameObj::On_Post_Load();
Cinematic_Init();
}
/*
**
*/
void CinematicGameObj::Set_Sound( int sound_def_id, const char * bone_name )
{
// Stop Old Sound
if ( Sound != NULL ) {
Sound->Stop();
Sound->Attach_To_Object( NULL );
Sound->Remove_From_Scene();
Sound->Release_Ref();
Sound = NULL;
}
// Start new Sound
if ( sound_def_id != 0 ) {
Sound = WWAudioClass::Get_Instance()->Create_Continuous_Sound( sound_def_id );
if ( Sound != NULL ) {
RenderObjClass * model = Peek_Model();
WWASSERT( model );
int bone_index = model->Get_Bone_Index( bone_name );
Sound->Attach_To_Object( Peek_Model(), bone_index );
Sound->Add_To_Scene( true );
}
}
}
void CinematicGameObj::Think( void )
{
{ WWPROFILE( "Cinematic Think" );
// If auto fire weapon
if ( Get_Definition().AutoFireWeapon ) {
PhysicalGameObj * enemy = NULL;
Vector3 my_pos;
Get_Position( &my_pos );
// if any enemies can be found in range
SLNode<BaseGameObj> *objnode;
for ( objnode = GameObjManager::Get_Game_Obj_List()->Head(); objnode; objnode = objnode->Next()) {
PhysicalGameObj *obj = objnode->Data()->As_PhysicalGameObj();
if ( obj && obj->Peek_Physical_Object() ) { // zones have no phy obj CHANGE THIS
if ( obj == this ) {
continue;
}
if ( Is_Teammate( obj ) ) {
continue;
}
Vector3 v;
obj->Get_Position(&v);
v -= my_pos;
if ( v.Length() < Get_Weapon()->Get_Range() ) {
enemy = obj;
}
}
}
if ( enemy != NULL ) {
Vector3 enemy_pos;
enemy->Get_Position( &enemy_pos );
enemy_pos.Z += 1;
if ( Set_Targeting( enemy_pos ) == false ) {
Get_Weapon()->Set_Primary_Triggered( false );
} else {
Get_Weapon()->Set_Primary_Triggered( true ); // Fire Primary
}
} else {
Get_Weapon()->Set_Primary_Triggered( false );
}
}
if ( Get_Definition().CameraRelative && COMBAT_CAMERA != NULL ) {
Matrix3D tm = COMBAT_CAMERA->Get_Transform();
tm.Rotate_Z( DEG_TO_RADF(90.0) );
tm.Rotate_Y( DEG_TO_RADF(90.0) );
Set_Transform( tm );
}
}
ArmedGameObj::Think();
}
void CinematicGameObj::Post_Think( void )
{
ArmedGameObj::Post_Think();
WWPROFILE( "Cinematic PostThink" );
// Animation is handled by the DynamicAnimPhysClass for this class
WWASSERT(Get_Anim_Control() == NULL);
if (Get_Definition().DestroyAfterAnimation) {
PhysClass * pobj = Peek_Physical_Object();
if (pobj != NULL) {
DynamicAnimPhysClass * dpobj = pobj->As_DynamicAnimPhysClass();
if ((dpobj != NULL) &&
(dpobj->Get_Animation_Manager().Peek_Animation() != NULL) &&
(dpobj->Get_Animation_Manager().Is_At_Target()) )
{
Set_Delete_Pending();
}
}
}
}
void CinematicGameObj::Completely_Damaged( const OffenseObjectClass & damager )
{
if ( Get_Definition().KilledExplosion != 0 ) {
Vector3 pos;
Get_Position(&pos);
WWASSERT(pos.Is_Valid());// most likely candidate for explosion damage bug....?
// If the object has a moving bounding box, use its center point for the explosion
RenderObjClass * model = Peek_Model();
if (model != NULL) {
RenderObjClass * bbox = model->Get_Sub_Object_By_Name("BoundingBox");
if (bbox != NULL) {
Matrix3D bbox_tm = bbox->Get_Transform();
bbox_tm.Get_Translation(&pos);
REF_PTR_RELEASE(bbox);
}
}
ExplosionManager::Create_Explosion_At( Get_Definition().KilledExplosion, pos, damager.Get_Owner() ); // no one gets credit for this
}
Set_Delete_Pending();
}
float CinematicGameObj::Get_Animation_Length( void )
{
float length = 0;
//
// Try to get the dynamic anim phys object from the physics object
//
PhysClass *phys_obj = Peek_Physical_Object();
if (phys_obj != NULL) {
DynamicAnimPhysClass * dynamic_anim_phys = phys_obj->As_DynamicAnimPhysClass();
if (dynamic_anim_phys != NULL) {
//
// Peek at this object's animation
//
AnimCollisionManagerClass &anim_mgr = dynamic_anim_phys->Get_Animation_Manager();
HAnimClass *anim = anim_mgr.Peek_Animation();
if (anim != NULL) {
//
// Return the length of the animation to the caller
//
length = anim->Get_Total_Time();
}
}
}
return length;
}
/*
void
CinematicGameObj::Import_Creation( BitStreamClass &packet )
{
ArmedGameObj::Import_Creation (packet);
return ;
}
*/
void CinematicGameObj::Export_Rare( BitStreamClass &packet )
{
ArmedGameObj::Export_Rare( packet );
StringClass animation_name;
AnimCollisionManagerClass::AnimModeType anim_mode = AnimCollisionManagerClass::ANIMATE_TARGET;
//
// Dig the animation data out of the physics object
//
DynamicAnimPhysClass *dynanim = Peek_Physical_Object()->As_DynamicAnimPhysClass();
if (dynanim != NULL) {
AnimCollisionManagerClass &anim_mgr = dynanim->Get_Animation_Manager();
//
// Get the animation name
//
HAnimClass *anim = anim_mgr.Peek_Animation();
if (anim != NULL) {
animation_name = anim->Get_Name();
}
//
// Get the animation mode
//
anim_mode = anim_mgr.Get_Animation_Mode ();
}
//
// Send the animation data to the client
//
packet.Add_Terminated_String( (const char *)animation_name, true );
packet.Add( anim_mode );
return ;
}
void CinematicGameObj::Import_Rare( BitStreamClass &packet )
{
ArmedGameObj::Import_Rare( packet );
//
// Get information about the animation
//
StringClass animation_name;
int anim_mode = AnimCollisionManagerClass::ANIMATE_TARGET;
packet.Get_Terminated_String( animation_name.Get_Buffer( 256 ), 256, true );
packet.Get( anim_mode );
//
// Pass the animation information onto the controller
//
DynamicAnimPhysClass *dynanim = Peek_Physical_Object()->As_DynamicAnimPhysClass();
if (dynanim != NULL) {
AnimCollisionManagerClass &anim_mgr = dynanim->Get_Animation_Manager();
anim_mgr.Set_Animation( animation_name );
anim_mgr.Set_Animation_Mode( (AnimCollisionManagerClass::AnimModeType)anim_mode );
}
return ;
}

View File

@@ -0,0 +1,129 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/cinematicgameobj.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/17/01 4:24p $*
* *
* $Revision:: 19 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef CINEMATICGAMEOBJ_H
#define CINEMATICGAMEOBJ_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef ARMEDGAMEOBJ_H
#include "armedgameobj.h"
#endif
class AudibleSoundClass;
/*
** CinematicGameObjDef - Defintion class for a CinematicGameObj
*/
class CinematicGameObjDef : public ArmedGameObjDef
{
public:
CinematicGameObjDef( void );
virtual uint32 Get_Class_ID( void ) const;
virtual PersistClass * Create( void ) const ;
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
virtual const PersistFactoryClass & Get_Factory( void ) const;
DECLARE_EDITABLE( CinematicGameObjDef, ArmedGameObjDef );
protected:
int SoundDefID;
StringClass SoundBoneName;
StringClass AnimationName;
bool AutoFireWeapon;
bool DestroyAfterAnimation;
bool CameraRelative;
friend class CinematicGameObj;
};
/*
**
*/
class CinematicGameObj : public ArmedGameObj {
public:
CinematicGameObj();
virtual ~CinematicGameObj();
// Definitions
virtual void Init( void );
void Init( const CinematicGameObjDef & definition );
const CinematicGameObjDef & Get_Definition( void ) const ;
void Cinematic_Init( void );
// Save / Load / Construction Factory
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
virtual void On_Post_Load( void );
virtual const PersistFactoryClass & Get_Factory( void ) const;
// Think
virtual void Think( void );
virtual void Post_Think( void );
// Type Identification
virtual CinematicGameObj *As_CinematicGameObj( void ) { return this; }
// Sound
void Set_Sound( int sound_def_id, const char * bone_name = "" );
// Damage
virtual bool Takes_Explosion_Damage( void ) { return false; }
virtual void Completely_Damaged( const OffenseObjectClass & damager );
// Information
float Get_Animation_Length( void );
// Network support
//TSS: why import with no export?
//virtual void Import_Creation( BitStreamClass &packet );
// Network support
virtual void Export_Rare( BitStreamClass &packet );
virtual void Import_Rare( BitStreamClass &packet );
protected:
AudibleSoundClass *Sound;
};
#endif // CINEMATICGAMEOBJ_H

View File

@@ -0,0 +1,179 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/clientcontrol.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/21/01 10:44a $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "clientcontrol.h"
#include "networkobjectfactory.h"
#include "combat.h"
#include "smartgameobj.h"
#include "gameobjmanager.h"
#include "apppackettypes.h"
CClientControl * PClientControl = NULL;
DECLARE_NETWORKOBJECT_FACTORY(CClientControl, NETCLASSID_CLIENTCONTROL);
#pragma message("(TSS) high priority for me to fix this CClientControl bug...")
//
// TSS2001 problem: destruction of this object on the server. Quitting and rejoining
// a game will crash the server.
//
//-----------------------------------------------------------------------------
CClientControl::CClientControl(void)
{
ClientId = -1;
SmartObjId = -1;
Set_App_Packet_Type(APPPACKETTYPE_CLIENTCONTROL);
}
//-----------------------------------------------------------------------------
CClientControl::~CClientControl(void)
{
}
//-----------------------------------------------------------------------------
void
CClientControl::Init(void)
{
WWASSERT(CombatManager::I_Am_Client());
ClientId = CombatManager::Get_My_Id();
Set_Network_ID(NetworkObjectMgrClass::Get_New_Client_ID());
Set_Object_Dirty_Bit(0, NetworkObjectClass::BIT_CREATION, true);
}
//-----------------------------------------------------------------------------
void
CClientControl::Set_Update_Flag(int id)
{
WWASSERT(CombatManager::I_Am_Client());
SmartObjId = id;
if (id != -1) {
Set_Object_Dirty_Bit(0, NetworkObjectClass::BIT_FREQUENT, true);
}
}
//-----------------------------------------------------------------------------
void
CClientControl::Export_Creation(BitStreamClass & packet)
{
WWASSERT(CombatManager::I_Am_Client());
NetworkObjectClass::Export_Creation(packet);
packet.Add(ClientId);
}
//-----------------------------------------------------------------------------
void
CClientControl::Import_Creation(BitStreamClass & packet)
{
WWASSERT(CombatManager::I_Am_Server());
NetworkObjectClass::Import_Creation(packet);
packet.Get(ClientId);
}
//-----------------------------------------------------------------------------
void
CClientControl::Export_Frequent(BitStreamClass & packet)
{
WWASSERT(CombatManager::I_Am_Client());
/*
packet.Add(SmartObjId);
if (SmartObjId != -1) {
SmartGameObj * p_smart_go = GameObjManager::Find_SmartGameObj(SmartObjId);
WWASSERT(p_smart_go != NULL);
p_smart_go->Export_Control_Cs(packet);
p_smart_go->Export_State_Cs(packet);
}
*/
SmartGameObj * p_smart_go = NULL;
if (SmartObjId != -1) {
p_smart_go = GameObjManager::Find_SmartGameObj(SmartObjId);
if (p_smart_go == NULL) {
SmartObjId = -1;
}
}
packet.Add(SmartObjId);
if (SmartObjId != -1) {
WWASSERT(p_smart_go != NULL);
p_smart_go->Export_Control_Cs(packet);
p_smart_go->Export_State_Cs(packet);
}
SmartObjId = -1;//hack
}
//-----------------------------------------------------------------------------
void
CClientControl::Import_Frequent(BitStreamClass & packet)
{
WWASSERT(CombatManager::I_Am_Server());
packet.Get(SmartObjId);
if (SmartObjId != -1) {
SmartGameObj * p_smart_go = GameObjManager::Find_SmartGameObj(SmartObjId);
//WWASSERT(p_smart_go != NULL);
if (p_smart_go == NULL) {
packet.Flush();
} else {
p_smart_go->Import_Control_Cs(packet);
//
// Note: org code had control owner test here, reapply if problems arise.
//
p_smart_go->Import_State_Cs(packet);
}
}
}

View File

@@ -0,0 +1,79 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/clientcontrol.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/17/01 4:18p $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CLIENTCONTROL_H__
#define __CLIENTCONTROL_H__
#include "networkobject.h"
#include "netclassids.h"
#include "control.h"
//-----------------------------------------------------------------------------
//
// A C-S mirrored object to represent client control and targeting data
//
class CClientControl : public NetworkObjectClass
{
public:
CClientControl();
~CClientControl();
void Init(void);
virtual uint32 Get_Network_Class_ID(void) const {return NETCLASSID_CLIENTCONTROL;}
virtual void Delete(void) {delete this;}
void Set_Update_Flag(int id);
virtual void Export_Creation(BitStreamClass &packet);
virtual void Import_Creation(BitStreamClass &packet);
virtual void Export_Frequent(BitStreamClass &packet);
virtual void Import_Frequent(BitStreamClass &packet);
private:
int ClientId;
int SmartObjId;
};
//-----------------------------------------------------------------------------
extern CClientControl * PClientControl;
//-----------------------------------------------------------------------------
#endif // __CLIENTCONTROL_H__

52
Code/Combat/colors.cpp Normal file
View File

@@ -0,0 +1,52 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/colors.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 9/25/00 3:44p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "colors.h"
#include "playertype.h"
#include "wwdebug.h"
Vector3 Get_Color_For_Team(int team)
{
WWASSERT(team == PLAYERTYPE_NOD || team == PLAYERTYPE_GDI);
if (team == PLAYERTYPE_NOD) {
return COLOR_TEAM_0;
} else {
return COLOR_TEAM_1;
}
}

67
Code/Combat/colors.h Normal file
View File

@@ -0,0 +1,67 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/colors.h $*
* *
* $Author:: Denzil_l $*
* *
* $Modtime:: 11/07/01 7:53p $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef COLORS_H
#define COLORS_H
#include "vector3.h"
const Vector3 COLOR_TEAM_0 = Vector3(1.0f, 0.0f, 0.0f);
const Vector3 COLOR_TEAM_1 = Vector3(1.0f, 0.8f, 0.0f);
const Vector3 COLOR_NEUTRAL = Vector3(0.8f, 0.8f, 0.8f);
const Vector3 COLOR_RENEGADE = Vector3(1.0f, 1.0f, 1.0f);
const Vector3 COLOR_PUBLIC_TEXT = Vector3(1.0f, 1.0f, 1.0f);
const Vector3 COLOR_PRIVATE_TEXT = Vector3(0.0f, 0.0f, 1.0f);
const Vector3 COLOR_PAGED_TEXT = Vector3(0.0f, 1.0f, 1.0f);
const Vector3 COLOR_INVITE_TEXT = Vector3(1.0f, 0.0f, 1.0f);
const Vector3 COLOR_CONSOLE_TEXT = Vector3(1.0f, 1.0f, 1.0f);
Vector3 Get_Color_For_Team(int team);
#endif // COLORS_H
//const Vector3 COLOR_KOTH = Vector3(0.2f, 1.0f, 0.2f);
//const Vector3 COLOR_CHAMPION = Vector3(0.0f, 1.0f, 1.0f);

1374
Code/Combat/combat.cpp Normal file

File diff suppressed because it is too large Load Diff

351
Code/Combat/combat.h Normal file
View File

@@ -0,0 +1,351 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/combat.h $*
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 2/17/02 10:27a $*
* *
* $Revision:: 130 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef COMBAT_H
#define COMBAT_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef GAMEOBJREF_H
#include "gameobjref.h"
#endif
#ifndef VECTOR3_H
#include "vector3.h"
#endif
#ifndef WWSTRING_H
#include "wwstring.h"
#endif
/*
**
*/
class PhysicsSceneClass;
class CameraClass;
class CCameraClass;
class SmartGameObj;
class ArmedGameObj;
class PhysicalGameObj;
class SimpleSceneClass;
class BaseGameObj;
class VehicleGameObj;
class SoldierGameObj;
class DazzleLayerClass;
class MessageWindowClass;
class SoundEnvironmentClass;
/*
**
*/
#define COMBAT_CAMERA CombatManager::Get_Camera()
#define COMBAT_STAR CombatManager::Get_The_Star()
#define COMBAT_SCENE CombatManager::Get_Scene()
#define COMBAT_DAZZLE_LAYER CombatManager::Get_Dazzle_Layer()
/*
** Collision Groups
*/
typedef enum {
DEFAULT_COLLISION_GROUP = 0, // collides with everything
UNCOLLIDEABLE_GROUP, // collides with nothing
TERRAIN_ONLY_COLLISION_GROUP, // collides only with terrain
BULLET_COLLISION_GROUP, // collides with everything but itself
TERRAIN_AND_BULLET_COLLISION_GROUP, // collides with terrain and bullets
BULLET_ONLY_COLLISION_GROUP, // collides only with bullets
SOLDIER_COLLISION_GROUP, // collides with everything (but only soldiers use it)
SOLDIER_GHOST_COLLISION_GROUP, // collides with everything but soldiers
TERRAIN_COLLISION_GROUP = 15, // Terrain must be 15
} Collision_Group_Type;
/*
**
*/
class CombatNetworkHandlerClass {
public:
virtual bool Can_Damage(ArmedGameObj * p_armed_damager, PhysicalGameObj * p_phys_victim) = 0;
virtual float Get_Damage_Factor(ArmedGameObj * p_armed_damager, PhysicalGameObj * p_phys_victim) = 0;
virtual void On_Soldier_Kill(SoldierGameObj * p_soldier, SoldierGameObj * p_victim) = 0;
virtual void On_Soldier_Death(SoldierGameObj * p_soldier) = 0;
virtual bool Is_Gameplay_Permitted(void) = 0;
};
/*
**
*/
class CombatMiscHandlerClass {
public:
virtual void Mission_Complete( bool success ) = 0;
virtual void Star_Killed( void ) = 0;
};
/*
**
*/
class CombatManager {
public:
// Init and Shutdown should be called once per program execution
static void Init( bool render_available = true );
static void Shutdown( void );
// Scene_Init is called by the game, but not the editor
static void Scene_Init( void );
// Level Loading functions get called for each level loaded.
static void Pre_Load_Level( bool render_available = true );
static void Load_Level_Threaded( const char * map_name, bool preload_assets );
static bool Is_Load_Level_Complete( void );
static bool Is_Loading_Level( void );
static void Post_Load_Level( void );
static void Unload_Level( void );
// Main Loop functions
static void Generate_Control( void );
static void Think( void );
static void Render( void );
static void Handle_Input( void );
// Save/Load
static bool Save( ChunkSaveClass &csave );
static bool Load( ChunkLoadClass &cload );
// Client/Server Settings
static void Set_I_Am_Server( bool yes ) { IAmServer = yes; }
static void Set_I_Am_Client( bool yes ) { IAmClient = yes; }
static bool I_Am_Server( void ) { return IAmServer; }
static bool I_Am_Client( void ) { return IAmClient; }
static bool I_Am_Only_Client( void ) { return IAmClient && !IAmServer; }
static bool I_Am_Only_Server( void ) { return IAmServer && !IAmClient; }
static bool I_Am_Client_Server(void) { return IAmClient && IAmServer;}
static void Set_Friendly_Fire_Permitted( bool yes ) { FriendlyFirePermitted = yes; }
static bool Is_Friendly_Fire_Permitted( void ) { return FriendlyFirePermitted; }
static void Set_Beacon_Placement_Ends_Game( bool yes ){ BeaconPlacementEndsGame = yes; }
static bool Does_Beacon_Placement_Ends_Game( void ) { return BeaconPlacementEndsGame; }
static void Set_My_Id( int id ) { MyId = id; }
static int Get_My_Id( void ) { return MyId; }
// Latency support
static void Set_Last_Round_Trip_Ping_Ms( DWORD ping ) { LastRoundTripPingMs = ping; }
static DWORD Get_Last_Round_Trip_Ping_Ms( void ) { return LastRoundTripPingMs; }
static void Set_Avg_Round_Trip_Ping_Ms( DWORD ping ) { AvgRoundTripPingMs = ping; }
static DWORD Get_Avg_Round_Trip_Ping_Ms( void ) { return AvgRoundTripPingMs; }
// Network Handler Functions
static void Set_Combat_Network_Handler( CombatNetworkHandlerClass * handler ) { NetworkHandler = handler; }
static bool Can_Damage(ArmedGameObj * p_armed_damager, PhysicalGameObj * p_phys_victim);
static float Get_Damage_Factor(ArmedGameObj * p_armed_damager, PhysicalGameObj * p_phys_victim);
static void On_Soldier_Kill(SoldierGameObj * p_soldier, SoldierGameObj * p_victim);
static void On_Soldier_Death(SoldierGameObj * p_soldier);
static bool Is_Gameplay_Permitted(void);
// Misc Handler
static void Set_Combat_Misc_Handler( CombatMiscHandlerClass * handler ) { MiscHandler = handler; }
static void Mission_Complete( bool success );
static void Star_Killed( void );
// The Star
static void Set_The_Star( SoldierGameObj *target, bool is_star_determining_target = true );
static SoldierGameObj * Get_The_Star( void ) { return (SoldierGameObj *)TheStar.Get_Ptr(); }
static void Update_Star( void );
static void Update_Star_Targeting( void );
static bool Is_Star_Determining_Target(void) {return IsStarDeterminingTarget;}
static void Set_Is_Star_Determining_Target(bool flag) {IsStarDeterminingTarget = flag;}
// The Scene
static PhysicsSceneClass *Get_Scene( void );
static SimpleSceneClass *Get_Background_Scene( void ) { return BackgroundScene; }
static CCameraClass *Get_Camera( void ) { return MainCamera; }
static SoundEnvironmentClass *Get_Sound_Environment( void ) { return SoundEnvironment; }
static void Set_Camera_Profile( const char * profile_name );
static void Set_Camera_Vehicle( VehicleGameObj * obj, int seat = 0 );
static bool Is_In_Camera_Frustrum(Vector3 & position);
static bool Are_Observers_Active( void ) { return AreObserversActive; }
static void Set_Observers_Active( bool onoff ) { AreObserversActive = onoff; }
static bool Is_First_Load( void ) { return IsFirstLoad; }
static void Set_First_Load( bool onoff ) { IsFirstLoad = onoff; }
static void Do_Skeleton_Slider_Demo( void );
static void Toggle_Skeleton_Slider_Demo( void ) { EnableSkeletonSliderDemo = !EnableSkeletonSliderDemo; }
static bool Is_Skeleton_Slider_Demo_Enabled( void ) { return EnableSkeletonSliderDemo; }
static DazzleLayerClass * Get_Dazzle_Layer(void) { return DazzleLayer; }
// First Person
static void Set_First_Person( bool on_off ) { FirstPerson = on_off; }
static bool Is_First_Person( void ) { return FirstPerson; }
static void Set_First_Person_Default( bool on_off ) { FirstPersonDefault = on_off; }
static bool Get_First_Person_Default( void ) { return FirstPersonDefault; }
// Difficulty
static void Set_Difficulty_Level( int level ) { DifficultyLevel = level; }
static int Get_Difficulty_Level( void ) { return DifficultyLevel; }
static bool Are_Transitions_Automatic( void ) { return AutoTransitions; }
static void Set_Transitions_Automatic( bool state ) { AutoTransitions = state; }
// Message window
static MessageWindowClass * Get_Message_Window (void) { return MessageWindow; }
static void Show_Star_Damage_Direction( int direction ) { StarDamageDirection |= 1 << (direction&7); }
static int Get_Star_Damage_Direction( void ) { return StarDamageDirection; }
static void Clear_Star_Damage_Direction( void ) { StarDamageDirection = 0; }
static int Get_Sync_Time( void ) { return SyncTime; }
static bool Is_Game_Paused( void ) { return IsGamePaused; }
static void Register_Star_Killer( ArmedGameObj * killer );
static const char * Get_Start_Script( void ) { return StartScript; }
static const char * Get_Respawn_Script( void ) { return RespawnScript; }
static void Set_Start_Script( const char * string ) { StartScript = string; }
static void Set_Respawn_Script( const char * string ) { RespawnScript = string; }
static void Request_Autosave( bool state = true ) { AutosaveRequested = state; }
static bool Is_Autosave_Requested( void ) { return AutosaveRequested; }
static int Get_Reload_Count( void ) { return ReloadCount; }
static bool Is_Hit_Reticle_Enabled( void ) { return HitReticleEnabled; }
static void Toggle_Hit_Reticle_Enabled( void ) { HitReticleEnabled = !HitReticleEnabled; }
static const char * Get_Last_LSD_Name( void ) { return LastLSDName; };
static void Set_Last_LSD_Name( const char * name ) { LastLSDName = name; };
static int Get_Load_Progress( void ) { return LoadProgress; };
static void Inc_Load_Progress( void ) { LoadProgress++; };
static void Set_Load_Progress( int set ) { LoadProgress = set; };
private:
static bool IAmServer;
static bool IAmClient;
static bool IAmOnlyClient;
static bool IAmOnlyServer;
static int MyId;
static int SyncTime;
static bool IsGamePaused;
static bool IsLevelInitialized;
static bool FriendlyFirePermitted;
static bool BeaconPlacementEndsGame;
static bool FirstPerson;
static bool FirstPersonDefault;
static CCameraClass * MainCamera;
static SimpleSceneClass * BackgroundScene;
static SoundEnvironmentClass * SoundEnvironment;
static DazzleLayerClass * DazzleLayer;
static MessageWindowClass * MessageWindow;
static GameObjReference TheStar;
static bool IsStarDeterminingTarget;
static bool IsFirstLoad;
static bool AreObserversActive;
static bool EnableSkeletonSliderDemo;
static int DifficultyLevel;
static bool AutoTransitions;
static int StarDamageDirection;
static int StarKillerID;
static CombatNetworkHandlerClass * NetworkHandler;
static CombatMiscHandlerClass * MiscHandler;
static StringClass StartScript;
static StringClass RespawnScript;
static int ReloadCount;
static bool HitReticleEnabled;
static bool IsGameplayPermitted;
/*
** Combat Mode Management
*/
typedef enum {
COMBAT_MODE_NONE,
COMBAT_MODE_FIRST_PERSON,
COMBAT_MODE_THIRD_PERSON,
COMBAT_MODE_SNIPING,
COMBAT_MODE_IN_VEHICLE,
COMBAT_MODE_ON_LADDER,
COMBAT_MODE_DIEING,
COMBAT_MODE_CORPSE,
COMBAT_MODE_SNAP_SHOT,
};
static int CombatMode;
static bool AutosaveRequested;
static void Set_Combat_Mode( int mode );
static void Update_Combat_Mode( void );
/*
** Latency Support
*/
static DWORD LastRoundTripPingMs;
static DWORD AvgRoundTripPingMs;
static StringClass LastLSDName;
static int LoadProgress;
static bool MultiplayRenderingAllowed;
};
#endif

304
Code/Combat/combatchunkid.h Normal file
View File

@@ -0,0 +1,304 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/combatchunkid.h $*
* *
* $Author:: Denzil_l $*
* *
* $Modtime:: 11/21/01 10:26a $*
* *
* $Revision:: 55 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef COMBATCHUNKID_H
#define COMBATCHUNKID_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef SAVELOADIDS_H
#include "saveloadids.h"
#endif
#ifndef DEFINITIONCLASSIDS_H
#include "definitionclassids.h"
#endif
/*
** CHUNKIDs
*/
enum {
CHUNKID_COMBAT = CHUNKID_COMBAT_BEGIN,
CHUNKID_TIMER,
CHUNKID_TIMER_GAME_OBJ,
CHUNKID_TIMER_GAME_OBJ_CUSTOM,
CHUNKID_GAME_OBJECTS_BEGIN = CHUNKID_COMBAT_BEGIN + 0x100,
CHUNKID_GAME_OBJECT_BULLET,
CHUNKID_GAME_OBJECT_C4,
CHUNKID_GAME_OBJECT_DEF_C4,
XXXCHUNKID_GAME_OBJECT_COMMANDO,
XXXCHUNKID_GAME_OBJECT_DEF_COMMANDO,
CHUNKID_GAME_OBJECT_POWERUP,
CHUNKID_GAME_OBJECT_DEF_POWERUP,
CHUNKID_GAME_OBJECT_SAMSITE,
CHUNKID_GAME_OBJECT_DEF_SAMSITE,
CHUNKID_GAME_OBJECT_SIMPLE,
CHUNKID_GAME_OBJECT_DEF_SIMPLE,
XXXCHUNKID_GAME_OBJECT_SIMPLE3,
XXXCHUNKID_GAME_OBJECT_DEF_SIMPLE3,
CHUNKID_GAME_OBJECT_SOLDIER,
CHUNKID_GAME_OBJECT_DEF_SOLDIER,
CHUNKID_GAME_OBJECT_VEHICLE,
CHUNKID_GAME_OBJECT_VISUAL,
CHUNKID_GAME_OBJECT_TIMED_VISUAL,
CHUNKID_GAME_OBJECT_ANIMATED_VISUAL,
CHUNKID_GAME_OBJECT_PROJECTILE_VISUAL,
CHUNKID_GAME_OBJECT_XXXXXXXXXXXXXXXXX,
XXXCHUNKID_GAME_OBJECT_TANK,
XXXCHUNKID_GAME_OBJECT_DEF_TANK,
XXXCHUNKID_GAME_OBJECT_TURRET,
XXXCHUNKID_GAME_OBJECT_DEF_TURRET,
XXXCHUNKID_GAME_OBJECT_BIKE,
XXXCHUNKID_GAME_OBJECT_DEF_BIKE,
XXXCHUNKID_GAME_OBJECT_FLYING,
XXXCHUNKID_GAME_OBJECT_DEF_FLYING,
XXXCHUNKID_GAME_OBJECT_CAR,
XXXCHUNKID_GAME_OBJECT_DEF_CAR,
CHUNKID_SPAWNER,
CHUNKID_SPAWNER_DEF,
CHUNKID_GAME_OBJECT_SCRIPT_ZONE,
CHUNKID_GAME_OBJECT_DEF_SCRIPT_ZONE,
CHUNKID_GAME_OBJECT_TRANSITION,
CHUNKID_GAME_OBJECT_DEF_TRANSITION,
// MISC ITEMS
CHUNKID_BACKGROUND_MGR,
CHUNKID_WEAPON_DEF,
CHUNKID_AMMO_DEF,
CHUNKID_GAME_OBJECT_DEF_VEHICLE,
CHUNKID_EXPLOSION_DEF,
CHUNKID_GAME_OBJECT_CINEMATIC,
CHUNKID_GAME_OBJECT_DEF_CINEMATIC,
CHUNKID_GAME_OBJECT_DAMAGE_ZONE,
CHUNKID_GAME_OBJECT_DEF_DAMAGE_ZONE,
CHUNKID_GAME_OBJECT_SPECIAL_EFFECTS,
CHUNKID_GAME_OBJECT_DEF_SPECIAL_EFFECTS,
CHUNKID_GAME_OBJECT_SAKURA_BOSS,
CHUNKID_GAME_OBJECT_DEF_SAKURA_BOSS,
CHUNKID_GAME_OBJECT_BUILDING,
CHUNKID_GAME_OBJECT_DEF_BUILDING,
CHUNKID_GAME_OBJECT_BEACON,
CHUNKID_GAME_OBJECT_DEF_BEACON,
CHUNKID_GAME_OBJECT_REFINERY,
CHUNKID_GAME_OBJECT_DEF_REFINERY,
CHUNKID_GAME_OBJECT_POWERPLANT,
CHUNKID_GAME_OBJECT_DEF_POWERPLANT,
CHUNKID_GAME_OBJECT_SOLDIER_FACTORY,
CHUNKID_GAME_OBJECT_DEF_SOLDIER_FACTORY,
CHUNKID_GAME_OBJECT_VEHICLE_FACTORY,
CHUNKID_GAME_OBJECT_DEF_VEHICLE_FACTORY,
CHUNKID_GAME_OBJECT_AIRSTRIP,
CHUNKID_GAME_OBJECT_DEF_AIRSTRIP,
CHUNKID_GAME_OBJECT_WARFACTORY,
CHUNKID_GAME_OBJECT_DEF_WARFACTORY,
CHUNKID_GAME_OBJECT_COMCENTER,
CHUNKID_GAME_OBJECT_DEF_COMCENTER,
CHUNKID_GAME_OBJECT_REPAIR_BAY,
CHUNKID_GAME_OBJECT_DEF_REPAIR_BAY,
CHUNKID_MAPMGR,
CHUNKID_ENCYCLOPEDIAMGR,
CHUNKID_GAME_OBJECT_MENDOZA_BOSS,
CHUNKID_GAME_OBJECT_DEF_MENDOZA_BOSS,
CHUNKID_GAME_OBJECT_RAVESHAW_BOSS,
CHUNKID_GAME_OBJECT_DEF_RAVESHAW_BOSS,
CHUNKID_GAME_OBJECT_OBSERVERS_BEGIN = CHUNKID_COMBAT_BEGIN + 0x200,
CHUNKID_SOLDIER_OBSERVER,
CHUNKID_BEACON_MONITOR,
CHUNKID_BUILDINGS_BEGIN = CHUNKID_COMBAT_BEGIN + 0x301,
CHUNKID_BUILDING,
CHUNKID_BUILDINGS_DEF_BEGIN = CHUNKID_COMBAT_BEGIN + 0x401,
CHUNKID_BUILDING_DEF,
CHUNKID_ACTION_CODE_BEGIN = CHUNKID_COMBAT_BEGIN + 0x500,
CHUNKID_ACTION_CODE_FOLLOW_INPUT,
CHUNKID_ACTION_CODE_STAND,
CHUNKID_ACTION_CODE_GOTO,
CHUNKID_ACTION_CODE_ENTER_EXIT,
CHUNKID_ACTION_CODE_ATTACK,
CHUNKID_ACTION_CODE_PLAY_ANIMATION,
CHUNKID_ACTION_CODE_FACE_LOCATION,
CHUNKID_ACTION_CODE_DIVE,
CHUNKID_ACTION_CODE_CONVERSATION,
CHUNKID_ACTION_CODE_DOCK,
CHUNKID_GLOBAL_SETTINGS_DEF = CHUNKID_COMBAT_BEGIN + 0x600,
CHUNKID_GLOBAL_SETTINGS_DEF_HUMAN_LOITER,
CHUNKID_GLOBAL_SETTINGS_DEF_GENERAL,
CHUNKID_GLOBAL_SETTINGS_DEF_HUD,
CHUNKID_GLOBAL_SETTINGS_DEF_EVA,
CHUNKID_GLOBAL_SETTINGS_DEF_CHAR_CLASS,
CHUNKID_GLOBAL_SETTINGS_DEF_HUMAN_ANIM_OVERRIDE,
CHUNKID_GLOBAL_SETTINGS_DEF_PURCHASE,
CHUNKID_GLOBAL_SETTINGS_DEF_TEAM_PURCHASE,
CHUNKID_GLOBAL_SETTINGS_DEF_CNCMODE,
CHUNKID_CONVERSATION_MGR = CHUNKID_COMBAT_BEGIN + 0x700,
CHUNKID_WEATHER_MGR = CHUNKID_COMBAT_BEGIN + 0x800,
CHUNKID_PLAYER_DATA = CHUNKID_COMBAT_BEGIN + 0x900,
CHUNKID_PLAYER_DATA_CPLAYER,
};
/*
** Game Object CLASSIDs
*/
enum {
CLASSID_GAME_OBJECT_DEF_SOLDIER = CLASSID_GAME_OBJECTS + 1,
XXXCLASSID_GAME_OBJECT_DEF_COMMANDO,
CLASSID_GAME_OBJECT_DEF_POWERUP,
CLASSID_GAME_OBJECT_DEF_SIMPLE,
XXXCLASSID_GAME_OBJECT_DEF_SIMPLE3,
CLASSID_GAME_OBJECT_DEF_C4,
CLASSID_GAME_OBJECT_DEF_SAMSITE,
XXCLASSID_GAME_OBJECT_DEF_TANK,
XXCLASSID_GAME_OBJECT_DEF_TURRET,
XXCLASSID_GAME_OBJECT_DEF_BIKE,
XXCLASSID_GAME_OBJECT_DEF_FLYING,
XXCLASSID_GAME_OBJECT_DEF_CAR,
CLASSID_SPAWNER_DEF,
CLASSID_GAME_OBJECT_DEF_SCRIPT_ZONE,
CLASSID_GAME_OBJECT_DEF_TRANSITION,
CLASSID_GAME_OBJECT_DEF_VEHICLE,
CLASSID_GAME_OBJECT_DEF_CINEMATIC,
CLASSID_GAME_OBJECT_DEF_DAMAGE_ZONE,
CLASSID_GAME_OBJECT_DEF_SPECIAL_EFFECTS,
CLASSID_GAME_OBJECT_DEF_SAKURA_BOSS,
XXXCLASSID_GAME_OBJECT_DEF_BUILDING,
CLASSID_GAME_OBJECT_DEF_BEACON,
CLASSID_GAME_OBJECT_DEF_MENDOZA_BOSS,
CLASSID_GAME_OBJECT_DEF_RAVESHAW_BOSS
// MISC DEFINITIONS
};
/*
** Munitions CLASSIDs
*/
enum {
CLASSID_DEF_WEAPON = CLASSID_MUNITIONS + 1,
CLASSID_DEF_AMMO,
CLASSID_DEF_EXPLOSION,
};
/*
** Building CLASSIDs
*/
enum {
CLASSID_GAME_OBJECT_DEF_BUILDING = CLASSID_BUILDINGS + 1,
CLASSID_GAME_OBJECT_DEF_REFINERY,
CLASSID_GAME_OBJECT_DEF_POWERPLANT,
CLASSID_GAME_OBJECT_DEF_SOLDIER_FACTORY,
CLASSID_GAME_OBJECT_DEF_VEHICLE_FACTORY,
CLASSID_GAME_OBJECT_DEF_AIRSTRIP,
CLASSID_GAME_OBJECT_DEF_WARFACTORY,
CLASSID_GAME_OBJECT_DEF_COMCENTER,
CLASSID_GAME_OBJECT_DEF_REPAIR_BAY,
};
/*
** GlobalSettings CLASSIDs
*/
enum {
CLASSID_GLOBAL_SETTINGS_DEF = CLASSID_GLOBAL_SETTINGS + 1,
CLASSID_GLOBAL_SETTINGS_DEF_HUMAN_LOITER,
CLASSID_GLOBAL_SETTINGS_DEF_GENERAL,
CLASSID_GLOBAL_SETTINGS_DEF_HUD,
CLASSID_GLOBAL_SETTINGS_DEF_EVA,
CLASSID_GLOBAL_SETTINGS_DEF_CHAR_CLASS,
CLASSID_GLOBAL_SETTINGS_DEF_HUMAN_ANIM_OVERRIDE,
CLASSID_GLOBAL_SETTINGS_DEF_PURCHASE,
CLASSID_GLOBAL_SETTINGS_DEF_TEAM_PURCHASE,
CLASSID_GLOBAL_SETTINGS_DEF_CNCMODE,
};
#endif // COMBATCHUNKID_H

View File

@@ -0,0 +1,112 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Renegade *
* *
* $Archive:: /Commando/Code/Combat/combatdazzle.cpp $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 6/15/01 9:09a $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* CombatDazzleClass::Compute_Dazzle_Visibility -- Computes visibility of a dazzle object in *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "combatdazzle.h"
#include "rinfo.h"
#include "camera.h"
#include "pscene.h"
#include "physcoltest.h"
#include "phys.h"
#include "combat.h"
#include "soldier.h"
CombatDazzleClass _TheCombatDazzleHandler;
/***********************************************************************************************
* CombatDazzleClass::Compute_Dazzle_Visibility -- Computes visibility of a dazzle object in t *
* *
* This dazzle visibility handler is used for the background and game scene in renegade. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 6/13/2001 gth : Created. *
*=============================================================================================*/
float CombatDazzleClass::Compute_Dazzle_Visibility
(
RenderInfoClass & rinfo,
DazzleRenderObjClass * obj,
const Vector3 & point
) const
{
/*
** If we are in first-person mode, don't collide against the star
*/
bool ignore_player = CombatManager::Is_First_Person();
if (ignore_player) {
if (COMBAT_STAR != NULL) {
COMBAT_STAR->Peek_Physical_Object()->Inc_Ignore_Counter();
}
}
/*
** Cast a ray from the camera to the dazzle position
*/
CastResultStruct res;
LineSegClass ray(rinfo.Camera.Get_Position(),point);
PhysRayCollisionTestClass raytest(ray,&res,0,COLLISION_TYPE_PROJECTILE);
PhysicsSceneClass * scene = PhysicsSceneClass::Get_Instance();
if (scene != NULL) {
scene->Cast_Ray(raytest);
}
/*
** Done
*/
if (ignore_player) {
if (COMBAT_STAR != NULL) {
COMBAT_STAR->Peek_Physical_Object()->Dec_Ignore_Counter();
}
}
if (res.Fraction == 1.0f) {
return 1.0f;
} else {
return 0.0f;
}
}

View File

@@ -0,0 +1,62 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Renegade *
* *
* $Archive:: /Commando/Code/Combat/combatdazzle.h $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 6/13/01 9:05a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef COMBATDAZZLE_H
#define COMBATDAZZLE_H
#include "always.h"
#include "dazzle.h"
/**
** CombatDazzleClass - this class handles the visibility callback for the combat scene.
** This handler should be installed while the background scene and the game scene
** are rendered and it determines visibility by asking the game scene to cast a ray
** from the camera to the dazzle position.
*/
class CombatDazzleClass : public DazzleVisibilityClass
{
float Compute_Dazzle_Visibility( RenderInfoClass & rinfo,
DazzleRenderObjClass * dazzle,
const Vector3 & point) const;
};
extern CombatDazzleClass _TheCombatDazzleHandler;
#endif

View File

@@ -0,0 +1,129 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/combatmaterialeffectmanager.cpp $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 10/19/01 10:16a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "combatmaterialeffectmanager.h"
#include "materialeffect.h"
#include "transitioneffect.h"
#include "assetmgr.h"
#include "texture.h"
#include "humanstate.h"
const char * DEATH_TRANSITION_TEXTURE = "REN_death.tga";
const char * SPAWN_TRANSITION_TEXTURE = "REN_spawn.tga";
const char * HEALTH_TEXTURE = "REN_repair.tga";
const char * ELECTROCUTION_TEXTURE = "REN_shock.tga";
const float SPAWN_TRANSITION_TIME = 2.0f;
TransitionEffectClass *
CombatMaterialEffectManager::Get_Spawn_Effect(void)
{
TransitionEffectClass * effect = NEW_REF(TransitionEffectClass,());
effect->Set_Parameter(1.0f);
effect->Set_Target_Parameter(0.0f);
effect->Set_Transition_Time(SPAWN_TRANSITION_TIME);
effect->Enable_Remove_On_Complete(true);
effect->Set_Max_Intensity(0.25f);
TextureClass * tex = WW3DAssetManager::Get_Instance()->Get_Texture(SPAWN_TRANSITION_TEXTURE);
effect->Set_Texture(tex);
REF_PTR_RELEASE(tex);
return effect;
}
TransitionEffectClass *
CombatMaterialEffectManager::Get_Death_Effect(void)
{
TransitionEffectClass * effect = NEW_REF(TransitionEffectClass,());
effect->Set_Parameter(0.0f);
effect->Set_Target_Parameter(1.0f);
effect->Set_Start_Delay(0.75f * CORPSE_PERSIST_TIME);
effect->Set_Transition_Time(0.25f * CORPSE_PERSIST_TIME);
effect->Set_Max_Intensity(0.5f);
effect->Set_Max_UV_Velocity(Vector2(3.75f,-6.0f));
TextureClass * tex = WW3DAssetManager::Get_Instance()->Get_Texture(DEATH_TRANSITION_TEXTURE);
effect->Set_Texture(tex);
REF_PTR_RELEASE(tex);
return effect;
}
TransitionEffectClass *
CombatMaterialEffectManager::Get_Health_Effect(void)
{
TransitionEffectClass * effect = NEW_REF(TransitionEffectClass,());
effect->Set_Parameter(0.0f);
effect->Set_Target_Parameter(0.49f);
effect->Set_Transition_Time(1.0f);
effect->Set_Max_Intensity(0.5f);
effect->Set_Min_UV_Velocity(Vector2(0.0f,-3.0f));
effect->Set_Max_UV_Velocity(Vector2(0.0f,-3.0f));
TextureClass * tex = WW3DAssetManager::Get_Instance()->Get_Texture(HEALTH_TEXTURE);
effect->Set_Texture(tex);
REF_PTR_RELEASE(tex);
return effect;
}
TransitionEffectClass *
CombatMaterialEffectManager::Get_Electrocution_Effect(void)
{
TransitionEffectClass * effect = NEW_REF(TransitionEffectClass,());
effect->Set_Parameter(0.0f);
effect->Set_Target_Parameter(0.49f);
effect->Set_Transition_Time(1.0f);
effect->Set_Max_Intensity(0.5f);
effect->Set_Min_UV_Velocity(Vector2(0.0f,-3.0f));
effect->Set_Max_UV_Velocity(Vector2(0.0f,-3.0f));
TextureClass * tex = WW3DAssetManager::Get_Instance()->Get_Texture(ELECTROCUTION_TEXTURE);
effect->Set_Texture(tex);
REF_PTR_RELEASE(tex);
return effect;
}

View File

@@ -0,0 +1,63 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/combatmaterialeffectmanager.h $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 8/06/01 5:05p $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef COMBATMATERIALEFFECTMANAGER_H
#define COMBATMATERIALEFFECTMANAGER_H
#include "always.h"
class TransitionEffectClass;
class CombatMaterialEffectManager
{
public:
static TransitionEffectClass * Get_Spawn_Effect(void);
static TransitionEffectClass * Get_Death_Effect(void);
static TransitionEffectClass * Get_Health_Effect(void);
static TransitionEffectClass * Get_Electrocution_Effect(void);
};
#endif

View File

@@ -0,0 +1,60 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/combatphysobserver.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 2/08/01 11:23a $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef COMBATPHYSOBSERVER_H
#define COMBATPHYSOBSERVER_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef PHYSOBSERVER_H
#include "physobserver.h"
#endif
class DamageableGameObj;
class PhysicalGameObj;
class BuildingGameObj;
class CombatPhysObserverClass : public PhysObserverClass {
public:
virtual DamageableGameObj * As_DamageableGameObj( void ) { return NULL; }
virtual PhysicalGameObj * As_PhysicalGameObj( void ) { return NULL; }
virtual BuildingGameObj * As_BuildingGameObj( void ) { return NULL; }
};
#endif // COMBATPHYSOBSERVER_H

View File

@@ -0,0 +1,238 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/combatsaveload.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 1/17/02 11:58a $*
* *
* $Revision:: 34 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "combatsaveload.h"
#include "chunkio.h"
#include "gameobjmanager.h"
#include "combat.h"
#include "debug.h"
#include "spawn.h"
#include "timemgr.h"
#include "scripts.h"
#include "persistentgameobjobserver.h"
#include "wwmemlog.h"
#include "cover.h"
#include "objectives.h"
#include "radar.h"
#include "building.h"
#include "bullet.h"
#include "backgroundmgr.h"
#include "weathermgr.h"
#include "weaponview.h"
#include "hud.h"
#include "screenfademanager.h"
/*
**
*/
CombatSaveLoadClass _CombatSaveLoad;
enum {
CHUNKID_GAMEOBJMANAGER = 916991654,
CHUNKID_COMBAT_GAME_MODE,
XXX_CHUNKID_TRANSITIONS,
CHUNKID_SPAWNERS,
XXXCHUNKID_TIME,
CHUNKID_SCRIPTS,
CHUNKID_PERSISTENT_GAME_OBJ_OBSERVERS,
CHUNKID_COVER,
CHUNKID_OBJECTIVES,
CHUNKID_RADAR,
XXXCHUNKID_BUILDINGS,
CHUNKID_GAME_OBJ_OBSERVERS,
CHUNKID_BULLETS,
CHUNKID_WEAPON_VIEW,
CHUNKID_DYNAMIC_BACKGROUND,
CHUNKID_DYNAMIC_WEATHER,
CHUNKID_HUD,
CHUNKID_SCREEN_FADE,
};
/*
**
*/
bool CombatSaveLoadClass::Save( ChunkSaveClass &csave )
{
WWMEMLOG(MEM_GAMEDATA);
csave.Begin_Chunk( CHUNKID_GAMEOBJMANAGER );
GameObjManager::Save( csave );
csave.End_Chunk();
// CombatManager should load before scripts for SyncTime
csave.Begin_Chunk( CHUNKID_COMBAT_GAME_MODE );
CombatManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_SPAWNERS );
SpawnManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_SCRIPTS );
ScriptManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_PERSISTENT_GAME_OBJ_OBSERVERS );
PersistentGameObjObserverManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_COVER );
CoverManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_OBJECTIVES );
ObjectiveManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_RADAR );
RadarManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_GAME_OBJ_OBSERVERS );
GameObjObserverManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_BULLETS );
BulletManager::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_WEAPON_VIEW );
WeaponViewClass::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DYNAMIC_BACKGROUND );
BackgroundMgrClass::Save_Dynamic( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DYNAMIC_WEATHER );
WeatherMgrClass::Save_Dynamic( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_HUD );
HUDClass::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_SCREEN_FADE );
ScreenFadeManager::Save( csave );
csave.End_Chunk();
return true;
}
bool CombatSaveLoadClass::Load( ChunkLoadClass &cload )
{
WWMEMLOG(MEM_GAMEDATA);
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_GAMEOBJMANAGER:
GameObjManager::Load( cload );
break;
case CHUNKID_COMBAT_GAME_MODE:
CombatManager::Load( cload );
break;
case CHUNKID_SPAWNERS:
SpawnManager::Load( cload );
break;
case CHUNKID_SCRIPTS:
ScriptManager::Load( cload );
break;
case CHUNKID_PERSISTENT_GAME_OBJ_OBSERVERS:
PersistentGameObjObserverManager::Load( cload );
break;
case CHUNKID_COVER:
CoverManager::Load( cload );
break;
case CHUNKID_OBJECTIVES:
ObjectiveManager::Load( cload );
break;
case CHUNKID_RADAR:
RadarManager::Load( cload );
break;
case CHUNKID_GAME_OBJ_OBSERVERS:
GameObjObserverManager::Load( cload );
break;
case CHUNKID_BULLETS:
BulletManager::Load( cload );
break;
case CHUNKID_WEAPON_VIEW:
WeaponViewClass::Load( cload );
break;
case CHUNKID_DYNAMIC_BACKGROUND:
BackgroundMgrClass::Load_Dynamic( cload );
break;
case CHUNKID_DYNAMIC_WEATHER:
WeatherMgrClass::Load_Dynamic( cload );
break;
case CHUNKID_HUD:
HUDClass::Load( cload );
break;
case CHUNKID_SCREEN_FADE:
ScreenFadeManager::Load( cload );
break;
default:
Debug_Say(( "Unrecognized CombatSaveLoad chunkID\n" ));
break;
}
cload.Close_Chunk();
}
SaveLoadSystemClass::Register_Post_Load_Callback(this);
return true;
}
void CombatSaveLoadClass::On_Post_Load(void)
{
}

View File

@@ -0,0 +1,76 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/combatsaveload.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 11/02/00 6:08p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef COMBATSAVELOAD_H
#define COMBATSAVELOAD_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef SAVELOADSUBSYSTEM_H
#include "saveloadsubsystem.h"
#endif
#ifndef COMBATCHUNKID_H
#include "combatchunkid.h"
#endif
/*
**
*/
class CombatSaveLoadClass : public SaveLoadSubSystemClass {
public:
CombatSaveLoadClass(void) {}
virtual ~CombatSaveLoadClass(void) {}
virtual uint32 Chunk_ID (void) const { return CHUNKID_COMBAT; }
protected:
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
virtual const char* Name() const { return "CombatSaveLoadClass"; }
virtual void On_Post_Load (void);
};
/*
**
*/
extern CombatSaveLoadClass _CombatSaveLoad;
#endif // COMBATSAVELOAD_H

View File

@@ -0,0 +1,75 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/combatsound.cpp $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 11/29/00 2:16p $*
* *
* $Revision:: 13 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "combatsound.h"
#include "wwaudio.h"
/*
**
*/
const char * CombatSoundTypeNames[NUM_DEFINED_SOUND_TYPES] =
{
"None",
"Old Weapon",
"Footsteps",
"Vehicle",
"Gunshot",
"Bullet Hit"
};
/*
**
*/
void CombatSoundManager::Init( void )
{
for ( int i = 0; i < NUM_DEFINED_SOUND_TYPES; i++ ) {
WWAudioClass::Get_Instance()->Add_Logical_Type( i, CombatSoundTypeNames[i] );
}
for ( i = SOUND_TYPE_DESIGNER01; i <= SOUND_TYPE_DESIGNER09; i++ ) {
StringClass type_name;
type_name.Format ("Designer%02d", (i - SOUND_TYPE_DESIGNER01) + 1);
WWAudioClass::Get_Instance()->Add_Logical_Type( i, type_name );
}
}
void CombatSoundManager::Shutdown( void )
{
WWAudioClass::Get_Instance()->Reset_Logical_Types();
}

93
Code/Combat/combatsound.h Normal file
View File

@@ -0,0 +1,93 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/combatsound.h $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 11/29/00 2:07p $*
* *
* $Revision:: 16 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef COMBATSOUND_H
#define COMBATSOUND_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef VECTOR3_H
#include "vector3.h"
#endif
class ScriptableGameObj;
/*
**
*/
typedef enum {
SOUND_TYPE_NONE,
SOUND_TYPE_OLD_WEAPON,
SOUND_TYPE_FOOTSTEPS,
SOUND_TYPE_VEHICLE,
SOUND_TYPE_GUNSHOT,
SOUND_TYPE_BULLET_HIT,
NUM_DEFINED_SOUND_TYPES,
SOUND_TYPE_DESIGNER01 = 991,
SOUND_TYPE_DESIGNER02,
SOUND_TYPE_DESIGNER03,
SOUND_TYPE_DESIGNER04,
SOUND_TYPE_DESIGNER05,
SOUND_TYPE_DESIGNER06,
SOUND_TYPE_DESIGNER07,
SOUND_TYPE_DESIGNER08,
SOUND_TYPE_DESIGNER09,
} CombatSoundType;
/*
**
*/
class CombatSound {
public:
Vector3 Position;
CombatSoundType Type;
ScriptableGameObj * Creator;
};
/*
**
*/
class CombatSoundManager {
public:
static void Init( void );
static void Shutdown( void );
};
#endif // COMBATSOUND_H

View File

@@ -0,0 +1,379 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/comcentergameobj.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 7/16/01 12:10p $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "comcentergameobj.h"
#include "basecontroller.h"
#include "wwhack.h"
#include "simpledefinitionfactory.h"
#include "persistfactory.h"
#include "definitionmgr.h"
#include "combatchunkid.h"
#include "debug.h"
#include "wwprofile.h"
#include "basecontroller.h"
#include "combat.h"
////////////////////////////////////////////////////////////////
// Hacks
////////////////////////////////////////////////////////////////
DECLARE_FORCE_LINK (ComCenter)
////////////////////////////////////////////////////////////////
// Editable and persist factories
////////////////////////////////////////////////////////////////
SimplePersistFactoryClass <ComCenterGameObjDef, CHUNKID_GAME_OBJECT_DEF_COMCENTER> _ComCenterGameObjDefPersistFactory;
SimplePersistFactoryClass <ComCenterGameObj, CHUNKID_GAME_OBJECT_COMCENTER> _ComCenterGameObjPersistFactory;
DECLARE_DEFINITION_FACTORY (ComCenterGameObjDef, CLASSID_GAME_OBJECT_DEF_COMCENTER, "Com Center") _ComCenterGameObjDefDefFactory;
////////////////////////////////////////////////////////////////
// Save/Load constants
////////////////////////////////////////////////////////////////
enum
{
CHUNKID_DEF_PARENT = 0x02211153,
CHUNKID_DEF_VARIABLES,
MICROCHUNKID_DEF_UNUSED = 1,
};
enum
{
CHUNKID_PARENT = 0x02211154,
CHUNKID_VARIABLES,
MICROCHUNKID_UNUSED = 1,
};
////////////////////////////////////////////////////////////////
//
// ComCenterGameObjDef
//
////////////////////////////////////////////////////////////////
ComCenterGameObjDef::ComCenterGameObjDef (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// ~ComCenterGameObjDef
//
////////////////////////////////////////////////////////////////
ComCenterGameObjDef::~ComCenterGameObjDef (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Class_ID
//
////////////////////////////////////////////////////////////////
uint32
ComCenterGameObjDef::Get_Class_ID (void) const
{
return CLASSID_GAME_OBJECT_DEF_COMCENTER;
}
////////////////////////////////////////////////////////////////
//
// Create
//
////////////////////////////////////////////////////////////////
PersistClass *
ComCenterGameObjDef::Create (void) const
{
ComCenterGameObj *building = new ComCenterGameObj;
building->Init (*this);
return building;
}
////////////////////////////////////////////////////////////////
//
// Create
//
////////////////////////////////////////////////////////////////
bool
ComCenterGameObjDef::Save (ChunkSaveClass &csave)
{
csave.Begin_Chunk (CHUNKID_DEF_PARENT);
BuildingGameObjDef::Save (csave);
csave.End_Chunk ();
csave.Begin_Chunk (CHUNKID_DEF_VARIABLES);
csave.End_Chunk ();
return true;
}
////////////////////////////////////////////////////////////////
//
// Load
//
////////////////////////////////////////////////////////////////
bool
ComCenterGameObjDef::Load (ChunkLoadClass &cload)
{
while (cload.Open_Chunk ())
{
switch (cload.Cur_Chunk_ID ())
{
case CHUNKID_DEF_PARENT:
BuildingGameObjDef::Load (cload);
break;
case CHUNKID_DEF_VARIABLES:
Load_Variables (cload);
break;
default:
Debug_Say (("Unrecognized Com Center Def chunkID\n"));
break;
}
cload.Close_Chunk ();
}
return true;
}
////////////////////////////////////////////////////////////////
//
// Load_Variables
//
////////////////////////////////////////////////////////////////
void
ComCenterGameObjDef::Load_Variables (ChunkLoadClass &cload)
{
while (cload.Open_Micro_Chunk ()) {
/*switch (cload.Cur_Micro_Chunk_ID ())
{
default:
Debug_Say (("Unrecognized Com Center Def Variable chunkID\n"));
break;
}*/
cload.Close_Micro_Chunk();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Factory
//
////////////////////////////////////////////////////////////////
const PersistFactoryClass &
ComCenterGameObjDef::Get_Factory (void) const
{
return _ComCenterGameObjDefPersistFactory;
}
////////////////////////////////////////////////////////////////
//
// ComCenterGameObj
//
////////////////////////////////////////////////////////////////
ComCenterGameObj::ComCenterGameObj (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// ~ComCenterGameObj
//
////////////////////////////////////////////////////////////////
ComCenterGameObj::~ComCenterGameObj (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Factory
//
////////////////////////////////////////////////////////////////
const PersistFactoryClass &
ComCenterGameObj::Get_Factory (void) const
{
return _ComCenterGameObjPersistFactory;
}
////////////////////////////////////////////////////////////////
//
// Init
//
////////////////////////////////////////////////////////////////
void ComCenterGameObj::Init( void )
{
Init( Get_Definition() );
}
////////////////////////////////////////////////////////////////
//
// Init
//
////////////////////////////////////////////////////////////////
void
ComCenterGameObj::Init (const ComCenterGameObjDef &definition)
{
BuildingGameObj::Init (definition);
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Definition
//
////////////////////////////////////////////////////////////////
const ComCenterGameObjDef &
ComCenterGameObj::Get_Definition (void) const
{
return (const ComCenterGameObjDef &)BaseGameObj::Get_Definition ();
}
////////////////////////////////////////////////////////////////
//
// Save
//
////////////////////////////////////////////////////////////////
bool
ComCenterGameObj::Save (ChunkSaveClass &csave)
{
csave.Begin_Chunk (CHUNKID_PARENT);
BuildingGameObj::Save (csave);
csave.End_Chunk ();
csave.Begin_Chunk (CHUNKID_VARIABLES);
csave.End_Chunk ();
return true;
}
////////////////////////////////////////////////////////////////
//
// Load
//
////////////////////////////////////////////////////////////////
bool
ComCenterGameObj::Load (ChunkLoadClass &cload)
{
while (cload.Open_Chunk ()) {
switch (cload.Cur_Chunk_ID ()) {
case CHUNKID_PARENT:
BuildingGameObj::Load (cload);
break;
case CHUNKID_VARIABLES:
Load_Variables (cload);
break;
default:
Debug_Say (("Unrecognized Com Center chunkID\n"));
break;
}
cload.Close_Chunk();
}
return true;
}
////////////////////////////////////////////////////////////////
//
// Load_Variables
//
////////////////////////////////////////////////////////////////
void
ComCenterGameObj::Load_Variables (ChunkLoadClass &cload)
{
while (cload.Open_Micro_Chunk ()) {
/*switch (cload.Cur_Micro_Chunk_ID ())
{
default:
Debug_Say (("Unrecognized Com Center Variable chunkID\n"));
break;
}*/
cload.Close_Micro_Chunk();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Destroyed
//
////////////////////////////////////////////////////////////////
void
ComCenterGameObj::On_Destroyed (void)
{
BuildingGameObj::On_Destroyed ();
//
// Switch off the radar for each player on this team
//
if (BaseController != NULL && CombatManager::I_Am_Server ()) {
BaseController->Check_Radar ();
}
return ;
}

View File

@@ -0,0 +1,157 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/comcentergameobj.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 7/16/01 11:20a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __COMCENTERGAMEOBJ_H
#define __COMCENTERGAMEOBJ_H
#include "always.h"
#include "building.h"
////////////////////////////////////////////////////////////////
// Forward delcarations
////////////////////////////////////////////////////////////////
class BaseControllerClass;
////////////////////////////////////////////////////////////////
//
// ComCenterGameObjDef
//
////////////////////////////////////////////////////////////////
class ComCenterGameObjDef : public BuildingGameObjDef
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
ComCenterGameObjDef (void);
~ComCenterGameObjDef (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
uint32 Get_Class_ID (void) const;
PersistClass * Create (void) const;
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
const PersistFactoryClass & Get_Factory (void) const;
////////////////////////////////////////////////////////////////
// Editable support
////////////////////////////////////////////////////////////////
DECLARE_EDITABLE (ComCenterGameObjDef, BuildingGameObjDef);
protected:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
////////////////////////////////////////////////////////////////
// Protected member data
////////////////////////////////////////////////////////////////
float UnloadTime;
float FundsGathered;
int HarvesterDefID;
////////////////////////////////////////////////////////////////
// Friends
////////////////////////////////////////////////////////////////
friend class ComCenterGameObj;
};
////////////////////////////////////////////////////////////////
//
// ComCenterGameObj
//
////////////////////////////////////////////////////////////////
class ComCenterGameObj : public BuildingGameObj
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
ComCenterGameObj (void);
~ComCenterGameObj (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
//
// Definition support
//
virtual void Init( void );
void Init (const ComCenterGameObjDef & definition);
const ComCenterGameObjDef & Get_Definition (void) const;
//
// RTTI
//
ComCenterGameObj * As_ComCenterGameObj (void) { return this; }
//
// Persist support
//
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
const PersistFactoryClass & Get_Factory (void) const;
//
// From BuildingGameObj
//
void On_Destroyed (void);
private:
////////////////////////////////////////////////////////////////
// Private methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
};
#endif //__COMCENTERGAMEOBJ_H

480
Code/Combat/control.cpp Normal file
View File

@@ -0,0 +1,480 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/control.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 2/21/02 5:08p $*
* *
* $Revision:: 34 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "control.h"
#include "wwdebug.h"
#include "input.h"
#include "wwmath.h"
#include "wwpacket.h"
#include "chunkio.h"
#include "debug.h"
#include <memory.h>
#include "combat.h"
//#include "clientinterpmodels.h"
#include "encoderlist.h"
#include "bitpackids.h"
// Should pack analogs of 1 and -1 into single bit
//
// TSS 03/08/99: I have scaled the floats down to bytes.... more optimisation later!
//
ControlClass & ControlClass::operator = (const ControlClass & src)
{
OneTimeBooleanBits = src.OneTimeBooleanBits;
ContinuousBooleanBits = src.ContinuousBooleanBits;
memcpy( AnalogValues, src.AnalogValues, sizeof(AnalogValues) );
return *this;
}
/*
**
*/
enum {
CHUNKID_VARIABLES = 914991110,
MICROCHUNKID_ONE_TIME_BOOL = 1,
MICROCHUNKID_CONTINUOUS_BOOL,
MICROCHUNKID_ANALOG,
MICROCHUNKID_PENDING_ONE_TIME_BOOL,
MICROCHUNKID_PENDING_CONTINUOUS_BOOL,
};
bool ControlClass::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ONE_TIME_BOOL, OneTimeBooleanBits );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_CONTINUOUS_BOOL, ContinuousBooleanBits );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_PENDING_ONE_TIME_BOOL, PendingOneTimeBooleanBits );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_PENDING_CONTINUOUS_BOOL, PendingContinuousBooleanBits );
csave.Begin_Micro_Chunk(MICROCHUNKID_ANALOG);
csave.Write(&AnalogValues[0],sizeof(AnalogValues));
csave.End_Micro_Chunk();
csave.End_Chunk();
return true;
}
bool ControlClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_ONE_TIME_BOOL, OneTimeBooleanBits );
READ_MICRO_CHUNK( cload, MICROCHUNKID_CONTINUOUS_BOOL, ContinuousBooleanBits );
READ_MICRO_CHUNK( cload, MICROCHUNKID_PENDING_ONE_TIME_BOOL, PendingOneTimeBooleanBits );
READ_MICRO_CHUNK( cload, MICROCHUNKID_PENDING_CONTINUOUS_BOOL, PendingContinuousBooleanBits );
case MICROCHUNKID_ANALOG:
cload.Read( &AnalogValues[0],sizeof(AnalogValues) );
break;
default:
Debug_Say(( "Unrecognized Control Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(( "Unrecognized Control chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
//JITTER
void ControlClass::Clear_Boolean( void )
{
WWASSERT( (8 * sizeof(ControlClass::OneTimeBooleanBits)) >= ControlClass::NUM_BOOLEAN_ONE_TIME );
WWASSERT( (8 * sizeof(ControlClass::ContinuousBooleanBits)) >= ControlClass::NUM_BOOLEAN_CONTINUOUS );
OneTimeBooleanBits = 0;
ContinuousBooleanBits = 0;
}
void ControlClass::Clear_Control( void )
{
WWASSERT( (8 * sizeof(ControlClass::OneTimeBooleanBits)) >= ControlClass::NUM_BOOLEAN_ONE_TIME );
WWASSERT( (8 * sizeof(ControlClass::ContinuousBooleanBits)) >= ControlClass::NUM_BOOLEAN_CONTINUOUS );
OneTimeBooleanBits = 0;
ContinuousBooleanBits = 0;
memset( AnalogValues, 0, sizeof(AnalogValues) );
}
enum {
CONTROL_MOVE_FORWARD = 0,
CONTROL_MOVE_BACKWARD,
CONTROL_MOVE_LEFT,
CONTROL_MOVE_RIGHT,
CONTROL_MOVE_UP,
CONTROL_MOVE_DOWN,
CONTROL_TURN_LEFT,
CONTROL_TURN_RIGHT,
} CONTROL_MOVE_BITS;
//-----------------------------------------------------------------------------
void ControlClass::Import_Cs( BitStreamClass & packet )
{
// Or in the new one time bits
ULONG otb_bits = packet.Get(otb_bits, BITPACK_ONE_TIME_BOOLEAN_BITS);
OneTimeBooleanBits |= otb_bits;
packet.Get(ContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
#if 01
packet.Get(AnalogValues[ANALOG_MOVE_FORWARD], BITPACK_ANALOG_VALUES);
packet.Get(AnalogValues[ANALOG_MOVE_LEFT], BITPACK_ANALOG_VALUES);
packet.Get(AnalogValues[ANALOG_MOVE_UP], BITPACK_ANALOG_VALUES);
packet.Get(AnalogValues[ANALOG_TURN_LEFT], BITPACK_ANALOG_VALUES);
#else
int control_move;
packet.Get( control_move, BITPACK_CONTROL_MOVES_CS);
AnalogValues[ANALOG_MOVE_FORWARD] = 0.0f;
AnalogValues[ANALOG_MOVE_LEFT] = 0.0f;
AnalogValues[ANALOG_MOVE_UP] = 0.0f;
AnalogValues[ANALOG_TURN_LEFT] = 0.0f;
if ( control_move & (1<<CONTROL_MOVE_FORWARD) ) {
AnalogValues[ANALOG_MOVE_FORWARD] = 1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_BACKWARD) ) {
AnalogValues[ANALOG_MOVE_FORWARD] = -1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_LEFT) ) {
AnalogValues[ANALOG_MOVE_LEFT] = 1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_RIGHT) ) {
AnalogValues[ANALOG_MOVE_LEFT] = -1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_UP) ) {
AnalogValues[ANALOG_MOVE_UP] = 1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_DOWN) ) {
AnalogValues[ANALOG_MOVE_UP] = -1.0f;
}
if ( control_move & (1<<CONTROL_TURN_LEFT) ) {
AnalogValues[ANALOG_TURN_LEFT] = 1.0f;
}
if ( control_move & (1<<CONTROL_TURN_RIGHT) ) {
AnalogValues[ANALOG_TURN_LEFT] = -1.0f;
}
#endif
for (int i = 0; i < ANALOG_CONTROL_COUNT; i++) {
if (fabs(AnalogValues[i]) < 0.005) {
//
// The code elsewhere has no tolerance for precision error on this
// value around zero...
//
AnalogValues[i] = 0;
}
}
}
//-----------------------------------------------------------------------------
void ControlClass::Export_Cs( BitStreamClass & packet )
{
// packet.Add(OneTimeBooleanBits, BITPACK_ONE_TIME_BOOLEAN_BITS);
packet.Add(PendingOneTimeBooleanBits, BITPACK_ONE_TIME_BOOLEAN_BITS);
PendingOneTimeBooleanBits = 0;
// packet.Add(ContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
packet.Add(PendingContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
PendingContinuousBooleanBits = 0;
#if 01
packet.Add(AnalogValues[ANALOG_MOVE_FORWARD], BITPACK_ANALOG_VALUES);
packet.Add(AnalogValues[ANALOG_MOVE_LEFT], BITPACK_ANALOG_VALUES);
packet.Add(AnalogValues[ANALOG_MOVE_UP], BITPACK_ANALOG_VALUES);
packet.Add(AnalogValues[ANALOG_TURN_LEFT], BITPACK_ANALOG_VALUES);
#else
int control_move = 0;
if ( AnalogValues[ANALOG_MOVE_FORWARD] > 0.5f ) {
control_move |= 1<<CONTROL_MOVE_FORWARD;
}
if ( AnalogValues[ANALOG_MOVE_FORWARD] < -0.5f ) {
control_move |= 1<<CONTROL_MOVE_BACKWARD;
}
if ( AnalogValues[ANALOG_MOVE_LEFT] > 0.5f ) {
control_move |= 1<<CONTROL_MOVE_LEFT;
}
if ( AnalogValues[ANALOG_MOVE_LEFT] < -0.5f ) {
control_move |= 1<<CONTROL_MOVE_RIGHT;
}
if ( AnalogValues[ANALOG_MOVE_UP] > 0.5f ) {
control_move |= 1<<CONTROL_MOVE_UP;
}
if ( AnalogValues[ANALOG_MOVE_UP] < -0.5f ) {
control_move |= 1<<CONTROL_MOVE_DOWN;
}
if ( AnalogValues[ANALOG_TURN_LEFT] > 0.5f ) {
control_move |= 1<<CONTROL_TURN_LEFT;
}
if ( AnalogValues[ANALOG_TURN_LEFT] < -0.5f ) {
control_move |= 1<<CONTROL_TURN_RIGHT;
}
packet.Add( control_move, BITPACK_CONTROL_MOVES_CS);
#endif
}
//-----------------------------------------------------------------------------
void ControlClass::Import_Sc(BitStreamClass & packet)
{
packet.Get(ContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
#if 01
packet.Get(AnalogValues[ANALOG_MOVE_FORWARD], BITPACK_ANALOG_VALUES);
packet.Get(AnalogValues[ANALOG_MOVE_LEFT], BITPACK_ANALOG_VALUES);
packet.Get(AnalogValues[ANALOG_MOVE_UP], BITPACK_ANALOG_VALUES);
packet.Get(AnalogValues[ANALOG_TURN_LEFT], BITPACK_ANALOG_VALUES);
#else
int control_move;
packet.Get( control_move, BITPACK_CONTROL_MOVES_SC);
AnalogValues[ANALOG_MOVE_FORWARD] = 0.0f;
AnalogValues[ANALOG_MOVE_LEFT] = 0.0f;
AnalogValues[ANALOG_MOVE_UP] = 0.0f;
if ( control_move & (1<<CONTROL_MOVE_FORWARD) ) {
AnalogValues[ANALOG_MOVE_FORWARD] = 1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_BACKWARD) ) {
AnalogValues[ANALOG_MOVE_FORWARD] = -1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_LEFT) ) {
AnalogValues[ANALOG_MOVE_LEFT] = 1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_RIGHT) ) {
AnalogValues[ANALOG_MOVE_LEFT] = -1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_UP) ) {
AnalogValues[ANALOG_MOVE_UP] = 1.0f;
}
if ( control_move & (1<<CONTROL_MOVE_DOWN) ) {
AnalogValues[ANALOG_MOVE_UP] = -1.0f;
}
/* if ( control_move & (1<<CONTROL_TURN_LEFT) ) {
AnalogValues[ANALOG_TURN_LEFT] = 1.0f;
}
if ( control_move & (1<<CONTROL_TURN_RIGHT) ) {
AnalogValues[ANALOG_TURN_LEFT] = -1.0f;
}*/
#endif
for (int i = 0; i < ANALOG_CONTROL_COUNT; i++) {
if (fabs(AnalogValues[i]) < 0.005) {
//
// The code elsewhere has no tolerance for precision error on this
// value around zero...
//
AnalogValues[i] = 0;
}
}
}
//-----------------------------------------------------------------------------
void ControlClass::Export_Sc(BitStreamClass & packet)
{
packet.Add(ContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
#if 01
packet.Add(AnalogValues[ANALOG_MOVE_FORWARD], BITPACK_ANALOG_VALUES);
packet.Add(AnalogValues[ANALOG_MOVE_LEFT], BITPACK_ANALOG_VALUES);
packet.Add(AnalogValues[ANALOG_MOVE_UP], BITPACK_ANALOG_VALUES);
packet.Add(AnalogValues[ANALOG_TURN_LEFT], BITPACK_ANALOG_VALUES);
#else
int control_move = 0;
if ( AnalogValues[ANALOG_MOVE_FORWARD] > 0.5f ) {
control_move |= 1<<CONTROL_MOVE_FORWARD;
}
if ( AnalogValues[ANALOG_MOVE_FORWARD] < -0.5f ) {
control_move |= 1<<CONTROL_MOVE_BACKWARD;
}
if ( AnalogValues[ANALOG_MOVE_LEFT] > 0.5f ) {
control_move |= 1<<CONTROL_MOVE_LEFT;
}
if ( AnalogValues[ANALOG_MOVE_LEFT] < -0.5f ) {
control_move |= 1<<CONTROL_MOVE_RIGHT;
}
if ( AnalogValues[ANALOG_MOVE_UP] > 0.5f ) {
control_move |= 1<<CONTROL_MOVE_UP;
}
if ( AnalogValues[ANALOG_MOVE_UP] < -0.5f ) {
control_move |= 1<<CONTROL_MOVE_DOWN;
}
/* if ( AnalogValues[ANALOG_TURN_LEFT] > 0.5f ) {
control_move |= 1<<CONTROL_TURN_LEFT;
}
if ( AnalogValues[ANALOG_TURN_LEFT] < -0.5f ) {
control_move |= 1<<CONTROL_TURN_RIGHT;
}*/
packet.Add( control_move, BITPACK_CONTROL_MOVES_SC);
#endif
}
//-----------------------------------------------------------------------------
/*
float ControlClass::Get_Clamp(AnalogControl control)
{
//
// This will definitely need improving...
//
float clamp;
switch (control) {
case ANALOG_MOVE_FORWARD :
clamp = Input::Get_Clamp(INPUT_FUNCTION_RUN_FORWARD);
break;
case ANALOG_MOVE_LEFT :
clamp = Input::Get_Clamp(INPUT_FUNCTION_RUN_LEFT);
break;
case ANALOG_MOVE_UP :
clamp = Input::Get_Clamp(INPUT_FUNCTION_RUN_FORWARD);
break;
case ANALOG_TURN_LEFT :
clamp = Input::Get_Clamp(INPUT_FUNCTION_TURN_LEFT);
break;
case ANALOG_WEAPON_UP :
clamp = Input::Get_Clamp(INPUT_FUNCTION_WEAPON_UP);
break;
case ANALOG_WEAPON_LEFT :
// clamp = 1.0f;
clamp = Input::Get_Clamp(INPUT_FUNCTION_WEAPON_LEFT);
break;
default:
WWASSERT(0);
}
WWASSERT(clamp > 0);
return clamp;
}
*/
/*
BYTE ControlClass::Scale_Analog(float clamp, float unscaled)
{
WWASSERT(unscaled > -clamp - WWMATH_EPSILON);
WWASSERT(unscaled < +clamp + WWMATH_EPSILON);
return (BYTE) (255 * WWMath::Clamp((unscaled + clamp) / (2 * clamp)));
}
float ControlClass::Unscale_Analog(float clamp, BYTE scaled)
{
float unscaled;
if (scaled == 127) { // scaling perturbs zero, special-case it
unscaled = 0;
} else {
unscaled = scaled / 255.0f * 2 * clamp - clamp;
}
WWASSERT(unscaled > -clamp - WWMATH_EPSILON);
WWASSERT(unscaled < +clamp + WWMATH_EPSILON);
return unscaled;
}
*/
void ControlClass::Set_Boolean( BooleanControl bcontrol, bool state )
{
int control = bcontrol;
if ( control >= BOOLEAN_CONTINUOUS_FIRST ) {
control -= BOOLEAN_CONTINUOUS_FIRST;
if (state) ContinuousBooleanBits |= (1 << control);
else ContinuousBooleanBits &= ~(1 << control);
PendingContinuousBooleanBits |= ContinuousBooleanBits;
} else {
control -= BOOLEAN_ONE_TIME_FIRST;
if (state) OneTimeBooleanBits |= (1 << control);
else OneTimeBooleanBits &= ~(1 << control);
PendingOneTimeBooleanBits |= OneTimeBooleanBits;
}
}
bool ControlClass::Get_Boolean( BooleanControl bcontrol )
{
int control = bcontrol;
if ( control >= BOOLEAN_CONTINUOUS_FIRST ) {
control -= BOOLEAN_CONTINUOUS_FIRST;
return ( ContinuousBooleanBits & (1 << control ) ) ? true : false;
} else {
control -= BOOLEAN_ONE_TIME_FIRST;
return ( OneTimeBooleanBits & (1 << control ) ) ? true : false;
}
}
void ControlClass::Set_Precision(void)
{
cEncoderList::Set_Precision(BITPACK_ONE_TIME_BOOLEAN_BITS, NUM_BOOLEAN_ONE_TIME);
cEncoderList::Set_Precision(BITPACK_CONTINUOUS_BOOLEAN_BITS, NUM_BOOLEAN_CONTINUOUS);
cEncoderList::Set_Precision(BITPACK_CONTROL_MOVES_CS, CONTROL_TURN_RIGHT+1); // 8
cEncoderList::Set_Precision(BITPACK_CONTROL_MOVES_SC, CONTROL_MOVE_DOWN+1); // 6
//
// TSS: I think that analog values are within this range, except for
// DEBUG_RAPID_MOVE...
//
cEncoderList::Set_Precision(BITPACK_ANALOG_VALUES, -1.0, 1.0, 0.01);
/*
//
// Proof that zero does not map to zero...
//
cPacket test;
float zero = 0.0f;
test.Add(zero, BITPACK_ANALOG_VALUES);
float zero2 = -999;
test.Get(zero2, BITPACK_ANALOG_VALUES);
*/
}

167
Code/Combat/control.h Normal file
View File

@@ -0,0 +1,167 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/control.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 2/21/02 5:06p $*
* *
* $Revision:: 36 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef CONTROL_H
#define CONTROL_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef WWMATH_H
#include "wwmath.h"
#endif
#ifndef WWDEBUG_H
#include "wwdebug.h"
#endif
/*
**
*/
class BitStreamClass;
class ChunkSaveClass;
class ChunkLoadClass;
/*
** ControlClass
*/
class ControlClass {
public:
typedef enum {
BOOLEAN_ONE_TIME_FIRST,
BOOLEAN_JUMP = BOOLEAN_ONE_TIME_FIRST,
// BOOLEAN_CROUCH,
BOOLEAN_WEAPON_NEXT,
BOOLEAN_WEAPON_PREV,
BOOLEAN_WEAPON_RELOAD,
BOOLEAN_WEAPON_USE,
BOOLEAN_DIVE_FORWARD,
BOOLEAN_DIVE_BACKWARD,
BOOLEAN_DIVE_LEFT,
BOOLEAN_DIVE_RIGHT,
BOOLEAN_ACTION, // was LADDER
BOOLEAN_SELECT_NO_WEAPON,
BOOLEAN_SELECT_WEAPON_0,
BOOLEAN_SELECT_WEAPON_1,
BOOLEAN_SELECT_WEAPON_2,
BOOLEAN_SELECT_WEAPON_3,
BOOLEAN_SELECT_WEAPON_4,
BOOLEAN_SELECT_WEAPON_5,
BOOLEAN_SELECT_WEAPON_6,
BOOLEAN_SELECT_WEAPON_7,
BOOLEAN_SELECT_WEAPON_8,
BOOLEAN_SELECT_WEAPON_9,
BOOLEAN_DROP_FLAG,
BOOLEAN_VEHICLE_TOGGLE_GUNNER,
BOOLEAN_CONTINUOUS_FIRST,
BOOLEAN_WEAPON_FIRE_PRIMARY = BOOLEAN_CONTINUOUS_FIRST,
BOOLEAN_WEAPON_FIRE_SECONDARY,
BOOLEAN_WALK,
BOOLEAN_CROUCH,
BOOLEAN_TOTAL, // Number of boolean channels
NUM_BOOLEAN_ONE_TIME = BOOLEAN_CONTINUOUS_FIRST - BOOLEAN_ONE_TIME_FIRST,
NUM_BOOLEAN_CONTINUOUS = BOOLEAN_TOTAL - BOOLEAN_CONTINUOUS_FIRST,
} BooleanControl;
typedef enum {
ANALOG_MOVE_FORWARD,
ANALOG_MOVE_LEFT,
ANALOG_MOVE_UP,
ANALOG_TURN_LEFT,
ANALOG_CONTROL_COUNT // Number of analog channels
} AnalogControl;
ControlClass( void ) : PendingOneTimeBooleanBits( 0 ) { Clear_Control(); }
~ControlClass( void ) {}
bool Save( ChunkSaveClass & csave );
bool Load( ChunkLoadClass & cload );
void Clear_Control( void );
void Clear_Boolean( void );
ControlClass & operator = (const ControlClass & src);
// Boolean Controls
void Set_Boolean( BooleanControl control, bool state = true );
bool Get_Boolean( BooleanControl control );
void Clear_One_Time_Boolean( void ) {OneTimeBooleanBits = 0;}
unsigned long Get_One_Time_Boolean_Bits(void) {return OneTimeBooleanBits;}
unsigned char Get_Continuous_Boolean_Bits(void) {return ContinuousBooleanBits;}
// Analog Controls
void Set_Analog( AnalogControl control, float value );
float Get_Analog( AnalogControl control );
//float Get_Clamp( AnalogControl control );
//unsigned char Scale_Analog(float clamp, float unscaled);
//float Unscale_Analog(float clamp, unsigned char scaled);
// Import & Export
void Import_Cs( BitStreamClass & packet );
void Export_Cs( BitStreamClass & packet );
void Import_Sc( BitStreamClass & packet );
void Export_Sc( BitStreamClass & packet );
static void Set_Precision(void);
private:
unsigned long OneTimeBooleanBits;
unsigned long PendingOneTimeBooleanBits;
unsigned char ContinuousBooleanBits;
unsigned char PendingContinuousBooleanBits;
float AnalogValues[ ANALOG_CONTROL_COUNT ];
};
inline void ControlClass::Set_Analog( AnalogControl control, float value )
{
WWASSERT(WWMath::Is_Valid_Float(value));
AnalogValues[ control ] = value;
}
inline float ControlClass::Get_Analog( AnalogControl control )
{
WWASSERT(WWMath::Is_Valid_Float(AnalogValues[ control ]));
return AnalogValues[ control ];
}
#endif // CONTROL_H

View File

@@ -0,0 +1,477 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/conversation.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 10/29/01 10:23p $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "conversation.h"
#include "chunkio.h"
#include "soldier.h"
////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////
enum
{
CHUNKID_BASE_CLASS = 0x08090315,
CHUNKID_VARIABLES,
CHUNKID_ORATOR,
CHUNKID_REMARK
};
enum
{
VARID_NAME = 0,
VARID_ID,
XXXX_VARID_REMARK,
VARID_OLD_PTR,
XXXXX_PLAYERTYPE,
VARID_ISINNATE,
VARID_PROBABILITY,
VARID_AI_STATE,
VARID_CATEGORY_ID,
VARID_LOOKAT_OBJID,
VARID_PRIORITY,
VARID_MAXDIST,
VARID_IS_INTERRUPTABLE,
VARID_ISKEY
};
////////////////////////////////////////////////////////////////
//
// ConversationClass
//
////////////////////////////////////////////////////////////////
ConversationClass::ConversationClass (void) :
ID (0),
IsInnate (true),
IsKey (false),
Probability (1.0F),
AIState (AI_STATE_IDLE),
CategoryID (0),
LookAtObjID (0),
Priority (30),
MaxDist (0),
IsInterruptable (true)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// ConversationClass
//
////////////////////////////////////////////////////////////////
ConversationClass::ConversationClass (const ConversationClass &src) :
ID (0),
IsInnate (true),
IsKey (false),
Probability (1.0F),
AIState (AI_STATE_IDLE),
CategoryID (0),
LookAtObjID (0),
Priority (30),
MaxDist (0),
IsInterruptable (true)
{
(*this) = src;
return ;
}
////////////////////////////////////////////////////////////////
//
// ~ConversationClass
//
////////////////////////////////////////////////////////////////
ConversationClass::~ConversationClass (void)
{
Clear_Remarks ();
Clear_Orators ();
return ;
}
////////////////////////////////////////////////////////////////
//
// operator=
//
////////////////////////////////////////////////////////////////
const ConversationClass &
ConversationClass::operator= (const ConversationClass &src)
{
//
// Start fresh
//
Clear_Remarks ();
Clear_Orators ();
//
// Copy the simple data
//
Name = src.Name;
ID = src.ID;
LookAtObjID = src.LookAtObjID;
Priority = src.Priority;
MaxDist = src.MaxDist;
IsInterruptable = src.IsInterruptable;
//
// Copy the remark list
//
for (int index = 0; index < src.RemarkList.Count (); index ++) {
const ConversationRemarkClass &remark = src.RemarkList[index];
Add_Remark (remark);
}
//
// Copy the orator list
//
for (index = 0; index < src.OratorList.Count (); index ++) {
const OratorClass &orator = src.OratorList[index];
Add_Orator (orator);
}
return (*this);
}
////////////////////////////////////////////////////////////////
//
// Clear_Orators
//
////////////////////////////////////////////////////////////////
void
ConversationClass::Clear_Orators (void)
{
OratorList.Delete_All ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Clear_Remarks
//
////////////////////////////////////////////////////////////////
void
ConversationClass::Clear_Remarks (void)
{
RemarkList.Delete_All ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Orator_Count
//
////////////////////////////////////////////////////////////////
int
ConversationClass::Get_Orator_Count (void) const
{
return OratorList.Count ();
}
////////////////////////////////////////////////////////////////
//
// Add_Orator
//
////////////////////////////////////////////////////////////////
void
ConversationClass::Add_Orator (const OratorClass &orator)
{
OratorList.Add (orator);
return ;
}
////////////////////////////////////////////////////////////////
//
// Add_Remark
//
////////////////////////////////////////////////////////////////
void
ConversationClass::Add_Remark (const ConversationRemarkClass &remark)
{
RemarkList.Add (remark);
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Remark_Info
//
////////////////////////////////////////////////////////////////
bool
ConversationClass::Get_Remark_Info (int index, ConversationRemarkClass &remark)
{
bool retval = false;
WWASSERT (index >= 0 && index < RemarkList.Count ());
if (index >= 0 && index < RemarkList.Count ()) {
//
// Return the remark information to the caller
//
remark = RemarkList[index];
retval = true;
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Save
//
////////////////////////////////////////////////////////////////
bool
ConversationClass::Save (ChunkSaveClass &csave)
{
csave.Begin_Chunk (CHUNKID_VARIABLES);
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_NAME, Name);
WRITE_MICRO_CHUNK (csave, VARID_ID, ID);
WRITE_MICRO_CHUNK (csave, VARID_ISINNATE, IsInnate);
WRITE_MICRO_CHUNK (csave, VARID_ISKEY, IsKey);
WRITE_MICRO_CHUNK (csave, VARID_PROBABILITY, Probability);
WRITE_MICRO_CHUNK (csave, VARID_AI_STATE, AIState);
WRITE_MICRO_CHUNK (csave, VARID_CATEGORY_ID, CategoryID);
WRITE_MICRO_CHUNK (csave, VARID_LOOKAT_OBJID, LookAtObjID);
WRITE_MICRO_CHUNK (csave, VARID_PRIORITY, Priority);
WRITE_MICRO_CHUNK (csave, VARID_MAXDIST, MaxDist);
WRITE_MICRO_CHUNK (csave, VARID_IS_INTERRUPTABLE, IsInterruptable);
//
// Save our current pointer so we can remap it on load
//
ConversationClass *old_ptr = this;
WRITE_MICRO_CHUNK (csave, VARID_OLD_PTR, old_ptr);
csave.End_Chunk ();
//
// Save the orator list
//
for (int index = 0; index < OratorList.Count (); index ++) {
OratorClass &orator = OratorList[index];
//
// Save this orator to its own chunk
//
csave.Begin_Chunk (CHUNKID_ORATOR);
orator.Save (csave);
csave.End_Chunk ();
}
//
// Save the remark list
//
for (index = 0; index < RemarkList.Count (); index ++) {
ConversationRemarkClass &remark = RemarkList[index];
//
// Save this remark to its own chunk
//
csave.Begin_Chunk (CHUNKID_REMARK);
remark.Save (csave);
csave.End_Chunk ();
}
return true;
}
////////////////////////////////////////////////////////////////
//
// Load
//
////////////////////////////////////////////////////////////////
bool
ConversationClass::Load (ChunkLoadClass &cload)
{
OratorList.Resize (10);
while (cload.Open_Chunk ()) {
switch (cload.Cur_Chunk_ID ()) {
case CHUNKID_VARIABLES:
Load_Variables (cload);
break;
case CHUNKID_ORATOR:
{
OratorList.Add (OratorClass ());
OratorList[OratorList.Count () - 1].Load (cload);
}
break;
case CHUNKID_REMARK:
{
ConversationRemarkClass remark;
remark.Load (cload);
RemarkList.Add (remark);
}
break;
}
cload.Close_Chunk ();
}
return true;
}
///////////////////////////////////////////////////////////////////////
//
// Load_Variables
//
///////////////////////////////////////////////////////////////////////
void
ConversationClass::Load_Variables (ChunkLoadClass &cload)
{
ConversationClass *old_ptr = NULL;
//
// Loop through all the microchunks that define the variables
//
while (cload.Open_Micro_Chunk ()) {
switch (cload.Cur_Micro_Chunk_ID ()) {
READ_MICRO_CHUNK_WWSTRING (cload, VARID_NAME, Name);
READ_MICRO_CHUNK (cload, VARID_ID, ID);
READ_MICRO_CHUNK (cload, VARID_OLD_PTR, old_ptr);
READ_MICRO_CHUNK (cload, VARID_ISINNATE, IsInnate);
READ_MICRO_CHUNK (cload, VARID_ISKEY, IsKey);
READ_MICRO_CHUNK (cload, VARID_PROBABILITY, Probability);
READ_MICRO_CHUNK (cload, VARID_AI_STATE, AIState);
READ_MICRO_CHUNK (cload, VARID_CATEGORY_ID, CategoryID);
READ_MICRO_CHUNK (cload, VARID_LOOKAT_OBJID, LookAtObjID);
READ_MICRO_CHUNK (cload, VARID_PRIORITY, Priority);
READ_MICRO_CHUNK (cload, VARID_MAXDIST, MaxDist);
READ_MICRO_CHUNK (cload, VARID_IS_INTERRUPTABLE, IsInterruptable);
//
// Old-style remark (for backwards compatiblility)
//
case XXXX_VARID_REMARK:
{
struct
{
int OratorID;
int TextID;
} OldRemarkStruct;
//
// Read the old data from the chunk
//
cload.Read (&OldRemarkStruct, sizeof (OldRemarkStruct));
//
// Convert the data
//
ConversationRemarkClass remark;
remark.Set_Orator_ID (OldRemarkStruct.OratorID);
remark.Set_Text_ID (OldRemarkStruct.TextID);
//
// Add this remark to our list
//
Add_Remark (remark);
}
break;
}
cload.Close_Micro_Chunk ();
}
//
// Register our old pointer so other objects can safely remap to it
//
WWASSERT (old_ptr != NULL);
SaveLoadSystemClass::Register_Pointer (old_ptr, this);
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Get_Orator
//
///////////////////////////////////////////////////////////////////////
OratorClass *
ConversationClass::Get_Orator (int index)
{
OratorClass *orator = NULL;
if (index >= 0 && index < OratorList.Count ()) {
orator = &OratorList[index];
}
return orator;
}
///////////////////////////////////////////////////////////////////////
//
// Find_Orator
//
///////////////////////////////////////////////////////////////////////
OratorClass *
ConversationClass::Find_Orator (int orator_id)
{
OratorClass *orator = NULL;
for (int index = 0; index < OratorList.Count (); index ++) {
OratorClass *curr_orator = &OratorList[index];
//
// Is this the orator we are looking for?
//
if (curr_orator->Get_ID () == orator_id) {
orator = curr_orator;
break;
}
}
return orator;
}

176
Code/Combat/conversation.h Normal file
View File

@@ -0,0 +1,176 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/conversation.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 10/29/01 10:23p $*
* *
* $Revision:: 8 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __CONVERSATION_H
#define __CONVERSATION_H
#include "wwstring.h"
#include "vector.h"
#include "refcount.h"
#include "orator.h"
#include "soldier.h"
#include "conversationremark.h"
////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////
class ChunkSaveClass;
class ChunkLoadClass;
////////////////////////////////////////////////////////////////
//
// ConversationClass
//
////////////////////////////////////////////////////////////////
class ConversationClass : public RefCountClass
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
ConversationClass (void);
ConversationClass (const ConversationClass &src);
virtual ~ConversationClass (void);
////////////////////////////////////////////////////////////////
// Public operators
////////////////////////////////////////////////////////////////
const ConversationClass & operator= (const ConversationClass &src);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
//
// Save/load methods
//
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
//
// Identification methods
//
int Get_ID (void) const { return ID; }
void Set_ID (int id) { ID = id; }
const char * Get_Name (void) const { return Name; }
void Set_Name (const char *name) { Name = name; }
//
// Orator information
//
int Get_Orator_Count (void) const;
OratorClass * Get_Orator (int index);
OratorClass * Find_Orator (int orator_id);
void Add_Orator (const OratorClass &orator);
void Clear_Orators (void);
//
// State requirements
//
SoldierAIState Get_AI_State( void ) const { return AIState; }
void Set_AI_State( SoldierAIState state ) { AIState = state; }
//
// Remark access
//
int Get_Remark_Count (void) const { return RemarkList.Count (); }
bool Get_Remark_Info (int index, ConversationRemarkClass &remark);
void Add_Remark (const ConversationRemarkClass &remark);
void Clear_Remarks (void);
//
// Accessors
//
bool Is_Innate (void) const { return IsInnate; }
void Set_Is_Innate (bool is_innate) { IsInnate = is_innate; }
bool Is_Key (void) const { return IsKey; }
void Set_Is_Key (bool is_key) { IsKey = is_key; }
float Get_Probability (void) const { return Probability; }
void Set_Probability (float percent) { Probability = percent; }
int Get_Category_ID (void) const { return CategoryID; }
void Set_Category_ID (int id) { CategoryID = id; }
int Get_Look_At_Obj_ID (void) const { return LookAtObjID; }
void Set_Look_At_Obj_ID (int id) { LookAtObjID = id; }
int Get_Priority (void) const { return Priority; }
void Set_Priority (int priority) { Priority = priority; }
float Get_Max_Dist (void) const { return MaxDist; }
void Set_Max_Dist (float max_dist) { MaxDist = max_dist; }
bool Is_Interruptable (void) const { return IsInterruptable; }
void Set_Is_Interruptable (bool onoff) { IsInterruptable = onoff; }
protected:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
////////////////////////////////////////////////////////////////
// Protected member data
////////////////////////////////////////////////////////////////
StringClass Name;
int ID;
DynamicVectorClass<ConversationRemarkClass> RemarkList;
DynamicVectorClass<OratorClass> OratorList;
SoldierAIState AIState;
bool IsInnate;
bool IsKey;
float Probability;
int CategoryID;
int LookAtObjID;
int Priority;
float MaxDist;
bool IsInterruptable;
};
#endif //__CONVERSATION_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,246 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/conversationmgr.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/15/02 9:37p $*
* *
* $Revision:: 16 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __CONVERSATION_MGR_H
#define __CONVERSATION_MGR_H
#include "saveloadsubsystem.h"
#include "vector.h"
////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////
class ChunkSaveClass;
class ChunkLoadClass;
class ConversationClass;
class ActiveConversationClass;
class PhysicalGameObj;
class OratorClass;
////////////////////////////////////////////////////////////////
// Singleton instance
////////////////////////////////////////////////////////////////
extern class ConversationMgrClass _ConversationMgrSaveLoad;
////////////////////////////////////////////////////////////////
// Typedefs
////////////////////////////////////////////////////////////////
typedef DynamicVectorClass<ConversationClass *> CONVERSATION_LIST;
typedef DynamicVectorClass<ActiveConversationClass *> ACTIVE_CONVERSATION_LIST;
////////////////////////////////////////////////////////////////
//
// ConversationMgrClass
//
////////////////////////////////////////////////////////////////
class ConversationMgrClass : public SaveLoadSubSystemClass
{
public:
////////////////////////////////////////////////////////////////
// Public constants
////////////////////////////////////////////////////////////////
typedef enum
{
CATEGORY_GLOBAL = 0,
CATEGORY_LEVEL,
CATEGORY_MAX
} CATEGORY;
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
ConversationMgrClass (void);
virtual ~ConversationMgrClass (void);
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
//
// Initialization
//
static void Initialize (void) {}
static void Shutdown (void) { Reset (); }
//
// Conversation editing
//
static void Add_Conversation (ConversationClass *conversation);
static int Get_Conversation_Count (void);
static int Get_Conversation_Count (int category_index) { return ConversationList[category_index].Count (); }
static ConversationClass * Peek_Conversation (int index);
static ConversationClass * Peek_Conversation (int category_index, int index) { return ConversationList[category_index][index]; }
static void Remove_Conversation (ConversationClass *conversation);
//
// Runtime conversation access
//
static ActiveConversationClass * Create_New_Conversation (ConversationClass *conversation, DynamicVectorClass<PhysicalGameObj *> &buddy_list);
static ActiveConversationClass * Create_New_Conversation (ConversationClass *conversation);
static void Start_Conversation (PhysicalGameObj *orator);
static ActiveConversationClass * Start_Conversation (PhysicalGameObj *orator, const char *conversation_name, bool force = false);
static ActiveConversationClass * Start_Conversation (PhysicalGameObj *orator, int conversation_id, bool force = false);
static ActiveConversationClass * Start_Conversation (PhysicalGameObj *orator, ConversationClass *conversation, bool force = false);
static ConversationClass * Pick_Conversation (PhysicalGameObj *initiator, const DynamicVectorClass<PhysicalGameObj *> &available_orator_list, DynamicVectorClass<PhysicalGameObj *> &orator_list);
static ConversationClass * Find_Conversation (const char *conversation_name);
static ConversationClass * Find_Conversation (int conversation_id);
static ActiveConversationClass * Find_Active_Conversation (int id);
static void Reset_All_Other_Conversations (ActiveConversationClass *active_conversation);
static bool Is_Key_Conversation_Playing (void);
static int Get_Active_Conversation_Count (void) { return ActiveConversationList.Count (); }
static void Think (void);
//
// State access
//
static void Reset (void);
static void Reset_Conversations (int category_index, bool reset_start_id = false);
static void Reset_Active_Conversations (void);
static void Set_Category_To_Save (CATEGORY category_index) { SaveCategoryID = category_index; }
//
// EmotIcon control
//
static bool Are_Emot_Icons_Displayed (void) { return DisplayEmotIcons; }
static void Display_Emot_Icons (bool onoff) { DisplayEmotIcons = onoff; }
//
// From SaveLoadSubSystemClass
//
uint32 Chunk_ID (void) const;
protected:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
static void Build_Buddy_List (PhysicalGameObj *orator, DynamicVectorClass<PhysicalGameObj *> &list, bool include_soldier);
static bool Test_Conversation (PhysicalGameObj *initiator, ConversationClass *conversation, DynamicVectorClass<PhysicalGameObj *> &buddy_list, bool force = false);
static bool Test_Orator (ConversationClass *conversation, OratorClass *orator, PhysicalGameObj *game_obj);
//
// From SaveLoadSubSystemClass
//
bool Contains_Data (void) const { return true; }
const char * Name (void) const { return "ConversationMgrClass"; }
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
void Load_Variables (ChunkLoadClass &cload);
bool Load_Conversations (ChunkLoadClass &cload, int category_id);
private:
////////////////////////////////////////////////////////////////
// Private member data
////////////////////////////////////////////////////////////////
static CONVERSATION_LIST ConversationList[CATEGORY_MAX];
static ACTIVE_CONVERSATION_LIST ActiveConversationList;
static int NextActiveConversationID;
static int NextGlobalConversationID;
static int NextLevelConversationID;
static CATEGORY SaveCategoryID;
static bool DisplayEmotIcons;
};
////////////////////////////////////////////////////////////////
// Get_Conversation_Count
////////////////////////////////////////////////////////////////
inline int
ConversationMgrClass::Get_Conversation_Count (void)
{
int total = 0;
for (int index = 0; index < CATEGORY_MAX; index ++) {
total += ConversationList[index].Count ();
}
return total;
}
////////////////////////////////////////////////////////////////
// Peek_Conversation
////////////////////////////////////////////////////////////////
inline ConversationClass *
ConversationMgrClass::Peek_Conversation (int index_to_find)
{
ConversationClass *conversation = NULL;
//
// Loop over all the categories
//
for (int index = 0; index < CATEGORY_MAX; index ++) {
//
// Is the specified index inside of this category?
//
int curr_count = ConversationList[index].Count ();
if (index_to_find < curr_count) {
//
// Index into this category to find the conversation
//
conversation = ConversationList[index][index_to_find];
break;
} else {
//
// Adjust the specified index to be within the range
// of the next category
//
index_to_find -= curr_count;
}
}
return conversation;
}
#endif //__CONVERSATION_MGR_H

View File

@@ -0,0 +1,177 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/conversationremark.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/25/01 3:09p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "conversationremark.h"
#include "chunkio.h"
////////////////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////////////////
enum
{
CHUNKID_BASE_CLASS = 0x01250306,
CHUNKID_VARIABLES,
};
enum
{
VARID_ORATORID = 0,
VARID_TEXTID,
VARID_ANIMATION_NAME
};
////////////////////////////////////////////////////////////////
//
// ConversationRemarkClass
//
////////////////////////////////////////////////////////////////
ConversationRemarkClass::ConversationRemarkClass (void) :
OratorID (0),
TextID (0)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// ConversationRemarkClass
//
////////////////////////////////////////////////////////////////
ConversationRemarkClass::ConversationRemarkClass (const ConversationRemarkClass &src) :
OratorID (0),
TextID (0)
{
(*this) = src;
return ;
}
////////////////////////////////////////////////////////////////
//
// ~ConversationRemarkClass
//
////////////////////////////////////////////////////////////////
ConversationRemarkClass::~ConversationRemarkClass (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// operator=
//
////////////////////////////////////////////////////////////////
const ConversationRemarkClass &
ConversationRemarkClass::operator= (const ConversationRemarkClass &src)
{
OratorID = src.OratorID;
TextID = src.TextID;
AnimationName = src.AnimationName;
return *this;
}
////////////////////////////////////////////////////////////////
//
// Save
//
////////////////////////////////////////////////////////////////
bool
ConversationRemarkClass::Save (ChunkSaveClass &csave)
{
csave.Begin_Chunk (CHUNKID_VARIABLES);
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_ANIMATION_NAME, AnimationName);
WRITE_MICRO_CHUNK (csave, VARID_ORATORID, OratorID);
WRITE_MICRO_CHUNK (csave, VARID_TEXTID, TextID);
csave.End_Chunk ();
return true;
}
////////////////////////////////////////////////////////////////
//
// Load
//
////////////////////////////////////////////////////////////////
bool
ConversationRemarkClass::Load (ChunkLoadClass &cload)
{
while (cload.Open_Chunk ()) {
switch (cload.Cur_Chunk_ID ()) {
case CHUNKID_VARIABLES:
Load_Variables (cload);
break;
}
cload.Close_Chunk ();
}
return true;
}
///////////////////////////////////////////////////////////////////////
//
// Load_Variables
//
///////////////////////////////////////////////////////////////////////
void
ConversationRemarkClass::Load_Variables (ChunkLoadClass &cload)
{
//
// Loop through all the microchunks that define the variables
//
while (cload.Open_Micro_Chunk ()) {
switch (cload.Cur_Micro_Chunk_ID ()) {
READ_MICRO_CHUNK_WWSTRING (cload, VARID_ANIMATION_NAME, AnimationName);
READ_MICRO_CHUNK (cload, VARID_ORATORID, OratorID);
READ_MICRO_CHUNK (cload, VARID_TEXTID, TextID);
}
cload.Close_Micro_Chunk ();
}
return ;
}

View File

@@ -0,0 +1,119 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/conversationremark.h $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/31/01 11:11a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef __CONVERSATIONREMARK_H
#define __CONVERSATIONREMARK_H
#include "wwstring.h"
#include "simplevec.h"
#include "refcount.h"
#include "orator.h"
#include "soldier.h"
////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////
class ChunkSaveClass;
class ChunkLoadClass;
////////////////////////////////////////////////////////////////
//
// ConversationRemarkClass
//
////////////////////////////////////////////////////////////////
class ConversationRemarkClass
{
public:
////////////////////////////////////////////////////////////////
// Public constructors/destructors
////////////////////////////////////////////////////////////////
ConversationRemarkClass (void);
ConversationRemarkClass (const ConversationRemarkClass &src);
virtual ~ConversationRemarkClass (void);
////////////////////////////////////////////////////////////////
// Public operators
////////////////////////////////////////////////////////////////
const ConversationRemarkClass & operator= (const ConversationRemarkClass &src);
bool operator== (const ConversationRemarkClass &src) { return (TextID == src.TextID) && (OratorID == src.OratorID); }
bool operator!= (const ConversationRemarkClass &src) { return (TextID != src.TextID) || (OratorID != src.OratorID); }
////////////////////////////////////////////////////////////////
// Public methods
////////////////////////////////////////////////////////////////
//
// Save/Load methods
//
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
//
// Accessors
//
int Get_Orator_ID (void) const { return OratorID; }
void Set_Orator_ID (int id) { OratorID = id; }
int Get_Text_ID (void) const { return TextID; }
void Set_Text_ID (int id) { TextID = id; }
const StringClass & Get_Animation_Name (void) const { return AnimationName; }
void Set_Animation_Name (const char *name) { AnimationName = name; }
protected:
////////////////////////////////////////////////////////////////
// Protected methods
////////////////////////////////////////////////////////////////
void Load_Variables (ChunkLoadClass &cload);
////////////////////////////////////////////////////////////////
// Protected data types
////////////////////////////////////////////////////////////////
int OratorID;
int TextID;
StringClass AnimationName;
};
#endif //__CONVERSATIONREMARK_H

293
Code/Combat/cover.cpp Normal file
View File

@@ -0,0 +1,293 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/cover.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 4/17/01 11:44a $*
* *
* $Revision:: 7 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "cover.h"
#include "debug.h"
#include "chunkio.h"
#include "saveload.h"
#include "crandom.h"
/*
**
*/
DynamicVectorClass<CoverEntryClass *> CoverManager::CoverPositions;
/*
**
*/
void CoverManager::Init( void )
{
}
void CoverManager::Shutdown( void )
{
Remove_All();
}
/*
**
*/
enum {
CHUNKID_COVER_ENTRY = 524001203,
};
bool CoverManager::Save( ChunkSaveClass & csave )
{
for ( int index = 0; index < CoverPositions.Count(); index++ ) {
csave.Begin_Chunk( CHUNKID_COVER_ENTRY );
CoverPositions[index]->Save( csave );
csave.End_Chunk();
}
return true;
}
bool CoverManager::Load( ChunkLoadClass & cload )
{
WWASSERT( CoverPositions.Count() == 0 );
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_COVER_ENTRY:
{
CoverEntryClass * cover = NEW_REF( CoverEntryClass, () );
cover->Load( cload );
Add_Entry( cover );
cover->Release_Ref();
break;
}
default:
Debug_Say(( "Unrecognized CombatSaveLoad chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
/*
**
*/
void CoverManager::Add_Entry( CoverEntryClass * entry )
{
if ( entry != NULL ) {
entry->Add_Ref();
CoverPositions.Add( entry );
}
}
void CoverManager::Remove_Entry( CoverEntryClass * entry )
{
if ( entry != NULL ) {
CoverPositions.Delete( entry );
entry->Release_Ref();
}
}
void CoverManager::Remove_All( void )
{
while ( CoverPositions.Count() ) {
CoverPositions[0]->Release_Ref();
CoverPositions.Delete( 0 );
}
}
/*
**
*/
CoverEntryClass * CoverManager::Request_Cover( const Vector3 & cur_pos, const Vector3 & danger, float max_dist )
{
// Find a cover spot, not in use, within max_dist, that blocks from danger
int best_index = -1;
int best_dist = max_dist;
for ( int index = 0; index < CoverPositions.Count(); index++ ) {
CoverEntryClass * cover = CoverPositions[ index ];
if ( cover->Get_In_Use() ) {
continue; // Already in use
}
Vector3 range_vector = cur_pos - cover->Get_Transform().Get_Translation();
float dist = range_vector.Length();
if ( dist > max_dist ) {
continue; // Too far away
}
if ( !Is_Cover_Safe( cover, danger ) ) {
continue; // Does not provide cover
}
if ( best_dist < dist ) {
continue; // Already ahave a better one
}
if ( best_index != -1 ) {
if ( FreeRandom.Get_Int() & 1 ) {
continue;
}
}
best_index = index;
best_dist = dist;
}
if ( best_index != -1 ) {
// Debug_Say(( "Chose cover # %d\n", best_index ));
CoverPositions[ best_index ]->Set_In_Use( true );
return CoverPositions[best_index];
}
return NULL;
}
void CoverManager::Release_Cover( CoverEntryClass * entry )
{
WWASSERT( entry->Get_In_Use() );
entry->Set_In_Use( false );
}
bool CoverManager::Is_Cover_Safe( CoverEntryClass * cover, const Vector3 & danger )
{
WWASSERT( cover );
Vector3 danger_local;
Matrix3D::Inverse_Transform_Vector( cover->Get_Transform(), danger, &danger_local );
if ( danger_local.X < WWMath::Fabs(danger_local.Y) ) {
return false;
}
return true;
}
/*
**
*/
enum {
CHUNKID_VARIABLES = 524001323,
MICROCHUNKID_TRANSFORM = 1,
MICROCHUNKID_CROUCH,
MICROCHUNKID_IN_USE,
MICROCHUNKID_ATTACK_POSITION,
MICROCHUNKID_REMAP_PTR,
};
bool CoverEntryClass::Save( ChunkSaveClass & csave )
{
CoverEntryClass * me = this;
csave.Begin_Chunk( CHUNKID_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_TRANSFORM, Transform );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_CROUCH, Crouch );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_IN_USE, InUse );
for ( int i = 0; i < AttackPositionList.Count(); i++ ) {
Vector3 pos = AttackPositionList[i];
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ATTACK_POSITION, pos );
}
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_REMAP_PTR, me );
csave.End_Chunk();
return true;
}
bool CoverEntryClass::Load( ChunkLoadClass & cload )
{
WWASSERT( AttackPositionList.Count() == 0 );
CoverEntryClass * old_me = NULL;
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_TRANSFORM, Transform );
READ_MICRO_CHUNK( cload, MICROCHUNKID_CROUCH, Crouch );
READ_MICRO_CHUNK( cload, MICROCHUNKID_IN_USE, InUse );
case MICROCHUNKID_ATTACK_POSITION:
{
Vector3 pos;
cload.Read(&pos,sizeof(pos));
AttackPositionList.Add( pos );
break;
}
READ_MICRO_CHUNK( cload, MICROCHUNKID_REMAP_PTR, old_me );
default:
Debug_Say(( "Unrecognized CoverEntry Variable chunkID %d\n", cload.Cur_Micro_Chunk_ID() ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(( "Unrecognized CoverEntry chunkID\n" ));
break;
}
cload.Close_Chunk();
}
// publish my remap pair
WWASSERT(old_me != NULL);
if (old_me != NULL) {
SaveLoadSystemClass::Register_Pointer( old_me, this );
}
return true;
}
Vector3 CoverEntryClass::Get_Attack_Position( Vector3 & enemy_pos )
{
// Find a cover position that will allow attack of enemy_pos (not yet)
// default to cover spot
Vector3 pos = Transform.Get_Translation();
if ( AttackPositionList.Count() ) {
int index = FreeRandom.Get_Int( AttackPositionList.Count() );
pos = AttackPositionList[index];
}
return pos;
}

122
Code/Combat/cover.h Normal file
View File

@@ -0,0 +1,122 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/cover.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 9/12/00 5:56p $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef COVER_H
#define COVER_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef MATRIX3D_H
#include "matrix3d.h"
#endif
#ifndef VECTOR_H
#include "vector.h"
#endif
#ifndef REFCOUNT_H
#include "refcount.h"
#endif
class ChunkSaveClass;
class ChunkLoadClass;
/*
**
*/
typedef DynamicVectorClass<Vector3> AttackPositionListType;
class CoverEntryClass : public RefCountClass {
public:
CoverEntryClass( void ) : Transform(1), Crouch( false ), InUse( false ) {}
~CoverEntryClass( void ) {}
bool Save( ChunkSaveClass & csave );
bool Load( ChunkLoadClass & cload );
void Set_Transform( const Matrix3D & tm ) { Transform = tm; }
const Matrix3D & Get_Transform( void ) { return Transform; }
AttackPositionListType * Get_Attack_Position_List( void ) { return &AttackPositionList; }
Vector3 Get_Attack_Position( Vector3 & enemy_pos );
void Set_Crouch( bool crouch ) { Crouch = crouch; }
bool Get_Crouch( void ) { return Crouch; }
void Set_In_Use( bool in_use ) { InUse = in_use; }
bool Get_In_Use( void ) { return InUse; }
private:
Matrix3D Transform;
AttackPositionListType AttackPositionList;
bool Crouch;
bool InUse;
};
/*
**
*/
class CoverManager {
public:
static void Init( void );
static void Shutdown( void );
static bool Save( ChunkSaveClass & csave );
static bool Load( ChunkLoadClass & cload );
static void Add_Entry( CoverEntryClass * entry );
static void Remove_Entry( CoverEntryClass * entry );
static void Remove_All( void );
static CoverEntryClass * Request_Cover( const Vector3 & cur_pos, const Vector3 & danger, float max_dist );
static void Release_Cover( CoverEntryClass * entry );
static bool Is_Cover_Safe( CoverEntryClass * cover, const Vector3 & danger );
private:
static DynamicVectorClass<CoverEntryClass *> CoverPositions;
};
#endif // COVER_H

40
Code/Combat/crandom.cpp Normal file
View File

@@ -0,0 +1,40 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Shell/crandom.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 5/29/98 9:48a $*
* *
* $Revision:: 1 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "crandom.h"
CRandom FreeRandom;

123
Code/Combat/crandom.h Normal file
View File

@@ -0,0 +1,123 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/crandom.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 5/09/01 3:48p $*
* *
* $Revision:: 2 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef CRANDOM_H
#define CRANDOM_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef RANDOM_H
#include "random.h"
#endif
#ifndef WWDEBUG_H
#include "wwdebug.h"
#endif
#define CRANDOM_FLOAT_RANGE 0x1000
/*
** Commando Random Numbers Manager
*/
class CRandom {
public:
CRandom( void ) {}
~CRandom( void ) {}
// Get a random 32 bit long integer
inline int Get_Int( void ) { return Generator(); }
// Get a random 32 bit long integer less than max
inline int Get_Int( int max ) { WWASSERT( max > 0 ); return (Generator() & 0x7FFFFFFF) % max; }
// Get a random 32 bit long between min and max (both inclusive)
inline int Get_Int( int min, int max );
// Get a random float between 0 and 1 (both inclusive)
inline float Get_Float( void ) { return (float)(Get_Int( CRANDOM_FLOAT_RANGE+1 )) / (float)CRANDOM_FLOAT_RANGE; }
// Get a random float between 0 and max (both inclusive)
inline float Get_Float( float max ) { return Get_Float() * max; }
// Get a random float between min and max (both inclusive)
inline float Get_Float( float min, float max );
private:
Random2Class Generator;
};
// Get a random 32 bit long between min and max (both inclusive)
inline int CRandom::Get_Int( int min, int max )
{
// make sure we have a valid range
if ( min > max ) {
int temp = min;
min = max;
max = temp;
}
// Get one
return Get_Int( max - min ) + min;
}
// Get a random float between min and max (both inclusive)
inline float CRandom::Get_Float( float min, float max )
{
// make sure we have a valid range
if ( min > max ) {
float temp = min;
min = max;
max = temp;
}
// Get one
return Get_Float() * ( max - min ) + min;
}
/*
** A free random number generator. This can be used for any numbers not required to
** be synced between other computers. Good for simple visual and sound effects.
*/
extern CRandom FreeRandom;
#endif

View File

@@ -0,0 +1,191 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/csdamageevent.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 11/24/01 10:36a $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "csdamageevent.h"
#include <stdio.h>
#include <stdlib.h>
#include "networkobjectfactory.h"
#include "combat.h"
#include "networkobjectmgr.h"
#include "gameobjmanager.h"
#include "apppackettypes.h"
#include "damage.h"
#include "armedgameobj.h"
#include "debug.h"
DECLARE_NETWORKOBJECT_FACTORY(cCsDamageEvent, NETCLASSID_CSDAMAGEEVENT);
//
// Class statics
//
bool cCsDamageEvent::AreClientsTrusted = true;
//-----------------------------------------------------------------------------
cCsDamageEvent::cCsDamageEvent(void)
{
SenderId = 0;
DamagerGOID = 0;
DamageeGOID = 0;
Damage = 0;
Warhead = 0;
Set_App_Packet_Type(APPPACKETTYPE_CSDAMAGEEVENT);
Set_Unreliable_Override(true);
}
//-----------------------------------------------------------------------------
void
cCsDamageEvent::Init
(
int damager_go_id,
int damagee_go_id,
float damage,
int warhead
)
{
WWASSERT(CombatManager::I_Am_Only_Client());
WWASSERT(AreClientsTrusted);
SenderId = CombatManager::Get_My_Id();
DamagerGOID = damager_go_id;
DamageeGOID = damagee_go_id;
Damage = damage;
Warhead = warhead;
Set_Network_ID(NetworkObjectMgrClass::Get_New_Client_ID());
Set_Object_Dirty_Bit(0, BIT_CREATION, true);
}
//-----------------------------------------------------------------------------
void
cCsDamageEvent::Act
(
void
)
{
WWASSERT(CombatManager::I_Am_Server());
if (AreClientsTrusted)
{
// process the member data here. Include sanity checks.
// Find the gameobj with the damagee id
PhysicalGameObj * obj = GameObjManager::Find_PhysicalGameObj( DamageeGOID );
if ( obj ) {
// Make an offense object
PhysicalGameObj * damager = GameObjManager::Find_PhysicalGameObj( DamagerGOID );
if ( damager != NULL && damager->As_ArmedGameObj() != NULL ) {
OffenseObjectClass offense( Damage, Warhead, damager->As_ArmedGameObj());
// obj->Get_Defense_Object()->Do_Damage( offense );
// We need to use apply damage extended in order to allow things to die.
offense.ForceServerDamage = true;
#if 0
// guess at the damage direction
Vector3 direction;
Vector3 pos;
damager->Get_Position( &pos );
obj->Get_Position( &direction );
direction -= pos;
direction.Normalize();
obj->Apply_Damage_Extended( offense, 1.0f, direction );
#else
obj->Apply_Damage_Extended( offense );
#endif
// Debug_Say(( "Applying Client damage of %f from %d to %d\n", Damage, DamagerGOID, DamageeGOID ));
} else {
// Debug_Say(( "Error: Client damage Damagee %d not found\n", DamageeGOID ));
}
} else {
// Debug_Say(( "Error: Client damage Damagee %d not found\n", DamageeGOID ));
}
} else {
Debug_Say(( "Error: Receiving Client damage when clients are not trusted\n" ));
}
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cCsDamageEvent::Export_Creation
(
BitStreamClass & packet
)
{
WWASSERT(CombatManager::I_Am_Only_Client());
NetworkObjectClass::Export_Creation(packet);
WWASSERT(SenderId > 0);
packet.Add(SenderId);
packet.Add(DamagerGOID);
packet.Add(DamageeGOID);
packet.Add(Damage);
packet.Add(Warhead);
Set_Delete_Pending();
}
//-----------------------------------------------------------------------------
void
cCsDamageEvent::Import_Creation
(
BitStreamClass & packet
)
{
WWASSERT(CombatManager::I_Am_Server());
NetworkObjectClass::Import_Creation(packet);
packet.Get(SenderId);
packet.Get(DamagerGOID);
packet.Get(DamageeGOID);
packet.Get(Damage);
packet.Get(Warhead);
WWASSERT(SenderId > 0);
Act();
}

View File

@@ -0,0 +1,78 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/csdamageevent.h $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 11/24/01 10:34a $*
* *
* $Revision:: 3 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __CSDAMAGEEVENT_H__
#define __CSDAMAGEEVENT_H__
#include "networkobject.h"
#include "netclassids.h"
//-----------------------------------------------------------------------------
//
// A C->S reliably mirrored event for client authoritative damage
//
class cCsDamageEvent : public NetworkObjectClass
{
public:
cCsDamageEvent(void);
void Init( int damager_go_id, int damagee_go_id, float damage, int warhead );
virtual void Export_Creation(BitStreamClass &packet);
virtual void Import_Creation(BitStreamClass &packet);
virtual uint32 Get_Network_Class_ID(void) const {return NETCLASSID_CSDAMAGEEVENT;}
virtual void Delete(void) {delete this;}
static void Set_Are_Clients_Trusted(bool flag) {AreClientsTrusted = flag;}
static bool Get_Are_Clients_Trusted(void) {return AreClientsTrusted;}
private:
virtual void Act(void);
int SenderId;
int DamagerGOID;
int DamageeGOID;
float Damage;
int Warhead;
static bool AreClientsTrusted;
};
//-----------------------------------------------------------------------------
#endif // __CSDAMAGEEVENT_H__

1411
Code/Combat/damage.cpp Normal file

File diff suppressed because it is too large Load Diff

349
Code/Combat/damage.h Normal file
View File

@@ -0,0 +1,349 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/damage.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 2/13/02 6:06p $*
* *
* $Revision:: 52 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef DAMAGE_H
#define DAMAGE_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef GAMEOBJREF_H
#include "gameobjref.h"
#endif
#ifndef _DATASAFE_H
#include "..\commando\datasafe.h"
#endif //_DATASAFE_H
#include "editable.h"
/*
**
*/
typedef unsigned int ArmorType;
typedef unsigned int WarheadType;
typedef safe_unsigned_int SafeArmorType;
typedef safe_unsigned_int SafeWarheadType;
class ArmedGameObj;
class DamageableGameObj;
class BitStreamClass;
class ChunkSaveClass;
class ChunkLoadClass;
/*
**
*/
class ArmorWarheadManager {
public:
// Build
static void Init( void );
static void Shutdown( void );
static bool Is_Armor_Soft( ArmorType armor );
// Type additions/access
static int Get_Num_Armor_Types( void );
static ArmorType Get_Armor_Type( const char *name );
static const char * Get_Armor_Name( ArmorType type );
static int Get_Num_Warhead_Types( void );
static WarheadType Get_Warhead_Type( const char *name );
static const char * Get_Warhead_Name( WarheadType type );
// Save IDs
static int Get_Armor_Save_ID( ArmorType type );
static ArmorType Find_Armor_Save_ID( int id );
static int Get_Warhead_Save_ID( WarheadType type );
static ArmorType Find_Warhead_Save_ID( int id );
// Damage Multiplier Settings
// static void Set_Damage_Multiplier( ArmorType armor, WarheadType warhead, float multiplier );
static float Get_Damage_Multiplier( ArmorType armor, WarheadType warhead );
// Shield Absorbsion Settings
// static void Set_Shield_Absorbsion( ArmorType armor, WarheadType warhead, float percent );
static float Get_Shield_Absorbsion( ArmorType armor, WarheadType warhead );
typedef enum {
SPECIAL_DAMAGE_TYPE_NONE,
SPECIAL_DAMAGE_TYPE_FIRE,
SPECIAL_DAMAGE_TYPE_CHEM,
SPECIAL_DAMAGE_TYPE_ELECTRIC,
SPECIAL_DAMAGE_TYPE_CNC_FIRE,
SPECIAL_DAMAGE_TYPE_CNC_CHEM,
SPECIAL_DAMAGE_TYPE_SUPER_FIRE,
NUM_SPECIAL_DAMAGE_TYPES, // Keep synced with ouch_types
} SpecialDamageType;
static SpecialDamageType Get_Special_Damage_Type( WarheadType type );
static float Get_Special_Damage_Probability( WarheadType type );
static WarheadType Get_Special_Damage_Warhead( SpecialDamageType type );
static float Get_Special_Damage_Duration( SpecialDamageType type );
static float Get_Special_Damage_Scale( SpecialDamageType type );
static const char * Get_Special_Damage_Explosion( SpecialDamageType type );
static float Get_Visceroid_Probability( WarheadType type );
static bool Is_Skin_Impervious( SpecialDamageType type, ArmorType skin );
private:
static safe_float *Multipliers;
static safe_float *Absorbsion;
};
/*
**
*/
class OffenseObjectClass {
#define DEFAULT_DAMAGE 1.0f
public:
// Constructors & Destructor
OffenseObjectClass( float damage = DEFAULT_DAMAGE, WarheadType warhead = 0, ArmedGameObj *owner = NULL ) : \
Damage( damage ), Warhead( warhead ), ForceServerDamage( false ), EnableClientDamage( false ) { Set_Owner( owner ); }
OffenseObjectClass( const OffenseObjectClass & base );
~OffenseObjectClass() { Set_Owner( NULL ); };
bool Save( ChunkSaveClass & csave );
bool Load( ChunkLoadClass & cload );
// Offensive Damage Rating (ODR)
void Set_Damage( float damage ) { Damage = damage; }
float Get_Damage( void ) const { return Damage; }
// Warhead
void Set_Warhead( WarheadType warhead ) { Warhead = warhead; }
WarheadType Get_Warhead( void ) const { return Warhead; }
// Owner
void Set_Owner( ArmedGameObj *owner ) { Owner = (ScriptableGameObj *)owner; }
ArmedGameObj *Get_Owner( void ) const { return (ArmedGameObj *)Owner.Get_Ptr(); }
// Special flag to force servers to apply damage. Only needed for client authoratative damage
bool ForceServerDamage;
// Special flag to disable client damage. So it only works for bullets. Only needed for client authoratative damage
bool EnableClientDamage;
private:
// safe_float Damage;
float Damage;
WarheadType Warhead;
GameObjReference Owner;
};
/**
** DefenseObjectClass
** This is a class that is meant to be embedded inside a game object and handles all health/damage
** tracking. Also, the definition for the game object which embeds this object can embed a
** DefenseObjectDefClass to automatically get all of the settings.
**
*/
class DefenseObjectDefClass;
class DefenseObjectClass {
#define DEFAULT_HEALTH 100.0f
public:
// Constructors & Destructor
DefenseObjectClass( float health = DEFAULT_HEALTH, ArmorType skin = 0 ) :
Health( health ), HealthMax( health ), Skin( skin ), ShieldStrength( 0 ), ShieldStrengthMax( 0 ), ShieldType( 0 ), CanObjectDie( true ) {};//,
//LastSentHealth( -1 ), LastSentSkin( -1 ), LastSentShieldStrength( -1 ), LastSentShieldType( -1 ) {};
~DefenseObjectClass() {};
// DefenseObjects now have a pointer to their cooresponing GameObj to report damage and scoring to the PlayerData
void Init( const DefenseObjectDefClass & def, DamageableGameObj * owner);
bool Save( ChunkSaveClass & csave );
bool Load( ChunkLoadClass & cload );
// Owner
void Set_Owner( DamageableGameObj *owner ) { Owner = (ScriptableGameObj *)owner; }
DamageableGameObj *Get_Owner( void ) const { return (DamageableGameObj *)Owner.Get_Ptr(); }
// Skin
void Set_Skin( ArmorType skin ) { Skin = skin; }
ArmorType Get_Skin( void ) const { return Skin; }
enum {MAX_MAX_HEALTH = 2000};//500};
enum {MAX_MAX_SHIELD_STRENGTH = 2000};//500};
// Health
void Set_Health(float health);
void Add_Health(float add_health);
float Get_Health(void) const ;
void Set_Health_Max(float health);
float Get_Health_Max(void) const ;
// Shield
void Set_Shield_Strength(float str);
void Add_Shield_Strength(float str);
float Get_Shield_Strength(void) const ;
void Set_Shield_Strength_Max(float str);
float Get_Shield_Strength_Max(void) const ;
void Set_Shield_Type( ArmorType type );
unsigned long Get_Shield_Type( void ) const { return ShieldType; }
// Apply Damage
float Apply_Damage( const OffenseObjectClass & offense, float scale = 1.0f, int alternate_skin = -1 );
float Do_Damage( const OffenseObjectClass & offense, float scale = 1.0f, int alternate_skin = -1 );
// Request_Damage
void Request_Damage( const OffenseObjectClass & offense, float scale = 1.0f );
// Will an apply damage call actually repair?
bool Is_Repair( const OffenseObjectClass & offense, float scale = 1.0f );
// Would an apply damage call actually damage?
bool Would_Damage( const OffenseObjectClass & offense, float scale = 1.0f );
bool Is_Soft( void );
void Set_Can_Object_Die( bool onoff ) { CanObjectDie = onoff; }
// State import/export
virtual void Import( BitStreamClass & packet );
virtual void Export( BitStreamClass & packet );
static void Set_Precision(void);
float Get_Damage_Points(void) const { return DamagePoints; }
float Get_Death_Points(void) const { return DeathPoints; }
#ifdef WWDEBUG
static bool Toggle_One_Shot_Kills(void) { OneShotKills = !OneShotKills; return OneShotKills; }
#endif // _WWDEBUG
private:
safe_float Health;
safe_float HealthMax;
SafeArmorType Skin;
safe_float ShieldStrength;
safe_float ShieldStrengthMax;
SafeArmorType ShieldType;
safe_float DamagePoints;
safe_float DeathPoints;
bool CanObjectDie;
GameObjReference Owner;
void Mark_Owner_Dirty( void );
#ifdef WWDEBUG
static bool OneShotKills;
#endif // _WWDEBUG
};
/**
** DefenseObjectDefClass
** This class is meant to be a component of a definition class for a game or physics
** object which contains a DefenseObject. Use the associated macro to make all of
** the member variables editable in your class.
*/
class DefenseObjectDefClass
{
public:
DefenseObjectDefClass(void);
~DefenseObjectDefClass(void);
bool Save(ChunkSaveClass &csave);
bool Load(ChunkLoadClass &cload);
public:
safe_float Health;
safe_float HealthMax;
SafeArmorType Skin;
safe_float ShieldStrength;
safe_float ShieldStrengthMax;
SafeArmorType ShieldType;
safe_float DamagePoints;
safe_float DeathPoints;
};
/*
** Use this macro to make all of the member variables in a DefenseObjectDefClass editable.
** The first parameter to the macro is the type-name of your class (e.g. PhysicalGameObjectDef) and
** the second parameter is the name of the member variable which is the defense object def.
*/
#ifdef PARAM_EDITING_ON
#define DEFENSEOBJECTDEF_EDITABLE_PARAMS( class_name, member_name ) \
\
int param_counter; \
NAMED_EDITABLE_PARAM( class_name, ParameterClass::TYPE_FLOAT, member_name ## .Health, "Health"); \
NAMED_EDITABLE_PARAM( class_name, ParameterClass::TYPE_FLOAT, member_name ## .HealthMax, "HealthMax"); \
\
EnumParameterClass * skin_param = new EnumParameterClass( (int*)& member_name ## .Skin ); \
skin_param->Set_Name("Skin"); \
for ( param_counter = 0; param_counter < ArmorWarheadManager::Get_Num_Armor_Types(); param_counter++ ) { \
skin_param->Add_Value(ArmorWarheadManager::Get_Armor_Name(param_counter), param_counter); \
} \
GENERIC_EDITABLE_PARAM(class_name,skin_param) \
\
NAMED_EDITABLE_PARAM( class_name, ParameterClass::TYPE_FLOAT, member_name ## .ShieldStrength, "ShieldStrength" ); \
NAMED_EDITABLE_PARAM( class_name, ParameterClass::TYPE_FLOAT, member_name ## .ShieldStrengthMax, "ShieldStrengthMax" ); \
\
EnumParameterClass * shield_param = new EnumParameterClass( (int *)& member_name ## .ShieldType ); \
shield_param->Set_Name ("Shield Type"); \
for ( param_counter = 0; param_counter < ArmorWarheadManager::Get_Num_Armor_Types(); param_counter++ ) { \
shield_param->Add_Value(ArmorWarheadManager::Get_Armor_Name(param_counter),param_counter); \
} \
GENERIC_EDITABLE_PARAM(class_name,shield_param) \
\
NAMED_EDITABLE_PARAM( class_name, ParameterClass::TYPE_FLOAT, member_name ## .DamagePoints, "DamagePoints"); \
NAMED_EDITABLE_PARAM( class_name, ParameterClass::TYPE_FLOAT, member_name ## .DeathPoints, "DeathPoints");
#else
#define DEFENSEOBJECTDEF_EDITABLE_PARAMS( class_name, member_name )
#endif
#endif // DAMAGE_H

View File

@@ -0,0 +1,457 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/damageablegameobj.cpp $*
* *
* $Author:: Tom_s $*
* *
* $Modtime:: 12/18/01 3:02p $*
* *
* $Revision:: 19 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "damageablegameobj.h"
#include "debug.h"
#include "armedgameobj.h"
#include "playertype.h"
#include "colors.h"
/*
** DamageableGameObjDef - Defintion class for a DamageableGameObj
*/
DamageableGameObjDef::DamageableGameObjDef( void ) :
TranslatedNameID( 0 ),
EncyclopediaType( EncyclopediaMgrClass::TYPE_UNKNOWN ),
EncyclopediaID( 0 ),
NotTargetable( false ),
DefaultPlayerType( PLAYERTYPE_NEUTRAL )
{
DEFENSEOBJECTDEF_EDITABLE_PARAMS( DamageableGameObjDef, DefenseObjectDef );
EDITABLE_PARAM( DamageableGameObjDef, ParameterClass::TYPE_STRINGSDB_ID, TranslatedNameID );
FILENAME_PARAM( DamageableGameObjDef, InfoIconTextureFilename, "InfoIconTextureFilename", ".TGA" );
#ifdef PARAM_EDITING_ON
EnumParameterClass *param = new EnumParameterClass( (int *)&EncyclopediaType );
param->Set_Name( "Encyclopedia Type" );
param->Add_Value( "<NA>", 0 );
param->Add_Value( "Character", EncyclopediaMgrClass::TYPE_CHARACTER );
param->Add_Value( "Weapon", EncyclopediaMgrClass::TYPE_WEAPON );
param->Add_Value( "Vehicle", EncyclopediaMgrClass::TYPE_VEHICLE );
param->Add_Value( "Building", EncyclopediaMgrClass::TYPE_BUILDING );
GENERIC_EDITABLE_PARAM( DamageableGameObjDef, param )
param = new EnumParameterClass( &DefaultPlayerType );
param->Set_Name ("PlayerType");
param->Add_Value ( "Mutant", PLAYERTYPE_MUTANT );
param->Add_Value ( "Unteamed", PLAYERTYPE_NEUTRAL );
param->Add_Value ( "Renegade", PLAYERTYPE_RENEGADE );
param->Add_Value ( "Nod", PLAYERTYPE_NOD );
param->Add_Value ( "GDI", PLAYERTYPE_GDI );
GENERIC_EDITABLE_PARAM(DamageableGameObjDef,param)
#endif
EDITABLE_PARAM( DamageableGameObjDef, ParameterClass::TYPE_INT, EncyclopediaID );
EDITABLE_PARAM( DamageableGameObjDef, ParameterClass::TYPE_BOOL, NotTargetable );
return ;
}
enum {
CHUNKID_DEF_PARENT = 207011205,
CHUNKID_DEF_VARIABLES,
CHUNKID_DEF_DEFENSEOBJECTDEF,
MICROCHUNKID_DEF_TRANSLATED_NAME_ID = 1,
MICROCHUNKID_DEF_INFO_ICON_TEXTURE_FILENAME,
MICROCHUNKID_DEF_ENCY_TYPE,
MICROCHUNKID_DEF_ENCY_ID,
MICROCHUNKID_DEF_NOT_TARGETABLE,
MICROCHUNKID_DEF_DEFAULT_PLAYER_TYPE,
};
bool DamageableGameObjDef::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_DEF_PARENT );
ScriptableGameObjDef::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_TRANSLATED_NAME_ID, TranslatedNameID );
WRITE_MICRO_CHUNK_WWSTRING( csave, MICROCHUNKID_DEF_INFO_ICON_TEXTURE_FILENAME, InfoIconTextureFilename );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_ENCY_TYPE, EncyclopediaType );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_ENCY_ID, EncyclopediaID );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_NOT_TARGETABLE, NotTargetable );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_DEFAULT_PLAYER_TYPE, DefaultPlayerType );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DEF_DEFENSEOBJECTDEF );
DefenseObjectDef.Save(csave);
csave.End_Chunk();
return true;
}
bool DamageableGameObjDef::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_DEF_PARENT:
ScriptableGameObjDef::Load( cload );
break;
case CHUNKID_DEF_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_TRANSLATED_NAME_ID, TranslatedNameID );
READ_MICRO_CHUNK_WWSTRING( cload, MICROCHUNKID_DEF_INFO_ICON_TEXTURE_FILENAME, InfoIconTextureFilename );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_ENCY_TYPE, EncyclopediaType );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_ENCY_ID, EncyclopediaID );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_NOT_TARGETABLE, NotTargetable );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_DEFAULT_PLAYER_TYPE, DefaultPlayerType );
default:
Debug_Say(( "Unhandled MicroChunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Micro_Chunk();
}
break;
case CHUNKID_DEF_DEFENSEOBJECTDEF:
DefenseObjectDef.Load(cload);
break;
default:
Debug_Say(( "Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
return true;
}
/*
** DamageableGameObj
*/
DamageableGameObj::DamageableGameObj( void ) :
IsHealthBarDisplayed( true )
{
Set_Player_Type(PLAYERTYPE_NEUTRAL);
}
DamageableGameObj::~DamageableGameObj( void )
{
Remove_All_Observers();
}
/*
**
*/
void DamageableGameObj::Init( const DamageableGameObjDef & definition )
{
ScriptableGameObj::Init( definition );
Copy_Settings( definition );
return ;
}
/*
**
*/
void DamageableGameObj::Copy_Settings( const DamageableGameObjDef & definition )
{
Set_Player_Type(definition.DefaultPlayerType);
DefenseObject.Init(definition.DefenseObjectDef, this );
return ;
}
/*
**
*/
void DamageableGameObj::Re_Init( const DamageableGameObjDef & definition )
{
int old_player_type = PlayerType;
//
// Record the health and shield percent so we can restore the
// appropriate amount of health and shield after we've re-initialized
//
//float health_percent = DefenseObject.Get_Health() / DefenseObject.Get_Health_Max();
//float shield_percent = DefenseObject.Get_Shield_Strength() / DefenseObject.Get_Shield_Strength_Max();
//
// Re-initialize the base class
//
ScriptableGameObj::Re_Init( definition );
//
// Copy any internal settings from the definition
//
Copy_Settings( definition );
//
// Reset the health and shield to appropriate values
//
//DefenseObject.Set_Health (DefenseObject.Get_Health_Max () * health_percent);
//DefenseObject.Set_Shield_Strength (DefenseObject.Get_Shield_Strength_Max () * shield_percent);
Set_Player_Type( old_player_type );
return ;
}
const DamageableGameObjDef & DamageableGameObj::Get_Definition( void ) const
{
return (const DamageableGameObjDef &)BaseGameObj::Get_Definition();
}
/*
** DamageableGameObj Save and Load
*/
enum {
CHUNKID_PARENT = 207011212,
CHUNKID_DEFENSEOBJECT,
CHUNKID_VARIABLES,
MICROCHUNKID_PLAYER_TYPE = 1,
MICROCHUNKID_IS_HEALTH_BAR_DISPLAYED,
};
bool DamageableGameObj::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_PARENT );
ScriptableGameObj::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_PLAYER_TYPE, PlayerType );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_IS_HEALTH_BAR_DISPLAYED, IsHealthBarDisplayed );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DEFENSEOBJECT );
DefenseObject.Save(csave);
csave.End_Chunk();
return true;
}
bool DamageableGameObj::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_PARENT:
ScriptableGameObj::Load( cload );
break;
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_PLAYER_TYPE, PlayerType );
READ_MICRO_CHUNK( cload, MICROCHUNKID_IS_HEALTH_BAR_DISPLAYED, IsHealthBarDisplayed );
default:
Debug_Say(( "Unhandled MicroChunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Micro_Chunk();
}
break;
case CHUNKID_DEFENSEOBJECT:
DefenseObject.Load( cload );
break;
default:
Debug_Say(( "Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
return true;
}
void DamageableGameObj::Apply_Damage( const OffenseObjectClass & damager, float scale, int alternate_skin )
{
if ( DefenseObject.Get_Health() <= 0 ) {
return;
}
if (Is_Delete_Pending()) {
return;
}
float old_health = DefenseObject.Get_Health();
float old_shield = DefenseObject.Get_Shield_Strength();
DefenseObject.Apply_Damage( damager, scale, alternate_skin );
float new_health = DefenseObject.Get_Health();
float new_shield = DefenseObject.Get_Shield_Strength();
float diff = old_health + old_shield - new_health - new_shield;
// Notify the observers
const GameObjObserverList & observer_list = Get_Observers();
for( int index = 0; index < observer_list.Count(); index++ ) {
observer_list[ index ]->Damaged( this, damager.Get_Owner(), diff );
}
if ( DefenseObject.Get_Health() <= 0 ) {
// notify the observers
for( int index = 0; index < observer_list.Count(); index++ ) {
observer_list[ index ]->Killed( this, damager.Get_Owner() );
}
Completely_Damaged( damager );
}
}
//------------------------------------------------------------------------------------
/*void DamageableGameObj::Get_Information( StringClass & string )
{
// If we just came from the editor, call created on all out observers
const GameObjObserverList & observer_list = Get_Observers();
for( int index = 0; index < observer_list.Count(); index++ ) {
StringClass temp;
temp.Format( "%s\n", observer_list[ index ]->Get_Name() );
string += temp;
}
} */
/*
**
*/
void DamageableGameObj::Export_Occasional( BitStreamClass &packet )
{
ScriptableGameObj::Export_Occasional( packet );
//
// Export the defense object's state
//
DefenseObject.Export (packet);
}
/*
**
*/
void DamageableGameObj::Import_Occasional( BitStreamClass &packet )
{
ScriptableGameObj::Import_Occasional( packet );
//
// Update the defense object's state
//
float old_health = DefenseObject.Get_Health();
DefenseObject.Import (packet);
float new_health = DefenseObject.Get_Health();
/*
//
// Hack !
//
if ( Is_Delete_Pending() ) {
if ( new_health != 0 ) {
DefenseObject.Set_Health( 0 );
new_health = DefenseObject.Get_Health();
}
} else {
if ( new_health == 0 ) {
DefenseObject.Set_Health( 0.01f );
new_health = DefenseObject.Get_Health();
}
}
*/
if (old_health > 0 && old_health > new_health) {
// Notify the observers that we are damaged
const GameObjObserverList& observer_list = Get_Observers();
int count = observer_list.Count();
for (int index = 0; index < count; ++index) {
observer_list[index]->Damaged(this, NULL, old_health - new_health);
}
}
//
// Check to see if the object is completely damaged
//
if ( old_health > 0 && new_health <= 0 ) {
// Notify the observers that the building has been destroyed
const GameObjObserverList& observer_list = Get_Observers();
int count = observer_list.Count();
for (int index = 0; index < count; ++index) {
observer_list[index]->Killed(this, NULL);
}
OffenseObjectClass dummy_offense_obj;
Completely_Damaged( dummy_offense_obj );
}
}
//-----------------------------------------------------------------------------
bool DamageableGameObj::Is_Team_Player(void)
{
return PlayerType == PLAYERTYPE_NOD || PlayerType == PLAYERTYPE_GDI;
}
//-----------------------------------------------------------------------------
Vector3 DamageableGameObj::Get_Team_Color(void)
{
return Get_Color_For_Team(PlayerType);
}
//-----------------------------------------------------------------------------
void DamageableGameObj::Set_Player_Type(int id)
{
PlayerType = id;
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_RARE, true );
}
//-----------------------------------------------------------------------------
bool DamageableGameObj::Is_Teammate(DamageableGameObj * p_obj)
{
WWASSERT(p_obj != NULL);
return ((p_obj == this) ||
(Is_Team_Player() && Get_Player_Type() == p_obj->Get_Player_Type()));
}
bool DamageableGameObj::Is_Enemy(DamageableGameObj * p_obj)
{
WWASSERT(p_obj != NULL);
return ( (p_obj != this) && Player_Types_Are_Enemies( Get_Player_Type(), p_obj->Get_Player_Type() ) );
}

View File

@@ -0,0 +1,158 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/damageablegameobj.h $*
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 2/19/02 1:45p $*
* *
* $Revision:: 21 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#if defined(_MSC_VER)
#pragma once
#endif
#ifndef DAMAGEABLEGAMEOBJ_H
#define DAMAGEABLEGAMEOBJ_H
#include "always.h"
#include "scriptablegameobj.h"
#include "damage.h"
#include "encyclopediamgr.h"
/*
** DamageableGameObjDef - Defintion class for a DamageableGameObj
*/
class DamageableGameObjDef : public ScriptableGameObjDef
{
public:
DamageableGameObjDef( void );
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
DECLARE_EDITABLE( DamageableGameObjDef, ScriptableGameObjDef );
int Get_Name_ID (void) const { return TranslatedNameID; }
//
// Encyclopedia information
//
EncyclopediaMgrClass::TYPE Get_Encyclopedia_Type (void) const { return EncyclopediaType; }
int Get_Encyclopedia_ID (void) const { return EncyclopediaID; }
//
// Icon information
//
const StringClass & Get_Icon_Filename (void) const { return InfoIconTextureFilename; }
int Get_Translated_Name_ID (void) const { return TranslatedNameID; }
const DefenseObjectDefClass & Get_DefenseObjectDef( void ) const { return DefenseObjectDef; }
//
// Accessors (added as needed)
//
int Get_Default_Player_Type(void) const { return DefaultPlayerType; }
protected:
DefenseObjectDefClass DefenseObjectDef;
StringClass InfoIconTextureFilename;
int TranslatedNameID;
EncyclopediaMgrClass::TYPE EncyclopediaType;
int EncyclopediaID;
bool NotTargetable;
int DefaultPlayerType;
friend class DamageableGameObj;
};
/*
**
*/
class DamageableGameObj : public ScriptableGameObj
{
public:
// Constructor and Destructor
DamageableGameObj( void );
virtual ~DamageableGameObj( void );
// Definitions
void Init( const DamageableGameObjDef & definition );
void Copy_Settings( const DamageableGameObjDef & definition );
void Re_Init( const DamageableGameObjDef & definition );
const DamageableGameObjDef & Get_Definition( void ) const ;
// Save / Load
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
DefenseObjectClass * Get_Defense_Object( void ) { return &DefenseObject; }
virtual void Apply_Damage( const OffenseObjectClass & damager, float scale = 1.0f, int alternate_skin = -1 );
virtual void Completely_Damaged( const OffenseObjectClass & damager ) {};
// Information settings
const StringClass & Get_Info_Icon_Texture_Filename( void ) { return Get_Definition().InfoIconTextureFilename; }
int Get_Translated_Name_ID( void ) const { return Get_Definition().TranslatedNameID; }
virtual bool Is_Targetable( void ) const { return !Get_Definition().NotTargetable; }
virtual bool Is_Health_Bar_Displayed( void ) const { return IsHealthBarDisplayed; }
virtual void Set_Is_Health_Bar_Displayed( bool state ) { IsHealthBarDisplayed = state; }
// Type identification
virtual DamageableGameObj *As_DamageableGameObj( void ) { return this; }
// Teams / Playertypes
virtual int Get_Player_Type(void) const {return PlayerType;}
virtual void Set_Player_Type(int type);
bool Is_Team_Player(void);
Vector3 Get_Team_Color(void);
bool Is_Teammate(DamageableGameObj * p_obj);
bool Is_Enemy(DamageableGameObj * p_obj);
//
// Network support
//
virtual void Import_Occasional( BitStreamClass &packet );
virtual void Export_Occasional( BitStreamClass &packet );
protected:
DefenseObjectClass DefenseObject;
int PlayerType;
bool IsHealthBarDisplayed;
};
#endif // DAMAGEABLEGAMEOBJ_H

View File

@@ -0,0 +1,494 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/damageablestaticphys.cpp $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 8/17/01 7:15p $*
* *
* $Revision:: 19 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "damageablestaticphys.h"
#include "simpledefinitionfactory.h"
#include "persistfactory.h"
#include "wwphysids.h"
#include "hanim.h"
#include "wwdebug.h"
#include "wwhack.h"
#include "combat.h"
#include "explosion.h"
DECLARE_FORCE_LINK( damageablestaticphys );
/*
** Chunk Id's used by DamageableStaticPhysDefClass
*/
enum
{
DAMAGEABLESTATICPHYSDEF_CHUNK_STATICANIMPHYSDEF = 7311734,
DAMAGEABLESTATICPHYSDEF_CHUNK_VARIABLES,
DAMAGEABLESTATICPHYSDEF_CHUNK_DEFENSEOBJECTDEF,
DAMAGEABLESTATICPHYSDEF_VARIABLE_KILLEDEXPLOSION = 0x00,
DAMAGEABLESTATICPHYSDEF_VARIABLE_RESETAFTERANIM,
DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVELOOPSTART,
DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVELOOPEND,
DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVETWITCHSTART,
DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVETWITCHEND,
DAMAGEABLESTATICPHYSDEF_VARIABLE_DEATHTRANSITIONSTART,
DAMAGEABLESTATICPHYSDEF_VARIABLE_DEATHTRANSITIONEND,
DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADLOOPSTART,
DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADLOOPEND,
DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADTWITCHSTART,
DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADTWITCHEND,
DAMAGEABLESTATICPHYSDEF_VARIABLE_PLAYTWITCHESTOCOMPLETION,
};
/*
** Chunk Id's used by DamageableStaticPhysClass
*/
enum
{
DAMAGEABLESTATICPHYS_CHUNK_STATICANIMPHYS = 7311740,
DAMAGEABLESTATICPHYS_CHUNK_DEFENSEOBJECT,
DAMAGEABLESTATICPHYS_CHUNK_VARIABLES,
DAMAGEABLESTATICPHYS_VARIABLE_CURSTATE = 0x00,
};
/************************************************************************************************
**
** DamageableStaticPhysDefClass Implementation
**
************************************************************************************************/
SimplePersistFactoryClass<DamageableStaticPhysDefClass, PHYSICS_CHUNKID_DAMAGEABLESTATICPHYSDEF> _DamageableStaticPhysDefPersistFactory;
DECLARE_DEFINITION_FACTORY(DamageableStaticPhysDefClass, CLASSID_DAMAGEABLESTATICPHYSDEF, "DamageableStaticPhys") _DamageableStaticPhysDefDefFactory;
DamageableStaticPhysDefClass::DamageableStaticPhysDefClass(void) :
StaticAnimPhysDefClass(),
KilledExplosion(0),
LiveLoopStart(0),
LiveLoopEnd(0),
LiveTwitchStart(0),
LiveTwitchEnd(0),
DeathTransitionStart(0),
DeathTransitionEnd(0),
DeadLoopStart(0),
DeadLoopEnd(0),
DeadTwitchStart(0),
DeadTwitchEnd(0),
PlayTwitchesToCompletion(false)
{
PARAM_SEPARATOR(DamageableStaticPhysDefClass, "Damage Behavior Controls");
EDITABLE_PARAM(DamageableStaticPhysDefClass, ParameterClass::TYPE_EXPLOSIONDEFINITIONID, KilledExplosion);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, LiveLoopStart, 0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, LiveLoopEnd, 0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, LiveTwitchStart, 0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, LiveTwitchEnd,0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, DeathTransitionStart,0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, DeathTransitionEnd,0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, DeadLoopStart,0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, DeadLoopEnd,0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, DeadTwitchStart,0, 999);
INT_EDITABLE_PARAM(DamageableStaticPhysDefClass, DeadTwitchEnd,0, 999);
EDITABLE_PARAM(DamageableStaticPhysDefClass,ParameterClass::TYPE_BOOL,PlayTwitchesToCompletion);
DEFENSEOBJECTDEF_EDITABLE_PARAMS(DamageableStaticPhysDefClass, DefenseObjectDef);
}
uint32 DamageableStaticPhysDefClass::Get_Class_ID(void) const
{
return CLASSID_DAMAGEABLESTATICPHYSDEF;
}
bool DamageableStaticPhysDefClass::Is_Type(const char * type_name)
{
if (stricmp(type_name,DamageableStaticPhysDefClass::Get_Type_Name()) == 0) {
return true;
} else {
return StaticAnimPhysDefClass::Is_Type(type_name);
}
}
PersistClass * DamageableStaticPhysDefClass::Create(void) const
{
DamageableStaticPhysClass * obj = new DamageableStaticPhysClass;
obj->Init(*this);
return obj;
}
bool DamageableStaticPhysDefClass::Save(ChunkSaveClass & csave)
{
csave.Begin_Chunk(DAMAGEABLESTATICPHYSDEF_CHUNK_STATICANIMPHYSDEF);
StaticAnimPhysDefClass::Save(csave);
csave.End_Chunk();
csave.Begin_Chunk(DAMAGEABLESTATICPHYSDEF_CHUNK_VARIABLES);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_KILLEDEXPLOSION, KilledExplosion);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVELOOPSTART,LiveLoopStart);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVELOOPEND,LiveLoopEnd);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVETWITCHSTART,LiveTwitchStart);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVETWITCHEND,LiveTwitchEnd);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEATHTRANSITIONSTART,DeathTransitionStart);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEATHTRANSITIONEND,DeathTransitionEnd);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADLOOPSTART,DeadLoopStart);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADLOOPEND,DeadLoopEnd);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADTWITCHSTART,DeadTwitchStart);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADTWITCHEND,DeadTwitchEnd);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYSDEF_VARIABLE_PLAYTWITCHESTOCOMPLETION,PlayTwitchesToCompletion);
csave.End_Chunk();
csave.Begin_Chunk(DAMAGEABLESTATICPHYSDEF_CHUNK_DEFENSEOBJECTDEF);
DefenseObjectDef.Save(csave);
csave.End_Chunk();
return true;
}
bool DamageableStaticPhysDefClass::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case DAMAGEABLESTATICPHYSDEF_CHUNK_STATICANIMPHYSDEF:
StaticAnimPhysDefClass::Load( cload );
break;
case DAMAGEABLESTATICPHYSDEF_CHUNK_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_KILLEDEXPLOSION, KilledExplosion);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVELOOPSTART,LiveLoopStart);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVELOOPEND,LiveLoopEnd);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVETWITCHSTART,LiveTwitchStart);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_LIVETWITCHEND,LiveTwitchEnd);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEATHTRANSITIONSTART,DeathTransitionStart);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEATHTRANSITIONEND,DeathTransitionEnd);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADLOOPSTART,DeadLoopStart);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADLOOPEND,DeadLoopEnd);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADTWITCHSTART,DeadTwitchStart);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_DEADTWITCHEND,DeadTwitchEnd);
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYSDEF_VARIABLE_PLAYTWITCHESTOCOMPLETION,PlayTwitchesToCompletion);
default:
WWDEBUG_SAY(( "Unrecognized DamageableStaticPhysDef Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
case DAMAGEABLESTATICPHYSDEF_CHUNK_DEFENSEOBJECTDEF:
DefenseObjectDef.Load(cload);
break;
default:
WWDEBUG_SAY(( "Unrecognized DamageableStaticPhysDef chunkID\n" ));
break;
}
cload.Close_Chunk();
}
return true;
}
const PersistFactoryClass & DamageableStaticPhysDefClass::Get_Factory (void) const
{
return _DamageableStaticPhysDefPersistFactory;
}
/************************************************************************************************
**
** DamageableStaticPhysClass Implementation
**
************************************************************************************************/
SimplePersistFactoryClass<DamageableStaticPhysClass, PHYSICS_CHUNKID_DAMAGEABLESTATICPHYS> _DamageableStaticPhysPersistFactory;
const PersistFactoryClass & DamageableStaticPhysClass::Get_Factory (void) const
{
return _DamageableStaticPhysPersistFactory;
}
DamageableStaticPhysClass::DamageableStaticPhysClass(void) :
CurState(STATE_LIVE_LOOP)
{
}
DamageableStaticPhysClass::~DamageableStaticPhysClass( void )
{
}
void DamageableStaticPhysClass::Init( const DamageableStaticPhysDefClass & def )
{
// DamageableStaticPhys are not PhysicalGameObjs, so pass in a NULL owner
DefenseObject.Init(def.DefenseObjectDef, NULL);
StaticAnimPhysClass::Init(def);
Start_Loop();
}
void DamageableStaticPhysClass::Timestep(float dt)
{
StaticAnimPhysClass::Timestep(dt);
/*
** If we just reached a target, then transition into the loop for our current health state
*/
if ( (Get_Animation_Manager().Get_Animation_Mode() == AnimCollisionManagerClass::ANIMATE_TARGET) &&
(Get_Animation_Manager().Is_At_Target()) )
{
Start_Loop();
}
}
void DamageableStaticPhysClass::Apply_Damage_Static( const OffenseObjectClass & offense )
{
/*
** If we're already completely damaged, possibly start a twitch and then return
*/
if (DefenseObject.Get_Health() <= 0) {
Play_Twitch();
return;
}
/*
** Apply the damage
*/
float new_health = DefenseObject.Apply_Damage(offense);
/*
** If we just lost all of our health, implement all of the
** destruction effects.
*/
if (new_health <= 0) {
/*
** Play our animation to the last frame
*/
Play_Death_Transition();
/*
** Set off an explosion if the user defined one
*/
const DamageableStaticPhysDefClass * def = Get_DamageableStaticPhysDef();
if (def->KilledExplosion != 0) {
ExplosionManager::Create_Explosion_At(def->KilledExplosion,Get_Transform(),NULL);
}
} else {
/*
** We were hit but didn't lose all of our health, so play a twitch
*/
Play_Twitch();
}
}
void DamageableStaticPhysClass::Reset_Health(void)
{
DefenseObject.Set_Health(DefenseObject.Get_Health_Max());
Start_Loop();
}
void DamageableStaticPhysClass::Start_Loop(void)
{
const DamageableStaticPhysDefClass * def = Get_DamageableStaticPhysDef();
if (def != NULL) {
int frame0,frame1;
if (DefenseObject.Get_Health() > 0) {
frame0 = def->LiveLoopStart;
frame1 = def->LiveLoopEnd;
CurState = STATE_LIVE_LOOP;
} else {
frame0 = def->DeadLoopStart;
frame1 = def->DeadLoopEnd;
CurState = STATE_DEAD_LOOP;
}
if (frame0 != frame1) {
Get_Animation_Manager().Set_Animation_Mode(AnimCollisionManagerClass::ANIMATE_LOOP);
Get_Animation_Manager().Set_Current_Frame(frame0);
Get_Animation_Manager().Set_Loop_Start(frame0);
Get_Animation_Manager().Set_Loop_End(frame1);
} else {
Get_Animation_Manager().Set_Animation_Mode(AnimCollisionManagerClass::ANIMATE_MANUAL);
Get_Animation_Manager().Set_Current_Frame(frame0);
}
} else {
WWDEBUG_SAY(("ERROR: Missing definition for damageable object: %s\n",Model->Get_Name()));
}
}
void DamageableStaticPhysClass::Play_Twitch(void)
{
/*
** Never interrupt death transitions.
*/
if (CurState == STATE_DEATH_TRANSITION) {
return;
}
/*
** Play the appropriate twitch depending on whether we are alive or dead
*/
const DamageableStaticPhysDefClass * def = Get_DamageableStaticPhysDef();
if (def != NULL) {
/*
** Don't interrupt other twitches if the designer doesn't want us to
*/
if ((def->PlayTwitchesToCompletion == false) ||
((CurState != STATE_LIVE_TWITCH) && (CurState != STATE_DEAD_TWITCH)))
{
int frame0,frame1;
if (DefenseObject.Get_Health() > 0) {
frame0 = def->LiveTwitchStart;
frame1 = def->LiveTwitchEnd;
CurState = STATE_LIVE_TWITCH;
} else {
frame0 = def->DeadTwitchStart;
frame1 = def->DeadTwitchEnd;
CurState = STATE_DEAD_TWITCH;
}
if (frame0 != frame1) {
Get_Animation_Manager().Set_Animation_Mode(AnimCollisionManagerClass::ANIMATE_TARGET);
Get_Animation_Manager().Set_Current_Frame(frame0);
Get_Animation_Manager().Set_Target_Frame(frame1);
}
}
} else {
WWDEBUG_SAY(("ERROR: Missing definition for damageable object: %s\n",Model->Get_Name()));
}
}
void DamageableStaticPhysClass::Play_Death_Transition(void)
{
const DamageableStaticPhysDefClass * def = Get_DamageableStaticPhysDef();
if (def != NULL) {
if (def->DeathTransitionStart != def->DeathTransitionEnd) {
CurState = STATE_DEATH_TRANSITION;
Get_Animation_Manager().Set_Animation_Mode(AnimCollisionManagerClass::ANIMATE_TARGET);
Get_Animation_Manager().Set_Current_Frame(def->DeathTransitionStart);
Get_Animation_Manager().Set_Target_Frame(def->DeathTransitionEnd);
} else {
Start_Loop();
}
} else {
WWDEBUG_SAY(("ERROR: Missing definition for damageable object: %s\n",Model->Get_Name()));
}
}
bool DamageableStaticPhysClass::Save( ChunkSaveClass & csave )
{
/*
** Save the parent class data
*/
csave.Begin_Chunk(DAMAGEABLESTATICPHYS_CHUNK_STATICANIMPHYS);
StaticAnimPhysClass::Save( csave );
csave.End_Chunk();
/*
** Save the contents of our damage object
*/
csave.Begin_Chunk(DAMAGEABLESTATICPHYS_CHUNK_DEFENSEOBJECT);
DefenseObject.Save(csave);
csave.End_Chunk();
/*
** Save our variables
*/
csave.Begin_Chunk(DAMAGEABLESTATICPHYS_CHUNK_VARIABLES);
WRITE_MICRO_CHUNK(csave, DAMAGEABLESTATICPHYS_VARIABLE_CURSTATE, CurState);
csave.End_Chunk();
return true;
}
bool DamageableStaticPhysClass::Load(ChunkLoadClass & cload)
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case DAMAGEABLESTATICPHYS_CHUNK_STATICANIMPHYS:
StaticAnimPhysClass::Load( cload );
break;
case DAMAGEABLESTATICPHYS_CHUNK_DEFENSEOBJECT:
DefenseObject.Load(cload);
break;
case DAMAGEABLESTATICPHYS_CHUNK_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK(cload, DAMAGEABLESTATICPHYS_VARIABLE_CURSTATE, CurState);
default:
WWDEBUG_SAY(( "Unrecognized DamageableStaticPhys Variable chunkID\n" ));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
WWDEBUG_SAY(( "Unrecognized DamageableStaticPhys chunkID\n" ));
break;
}
cload.Close_Chunk();
}
Start_Loop();
return true;
}

View File

@@ -0,0 +1,149 @@
/*
** Command & Conquer Renegade(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 O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/damageablestaticphys.h $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 8/17/01 8:27p $*
* *
* $Revision:: 9 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef DAMAGEABLESTATICPHYS_H
#define DAMAGEABLESTATICPHYS_H
#include "always.h"
#include "staticanimphys.h"
#include "damage.h"
class DamageableStaticPhysDefClass;
/**
** DamageableStaticPhysClass
** This is a static physics object which tracks its health. When the health drops to zero,
** it plays its animation and stops on the end frame.
*/
class DamageableStaticPhysClass : public StaticAnimPhysClass
{
public:
// Constructor and Destructor
DamageableStaticPhysClass( void );
virtual ~DamageableStaticPhysClass( void );
virtual void Timestep(float dt);
// RTTI
virtual DamageableStaticPhysClass * As_DamageableStaticPhysClass (void) { return this; }
// Definitions
void Init(const DamageableStaticPhysDefClass & definition);
const DamageableStaticPhysDefClass * Get_DamageableStaticPhysDef(void) const { WWASSERT( Definition ); return (DamageableStaticPhysDefClass *)Definition; }
// Damage Management
void Apply_Damage_Static( const OffenseObjectClass & offense );
void Reset_Health(void);
// Save / Load
virtual bool Save(ChunkSaveClass & csave);
virtual bool Load(ChunkLoadClass & cload);
virtual const PersistFactoryClass & Get_Factory(void) const;
protected:
void Start_Loop(void);
void Play_Twitch(void);
void Play_Death_Transition(void);
enum {
STATE_LIVE_LOOP = 0,
STATE_LIVE_TWITCH,
STATE_DEATH_TRANSITION,
STATE_DEAD_LOOP,
STATE_DEAD_TWITCH,
};
int CurState;
DefenseObjectClass DefenseObject;
friend class DSAPONetworkObjectClass;
};
/*
** DamageableStaticPhysDefClass
** Damageable static objects support two animation loops and several sequences. An object
** can have a pair of frame numbers that are looped between while it is alive (the "Live-Loop"),
** a pair that are looped while it is dead (the "Dead-Loop"), a "twitch" sequence that is played
** whenever it is shot in either the live or dead state, and a sequence that is played when the
** object transitions between alive and dead.
*/
class DamageableStaticPhysDefClass : public StaticAnimPhysDefClass
{
public:
DamageableStaticPhysDefClass(void);
virtual uint32 Get_Class_ID(void) const;
virtual const char * Get_Type_Name(void) { return "DamageableStaticPhysDef"; }
virtual bool Is_Type(const char *);
virtual PersistClass * Create(void) const ;
virtual bool Save(ChunkSaveClass & csave);
virtual bool Load(ChunkLoadClass & cload);
virtual const PersistFactoryClass & Get_Factory(void) const;
DECLARE_EDITABLE( DamageableStaticPhysDefClass, StaticAnimPhysDefClass );
protected:
int KilledExplosion;
int LiveLoopStart;
int LiveLoopEnd;
int LiveTwitchStart;
int LiveTwitchEnd;
int DeathTransitionStart;
int DeathTransitionEnd;
int DeadLoopStart;
int DeadLoopEnd;
int DeadTwitchStart;
int DeadTwitchEnd;
bool PlayTwitchesToCompletion;
DefenseObjectDefClass DefenseObjectDef;
friend class DamageableStaticPhysClass;
friend class DSAPONetworkObjectClass;
};
#endif // DAMAGEABLESTATICPHYS_H

273
Code/Combat/damagezone.cpp Normal file
View File

@@ -0,0 +1,273 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/damagezone.cpp $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 7/16/01 12:14p $*
* *
* $Revision:: 13 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "damagezone.h"
#include "persistfactory.h"
#include "combatchunkid.h"
#include "simpledefinitionfactory.h"
#include "debug.h"
#include "wwhack.h"
#include "gameobjmanager.h"
#include "smartgameobj.h"
#include "colmath.h"
#include "weapons.h"
#include "damage.h"
#include "wwprofile.h"
#include "combat.h"
#include "crandom.h"
DECLARE_FORCE_LINK( DamageZone )
SimplePersistFactoryClass<DamageZoneGameObjDef, CHUNKID_GAME_OBJECT_DEF_DAMAGE_ZONE> _DamageZoneGameObjDefPersistFactory;
DECLARE_DEFINITION_FACTORY(DamageZoneGameObjDef, CLASSID_GAME_OBJECT_DEF_DAMAGE_ZONE, "Damage Zone") _DamageZoneGameObjDefDefFactory;
DamageZoneGameObjDef::DamageZoneGameObjDef( void ) :
DamageRate( 10 ),
DamageWarhead( 1 ),
Color( 0.7F, 0, 0 )
{
#ifdef PARAM_EDITING_ON
EDITABLE_PARAM( DamageZoneGameObjDef, ParameterClass::TYPE_FLOAT, DamageRate );
EnumParameterClass *param;
param = new EnumParameterClass( &DamageWarhead );
param->Set_Name ( "Damage Warhead" );
for ( int i = 0; i < ArmorWarheadManager::Get_Num_Warhead_Types(); i++ ) {
param->Add_Value ( ArmorWarheadManager::Get_Warhead_Name( i ), i );
}
GENERIC_EDITABLE_PARAM(DamageZoneGameObjDef,param)
EDITABLE_PARAM( DamageZoneGameObjDef, ParameterClass::TYPE_COLOR, Color );
#endif //PARAM_EDITING_ON
}
uint32 DamageZoneGameObjDef::Get_Class_ID (void) const
{
return CLASSID_GAME_OBJECT_DEF_DAMAGE_ZONE;
}
PersistClass * DamageZoneGameObjDef::Create( void ) const
{
DamageZoneGameObj * zone = new DamageZoneGameObj;
zone->Init( *this );
return zone;
}
enum {
CHUNKID_DEF_PARENT = 626000947,
CHUNKID_DEF_VARIABLES,
XXXMICROCHUNKID_DEF_DAMAGE_TYPE = 1,
MICROCHUNKID_DEF_ZONE_COLOR,
MICROCHUNKID_DEF_DAMAGE_RATE,
MICROCHUNKID_DEF_DAMAGE_WARHEAD,
};
bool DamageZoneGameObjDef::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_DEF_PARENT );
BaseGameObjDef::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_DEF_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_ZONE_COLOR, Color );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_DAMAGE_RATE, DamageRate );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DEF_DAMAGE_WARHEAD, DamageWarhead );
csave.End_Chunk();
return true;
}
bool DamageZoneGameObjDef::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_DEF_PARENT:
BaseGameObjDef::Load( cload );
break;
case CHUNKID_DEF_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_ZONE_COLOR, Color );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_DAMAGE_RATE, DamageRate );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DEF_DAMAGE_WARHEAD, DamageWarhead );
default:
Debug_Say(("Unhandled Variable Chunk:%d File:%s Line:%d\r\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
return true;
}
const PersistFactoryClass & DamageZoneGameObjDef::Get_Factory (void) const
{
return _DamageZoneGameObjDefPersistFactory;
}
/*
**
*/
DamageZoneGameObj::DamageZoneGameObj( void ) :
DamageTimer( 0 )
{
}
DamageZoneGameObj::~DamageZoneGameObj( void )
{
}
void DamageZoneGameObj::Init( void )
{
Init( Get_Definition() );
}
void DamageZoneGameObj::Init( const DamageZoneGameObjDef & definition )
{
BaseGameObj::Init( definition );
}
const DamageZoneGameObjDef & DamageZoneGameObj::Get_Definition( void ) const
{
return (const DamageZoneGameObjDef &)BaseGameObj::Get_Definition();
}
enum {
CHUNKID_PARENT = 626000947,
CHUNKID_VARIABLES,
MICROCHUNKID_BOUNDING_BOX = 1,
MICROCHUNKID_DAMAGE_TIMER,
};
bool DamageZoneGameObj::Save( ChunkSaveClass & csave )
{
csave.Begin_Chunk( CHUNKID_PARENT );
BaseGameObj::Save( csave );
csave.End_Chunk();
csave.Begin_Chunk( CHUNKID_VARIABLES );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_BOUNDING_BOX, BoundingBox );
WRITE_MICRO_CHUNK( csave, MICROCHUNKID_DAMAGE_TIMER, DamageTimer );
csave.End_Chunk();
return true;
}
bool DamageZoneGameObj::Load( ChunkLoadClass &cload )
{
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case CHUNKID_PARENT:
BaseGameObj::Load( cload );
break;
case CHUNKID_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK( cload, MICROCHUNKID_BOUNDING_BOX, BoundingBox );
READ_MICRO_CHUNK( cload, MICROCHUNKID_DAMAGE_TIMER, DamageTimer );
default:
Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Micro_Chunk();
}
break;
default:
Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
return true;
}
SimplePersistFactoryClass<DamageZoneGameObj, CHUNKID_GAME_OBJECT_DAMAGE_ZONE> _DamageZonePersistFactory;
const PersistFactoryClass & DamageZoneGameObj::Get_Factory( void ) const
{
return _DamageZonePersistFactory;
}
void DamageZoneGameObj::Think( void )
{
WWPROFILE( "DamageZone Think" );
if ( !CombatManager::I_Am_Server() ) {
return;
}
// Only apply damage every second...
DamageTimer += TimeManager::Get_Frame_Seconds();
// Scramble it a bit so all don't hit at the same time...
float trigger = 1.0f;
trigger = FreeRandom.Get_Float( 1.0f, 1.5f );
if ( DamageTimer >= trigger ) {
// Debug_Say(( "Zone Damage %f\n", DamageTimer ));
OffenseObjectClass offense( Get_Definition().DamageRate, Get_Definition().DamageWarhead );
SLNode<SmartGameObj> * smart_objnode;
for (smart_objnode = GameObjManager::Get_Smart_Game_Obj_List()->Head(); smart_objnode; smart_objnode = smart_objnode->Next()) {
SmartGameObj * obj = smart_objnode->Data();
WWASSERT( obj != NULL );
Vector3 pos;
obj->Get_Position(&pos);
if ( CollisionMath::Overlap_Test(BoundingBox,pos) == CollisionMath::INSIDE ) {
obj->Apply_Damage_Extended( offense, DamageTimer );
}
}
DamageTimer = 0;
}
}

113
Code/Combat/damagezone.h Normal file
View File

@@ -0,0 +1,113 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/damagezone.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 7/16/01 11:20a $*
* *
* $Revision:: 12 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef DAMAGEZONE_H
#define DAMAGEZONE_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef OBBOX_H
#include "obbox.h"
#endif
#ifndef BASEGAMEOBJ_H
#include "basegameobj.h"
#endif
/*
** Damage Zone Definition
*/
class DamageZoneGameObjDef : public BaseGameObjDef
{
public:
DamageZoneGameObjDef( void );
virtual uint32 Get_Class_ID( void ) const;
virtual PersistClass * Create( void ) const ;
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
virtual const PersistFactoryClass & Get_Factory( void ) const;
DECLARE_EDITABLE( DamageZoneGameObjDef, BaseGameObjDef );
const Vector3 & Get_Color (void) const { return Color; }
protected:
float DamageRate;
int DamageWarhead;
Vector3 Color;
friend class DamageZoneGameObj;
};
/*
** Damage Zone
*/
class DamageZoneGameObj : public BaseGameObj
{
public:
DamageZoneGameObj( void );
virtual ~DamageZoneGameObj( void );
virtual void Init( void );
void Init( const DamageZoneGameObjDef & definition );
const DamageZoneGameObjDef & Get_Definition( void ) const;
virtual bool Save( ChunkSaveClass & csave );
virtual bool Load( ChunkLoadClass & cload );
virtual const PersistFactoryClass & Get_Factory( void ) const;
// Bounding Box
void Set_Bounding_Box( OBBoxClass & box ) { BoundingBox = box; }
const OBBoxClass & Get_Bounding_Box(void) { return BoundingBox; }
virtual void Think( void );
// Network support
//virtual bool Exists_On_Client( void ) const { return false; }
protected:
OBBoxClass BoundingBox;
float DamageTimer;
};
#endif

1023
Code/Combat/debug.cpp Normal file

File diff suppressed because it is too large Load Diff

226
Code/Combat/debug.h Normal file
View File

@@ -0,0 +1,226 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/debug.h $*
* *
* $Author:: Byon_g $*
* *
* $Modtime:: 12/18/01 10:36a $*
* *
* $Revision:: 27 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef DEBUG_H
#define DEBUG_H
#ifndef ALWAYS_H
#include "always.h"
#endif
#ifndef WWDEBUG_H
#include "wwdebug.h"
#endif
#ifndef BITTYPE_H
#include "bittype.h"
#endif
#ifndef __WIDESTRING_H
#include "widestring.h"
#endif
#ifndef VECTOR3_H
#include "vector3.h"
#endif
#ifndef VECTOR4_H
#include "vector4.h"
#endif
//#ifndef _CONTEXT
//struct CONTEXT;
//#define TEMP_CONTEXT_DEFINE
//#endif
//int Stack_Walk(unsigned long *return_addresses, int num_addresses, CONTEXT *context = NULL);
//#ifdef TEMP_CONTEXT_DEFINE
//#undef CONTEXT
//#endif
/*
**
*/
class DebugDisplayHandlerClass {
public:
virtual void Display_Text( const char * string, const Vector4 & color = Vector4( 1,1,1,1 ) ) = 0;
virtual void Display_Text( const WideStringClass & string, const Vector4 & color = Vector4( 1,1,1,1 ) ) = 0;
};
/*
**
*/
class DebugManager {
public:
static void Init( void );
static void Shutdown( void );
static void Update( void );
static void Load_Registry_Settings( const char * sub_key );
static void Save_Registry_Settings( const char * sub_key );
//
// Version number support. The major revision number is stored in the
// hiword of the version, the minor revision number is stored in the loword.
//
static int Get_Version_Number (void) { return VersionNumber; }
static void Set_Version_Number (int number) { VersionNumber = number; }
/*
** Debug Displaying
*/
enum DebugDevice {
DEBUG_DEVICE_SCREEN = 1<<0,
DEBUG_DEVICE_MONO = 1<<1,
DEBUG_DEVICE_SRDEBUG = 1<<2, // OBSOLETE!
DEBUG_DEVICE_DBWIN32 = 1<<3,
DEBUG_DEVICE_LOG = 1<<4,
DEBUG_DEVICE_WINDOWS = 1<<5,
};
static void Enable_Device( DebugDevice device ) { EnabledDevices |= device; }
static void Disable_Device( DebugDevice device ) { EnabledDevices &= ~device; }
static void Toggle_Device_Enabled( DebugDevice device ) { EnabledDevices ^= device; }
static bool Is_Device_Enabled( DebugDevice device ) { return (EnabledDevices & device) != 0; }
enum DebugType {
DEBUG_TYPE_INFORMATION = 1<<WWDEBUG_TYPE_INFORMATION,
DEBUG_TYPE_WARNING = 1<<WWDEBUG_TYPE_WARNING,
DEBUG_TYPE_ERROR = 1<<WWDEBUG_TYPE_ERROR,
DEBUG_TYPE_SCRIPT = 1<<(WWDEBUG_TYPE_USER+1),
DEBUG_TYPE_NETWORK_ADMIN = 1<<(WWDEBUG_TYPE_USER+2),
DEBUG_TYPE_NETWORK_BASIC = 1<<(WWDEBUG_TYPE_USER+3),
DEBUG_TYPE_NETWORK_PROLIFIC = 1<<(WWDEBUG_TYPE_USER+4),
};
static void Enable_Type( DebugType type ) { EnabledTypes |= type; }
static void Disable_Type( DebugType type ) { EnabledTypes &= ~type; }
static void Toggle_Type_Enabled( DebugType type ) { EnabledTypes ^= type; }
static bool Is_Type_Enabled( DebugType type ) { return (EnabledTypes & type) != 0; }
static void Display( char const *buffer );
static void Display_Script( char const *text, ... );
static void Display_Network_Admin( char const *text, ... );
static void Display_Network_Basic( char const *text, ... );
static void Display_Network_Prolific( char const *text, ... );
/*
** Debug Options
** (gth) Enable and disable debug options and triggers. Now that we've
** moved more functions to the console (rather than 10 billion key combinations)
** we need an interface for turning on and off some of the debug triggers.
*/
enum DebugOption {
DEBUG_INVERT_VIS = 1<<0,
DEBUG_DISABLE_VIS = 1<<1,
DEBUG_COLLISION_MESSAGES = 1<<2,
DEBUG_COLLISION_DISPLAY = 1<<3,
DEBUG_DISABLE_LIGHTS = 1<<4,
DEBUG_PROCESS_STATS = 1<<5,
DEBUG_SURFACE_CACHE = 1<<6,
};
static void Option_Enable( DebugOption option, bool onoff )
{ if ( onoff ) EnabledOptions |= option; else EnabledOptions &= ~option; }
static bool Option_Is_Enabled( DebugOption option ) { return (EnabledOptions & option) != 0; }
static void Option_Toggle( DebugOption option ) { EnabledOptions ^= option; }
// Misc Debug Functions
static void Measure_Frame_Textures( void );
// Outside handler display
static void Set_Display_Handler( DebugDisplayHandlerClass * handler ) { DisplayHandler = handler; }
static void Display_Text(const char * string, const Vector4 & color );
static void Display_Text(const char * string, const Vector3 & color = Vector3( 1,1,1 ) );
static void Display_Text(const WideStringClass & string, const Vector4 & color );
static void Display_Text(const WideStringClass & string, const Vector3 & color = Vector3( 1,1,1 ) );
static void Init_Logfile(void);
static void Write_To_File(LPCSTR str);
static LPCSTR Logfile_Name(void) {return LOGFILE;}
static void Enable_Memory_Logging( bool enable );
static bool Is_File_Logging_Enabled( void ) { return EnableFileLogging; }
static bool Is_Diag_Logging_Enabled( void ) { return EnableDiagLogging; }
static bool Load_Debug_Scripts( void ) { return LoadDebugScripts; }
static void Set_Is_Slave(bool isslave) {IsSlave = isslave;}
static bool Allow_Cinematic_Keys( void ) { return AllowCinematicKeys; };
private:
static int EnabledDevices;
static int EnabledTypes;
static int EnabledOptions;
static bool EnableFileLogging;
static bool EnableDiagLogging;
static bool LoadDebugScripts;
static int VersionNumber;
static bool AllowCinematicKeys;
static DebugDisplayHandlerClass * DisplayHandler;
static LPSTR LOGFILE;
static char LogfileNameBuffer[256];
static bool IsSlave;
/*
** Thread safety
*/
static CriticalSectionClass CriticalSection;
};
// macro to print
#define Debug_Say WWDEBUG_SAY
#define Debug_Warning WWDEBUG_WARNING
#define Debug_Error WWDEBUG_ERROR
#define Debug_Script(x) DebugManager::Display_Script x
#define Debug_Network_Basic(x) DebugManager::Display_Network_Basic x
#define Debug_Network_Prolific(x) DebugManager::Display_Network_Prolific x
#endif // DEBUG_H
//#define Debug_Network_Admin(x) DebugManager::Display_Network_Admin x

107
Code/Combat/diaglog.cpp Normal file
View File

@@ -0,0 +1,107 @@
/*
** Command & Conquer Renegade(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/>.
*/
/***********************************************************************************************
*** Confidential - Westwood Studios ***
***********************************************************************************************
* *
* Project Name : Commando *
* *
* $Archive:: /Commando/Code/Combat/diaglog.cpp $*
* *
* $Author:: Patrick $*
* *
* $Modtime:: 1/02/02 3:35p $*
* *
* $Revision:: 5 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "diaglog.h"
#include "ffactory.h"
#include "wwfile.h"
#include "timemgr.h"
#include <WTYPES.H> // for SYSTEMTIME
FileClass * _DiagLogFile = NULL;
/*
**
*/
void DiagLogClass::Init( void )
{
FileClass * file = NULL;
for ( int i = 0; i < 100; i++ ) {
StringClass filename;
filename.Format( "DIAGLOG%03d.TXT", i );
file = _TheWritingFileFactory->Get_File( filename );
if ( file == NULL || !file->Is_Available() ) {
break;
}
_TheWritingFileFactory->Return_File( file );
file = NULL;
}
if ( file != NULL ) {
file->Close();
file->Open(FileClass::WRITE);
_DiagLogFile = file;
}
SYSTEMTIME dt;
::GetSystemTime( &dt );
StringClass dt_string;
dt_string.Format( "%02d/%02d/%02d %02d:%02d:%02d", dt.wMonth, dt.wDay, dt.wYear, dt.wHour, dt.wMinute, dt.wSecond );
DIAG_LOG(( "OPEN", "%s", (const char *)dt_string ));
}
void DiagLogClass::Shutdown( void )
{
if ( _DiagLogFile != NULL ) {
SYSTEMTIME dt;
::GetSystemTime( &dt );
StringClass dt_string;
dt_string.Format( "%02d/%02d/%02d %02d:%02d:%02d", dt.wMonth, dt.wDay, dt.wYear, dt.wHour, dt.wMinute, dt.wSecond );
DIAG_LOG(( "CLOS", "%s", (const char *)dt_string ));
_DiagLogFile->Close();
_TheWritingFileFactory->Return_File( _DiagLogFile );
_DiagLogFile = NULL;
}
}
void DiagLogClass::Log_Timed( const char * type, const char * format, ... )
{
if ( _DiagLogFile != NULL ) {
va_list arg_list;
va_start (arg_list, format);
StringClass data;
data.Format_Args( format, arg_list );
va_end (arg_list);
StringClass line;
float time = TimeManager::Get_Total_Seconds();
line.Format( "%s; %1.2f; %s%c%c", type, time, data, 0x0D, 0x0A );
_DiagLogFile->Write( line, ::strlen( line ) );
}
}

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