Files
BT411/engine/MUNGA/DAMAGE.cpp
T
Joe DiPrimaandClaude Opus 5 5d6ded73f0 #110: cross-pod verified BOTH ways -- the cascade replicates, and peer fire alone drives it
Two two-node benches close the last stated gap ("no two-node run has watched a
peer's view of an arm death"), the second at the user's insistence on the REAL
field composition after the first used the self-damage scalpel:

1. mp_armchain.sh (scalpel): B self-destroys dz_rarm mid-fight.  A's screen
   receives the whole cascade -- [zone-repl] dz_rarm lvl 0->1 AND the cascaded
   dz_rgun lvl 0->1 -- plus the respawn reset coming back clean (1->0).  B's
   post-cascade AFC pushes turned out to be the RESPAWN RE-ARM, correct
   behavior, not a gate failure.  (Also confirmed: the self-damage harness
   dispatches a real Entity::TakeDamageMessage -- the identical path a peer's
   round takes, so the scalpel and the field share every line from the handler
   down.)

2. mp_armgrind.sh (the field composition): stand-off at 180, NO self-damage
   anywhere, A grinding B with real cross-pod fire for six minutes.  On B:
     * 25 incremental arm-zone hits from A's weapons via the cylinder tables
       (dz_rgun reached 1.0 from pure accumulation -- 15 cascades on rehits)
     * dz_rarm finished by B's OWN AFC bay cooking off (AmmoBinAFC100 BAY FIRE
       350, half into dz_rarm) -- itself lit by A's fire crits: peer-originated
       end to end
     * [cascade] zone 9 -> AFC100 + AmmoBinAFC100 + Condenser6 force-failed,
       fire gate refusals logged
   On A: [zone-repl] dz_rarm 0->1 and dz_rgun 0->1 -- the shooter SEES the arm
   and pod die.  B symmetrically received A's torso deaths.

Also: DamageZone::ReadUpdateRecord gets a change-only [zone-repl] diagnostic
(BT_MP_LOG) -- the probe that made the peer side measurable; mp_armgrind.sh
opens with the stale-node taskkill the other benches already had (a leftover
node from an aborted launch joined a later lobby as a third instance).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 09:09:49 -05:00

813 lines
18 KiB
C++

