Files
TeslaRel410/restoration/source410/BT/MISLANCH.CPP
T
CydandClaude Fable 5 76cfc64353 BT410 Phase 5.3.16: targeting + damage -- two-mech fights are LIVE
The simulation is now a FIGHT. Mech target slot (+0x388), authentic
Loaded->Firing gate (viewFireEnable && HasActiveTarget), UpdateTargeting
range refresh, and SendDamage via the engine TakeDamageMessage.

MECHDMG.CPP is BORN against the AUTHENTIC surviving CODE/BT/BT/MECHDMG.HPP:
the Mech ctor's Pass-3 hull zone fill constructs Mech__DamageZone per zone
(the Entity base only allocates the raw pointer array -- unfilled slots were
crash #1; a base-class fill parses each record short and skews the stream --
crash #2). Streamed ctor parses the full BT tail (flags / Scalar-weighted
criticals with the Master+Dynamic plug gate / LOD redirect table) and
normalizes the armor economy: scale[type]=1/(raw x armorPoints), legs
halved -- BT411-verified @0049ce50.

Live two-mech verification (BT_SPAWN_ENEMY harness in DropZoneReply):
20 named hull zones stream on both mechs; PPC lands 11.77/hit (12 x
chargeRatio^2, type 4), ER-M laser 3.43 (type 3), SRM6 salvos 5.83 x 6
rounds on independent zones (type 2, one message per missile -- burstCount
is NOT in the zone formula); repeat hits climb linearly, leg zones absorb
at half scale, zones reach 1.0 Burning/Destroyed. No-target and novice
regressions hold (weapons load but never fire without a target).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 10:21:43 -05:00

161 lines
4.5 KiB
C++

//===========================================================================//
// File: mislanch.cpp //
// Project: BattleTech Brick: Mech weapons //
// Contents: MissileLauncher -- a projectile weapon that fires missile salvos //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <bt.hpp>
#pragma hdrstop
#if !defined(MISLANCH_HPP)
# include <mislanch.hpp>
#endif
#if !defined(MECH_HPP)
# include <mech.hpp>
#endif
Derivation
MissileLauncher::ClassDerivations(
ProjectileWeapon::ClassDerivations,
"MissileLauncher"
);
MissileLauncher::SharedData
MissileLauncher::DefaultData(
MissileLauncher::ClassDerivations,
Subsystem::MessageHandlers,
Subsystem::AttributeIndex,
Subsystem::StateCount
);
MissileLauncher::MissileLauncher(
Mech *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &default_data
):
ProjectileWeapon(owner, subsystem_ID, subsystem_resource, default_data)
{
Check(owner);
Check_Pointer(subsystem_resource);
missileCount = subsystem_resource->missileCount;
//
// A salvo delivers missileCount missiles; split the per-shot damage across
// the salvo. (The per-missile launch mechanics live in FireWeapon, staged.)
//
if (missileCount > 0)
{
damageData.burstCount = missileCount;
damageData.damageAmount = damageData.damageAmount / (Scalar)missileCount;
}
Check_Fpu();
}
MissileLauncher::~MissileLauncher()
{
}
Logical
MissileLauncher::TestInstance() const
{
return IsDerivedFrom(ClassDerivations);
}
//
//#############################################################################
// Damage / death.
//#############################################################################
//
void
MissileLauncher::TakeDamage(Damage &damage)
{
Check(this);
ProjectileWeapon::TakeDamage(damage);
}
void
MissileLauncher::DeathReset(Logical /*full_reset*/)
{
Check(this);
}
//
// The missile-salvo discharge. Not yet reconstructed.
//
void
MissileLauncher::FireWeapon()
{
Check(this);
//
// PARTIAL (binary @004bcc60): the authentic body launches missileCount
// Missile entities toward the owner's target (each carrying the salvo-split
// damageData) and dumps the firing heat. The Missile entity spawn needs
// the entity-spawn + targeting waves; the view/target gate, ammo pull and
// recoil all live in the CALLER (ProjectileWeaponSimulation's Loaded case).
//
// Ballistic heatCostToFire is stored 1e7-unit-NATIVE in the stream (SRM6
// reads 5.06e7 = +641K on its own sink -- the same design magnitude as the
// PPC's +632K); dump it raw, under the heat-model experience gate (novice /
// standard fire generates no heat -- authentic). (The EMITTER's authored
// value is small and its 1e7 comes from the energy algebra.)
if (HeatModelActive())
{
AddPendingHeat(heatCostToFire);
}
//
// The salvo delivery: ONE TakeDamageMessage per missile, each carrying
// the salvo-split per-missile damage (the ctor split the authored amount
// across missileCount). The zone armor formula IGNORES burstCount
// (BT411 combat-damage: one message = one amount*scale application), so
// a single split message would under-deliver the salvo by the round
// count. INTERIM instant-hit with every round hitting (its own random
// zone) -- the Missile entity flight / seeker / proximity fuse joins the
// entity-spawn wave.
//
if (targetWithinRange && owner != NULL
&& owner->GetTargetEntity() != NULL)
{
for (int mm = 0; mm < missileCount; ++mm)
{
SendDamage(owner->GetTargetEntity(), damageData);
}
}
if (getenv("BT_MECH_LOG"))
{
DEBUG_STREAM << "[fire] '" << GetName()
<< "' FIRED (salvo of " << missileCount
<< ", recharge=" << rechargeRate
<< "s heat+=" << heatCostToFire << ")" << endl << flush;
}
}
//
// Model-load-time construction. Not yet reconstructed.
//
Logical
MissileLauncher::CreateStreamedSubsystem(
ResourceFile *,
NotationFile *,
const char *,
const char *,
SubsystemResource *,
NotationFile *,
const ResourceDirectories *,
int
)
{
Fail("MissileLauncher::CreateStreamedSubsystem -- mislanch.cpp not yet reconstructed");
return False;
}