diff --git a/game/reconstructed/mech4.cpp b/game/reconstructed/mech4.cpp index 21e2d2e..4e28719 100644 --- a/game/reconstructed/mech4.cpp +++ b/game/reconstructed/mech4.cpp @@ -5541,6 +5541,49 @@ void gBTGenSelKey = pulse ? s_gsID : 0; } + // SELF-DAMAGE HARNESS (BT_SELF_DAMAGE=, off by default). + // The whole RESPAWN family -- torso twist after respawn (#70), ammo/weapon + // reset (#22), coolant/heat/generator restore (#55), the respawn latch + // (#57) -- was untestable on a bench because nothing can kill the LOCAL + // pilot in solo: BT_MP_FORCE_DMG only targets REPLICANTS, and a solo + // dummy never shoots back. This dispatches an unaimed TakeDamage at our + // OWN mech once a second, through the SAME virtual Entity::Dispatch path + // a real beam hit uses -- so the cylinder hit-location lookup, the zone + // cascade, the vital-subsystem kill and the authentic death/respawn cycle + // all run for real. Nothing is poked directly. + // e.g. BT_SELF_DAMAGE=40 kills a fresh mech in well under a minute. + // ONE DEATH ONLY: latch off as soon as we die, so everything observed + // AFTER the respawn is the respawn's own doing and not the harness still + // shooting us. (Live damage knocks the power bus down, which is exactly + // the signal a respawn test is trying to read.) + static int s_sdSpent = 0; + if (IsMechDestroyed()) + s_sdSpent = 1; + if ((Entity *)this == application->GetViewpointEntity() + && getenv("BT_SELF_DAMAGE") && !s_sdSpent + && !IsMechDestroyed() && damageZoneCount > 0) + { + static float s_sdAccum = 0.0f; + s_sdAccum += dt; + if (s_sdAccum >= 1.0f) + { + s_sdAccum = 0.0f; + Damage dmg; + dmg.damageType = Damage::ExplosiveDamageType; + float want = (float)atof(getenv("BT_SELF_DAMAGE")); + dmg.damageAmount = (want > 0.0f) ? want : 20.0f; + dmg.burstCount = 1; + dmg.impactPoint = localOrigin.linearPosition; + Entity::TakeDamageMessage td( + Entity::TakeDamageMessageID, + sizeof(Entity::TakeDamageMessage), + GetEntityID(), -1 /*unaimed -> cylinder table resolves the zone*/, dmg); + DEBUG_STREAM << "[selfdmg] " << dmg.damageAmount + << " to own mech (unaimed)" << std::endl << std::flush; + Dispatch(&td); + } + } + // task #13 scripted verify (BT_VALVE_TEST=1): one MoveValve press at // frame ~600 -- Condenser1's valveState cycles 1 -> 5, so the flow // redistribution gives it 5/10 of the total coolant flow ([valve] log