#include "munga.h"
#pragma hdrstop
#include "segment.h"
#include "exptbl.h"
#include "fileutil.h"
#include "jmover.h"
#include "schain.h"
#include "notation.h"
#include "namelist.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MaterialList::MaterialList() :
materialList(NULL)
{
listIterator = new CStringSocketIterator(materialList);
Register_Object(listIterator);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MaterialList::~MaterialList()
{
DeletePlugs();
Unregister_Object(listIterator);
delete listIterator;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Damage::Damage()
{
damageAmount = 0.0f;
damageForce = Vector3D::Identity;
surfaceNormal.x = 0.0f;
surfaceNormal.y = 1.0f;
surfaceNormal.z = 0.0f;
impactPoint = Point3D::Identity;
burstCount = 1.0f;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EntitySegment*
DamageZone::GetCurrentEffectSite(Enumeration effect_site_type)
{
Check(this);
EntitySegment *return_segment;
switch(effect_site_type)
{
Return_Default_Effect:
case DefaultEffectSite:
default:
{
SChainIteratorOf<EntitySegment*> iterator(defaultEffectSiteChain);
Check(iterator.GetCurrent());
return iterator.GetCurrent();
}
case InternalVideoEffectSite:
{
SChainIteratorOf<EntitySegment*> iterator(internalVideoEffectSiteChain);
return_segment = iterator.GetCurrent();
if (return_segment)
{
Check(return_segment);
return return_segment;
}
else
{
goto Return_Default_Effect;
}
}
case ExternalVideoEffectSite:
{
SChainIteratorOf<EntitySegment*> iterator(externalVideoEffectSiteChain);
return_segment = iterator.GetCurrent();
if (return_segment)
{
Check(return_segment);
return return_segment;
}
else
{
goto Return_Default_Effect;
}
}
case InternalAudioEffectSite:
{
SChainIteratorOf<EntitySegment*> iterator(internalAudioEffectSiteChain);
return_segment = iterator.GetCurrent();
if (return_segment)
{
Check(return_segment);
return return_segment;
}
else
{
goto Return_Default_Effect;
}
}
case ExternalAudioEffectSite:
{
SChainIteratorOf<EntitySegment*> iterator(externalAudioEffectSiteChain);
return_segment = iterator.GetCurrent();
if (return_segment)
{
Check(return_segment);
return return_segment;
}
else
{
goto Return_Default_Effect;
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageZone::Reset(Logical )
{
SetDamageZoneState(DefaultState);
damageZoneGraphicState.SetState(ExistsGraphicState);
damageLevel = 0.0f;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageZone::WriteUpdateRecord(UpdateRecord *update_record)
{
Check(this);
Check_Pointer(update_record);
update_record->damageLevel = damageLevel;
update_record->damageZoneState = damageZoneState.GetState();
update_record->damageZoneGraphicState = damageZoneGraphicState.GetState();
update_record->damageZoneIndex = damageZoneIndex;
update_record->changedFlags = changedFlags;
update_record->recordLength = sizeof(*update_record);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Clear Flags here for MasterInstance DamageZones!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ResetChangedFlags();
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageZone::ReadUpdateRecord(UpdateRecord *update_record)
{
Check(this);
Check_Pointer(update_record);
Verify(damageZoneIndex == update_record->damageZoneIndex);
// #110 MP verification (BT): log a PEER-side zone state transition, so the
// two-node bench can prove the destruction cascade replicates. Change-only.
if (getenv("BT_MP_LOG")
&& (damageZoneGraphicState.GetState() != update_record->damageZoneGraphicState
|| (damageLevel < 1.0f && update_record->damageLevel >= 1.0f)))
{
DEBUG_STREAM << "[zone-repl] zone " << damageZoneIndex
<< " '" << (const char *)damageZoneName << "'"
<< " lvl " << damageLevel << "->" << update_record->damageLevel
<< " gstate " << damageZoneGraphicState.GetState()
<< "->" << update_record->damageZoneGraphicState << std::endl;
}
damageLevel = update_record->damageLevel;
damageZoneState.SetState(update_record->damageZoneState);
damageZoneGraphicState.SetState(update_record->damageZoneGraphicState);
changedFlags = update_record->changedFlags;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DamageZone::DamageZone(Simulation *owner, int damage_zone_index) :
Node(DamageZoneClassID),
materialTable(NULL, False),
damageZoneState(DamageStateCount),
damageZoneGraphicState(GraphicStateCount),
defaultEffectSiteChain(NULL),
internalVideoEffectSiteChain(NULL),
externalVideoEffectSiteChain(NULL),
internalAudioEffectSiteChain(NULL),
externalAudioEffectSiteChain(NULL)
{
Check(owner);
damageZoneIndex = damage_zone_index;
owningSimulation = owner;
damageLevel = 0.0f;
explosionTable = NULL;
for(int ii=0;ii<Damage::DamageTypeCount;ii++)
{
damageScale[ii] = 0.0f;
}
damageZoneName = "TrivialDamageZone_Name";
changedFlags = 0;
Reset();
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DamageZone::DamageZone(
Simulation *owning_simulation,
int damage_zone_index,
MemoryStream *stream
) :
Node(DamageZoneClassID),
materialTable(NULL, False),
damageZoneState(DamageStateCount),
damageZoneGraphicState(GraphicStateCount),
defaultEffectSiteChain(NULL),
internalVideoEffectSiteChain(NULL),
externalVideoEffectSiteChain(NULL),
internalAudioEffectSiteChain(NULL),
externalAudioEffectSiteChain(NULL)
{
Check(owning_simulation);
Check(stream);
owningSimulation = owning_simulation;
damageZoneIndex = damage_zone_index;
damageLevel = 0.0f;
explosionTable = NULL;
Reset();
*stream >> damageZoneName;
if (owningSimulation->IsDerivedFrom(*JointedMover::GetClassDerivations()))
{
JointedMover *jointed_mover = Cast_Object(
JointedMover*,
owningSimulation
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~
// Read in all Effect Sites
//~~~~~~~~~~~~~~~~~~~~~~~~~
//
int effect_site_count;
int effect_site_index;
EntitySegment *effect_site_segment;
//
//~~~~~~~~~~~~~~~~~~~~~~~
// Read in External Video
//~~~~~~~~~~~~~~~~~~~~~~~
//
for (int jj=0;jj<EffectSiteCount;++jj)
{
*stream >> effect_site_count;
for(int ii=0;ii<effect_site_count;++ii)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the Site Segment From the Index
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
*stream >> effect_site_index;
effect_site_segment = jointed_mover->GetSegment(effect_site_index);
Check(effect_site_segment);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Add the Segment to the Appropriate Chain
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
switch (jj)
{
case DefaultEffectSite:
defaultEffectSiteChain.Add(effect_site_segment);
break;
case ExternalVideoEffectSite :
externalVideoEffectSiteChain.Add(effect_site_segment);
break;
case InternalVideoEffectSite :
internalVideoEffectSiteChain.Add(effect_site_segment);
break;
case ExternalAudioEffectSite :
externalAudioEffectSiteChain.Add(effect_site_segment);
break;
case InternalAudioEffectSite :
internalAudioEffectSiteChain.Add(effect_site_segment);
break;
}
}
}
}
else
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Read in these for consistancy
// and for later improvements for
// not Jointed Mover Objects!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int filler_int;
for (int jj=0;jj<EffectSiteCount;++jj)
{
*stream >> filler_int;
}
}
*stream >> defaultArmorPoints;
int ii;
for (ii=0; ii<Damage::DamageTypeCount; ii++)
{
*stream >> damageScale[ii];
}
int skeleton_count;
EntitySegment::SkeletonType skl_type;
*stream >> skeleton_count;
for(ii=0;ii<skeleton_count;++ii)
{
*stream >> skl_type;
int material_count;
*stream >> material_count;
if(!material_count)
{
continue;
}
MaterialList *material_list = new MaterialList;
Register_Object(material_list);
for(int jj=0;jj<material_count;++jj)
{
CString new_material;
*stream >> new_material;
MaterialList::CStringPlug *new_plug =
new MaterialList::CStringPlug(new_material);
Register_Object(new_plug);
material_list->Add(new_plug);
}
material_list->First();
materialTable.AddValue(material_list, skl_type);
}
changedFlags = 0;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DamageZone::~DamageZone()
{
MaterialTableIterator iterator(materialTable);
iterator.DeletePlugs();
if (explosionTable)
{
Unregister_Object(explosionTable);
delete explosionTable;
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ExplosionTable*
DamageZone::CreateExplosionTable(MemoryStream *explosion_stream)
{
Check(this);
explosionTable = new ExplosionTable(explosion_stream);
Register_Object(explosionTable);
Check_Fpu();
return explosionTable;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageZone::TakeDamage(Damage &damage)
{
Check(this);
Check_Pointer(&damage);
damageLevel += damage.damageAmount * damageScale[damage.damageType];
Clamp(damageLevel, 0.0f, 1.0f);
SetDamageLevelChangedFlag();
if (damageLevel >= 1.0f)
{
SetDamageZoneState(BurningState);
SetGraphicState(DestroyedGraphicState);
SetGraphicStateChangedFlag();
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
DamageZone::TestInstance() const
{
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
DamageZone::CreateStreamedDamageZone(
NotationFile *model_file,
const char *,
NotationFile *skl_file,
CString damage_zone_name,
MemoryStream *damage_zone_stream,
NotationFile *dmg_file,
const ResourceDirectories *directories
)
{
Check_Pointer(damage_zone_name);
Check_Pointer(&damage_zone_stream);
Check_Pointer(directories);
Check(dmg_file);
*damage_zone_stream << damage_zone_name;
//
// Find dzone name in .dmg file
//
if(!dmg_file->PageExists(damage_zone_name))
{
std::cerr << damage_zone_name <<" listed in .skl, does not exist in .dmg file"<<std::endl;
Check_Fpu();
return -1;
}
if (skl_file)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Read and Write All The Effect Sites
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"DefaultEffectSiteName"
);
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"ExternalVideoEffectSiteName"
);
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"InternalVideoEffectSiteName"
);
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"ExternalAudioEffectSiteName"
);
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"InternalAudioEffectSiteName"
);
}
else
{
int zero_int(0);
for(int ii=0;ii<EffectSiteCount;++ii)
{
*damage_zone_stream << zero_int;
}
}
Scalar default_points;
if(!dmg_file->GetEntry(
damage_zone_name,
"WeaponDamagePoints",
&default_points
)
)
{
std::cerr<<damage_zone_name<<" Must have a WeaponDamagePoints"<<std::endl;
return False;
}
if (!default_points)
{
std::cerr<<"DefaultDamagePoints must have a non-zero value !"<<std::endl;
Check_Fpu();
return False;
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write default armor values
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
*damage_zone_stream << default_points;
//
// Read the damage Points values
//
float point_data;
Scalar modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"CollisionDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
if (point_data == 0.0f)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
Check_Fpu();
}
*damage_zone_stream << modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"BallisticDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
*damage_zone_stream << modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"ExplosiveDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
*damage_zone_stream << modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"LaserDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
*damage_zone_stream << modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"EnergyDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
*damage_zone_stream << modified_armor;
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get dzm filename
//~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NameList *dzm_namelist = model_file->MakeEntryList("video","dzm");
if(!dzm_namelist)
{
int zero_scalar(0.0f);
*damage_zone_stream << zero_scalar;
return True;
}
Register_Object(dzm_namelist);
int dzm_filecount;
dzm_filecount = dzm_namelist->EntryCount();
*damage_zone_stream << dzm_filecount;
if(dzm_filecount)
{
NameList::Entry *dzm_fileentry = dzm_namelist->GetFirstEntry();
while(dzm_fileentry)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// write out the skeleton type of the material
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//
CString dzm_entry_name;
dzm_entry_name = dzm_fileentry->GetName();
EntitySegment::SkeletonType skeleton_type;
if (! dzm_entry_name.Compare("dzm") )
{
skeleton_type = EntitySegment::SkeletonType_N;
}
else if (! dzm_entry_name.Compare("dzms") )
{
skeleton_type = EntitySegment::SkeletonType_S;
}
else if (! dzm_entry_name.Compare("dzmt") )
{
skeleton_type = EntitySegment::SkeletonType_T;
}
else if (! dzm_entry_name.Compare("dzmo") )
{
skeleton_type = EntitySegment::SkeletonType_O;
}
else if (! dzm_entry_name.Compare("dzma") )
{
skeleton_type = EntitySegment::SkeletonType_A;
}
else if (! dzm_entry_name.Compare("dzmb") )
{
skeleton_type = EntitySegment::SkeletonType_B;
}
else if (! dzm_entry_name.Compare("dzmc") )
{
skeleton_type = EntitySegment::SkeletonType_C;
}
else if (! dzm_entry_name.Compare("dzmd") )
{
skeleton_type = EntitySegment::SkeletonType_D;
}
*damage_zone_stream << skeleton_type;
//
// Get the name of the dzm File
//
char *filename = MakePathedFilename(
directories->videoDirectory,
dzm_fileentry->GetChar()
);
Register_Pointer(filename);
//
// Create a Notation file from the dzm ASCII File
//
NotationFile *dzm_file = new NotationFile(filename);
Register_Object(dzm_file);
NameList *material_list;
material_list = dzm_file->MakeEntryList(damage_zone_name, "material");
int entry_count(0);
if(material_list)
{
Register_Object(material_list);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write out how many materials
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
entry_count = material_list->EntryCount();
*damage_zone_stream << entry_count;
if(entry_count)
{
NameList::Entry *dzm_entry;
dzm_entry = material_list->GetFirstEntry();
Check(dzm_entry);
CString material_name;
while(dzm_entry)
{
material_name = dzm_entry->GetChar();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write out the material name
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
*damage_zone_stream << material_name;
dzm_entry = dzm_entry->GetNextEntry();
}
}
Unregister_Object(material_list);
delete material_list;
}
else
{
*damage_zone_stream << entry_count;
}
dzm_fileentry = dzm_fileentry->GetNextEntry();
Unregister_Pointer(filename);
delete filename;
Unregister_Object(dzm_file);
delete dzm_file;
}
}
Unregister_Object(dzm_namelist);
delete dzm_namelist;
Check_Fpu();
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
DamageZone::WriteEffectSegmentIndicies(
MemoryStream *damage_zone_stream,
const char *damage_zone_name,
NotationFile *dmg_file,
NotationFile *skl_file,
const char *effect_type
)
{
Check(dmg_file);
Check(skl_file);
Check_Pointer(damage_zone_name);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Make an Entry list for this type of effect Site
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int effect_count(0);
NameList::Entry *effect_entry;
NameList *effect_namelist = dmg_file->MakeEntryList(damage_zone_name, effect_type);
if (!effect_namelist)
{
//
//~~~~~~~~~~~
// No Entries
//~~~~~~~~~~~
//
*damage_zone_stream << effect_count;
Check_Fpu();
return 1;
}
else
{
Register_Object(effect_namelist);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write Out number of sites
//~~~~~~~~~~~~~~~~~~~~~~~~~~
//
effect_count = effect_namelist->EntryCount();
*damage_zone_stream << effect_count;
effect_entry = effect_namelist->GetFirstEntry();
CString site_page_name;
int effect_site_index;
while(effect_entry)
{
site_page_name = effect_entry->GetChar();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get SegmentIndex for this effect site Name
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
effect_site_index =
JointedMover::GetSegmentIndex(site_page_name, skl_file);
if (effect_site_index == -1)
{
std::cerr<<site_page_name<<" not found in skl file !"<<std::endl;
Unregister_Object(effect_namelist);
delete effect_namelist;
return -1;
}
//
//~~~~~~~~~~~~~~~~~~~~
// Write Out the Index
//~~~~~~~~~~~~~~~~~~~~
//
*damage_zone_stream << effect_site_index;
effect_entry = effect_entry->GetNextEntry();
}
Unregister_Object(effect_namelist);
delete effect_namelist;
}
Check_Fpu();
return 1;
}