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.
This commit is contained in:
Cyd
2026-06-24 21:28:16 -05:00
commit 2b8ca921cb
66341 changed files with 7923174 additions and 0 deletions
@@ -0,0 +1,597 @@
#include "MW4Headers.hpp"
#include "MWDamageObject.hpp"
#include "Subsystem.hpp"
#include "MWObject.hpp"
#include "Weapon.hpp"
#include "MWApplication.hpp"
#include "DamageDispatch.hpp"
#include "bucket.hpp"
#include "MWMission.hpp"
#include "windows.h"
#include "recscore.h" // jcem
//#############################################################################
//########################### MWInternalDamageObject #####################
//#############################################################################
extern int g_nMR;
MWInternalDamageObject::ClassData*
MWInternalDamageObject::DefaultData = NULL;
void MechWarrior4::MW4DamageSecurityCheckStart()
{
_asm
{
nop
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MWInternalDamageObject::InitializeClass()
{
Verify(!DefaultData);
DefaultData =
new ClassData(
MWInternalDamageObjectClassID,
"MechWarrior4::MWInternalDamageObject",
InternalDamageObject::DefaultData,
0,
NULL
);
Register_Object(DefaultData);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MWInternalDamageObject::TerminateClass()
{
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWInternalDamageObject::MWInternalDamageObject(
ClassData *class_data,
MemoryStream *stream
):
InternalDamageObject(class_data, stream),
// MSL 5.02 headshot
destroyedSubsystemChain(NULL),
subsystemChain(NULL)
{
Check_Pointer(this);
Check_Object(stream);
*stream >> m_maxMissileSlots;
*stream >> m_maxProjectileSlots;
*stream >> m_maxBeamSlots;
*stream >> m_maxOmniSlots;
m_missileSlotsAvailable = m_maxMissileSlots;
m_projectileSlotsAvailable = m_maxProjectileSlots;
m_beamSlotsAvailable = m_maxBeamSlots;
m_omniSlotsAvailable = m_maxOmniSlots;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MWInternalDamageObject::ConstructMWInternalDamageObjectStream(
MemoryStream *stream,
Page *instance_page
)
{
Check_Object(instance_page);
InternalDamageObject::ConstructInternalDamageObjectStream(
stream,
instance_page,
DefaultData->GetClassID()
);
int slots = 0;
instance_page->GetEntry("MissileSlots", &slots);
*stream << slots;
slots = 0;
instance_page->GetEntry("ProjectileSlots", &slots);
*stream << slots;
slots = 0;
instance_page->GetEntry("BeamSlots", &slots);
*stream << slots;
slots = 0;
instance_page->GetEntry("OmniSlots", &slots);
*stream << slots;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void*
MWInternalDamageObject::operator new(size_t size)
{
/*
gos_PushCurrentHeap(Adept::g_DamageObjectHeap);
void *temp = ::new(size_t);
gos_PopCurrentHeap();
return temp;
*/
return gos_Malloc(size,Adept::g_DamageObjectHeap);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MWInternalDamageObject::Save(MemoryStream *stream)
{
Check_Object(this);
InternalDamageObject::Save(stream, DefaultData->GetClassID());
*stream << m_maxMissileSlots;
*stream << m_maxProjectileSlots;
*stream << m_maxBeamSlots;
*stream << m_maxOmniSlots;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWInternalDamageObject::~MWInternalDamageObject()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MWInternalDamageObject::AddSubsystem(Subsystem *subsystem)
{
Check_Object(this);
Check_Object(subsystem);
int result = VerifySubsystem(subsystem);
if(result)
subsystemChain.Add(subsystem);
return result;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Subsystem*
MWInternalDamageObject::GetSubsystem(int type)
{
Check_Object(this);
ChainIteratorOf<Subsystem *> iterator(&subsystemChain);
Subsystem *subsystem;
while((subsystem = iterator.ReadAndNext()) != NULL)
{
Check_Object(subsystem);
const Subsystem::GameModel *model = subsystem->GetGameModel();
Check_Object(model);
if(model->itemID == type)
return subsystem;
}
return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MWInternalDamageObject::VerifySubsystem(Subsystem *subsystem)
{
Check_Object(this);
Check_Object(subsystem);
const Subsystem::GameModel *model = subsystem->GetGameModel();
subsystem->containedInSlotType = DoesHaveAvailableSlots(model->slotType, model->totalSlotsTaken);
return subsystem->containedInSlotType >= -1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MWInternalDamageObject::DoesHaveAvailableSlots(int slot_type, int slots_needed, bool check_omni, bool subtract_slot)
{
Check_Object(this);
switch(slot_type)
{
case -1:
return -1;
break;
case MissileSlotType:
if((m_missileSlotsAvailable - slots_needed) >= 0)
{
if(subtract_slot)
m_missileSlotsAvailable -= slots_needed;
return MissileSlotType;
}
break;
case ProjectileSlotType:
if((m_projectileSlotsAvailable - slots_needed) >= 0)
{
if(subtract_slot)
m_projectileSlotsAvailable -= slots_needed;
return ProjectileSlotType;
}
break;
case BeamSlotType:
if((m_beamSlotsAvailable - slots_needed) >= 0)
{
if(subtract_slot)
m_beamSlotsAvailable -= slots_needed;
return BeamSlotType;
}
break;
case OmniSlotType:
if((m_omniSlotsAvailable - slots_needed) >= 0)
{
if(subtract_slot)
m_omniSlotsAvailable -= slots_needed;
return OmniSlotType;
}
break;
}
if(check_omni)
{
if((m_omniSlotsAvailable - slots_needed) >= 0)
{
if(subtract_slot)
m_omniSlotsAvailable -= slots_needed;
return OmniSlotType;
}
}
return -2;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MWInternalDamageObject::FreeAvailableSlots(int slot_type, int num)
{
Check_Object(this);
switch(slot_type)
{
case MissileSlotType:
m_missileSlotsAvailable += num;
break;
case ProjectileSlotType:
m_projectileSlotsAvailable += num;
break;
case BeamSlotType:
m_beamSlotsAvailable += num;
break;
case OmniSlotType:
m_omniSlotsAvailable += num;
break;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MWInternalDamageObject::RollCriticalHit()
{
Check_Object(this);
int roll = Stuff::Random::GetLessThan(100);
if(roll <= 70)
return 0;
else if(roll >= 97)
return 3;
else if(roll >= 90)
return 2;
else
return 1;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MWInternalDamageObject::InflictCriticalHit()
{
Check_Object(this);
DamageDispatch *dispatch = DamageDispatch::GetInstance();
Check_Pointer(dispatch);
dispatch->InflictCriticalHit(*this);
}
void
MWInternalDamageObject::_InflictCriticalHit()
{
Check_Object(this);
//
//---------------------------------
//Get Number of Critical Hits taken
//---------------------------------
//
int num_crit_hits = RollCriticalHit();
ChainIteratorOf<Subsystem *> iterator(&subsystemChain);
for(int i=0; i<num_crit_hits; i++)
{
//
//---------------------------------
//Apply Critical Hits to Subsystems
//---------------------------------
//
int chain_size = iterator.GetSize();
if(chain_size > 0)
{
int roll = Stuff::Random::GetLessThan(iterator.GetSize());
Subsystem *subsystem = iterator.GetNth(roll);
Check_Object(subsystem);
bool does_destroy = subsystem->TakeCriticalHit();
if(does_destroy)
{
g_RSF.RecScore(CBucketManager::COMPONENT_DEATHS, ReplicatorID::Null, ReplicatorID::Null, 0, 0, (DWORD)subsystem); // jcem
// MSL 5.02 headshot
destroyedSubsystemChain.Add(subsystem); // So we can later completely remove the subsystem
subsystemChain.Remove(subsystem);
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
MWInternalDamageObject::TakeDamage(Scalar damage_taken, Entity__TakeDamageMessage *message)
{
Check_Object(this);
DamageDispatch *dispatch = DamageDispatch::GetInstance();
Check_Pointer(dispatch);
return (dispatch->TakeDamage(*this,damage_taken,message));
}
Scalar
MWInternalDamageObject::_TakeDamage(Scalar damage_taken, Entity__TakeDamageMessage *message)
{
Check_Object(this);
if (g_nMR == 2) {
return InternalDamageObject::TakeDamage(damage_taken, message);
}
int prev_num_subsystems = subsystemChain.GetSize();
Scalar rv = InternalDamageObject::TakeDamage(damage_taken, message);
if (Network::GetInstance()->AmIServer())
{
if(currentInternalDamage <= 0.0f)
{
KillAllContainedSubsystems();
}
}
const int num_subsystems = subsystemChain.GetSize();
if (num_subsystems < prev_num_subsystems)
{
MWApplication* mwapplication = Cast_Object(MWApplication*,MWApplication::GetInstance());
if (mwapplication->networkingFlag == false)
{
if (!mwapplication->IsCampCOOP())
return (rv);
}
MWMission *mission = Cast_Object(MWMission*,MWMission::GetInstance());
if ((mission == 0) ||
(mission->m_BucketManager == 0))
{
return (rv);
}
Adept::ReplicatorID me = parentEntity->GetReplicatorID();
const Adept::ReplicatorID& attacker = message->inflictingEntityID;
int num_subsystems_destroyed = prev_num_subsystems - num_subsystems;
if (num_subsystems_destroyed > 0)
{
MWMover *mover = Cast_Object(MWMover*, parentEntity);
Check_Object(mover);
if (mover->GetParentVehicle() && mover->GetParentVehicle()->IsDerivedFrom(Mech::DefaultData))
{
Mech *mech = Cast_Object(Mech *,mover->GetParentVehicle());
if (mech->IsDestroyed() == true)
{
return (rv);
}
me = mech->GetReplicatorID();
}
if(mover->GetParentVehicle() && mover->GetParentVehicle()->GetClassID() == MechClassID)
{
mission->m_BucketManager->NotifyAction(CBucketManager::COMPONENT_KILLS,attacker,num_subsystems_destroyed);
g_RSF.RecScore(CBucketManager::COMPONENT_KILLS, attacker, me, 0, 0, num_subsystems_destroyed); // jcem
mission->m_BucketManager->NotifyAction(CBucketManager::COMPONENT_DEATHS,me,num_subsystems_destroyed);
if (mwapplication->TeamsAreFriendly(me,attacker) == true)
{
mission->m_BucketManager->NotifyAction(CBucketManager::FRIENDLY_COMPONENT_KILLS,attacker,num_subsystems_destroyed,me);
mission->m_BucketManager->NotifyAction(CBucketManager::FRIENDLY_COMPONENT_DEATHS,me,num_subsystems_destroyed);
}
else
{
mission->m_BucketManager->NotifyAction(CBucketManager::ENEMY_COMPONENT_KILLS,attacker,num_subsystems_destroyed,me);
mission->m_BucketManager->NotifyAction(CBucketManager::ENEMY_COMPONENT_DEATHS,me,num_subsystems_destroyed);
}
}
#if !defined(NO_LOG)
// ngLog addition
int self = parentEntity->GetReplicatorID().connectionID;
int inflictor = message->inflictingEntityID.connectionID;
if(self >= 0 && inflictor >= 0) {
MWMover *mobj = Cast_Object(MWMover *, parentEntity);
Check_Object(mobj);
if(mobj && mobj->GetParentVehicle() && mobj->GetParentVehicle()->IsDerivedFrom(Mech::DefaultData)) {
Mech *mech = Cast_Object(Mech *, mobj->GetParentVehicle());
if(mech && mech->IsLanceMate()) {
self = mech->lancemateIndex + Maximum_Players;
}
}
// Check for local bots, weeding out stuff like buildings, tanks, etc.
Replicator *r = NULL;
Connection *conn = NULL;
// Check if inflictor is a bot
if(inflictor == Connection::Server->GetID()) {
conn = Network::GetInstance()->GetConnection(message->inflictingEntityID.connectionID);
if(conn) {
r = conn->FindReplicator(message->inflictingEntityID);
if(r && r->GetClassID() == MechClassID) {
Mech *inflict = Cast_Object(Mech *, r);
if(inflict && inflict->IsLanceMate()) {
inflictor = inflict->lancemateIndex + Maximum_Players;
}
}
}
}
MWApplication *app = MWApplication::GetInstance();
if(self >= Maximum_Players) {
app->lancemateConnectionData[self-Maximum_Players].comp_rcv[inflictor] += num_subsystems_destroyed;
app->lancemateConnectionData[self-Maximum_Players].stats_update = 1;
} else {
app->servedConnectionData[self].comp_rcv[inflictor] += num_subsystems_destroyed;
app->servedConnectionData[self].stats_update = 1;
}
if(inflictor >= Maximum_Players) {
app->lancemateConnectionData[inflictor-Maximum_Players].comp_inf[self] += num_subsystems_destroyed;
app->lancemateConnectionData[inflictor-Maximum_Players].stats_update = 1;
} else {
app->servedConnectionData[inflictor].comp_inf[self] += num_subsystems_destroyed;
app->servedConnectionData[inflictor].stats_update = 1;
}
}
#endif // !defined(NO_LOG)
}
}
return (rv);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MWInternalDamageObject::KillAllContainedSubsystems()
{
Check_Object(this);
DamageDispatch *dispatch = DamageDispatch::GetInstance();
Check_Pointer(dispatch);
dispatch->KillAllContainedSubsystems(*this);
}
void
MWInternalDamageObject::_KillAllContainedSubsystems()
{
ChainIteratorOf<Subsystem *> iterator(&subsystemChain);
Subsystem *subsystem;
while((subsystem = iterator.ReadAndNext()) != NULL)
{
Check_Object(subsystem);
bool does_destroy = subsystem->TakeCriticalHit();
if(does_destroy) {
g_RSF.RecScore(CBucketManager::COMPONENT_DEATHS, ReplicatorID::Null, ReplicatorID::Null, 0, 0, (DWORD)subsystem);
// MSL 5.02 headshot
destroyedSubsystemChain.Add(subsystem); // So we can later completely remove the subsystem
subsystemChain.Remove(subsystem);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MWInternalDamageObject::TestInstance() const
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
const char*
MWInternalDamageObject::SlotTypeAsciiToText(int slot_type)
{
switch(slot_type)
{
case MissileSlotType:
return "MissileSlot";
case ProjectileSlotType:
return "ProjectileSlot";
case BeamSlotType:
return "BeamSlot";
case OmniSlotType:
return "OmniSlot";
}
PAUSE(("That is a bad slot value"));
return "Bad";
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
MWInternalDamageObject::SlotTypeTextToAscii(const char *slot_type_string)
{
if(!_stricmp(slot_type_string, "MissileSlot"))
return MissileSlotType;
if(!_stricmp(slot_type_string, "ProjectileSlot"))
return ProjectileSlotType;
if(!_stricmp(slot_type_string, "BeamSlot"))
return BeamSlotType;
if(!_stricmp(slot_type_string, "OmniSlot"))
return OmniSlotType;
PAUSE(("That is a bad Slot Type String: %s", slot_type_string));
return -1;
}
void MechWarrior4::MW4DamageSecurityCheckStop()
{
_asm
{
nop
}
}