Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1718 lines
44 KiB
C++

//===========================================================================//
// File: DamageObject.cpp //
// Project: Adept Brick: DamageObject //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 03/08/99 DPB Created File
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#include "AdeptHeaders.hpp"
#include "DamageObject.hpp"
#include "Entity.hpp"
#include "Tool.hpp"
#include "Effect.hpp"
#include "Map.hpp"
#include "NameTable.hpp"
#include "Site.hpp"
//#############################################################################
//########################### DamageObject ###############################
//#############################################################################
extern int g_nMR;
DamageObject::ClassData*
DamageObject::DefaultData = NULL;
HGOSHEAP
Adept::g_DamageObjectHeap = NULL;
void __cdecl Adept::AdeptDamageSecurityCheckStart(void)
{
_asm
{
nop
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
DamageObjectClassID,
"Adept::DamageObject",
Receiver::DefaultData,
0,
NULL
);
Check_Object(DefaultData);
Verify(!g_DamageObjectHeap);
g_DamageObjectHeap = gos_CreateMemoryHeap("DamageObject");
Check_Pointer(g_DamageObjectHeap);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::TerminateClass()
{
Check_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
Check_Pointer(g_DamageObjectHeap);
gos_DestroyMemoryHeap(g_DamageObjectHeap);
g_DamageObjectHeap = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DamageObject::DamageObject(
ClassData *class_data,
MemoryStream *stream
):
Receiver(class_data)
{
Check_Pointer(this);
Check_Object(stream);
//Need to stream stuff in here
*stream >> baseArmorValue;
*stream >> currentArmorValue;
*stream >> scaleSplashDamage;
*stream >> damageObjectName;
*stream >> internalDamageObjectID;
*stream >> armorZone;
*stream >> damageLevel;
*stream >> m_armorType;
*stream >> maxArmorValue;
*stream >> m_specialConnectedToZone;
armorLevel = 1.0f;
damageArrayEntry = NULL;
armorArrayEntry = NULL;
internalDamageObject = NULL;
{for(int qqq = 0; qqq < DmgModifier_Count; qqq++)
{
m_aDamageModifier[qqq * 2] = 1.0f; // real value
m_aDamageModifier[qqq * 2 + 1] = 1.0f; // backup value
}}
m_HitPointPointer = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void*
DamageObject::operator new(size_t size)
{
/*
gos_PushCurrentHeap(g_DamageObjectHeap);
void *temp = ::new(size_t);
gos_PopCurrentHeap();
return temp;
*/
return gos_Malloc(size,g_DamageObjectHeap);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DamageObject::Reuse()
{
Check_Object(this);
m_HitPointPointer = NULL;
currentArmorValue = baseArmorValue;
damageLevel = NoArmorDamage;
if(damageArrayEntry)
*damageArrayEntry = damageLevel;
Scalar damage_percentage;
damage_percentage = 1.0f;
armorLevel = damage_percentage;
if (armorArrayEntry)
*armorArrayEntry = damage_percentage;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::ConstructDamageObjectStream(
MemoryStream *stream,
Page *page
)
{
Check_Object(stream);
Check_Object(page);
int internal_damage_zone_id;
int armor_zone;
const char *armor_zone_text = "";
page->GetEntry("ArmorZone", &armor_zone_text);
armor_zone = ArmorZoneTextToAscii(armor_zone_text);
const char *zone_name;
page->GetEntry("InternalDamageZone", &zone_name, true);
internal_damage_zone_id = InternalDamageObject::InternalZoneTextToAscii(zone_name);
const char *attached_zone_string;
int attached_to_zone = NullArmorZone;
if(page->GetEntry("SpecialAttachedToZone", &attached_zone_string))
attached_to_zone = ArmorZoneTextToAscii(attached_zone_string);
Stuff::Scalar
base_armor_value,
current_armor_value,
scale_splash_damage,
max_armor_value;
base_armor_value = 0.0f;
page->GetEntry("BaseArmorValue", &base_armor_value);
Verify(base_armor_value >= 0.0f);
max_armor_value = base_armor_value;
page->GetEntry("MaxArmorValue", &max_armor_value);
Verify(max_armor_value > 0.0f);
if (!page->GetEntry("CurrentArmorValue", &current_armor_value))
{
current_armor_value = base_armor_value;
}
if (!page->GetEntry("ScaleSplashDamage", &scale_splash_damage))
{
scale_splash_damage = 1.0f;
}
int damage_level = NoArmorDamage;
RegisteredClass::ClassID class_id = DefaultData->GetClassID();
MString damage_object_name = page->GetName();
int armor_type = DefaultArmorType;
*stream << class_id;
*stream << base_armor_value;
*stream << current_armor_value;
*stream << scale_splash_damage;
*stream << damage_object_name;
*stream << internal_damage_zone_id;
*stream << armor_zone;
*stream << damage_level;
*stream << armor_type;
*stream << max_armor_value;
*stream << attached_to_zone;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::Save(MemoryStream *stream)
{
Check_Object(this);
RegisteredClass::ClassID class_id = DefaultData->GetClassID();
*stream << class_id;
*stream << baseArmorValue;
*stream << currentArmorValue;
*stream << damageObjectName;
*stream << internalDamageObjectID;
*stream << armorZone;
*stream << damageLevel;
*stream << m_armorType;
*stream << maxArmorValue;
*stream << m_specialConnectedToZone;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DamageObject::~DamageObject()
{
}
// from here by jcem
Stuff::Scalar DamageObject::GetDamageModifier (int nIdx) const
{
gosASSERT((0 <= nIdx) && (nIdx < DmgModifier_Count * 2));
return m_aDamageModifier[nIdx];
}
void DamageObject::SetDamageModifier (int nIdx, Stuff::Scalar newvalue)
{
gosASSERT((0 <= nIdx) && (nIdx < DmgModifier_Count * 2));
m_aDamageModifier[nIdx] = newvalue;
}
// to here by jcem
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::Initialize(Entity *entity)
{
Check_Object(this);
Check_Object(entity);
parentEntity = entity;
DetermineDamageLevel();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
DamageObject::DetermineDamageLevel()
{
Check_Object(this);
int damage_level = NoArmorDamage;
Scalar damage_percentage;
if (baseArmorValue == 0)
damage_percentage = 0;
else
damage_percentage = currentArmorValue / baseArmorValue;
if(damage_percentage < 0.01f)
{
if(internalDamageObject)
{
if(internalDamageObject->currentInternalDamage <= 0.0f)
{
return InternalDestroyedDamage;
}
}
damage_level = ArmorDestroyedDamage;
}
else if(damage_percentage < 0.1f)
damage_level = BadArmorDamage;
else if(damage_percentage < 0.5f)
damage_level = MediumArmorDamage;
else if(damage_percentage < 0.75f)
damage_level = PartialArmorDamage;
return damage_level;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::TakeDamage(Entity__TakeDamageMessage *message, Entity *entity_hit)
{
Check_Object(this);
Check_Object(parentEntity);
Scalar internal_damage_taken = 0.0f;
// from here by jcem
if (message->typeOfDamage == SplashDamageType)
message->amountOfDamage *= m_aDamageModifier[DmgModifier_Splash * 2];
else
// to here by jcem
message->amountOfDamage *= m_aDamageModifier[DmgModifier_Default * 2];
// MSL 5.05 Advance Mode
if (message->amountOfModifier)
{
message->amountOfDamage *= 0.5f;
}
if (message->amountOfDamage < 0.1f)
message->amountOfDamage = 0.1f;
parentEntity->ReactToHit(message,this);
if (entity_hit != NULL)
{
entity_hit->ApplyVisualDamage(message, armorZone);
}
if (g_nMR == 2) {
Stuff::Scalar amount_of_damage = message->amountOfDamage;
if (message->typeOfDamage == SplashDamageType)
{
amount_of_damage *= scaleSplashDamage;
}
if (GetCurrentDamageLevel() == Destroyed)
{
//internal_damage_taken = amount_of_damage;
internalDamageObject->TakeDamage(amount_of_damage/*internal_damage_taken*/, message);
}
parentEntity->ReactToDamageTaken(amount_of_damage/*damage_actually_taken*/,message->inflictingEntityID,message->weaponID,(int)message->typeOfDamage);
return;
}
// if we are the server deal the damage...
// FUTURE UPGRADES!!!!!!
// If we are an instant weapon (beam) on the server take the damage
// Anything else gets the info stuck in a damage accumulator.
// That accumulator gets sent now and again.
if (Network::GetInstance()->AmIServer())
{
Stuff::Scalar amount_of_damage = message->amountOfDamage;
//only apply this if there is armor left
// MSL 5.03 Damage vs Armor Type Modified
// MSL 5.04 Penalty reduced from .667 to .333
// MSL 5.05 Corrected Formulas and changed to 40/40 reduction/penalty
if(currentArmorValue > 0)
{
if (m_armorType == ReflectiveArmor)
{
if(message->typeOfDamage == BeamDamageType)
{
amount_of_damage = amount_of_damage - (amount_of_damage * 0.4f);
}
if(message->typeOfDamage == ProjectileDamageType)
{
amount_of_damage = amount_of_damage + (amount_of_damage * 0.4f);
}
if(message->typeOfDamage == MissileDamageType)
{
amount_of_damage = amount_of_damage + (amount_of_damage * 0.4f);
}
}
if (m_armorType == ReactiveArmor)
{
if(message->typeOfDamage == ProjectileDamageType)
{
amount_of_damage = amount_of_damage - (amount_of_damage * 0.4f);
}
if(message->typeOfDamage == MissileDamageType)
{
amount_of_damage = amount_of_damage - (amount_of_damage * 0.4f);
}
if(message->typeOfDamage == BeamDamageType)
{
amount_of_damage = amount_of_damage + (amount_of_damage * 0.4f);
}
}
if (m_armorType == SolarianArmor)
{
if(message->typeOfDamage == ProjectileDamageType)
{
amount_of_damage = amount_of_damage - (amount_of_damage * 0.75f);
}
if(message->typeOfDamage == MissileDamageType)
{
amount_of_damage = amount_of_damage - (amount_of_damage * 0.75f);
}
if(message->typeOfDamage == BeamDamageType)
{
amount_of_damage = amount_of_damage - (amount_of_damage * 0.75f);
}
}
}
if(currentArmorValue == baseArmorValue)
{
internalDamageObject->m_firstHitTime = gos_GetElapsedTime() + 1.0f;
}
if (message->typeOfDamage == SplashDamageType)
{
amount_of_damage *= scaleSplashDamage;
}
Stuff::Scalar damage_actually_taken = amount_of_damage;
if(currentArmorValue > 0.0f)
{
currentArmorValue -= amount_of_damage;
if (m_HitPointPointer)
{
*m_HitPointPointer -= amount_of_damage;
}
if(currentArmorValue < 0.0f)
{
damage_actually_taken += currentArmorValue;
internal_damage_taken = 0.0f - currentArmorValue;
if (m_HitPointPointer)
{
*m_HitPointPointer += internal_damage_taken; // will be removed in internal damage object
}
currentArmorValue = 0.0f;
}
}
else
{
internal_damage_taken = amount_of_damage;
}
if (internal_damage_taken > 0.0f)
{
Check_Object(internalDamageObject);
damage_actually_taken += internalDamageObject->TakeDamage(internal_damage_taken, message);
}
parentEntity->ReactToDamageTaken(damage_actually_taken,message->inflictingEntityID,message->weaponID,(int)message->typeOfDamage);
}
else
{
Stuff::Scalar amount_of_damage = message->amountOfDamage;
if (message->typeOfDamage == SplashDamageType)
{
amount_of_damage *= scaleSplashDamage;
}
if (GetCurrentDamageLevel() == Destroyed)
{
internal_damage_taken = amount_of_damage;
internalDamageObject->TakeDamage(internal_damage_taken, message);
}
}
RefrehDamageState(); // jcem
}
void DamageObject::RefrehDamageState()
{
// jcem - Recalc/Refresh current DamageLevel/damageArrayEntry/armorLevel/armorArrayEntry
// this will be called after the modification of (currentArmorValue, internalDamageObject->currentInternalDamage...)
damageLevel = DetermineDamageLevel();
if(damageArrayEntry)
{
*damageArrayEntry = damageLevel;
}
Scalar damage_percentage;
if(internalDamageObject)
damage_percentage = (currentArmorValue+internalDamageObject->currentInternalDamage) / (baseArmorValue+internalDamageObject->baseInternalDamage);
else
damage_percentage = (currentArmorValue) / (baseArmorValue);
armorLevel = damage_percentage;
if (armorArrayEntry)
*armorArrayEntry = damage_percentage;
}
void DamageObject::RepairDamage(Scalar fRepair)
{
Stuff::Scalar fValue;
if (internalDamageObject)
{
fValue = internalDamageObject->baseInternalDamage * fRepair;
internalDamageObject->currentInternalDamage += fValue;
if (internalDamageObject->baseInternalDamage < internalDamageObject->currentInternalDamage)
{
fValue = internalDamageObject->currentInternalDamage - internalDamageObject->baseInternalDamage;
internalDamageObject->currentInternalDamage = internalDamageObject->baseInternalDamage;
}
else
{
fValue = 0.0;
}
}
else
{
fValue = 0.0;
}
fValue += (baseArmorValue * fRepair);
currentArmorValue += fValue;
if (baseArmorValue < currentArmorValue)
currentArmorValue = baseArmorValue;
RefrehDamageState();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
DamageObject::ArmorZoneTextToAscii(const char *armor_name)
{
if(!_stricmp(armor_name, "NullZone"))
return NullArmorZone;
else if(!_stricmp(armor_name, "LeftLeg"))
return LeftLegArmorZone;
else if(!_stricmp(armor_name, "RightLeg"))
return RightLegArmorZone;
else if(!_stricmp(armor_name, "LeftArm"))
return LeftArmArmorZone;
else if(!_stricmp(armor_name, "RightArm"))
return RightArmArmorZone;
else if(!_stricmp(armor_name, "RightTorso"))
return RightTorsoArmorZone;
else if(!_stricmp(armor_name, "LeftTorso"))
return LeftTorsoArmorZone;
else if(!_stricmp(armor_name, "CenterTorso"))
return CenterTorsoArmorZone;
else if(!_stricmp(armor_name, "CenterRearTorso"))
return CenterRearTorsoArmorZone;
else if(!_stricmp(armor_name, "Head"))
return HeadArmorZone;
else if(!_stricmp(armor_name, "Special1"))
return SpecialArmorZone1;
else if(!_stricmp(armor_name, "Special2"))
return SpecialArmorZone2;
return DefaultArmorZone;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
const char *
DamageObject::ArmorZoneAsciiToText(int armor_zone)
{
switch(armor_zone)
{
case NullArmorZone:
return "Null";
case LeftLegArmorZone:
return "LeftLeg";
case RightLegArmorZone:
return "RightLeg";
case LeftArmArmorZone:
return "LeftArm";
case RightArmArmorZone:
return "RightArm";
case RightTorsoArmorZone:
return "RightTorso";
case LeftTorsoArmorZone:
return "LeftTorso";
case CenterTorsoArmorZone:
return "CenterTorso";
case CenterRearTorsoArmorZone:
return "CenterRearTorso";
case HeadArmorZone:
return "Head";
case SpecialArmorZone1:
return "Special1";
case SpecialArmorZone2:
return "Special2";
}
return "Default";
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::SetType(int new_type)
{
Check_Object(this);
// MSL 5.0 Armor
// Verify(new_type >= FerroFiberusArmor);
Verify(new_type >= StandardArmor);
Verify(new_type < TypeCount);
m_armorType = new_type;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::AppendArmor(Scalar additive_armor)
{
Check_Object(this);
baseArmorValue += additive_armor;
currentArmorValue += additive_armor;
if (m_HitPointPointer)
{
*m_HitPointPointer += additive_armor;
}
Clamp(baseArmorValue, 1.0f, maxArmorValue);
if (currentArmorValue > maxArmorValue)
{
if (m_HitPointPointer)
{
*m_HitPointPointer -= (currentArmorValue - maxArmorValue);
}
}
Clamp(currentArmorValue, 1.0f, maxArmorValue);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
DamageObject::CanRepair()
{
Check_Object(this);
Check_Object(internalDamageObject);
bool value = false;
if((internalDamageObject->GetCurrentDamageLevel() != InternalDamageObject::Destroyed) &&
(GetCurrentDamageLevel() != NoDamage))
{
value = true;
}
return value;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageObject::TestInstance()
{
Verify(IsDerivedFrom(DefaultData));
}
//#############################################################################
//########################### InternalDamageObject #######################
//#############################################################################
InternalDamageObject::ClassData*
InternalDamageObject::DefaultData = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
InternalDamageObjectClassID,
"Adept::InternalDamageObject",
Receiver::DefaultData,
0,
NULL
);
Check_Object(DefaultData);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::TerminateClass()
{
Check_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
InternalDamageObject::InternalDamageObject(
ClassData *class_data,
MemoryStream *stream
):
Receiver(class_data),
m_sites(NULL, true),
// The same sites were being returned for each call. The iterators
// are now seperated into a weapon port iterator and and eject port
// iterator. Added this change to Vengeance, too --CBT 1/10/2002
m_weaponSiteIterator (&m_sites),
m_ejectionSiteIterator (&m_sites)
{
Check_Pointer(this);
Check_Object(stream);
//Need to stream stuff in here
*stream >> baseInternalDamage;
*stream >> currentInternalDamage;
*stream >> parentEntityName;
*stream >> damageMode;
*stream >> damageZone;
*stream >> damagePropagationZoneID;
*stream >> m_internalType;
*stream >> m_specialConnectedTo;
MemoryStreamIO_Read(stream, &damageEffects);
// MSL 5.02 headshot
if (damageMode == HeadShotDamageMode)
{
m_headShotFlag = true;
// MSL 5.05 Damage Mode
// damageMode = DestructionDamageMode;
}
else
m_headShotFlag = false;
// MSL 5.03 Gyro Hit
if (damageMode == GyroHitDamageMode)
{
m_gyrohitFlag = true;
// MSL 5.05 Damage Mode
damageMode = DestructionDamageMode;
}
else
m_gyrohitFlag = false;
currentDamageEffectResourceID = ResourceID::Null;
damagePropagationObject = NULL;
parentEntity = NULL;
currentDamageEffect = NULL;
m_HitPointPointer = NULL;
m_firstHitTime = gos_GetElapsedTime();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void*
InternalDamageObject::operator new(size_t size)
{
/*
gos_PushCurrentHeap(g_DamageObjectHeap);
void *temp = ::new(size_t);
gos_PopCurrentHeap();
return temp;
*/
return gos_Malloc(size,g_DamageObjectHeap);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::Reuse()
{
Check_Object(this);
m_HitPointPointer = NULL;
currentInternalDamage = baseInternalDamage;
currentDamageEffectResourceID = ResourceID::Null;
currentDamageEffect = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::ConstructInternalDamageObjectStream(
MemoryStream *stream,
Page *page,
RegisteredClass::ClassID class_id
)
{
Check_Object(stream);
Check_Object(page);
int
damage_zone;
int
damage_prop_zone = NullZone;
const char *internal_zone = "";
page->GetEntry("DamageZone", &internal_zone, true);
damage_zone = InternalZoneTextToAscii(internal_zone);
const char *zone_name;
if(page->GetEntry("DamagePropagationZone",&zone_name))
damage_prop_zone = InternalZoneTextToAscii(zone_name);
int attached_to = NullZone;
const char *attached_to_string;
if(page->GetEntry("SpecialAttachedToZone", &attached_to_string))
attached_to = InternalZoneTextToAscii(attached_to_string);
const char *parent_name = "NullParent";
page->GetEntry("ParentEntityName", &parent_name);
MString parent_entity_name = parent_name;
int
damage_mode;
const char *mode_name = "";
page->GetEntry("DamageMode", &mode_name);
damage_mode = DamageModeTextToAscii(mode_name);
Stuff::Scalar
base_internal_damage,
current_internal_damage,
base_armor_value,
current_armor_value;
page->GetEntry("BaseInternalDamage", &base_internal_damage, true);
Verify(base_internal_damage > 0);
if (!page->GetEntry("CurrentInternalDamage", &current_internal_damage))
{
current_internal_damage = base_internal_damage;
}
base_armor_value = 0.0f;
page->GetEntry("BaseArmorValue", &base_armor_value);
Verify(base_armor_value >= 0.0f);
if (!page->GetEntry("CurrentArmorValue", &current_armor_value))
{
current_armor_value = base_armor_value;
}
//
//---------------------------------------------
//Create the array of Damage Effect ResourceIDs
//---------------------------------------------
//
DynamicArrayOf<DamageEffectObject> damage_effects;
ChainOf<Note*> *list = page->MakeNoteChain("DamageEffect");
Check_Object(list);
Page::NoteIterator notes(list);
int entry_count = notes.GetSize();
Verify(entry_count >= 0);
damage_effects.SetLength(entry_count);
Note *note;
int i;
//
// For each entry, make entry in damage effect array
//
for (
i = 0;
(note = notes.ReadAndNext()) != NULL && i < entry_count;
i++
)
{
Check_Object(note);
const char *entry_data;
note->GetEntry(&entry_data);
Check_Pointer(entry_data);
MString entry_string;
MString effect_file_name;
entry_string = entry_data;
effect_file_name = entry_string.GetNthToken(0, ",");
Check_Object(Tool::Instance);
Check_Object(ResourceManager::Instance);
Resource effect_resource;
Tool::Instance->ConstructDataList(&effect_resource, effect_file_name);
Check_Object(&effect_resource);
Verify(effect_resource.DoesResourceExist());
MString percent_armor_string;
Scalar percent_armor;
percent_armor_string = entry_string.GetNthToken(1, ",");
sscanf(
percent_armor_string,
"%f ",
&percent_armor
);
damage_effects[i].resourceID = effect_resource.GetResourceID();
damage_effects[i].armorPercent = percent_armor;
}
Check_Object(list);
delete list;
int internal_type = DefaultInternalType;
*stream << class_id;
*stream << base_internal_damage;
*stream << current_internal_damage;
*stream << parent_entity_name;
*stream << damage_mode;
*stream << damage_zone;
*stream << damage_prop_zone;
*stream << internal_type;
*stream << attached_to;
MemoryStreamIO_Write(stream, &damage_effects);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::Save(MemoryStream *stream, RegisteredClass::ClassID class_id)
{
Check_Object(this);
*stream << class_id;
*stream << baseInternalDamage;
*stream << currentInternalDamage;
*stream << parentEntityName;
*stream << damageMode;
*stream << damageZone;
*stream << damagePropagationZoneID;
*stream << m_internalType;
*stream << m_specialConnectedTo;
MemoryStreamIO_Write(stream, &damageEffects);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
InternalDamageObject::~InternalDamageObject()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::Initialize(Entity *entity)
{
Check_Object(this);
Check_Object(entity);
parentEntity = entity;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
InternalDamageObject::TakeDamage(Scalar damage_taken, Entity__TakeDamageMessage *message)
{
Check_Object(this);
Check_Object(parentEntity);
Stuff::Scalar damage_already_distributed = 0.0f;
Scalar rv = 0;
if (g_nMR == 2) {
PlayDamageEffects(message);
//parentEntity->ReactToInternalDamage(damageMode);
return rv;
}
if (Network::GetInstance()->AmIServer())
{
if (currentInternalDamage > 0.0f)
{
rv = damage_taken;
if((damageMode == DestructionDamageMode) &&
(damageZone > NullZone) &&
(damageZone < VehicleHullZone) &&
(gos_GetElapsedTime() < m_firstHitTime) &&
(message->typeOfDamage != HighExplosiveDamageType))
{
if (m_HitPointPointer)
{
*m_HitPointPointer -= damage_taken;
}
currentInternalDamage -= damage_taken;
if (currentInternalDamage < 0.9f)
{
if (m_HitPointPointer)
{
*m_HitPointPointer += (0.9f - currentInternalDamage);
}
}
Min_Clamp(currentInternalDamage, 0.09f);
}
else
{
//
// If we've already used up some of the damage here, we don't want to propagate it
// below. Note that since we check for currentInternalDamage being <= 0 below we know that
// we only get there if damage_take > currentInternalDamage so it is safe to assume
// currentInternalDamage is the amount of damage already taken.
//
damage_already_distributed = currentInternalDamage;
if (m_HitPointPointer)
{
*m_HitPointPointer -= damage_taken;
}
currentInternalDamage -= damage_taken;
}
PlayDamageEffects(message);
// MSL 5.02 Head Shot
// MSL 5.03 Gyro Hit
if (m_headShotFlag == true)
parentEntity->ReactToInternalDamage(HeadShotDamageMode);
else
if (m_gyrohitFlag == true)
parentEntity->ReactToInternalDamage(GyroHitDamageMode);
else
parentEntity->ReactToInternalDamage(damageMode);
InflictCriticalHit();
}
if(currentInternalDamage <= 0.0f)
{
if(damagePropagationObject)
{
Check_Object(damagePropagationObject);
Scalar prop_amount = 0.0f;
// MSL 5.05 Used to determine percentage of damage propagated.
switch(m_internalType)
{
case StandardInternal:
prop_amount = 0.85f;
break;
case EndoSteelInternal:
prop_amount = 1.0f;
break;
}
// MSL 5.05 If Advancemode then modify propagation damage
if (message->amountOfModifier)
{
prop_amount *= 0.5f;
}
//
// If two items point to each other they can cause recursion that we don't want
// when both become destroyed. The legs pointing at each other causes this
//
// This solution won't work if they ever put in second order propagation, ie...
// lleg -> rleg (if destroyed) -> centertorso, or lleg->ltorso->ctorso
// The first case isn't supported by the code, and the second won't work once the
// ltorso is destroyed. The damage won't get to the center torso
if (damagePropagationObject->currentInternalDamage > 0.0f)
{
rv += damagePropagationObject->TakeDamage((Scalar)((damage_taken - damage_already_distributed) * prop_amount), message);
}
}
if(!parentEntity->IsDestroyed())
parentEntity->ReactToDestruction(damageMode, message->typeOfDamage);
}
}
else
{
// create the effects
PlayDamageEffects(message);
// MSL 5.02 Head Shot
// MSL 5.03 Gyro Hit
if (m_headShotFlag == true)
parentEntity->ReactToInternalDamage(HeadShotDamageMode);
else
if (m_gyrohitFlag == true)
parentEntity->ReactToInternalDamage(GyroHitDamageMode);
else
parentEntity->ReactToInternalDamage(damageMode);
}
return (rv);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::PlayDamageEffects(Entity__TakeDamageMessage *message)
{
Check_Object(this);
Check_Object(message);
if (message->quickDamage) // boardgame mode hit
return;
ResourceID want_to_play_effect;
want_to_play_effect = GetDamageEffectID();
if((currentDamageEffectResourceID == want_to_play_effect) ||
(want_to_play_effect == ResourceID::Null))
{
return;
}
currentDamageEffectResourceID = want_to_play_effect;
ClassID class_ID;
class_ID = Entity::GetClassIDFromDataListID(currentDamageEffectResourceID);
Verify(class_ID != NullClassID);
Effect::CreateMessage effect_create_message(
sizeof(Effect::CreateMessage),
DefaultEventPriority,
Entity::CreateMessage::DefaultFlags,
class_ID,
Effect::DefaultFlags,
currentDamageEffectResourceID,
LinearMatrix4D::Identity,
0.0f,
Entity::ExecutionStateEngine::AlwaysExecuteState,
NameTable::NullObjectID,
Entity::DefaultAlignment
);
MemoryStream stream(&effect_create_message, effect_create_message.messageLength);
Entity *entity;
ReplicatorID effect_id = Connection::Hermit->GetNextReplicatorID();
entity = Entity::CreateEntity(&stream, &effect_id, false);
Check_Object(entity);
currentDamageEffect =
Cast_Object(Effect *, entity);
Check_Object(Map::GetInstance());
Map::GetInstance()->AddChild(entity);
LinearMatrix4D effect_position = LinearMatrix4D::Identity;
// effect_position.AlignAxis(message->normal, Y_Axis, X_Axis, Z_Axis);
effect_position.BuildTranslation(message->hitOffset);
LinearMatrix4D effect_offset = LinearMatrix4D::Identity;
Point3D effect_offset_position;
Check_Object(parentEntity);
effect_offset_position.MultiplyByInverse(message->hitOffset, parentEntity->GetLocalToWorld());
effect_offset.BuildTranslation(effect_offset_position);
currentDamageEffect->SetFollowEntity(parentEntity);
currentDamageEffect->effectOffset = effect_offset;
entity->SetNewLocalToParent(effect_position);
entity->SyncMatrices(true);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ResourceID
InternalDamageObject::GetDamageEffectID()
{
Check_Object(this);
Scalar closest_armor = 1.0f;
ResourceID return_id;
return_id = ResourceID::Null;
for (int i = 0; i < damageEffects.GetLength(); i++)
{
Scalar damage_num = damageEffects[i].armorPercent;
if ((damage_num >= (currentInternalDamage / baseInternalDamage))
&& (damage_num <= closest_armor))
{
closest_armor = damage_num;
return_id = damageEffects[i].resourceID;
}
}
return return_id;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int InternalDamageObject::GetCurrentDamageLevel()
{
if (currentInternalDamage == baseInternalDamage)
{
return NoDamage;
}
if (currentInternalDamage <= 0.0f)
{
return Destroyed;
}
else
return Damaged;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void InternalDamageObject::SetCurrentDamageLevel(int level)
{
if (level != GetCurrentDamageLevel())
{
switch(level)
{
case NoDamage:
if (m_HitPointPointer)
{
*m_HitPointPointer += (baseInternalDamage - currentInternalDamage);
}
currentInternalDamage = baseInternalDamage;
break;
case Damaged:
if (m_HitPointPointer)
{
*m_HitPointPointer += ((baseInternalDamage*0.5f) - currentInternalDamage);
}
currentInternalDamage = baseInternalDamage*0.5f;
break;
case Destroyed:
if (m_HitPointPointer)
{
*m_HitPointPointer += (0-currentInternalDamage);
}
currentInternalDamage = 0.0f;
//parentEntity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0);
parentEntity->ReactToDestruction(damageMode, 0);
break;
}
}
}
// The same sites were being returned for each call. The iterators
// are now seperated into a weapon port iterator and and eject port
// iterator. Added this change to Vengeance, too --CBT 1/10/2002
Site*
InternalDamageObject::GetNextWeaponSite()
{
Check_Object(this);
Site *site = m_weaponSiteIterator.GetCurrent();
if(!site)
{
m_weaponSiteIterator.First();
site = m_weaponSiteIterator.GetCurrent();
}
else
{ //you have previously retuned a site, begin on the next
m_weaponSiteIterator.Next();
if(!m_weaponSiteIterator.GetCurrent())
m_weaponSiteIterator.First();
site = m_weaponSiteIterator.GetCurrent();
}
bool found = false;
int num = 0;
int total = m_sites.GetSize();
while((site) && (!found) && (num < total))
{
Check_Object(site);
char *name_lower = _strlwr((char *)site->GetName());
// CBT 1/24/02 - the mispelled string "missle" is included due to historical reasons
if((strstr(name_lower, "gun")) || (strstr(name_lower, "missile"))
|| (strstr(name_lower, "missle")) || (strstr(name_lower, "torsoport")))
found = true;
else
{
m_weaponSiteIterator.Next();
if(!m_weaponSiteIterator.GetCurrent())
m_weaponSiteIterator.First();
site = m_weaponSiteIterator.GetCurrent();
num ++;
}
}
if(found)
return site;
return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Site*
InternalDamageObject::GetNextEjectSite()
{
Site *site = m_ejectionSiteIterator.GetCurrent();
if(!site)
{
m_ejectionSiteIterator.First();
site = m_ejectionSiteIterator.GetCurrent();
}
else
{ //you have previously returned a site, begin on the next
m_ejectionSiteIterator.Next();
if(!m_ejectionSiteIterator.GetCurrent())
m_ejectionSiteIterator.First();
site = m_ejectionSiteIterator.GetCurrent();
}
bool found = false;
int num = 0;
int total = m_sites.GetSize();
while((site) && (!found) && (num < total))
{
Check_Object(site);
char *name_lower = _strlwr((char *)site->GetName());
if(strstr(name_lower, "shellport"))
found = true;
else
{
m_ejectionSiteIterator.Next();
if(!m_ejectionSiteIterator.GetCurrent())
m_ejectionSiteIterator.First();
site = m_ejectionSiteIterator.GetCurrent();
num ++;
}
}
if(found)
return site;
return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void InternalDamageObject::SilentDestruction()
{
if (m_HitPointPointer)
{
*m_HitPointPointer += (0-currentInternalDamage);
}
currentInternalDamage = 0.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int DamageObject::GetCurrentDamageLevel()
{
if (currentArmorValue == baseArmorValue)
{
return NoDamage;
}
if (currentArmorValue <= 0.0f)
{
return Destroyed;
}
else
return Damaged;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DamageObject::SetCurrentDamageLevel(int level)
{
if (level != GetCurrentDamageLevel())
{
switch(level)
{
case NoDamage:
if (m_HitPointPointer)
{
*m_HitPointPointer += (baseArmorValue - currentArmorValue);
}
currentArmorValue = baseArmorValue;
break;
case Damaged:
if (m_HitPointPointer)
{
*m_HitPointPointer += ((baseArmorValue*0.5f) - currentArmorValue);
}
currentArmorValue = baseArmorValue*0.5f;
break;
case Destroyed:
if (m_HitPointPointer)
{
*m_HitPointPointer += (0 - currentArmorValue);
}
currentArmorValue = 0.0f;
break;
}
}
damageLevel = DetermineDamageLevel();
if(damageArrayEntry)
{
*damageArrayEntry = damageLevel;
}
Scalar damage_percentage;
if(internalDamageObject)
damage_percentage = (currentArmorValue+internalDamageObject->currentInternalDamage) / (baseArmorValue+internalDamageObject->baseInternalDamage);
else
damage_percentage = (currentArmorValue) / (baseArmorValue);
armorLevel = damage_percentage;
if (armorArrayEntry)
*armorArrayEntry = damage_percentage;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Fix Bug #3100
// Damage Object are now refreshed when a mech sustains internal damage
void DamageObject::RefreshCurrentDamageLevel()
{
damageLevel = DetermineDamageLevel();
if(damageArrayEntry)
{
*damageArrayEntry = damageLevel;
}
Scalar damage_percentage;
if(internalDamageObject)
damage_percentage = (currentArmorValue+internalDamageObject->currentInternalDamage) / (baseArmorValue+internalDamageObject->baseInternalDamage);
else
damage_percentage = (currentArmorValue) / (baseArmorValue);
armorLevel = damage_percentage;
if (armorArrayEntry)
*armorArrayEntry = damage_percentage;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DamageObject::SilentDestruction()
{
if (m_HitPointPointer)
{
*m_HitPointPointer += (0 - currentArmorValue);
}
currentArmorValue = 0.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar DamageObject::GetHighResDamageLevel()
{
Scalar damage_level = currentArmorValue/baseArmorValue;
Clamp(damage_level, 0.0f, 1.0f);
return damage_level;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void DamageObject::SetHighResDamageLevel(Scalar damage_percentage)
{
if (m_HitPointPointer)
{
*m_HitPointPointer += ((baseArmorValue * damage_percentage) - currentArmorValue);
}
currentArmorValue = baseArmorValue * damage_percentage;
damageLevel = DetermineDamageLevel();
if(damageArrayEntry)
{
*damageArrayEntry = damageLevel;
}
Scalar fred;
if(internalDamageObject)
fred = (currentArmorValue+internalDamageObject->currentInternalDamage) / (baseArmorValue+internalDamageObject->baseInternalDamage);
else
fred = (currentArmorValue) / (baseArmorValue);
armorLevel = fred;
if (armorArrayEntry)
*armorArrayEntry = fred;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar InternalDamageObject::GetHighResDamageLevel()
{
Scalar damage_level = currentInternalDamage/baseInternalDamage;
Clamp(damage_level, 0.0f, 1.0f);
return damage_level;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void InternalDamageObject::SetHighResDamageLevel(Scalar damage_percentage)
{
if (GetCurrentDamageLevel() != Destroyed)
{
if (m_HitPointPointer)
{
*m_HitPointPointer += ((baseInternalDamage*damage_percentage)-currentInternalDamage);
}
currentInternalDamage = baseInternalDamage*damage_percentage;
if (damage_percentage == 0.0f)
{
if (m_HitPointPointer)
{
*m_HitPointPointer += (0-currentInternalDamage);
}
currentInternalDamage = 0.0f;
//parentEntity->ReactToDestruction(InternalDamageObject::DestructionDamageMode, 0);
parentEntity->ReactToDestruction(damageMode, 0);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
InternalDamageObject::DamageModeTextToAscii(const char *mode_name)
{
if(!_stricmp(mode_name, "GimpLeftDamageMode"))
return GimpLeftDamageMode;
else if(!_stricmp(mode_name, "GimpRightDamageMode"))
return GimpRightDamageMode;
else if(!_stricmp(mode_name, "DestructionDamageMode"))
return DestructionDamageMode;
// MSL 5.02 headshot
else if (!_stricmp(mode_name, "HeadShotDamageMode"))
return HeadShotDamageMode;
// MSL 5.03 Gyro Hit
else if (!_stricmp(mode_name, "GyroHitDamageMode"))
return GyroHitDamageMode;
else if(!_stricmp(mode_name, "DetachableDamageMode"))
return DetachableDamageMode;
// MSL 5.02 Engine
else if(!_stricmp(mode_name, "EngineDamageMode"))
return EngineDamageMode;
// MSL 5.05 Torso
else if(!_stricmp(mode_name, "TorsoLeftDamageMode"))
return TorsoLeftDamageMode;
else if(!_stricmp(mode_name, "TorsoRightDamageMode"))
return TorsoRightDamageMode;
else if(!_stricmp(mode_name, "ArmLeftDamageMode"))
return ArmLeftDamageMode;
else if(!_stricmp(mode_name, "ArmRightDamageMode"))
return ArmRightDamageMode;
return GeneralDamageMode;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
const char *
InternalDamageObject::DamageModeAsciiToText(int damage_mode)
{
switch(damage_mode)
{
case GimpLeftDamageMode:
return "GimpLeftDamageMode";
case GimpRightDamageMode:
return "GimpRightDamageMode";
case DestructionDamageMode:
return "DestructionDamageMode";
// MSL 5.02 headshot
case HeadShotDamageMode:
return "HeadShotDamageMode";
// MSL 5.03 Gyro Hit
case GyroHitDamageMode:
return "GyroHitDamageMode";
case DetachableDamageMode:
return "DetachableDamageMode";
case EngineDamageMode:
return "EngineDamageMode";
// MSL 5.05 Torso
case TorsoLeftDamageMode:
return "TorsoLeftDamageMode";
case TorsoRightDamageMode:
return "TorsoRightDamageMode";
case ArmLeftDamageMode:
return "ArmLeftDamageMode";
case ArmRightDamageMode:
return "ArmRightDamageMode";
}
return "GeneralDamageMode";
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
InternalDamageObject::InternalZoneTextToAscii(const char *mode_name)
{
if(!_stricmp(mode_name, "NullZone"))
return NullZone;
else if(!_stricmp(mode_name, "LeftLeg"))
return LeftLegZone;
else if(!_stricmp(mode_name, "RightLeg"))
return RightLegZone;
else if(!_stricmp(mode_name, "LeftArm"))
return LeftArmZone;
else if(!_stricmp(mode_name, "RightArm"))
return RightArmZone;
else if(!_stricmp(mode_name, "RightTorso"))
return RightTorsoZone;
else if(!_stricmp(mode_name, "LeftTorso"))
return LeftTorsoZone;
else if(!_stricmp(mode_name, "CenterTorso"))
return CenterTorsoZone;
else if(!_stricmp(mode_name, "Head"))
return HeadZone;
else if(!_stricmp(mode_name, "Special1"))
return SpecialZone1;
else if(!_stricmp(mode_name, "Special2"))
return SpecialZone2;
else if(!_stricmp(mode_name, "VehicleHull"))
return VehicleHullZone;
else if(!_stricmp(mode_name, "VehicleWeapon"))
return VehicleWeaponZone;
else if(!_stricmp(mode_name, "VehicleSpecial"))
return VehicleSpecialZone;
return DefaultZone;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
const char *
InternalDamageObject::InternalZoneAsciiToText(int internal_zone)
{
switch(internal_zone)
{
case NullZone:
return "Null";
case LeftLegZone:
return "LeftLeg";
case RightLegZone:
return "RightLeg";
case LeftArmZone:
return "LeftArm";
case RightArmZone:
return "RightArm";
case RightTorsoZone:
return "RightTorso";
case LeftTorsoZone:
return "LeftTorso";
case CenterTorsoZone:
return "CenterTorso";
case HeadZone:
return "Head";
case SpecialZone1:
return "Special1";
case SpecialZone2:
return "Special2";
case VehicleHullZone:
return "VehicleHull";
case VehicleWeaponZone:
return "VehicleWeapon";
case VehicleSpecialZone:
return "VehicleSpecial";
}
return "Default";
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::SetType(int new_type)
{
Check_Object(this);
Verify(new_type >= StandardInternal);
Verify(new_type < TypeCount);
m_internalType = new_type;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
InternalDamageObject::TestInstance()
{
Verify(IsDerivedFrom(DefaultData));
}
void __cdecl Adept::AdeptDamageSecurityCheckStop(void)
{
_asm
{
nop
}
}