bench: symbolic leg-zone targeting, gimp-follow/goto-release, legal egg colors
- BT_SELF_DAMAGE_ZONE=leg resolves the mech's actual leg zone via the streamed LegDamageZone flags (new Mech__DamageZone::IsLegZone) -- numeric zone ids are per-mech-type and a wrong one aims at a vital (killed the limp bench's mech instead of gimping it: 2 ticks, death cycle, respawn healed, harness spent -- 3 minutes of healthy circling). - BT_GOTO=gimp: beeline mode that prefers the nearest LIMPING peer (gimp half-states 3/4 ride the one-cell in every update record); stands and waits while nobody limps. BT_GOTO_RELEASE=1 hands the mech back to the keyboard once the beeline arrives. - MP.EGG/MP4.EGG/MP4L.EGG: color=Red and color=Blue are PATCH values, not colors (RES vehicletable colors: Black/Brown/Crimson/Green/Grey/Tan/ White) -- the two pilots carrying them rendered as untextured pastel mechs. Boreas Red->Crimson, Caicias Blue->Grey. MP4L.EGG = the 4-pilot bench egg on the open grass map. 4-node limp verification (user-eyeballed, all instances): the gimped mech step-drags with the authentic limp on every observer -- no skating (#82 holds in the 4-node overlap case). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
494f32efb4
commit
82f1ea1183
@@ -3504,10 +3504,11 @@ void
|
||||
{
|
||||
const char *gv = getenv("BT_GOTO");
|
||||
if (gv && !stricmp(gv, "enemy")) s_goto = 2; // chase nearest replicant
|
||||
else if (gv && !stricmp(gv, "gimp")) s_goto = 3; // follow the LIMPING peer (else nearest)
|
||||
else if (gv && sscanf(gv, "%f %f", &s_gx, &s_gz) == 2) s_goto = 1;
|
||||
else s_goto = 0;
|
||||
}
|
||||
if (s_goto == 2)
|
||||
if (s_goto == 2 || s_goto == 3)
|
||||
{
|
||||
// DYNAMIC target (test harness): beeline toward the CLOSEST live
|
||||
// peer replicant wherever it currently is -- MP spawn positions
|
||||
@@ -3515,7 +3516,14 @@ void
|
||||
extern int BTGetTargetCandidates(Entity *shooter, Entity **out, int maxOut);
|
||||
Entity *ec[32];
|
||||
const int enc = BTGetTargetCandidates((Entity *)this, ec, 32);
|
||||
float best = 1e30f; int found = 0;
|
||||
// mode 3 ("gimp"): prefer the nearest LIMPING peer -- the gimp
|
||||
// half-states 3/4 ride every update record in the one-cell
|
||||
// (movementMode), so a replicant knows. Falls back to nearest
|
||||
// while nobody limps (pre-damage phase), so the pack forms up
|
||||
// and then locks onto the wounded mech.
|
||||
float best = 1e30f, bestG = 1e30f;
|
||||
int found = 0, foundG = 0;
|
||||
float gxN = 0.0f, gzN = 0.0f, gxG = 0.0f, gzG = 0.0f;
|
||||
for (int ei = 0; ei < enc; ++ei)
|
||||
{
|
||||
Mech *em = (Mech *)ec[ei];
|
||||
@@ -3524,11 +3532,17 @@ void
|
||||
float edx = (float)ep.x - (float)localOrigin.linearPosition.x;
|
||||
float edz = (float)ep.z - (float)localOrigin.linearPosition.z;
|
||||
float ed2 = edx*edx + edz*edz;
|
||||
if (ed2 < best) { best = ed2; s_gx = (float)ep.x; s_gz = (float)ep.z; found = 1; }
|
||||
if (ed2 < best) { best = ed2; gxN = (float)ep.x; gzN = (float)ep.z; found = 1; }
|
||||
int emm = em->MovementMode(); // one-cell (simulationState) -- replicated
|
||||
if (s_goto == 3 && (emm == 3 || emm == 4)
|
||||
&& ed2 < bestG)
|
||||
{ bestG = ed2; gxG = (float)ep.x; gzG = (float)ep.z; foundG = 1; }
|
||||
}
|
||||
if (found) s_goto = 2; else { gBTGotoActive = 0; }
|
||||
if (foundG) { s_gx = gxG; s_gz = gzG; }
|
||||
else if (found) { s_gx = gxN; s_gz = gzN; }
|
||||
else { gBTGotoActive = 0; }
|
||||
}
|
||||
if (s_goto == 1 || (s_goto == 2 && (s_gx != 0.0f || s_gz != 0.0f)))
|
||||
if (s_goto == 1 || (s_goto >= 2 && (s_gx != 0.0f || s_gz != 0.0f)))
|
||||
{
|
||||
float ddx = s_gx - (float)localOrigin.linearPosition.x;
|
||||
float ddz = s_gz - (float)localOrigin.linearPosition.z;
|
||||
@@ -3554,7 +3568,7 @@ void
|
||||
// instead of ramming; a fixed point drives right up to the spot.
|
||||
// BT_GOTO_STOP overrides (issue #16 parallax test: approach the
|
||||
// dummy from range all the way in to 3/4-screen).
|
||||
float stopDist = (s_goto == 2) ? 300.0f : 5.0f;
|
||||
float stopDist = (s_goto >= 2) ? 300.0f : 5.0f;
|
||||
{
|
||||
static float s_stopOv = -1.0f;
|
||||
if (s_stopOv < 0.0f)
|
||||
@@ -3606,6 +3620,22 @@ void
|
||||
if (s_thrOv > 0.0f) gthr = s_thrOv;
|
||||
}
|
||||
gBTDrive.forcedThrottle = arrived ? 0.0f : gthr;
|
||||
// BT_GOTO_RELEASE=1: hand the mech BACK to the keyboard once
|
||||
// the beeline arrives -- the observer rig auto-converges on
|
||||
// the target, then the USER drives freely (goto disengages
|
||||
// for good; gBTDrive.forced held keys dead otherwise).
|
||||
{
|
||||
static int s_rel = -1;
|
||||
if (s_rel < 0) s_rel = getenv("BT_GOTO_RELEASE") ? 1 : 0;
|
||||
if (arrived && s_rel)
|
||||
{
|
||||
s_goto = 0;
|
||||
gBTGotoActive = 0;
|
||||
gBTDrive.forced = 0;
|
||||
gBTDrive.forcedThrottle = 0.0f;
|
||||
DEBUG_STREAM << "[goto] ARRIVED -- released to manual control\n" << std::flush;
|
||||
}
|
||||
}
|
||||
turn = gBTGotoTurn; // non-real-controls fallback path
|
||||
}
|
||||
}
|
||||
@@ -5727,7 +5757,21 @@ void
|
||||
{
|
||||
const char *ze = getenv("BT_SELF_DAMAGE_ZONE");
|
||||
if (ze != 0 && *ze != '\0')
|
||||
sdZone = atoi(ze);
|
||||
{
|
||||
if (!stricmp(ze, "leg"))
|
||||
{
|
||||
// symbolic: first streamed LEG zone of THIS mech --
|
||||
// numeric zone ids are per-mech-type and a wrong one
|
||||
// aims at a vital (killed the limp bench's mech).
|
||||
for (int zi = 0; zi < damageZoneCount; ++zi)
|
||||
{
|
||||
Mech__DamageZone *zz = Zone(zi);
|
||||
if (zz != 0 && zz->IsLegZone()) { sdZone = zi; break; }
|
||||
}
|
||||
}
|
||||
else
|
||||
sdZone = atoi(ze);
|
||||
}
|
||||
if (sdZone < -1 || sdZone >= damageZoneCount)
|
||||
sdZone = -1;
|
||||
}
|
||||
|
||||
@@ -254,6 +254,13 @@
|
||||
MechCriticalSubsystem
|
||||
**criticalSubsystems; // @0x1b4 array[criticalSubsystemCount]
|
||||
|
||||
public:
|
||||
// Bench query (BT_SELF_DAMAGE_ZONE=leg): leg zones stream the
|
||||
// LegDamageZone flags, so the harness resolves "the leg" symbolically --
|
||||
// zone NUMBERING is per-mech-type (MadCat 16, bhk1 18, ...) and a magic
|
||||
// number aimed at the wrong type has killed the mech instead of gimping.
|
||||
int IsLegZone() const { return (leftLeg || rightLeg) ? 1 : 0; }
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Damage-state descriptor table (binary this+0xd4). Streamed from the
|
||||
// type-0x1e resource by LoadCriticalSubsystems (FUN_0041e4a8 -> FUN_0042a748);
|
||||
|
||||
Reference in New Issue
Block a user