Experience levels WIRED: the egg field drives the simulation tier (Gitea #2)
BTPlayer's master ctor now seeds the flag block from btMission->ExperienceLevel() + AdvancedDamageOn() (accessors from the SURVIVED 1995 BTMSSN.HPP [T0]) instead of the NULL-stubbed scenario role -- the egg experience knob works for the first time. Both switch slot errors fixed vs the binary @4c0bc8; phantom btMission duplicate member removed (+0x1f8 IS Player::playerMission). SEVEN gate stubs unified onto the real flags (two found empirically): HeatModelActive, OwnerAdvancedDamage, LiveFireEnabled, ControlsAllowLights, powersub @4b0efc, emitter's file-local FUN_004ad7d4 + FUN_004ac9c8 stubs. FUN_004ac9c8 family swept (incl. a live raw-offset databinding trap in MechSubsystem::IsDamaged). Flag block renamed to its true semantics (simLive/heatModelOn/...), scoring-era names kept as comments. Includes the #5 [aud-tail] diag in emitter.cpp. ALL 19 shipped eggs say experience=expert -> default behavior UNCHANGED (per-tier verified: novice/standard = no heat/jams, authentic; veteran/ expert = today's exact behavior). Real delta: egg advancedDamage=1 now reaches player+0x264/0x268 (was hardwired 0). Follow-up flagged: the glass FE defaults empty experience to veteran (one tier below shipped). Awaiting human verification. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
a0cec48e3f
commit
d7158f1f82
@@ -49,7 +49,7 @@
|
||||
// FUN_004b9948 MechWeapon::GetMuzzlePoint FUN_004b9864 MechWeapon::ComputeAimOrientation
|
||||
// FUN_004b9728 MechWeapon::DrawWeaponPip FUN_004b9cbc MechWeapon::GetTargetPosition
|
||||
// FUN_004b0bd0 PoweredSubsystem simulation step FUN_004b0d50 PoweredSubsystem scalar query
|
||||
// FUN_004ad7d4 HeatableSubsystem "is online/active" FUN_004ac9c8 HeatableSubsystem heat-state query
|
||||
// FUN_004ad7d4 heat-model experience gate (player+0x260; HeatModelActive) FUN_004ac9c8 novice lockout (player+0x274==0; MechSubsystem::IsDamaged)
|
||||
// FUN_00417ab4 follow a SharedData link (voltage source / ammo bin)
|
||||
// FUN_0049fb54 Mech::IsDestroyed (movementMode 2||9) FUN_0041a1a4 IsDerivedFrom(classDerivations)
|
||||
// FUN_0041bbd8 AlarmIndicator::SetLevel(n) (weaponAlarm @0x350, state @0x364)
|
||||
@@ -74,6 +74,8 @@
|
||||
#endif
|
||||
#include <hostmgr.hpp> // HostManager::GetEntityPointer -- the update-record target resolve (task #51)
|
||||
#include <math.h> // sqrt -- the SeekVoltageResponse sampler (issue #11)
|
||||
#include <map> // [aud-tail] per-weapon previous-state tracking (Gitea #5, instrumentation only)
|
||||
#include <ctime> // [aud-tail] clock() ms timestamps (matches L4AUDLVL.cpp)
|
||||
|
||||
// E8 (bring-up): the player fire input. The controls mapper that would normally write
|
||||
// the weapon's fireImpulse is bypassed (mech4.cpp), so EmitterSimulation reads this
|
||||
@@ -108,8 +110,12 @@ static void Normalize(EulerAngles &) {}
|
||||
static void MakeIdentity(LinearMatrix &m) { m.BuildIdentity(); }
|
||||
static void CopyColor(void *, const void *) {}
|
||||
|
||||
// engine-internal artifacts the decomp called by address (stand-ins)
|
||||
static int FUN_004ad7d4(void *) { return 1; } // HeatableSubsystem active?
|
||||
// (issue #2: the local FUN_004ad7d4 `return 1` / FUN_004ac9c8 `return 0`
|
||||
// stand-ins are RETIRED -- FUN_004ad7d4 is the player+0x260 HEAT-MODEL
|
||||
// experience gate (HeatSink::HeatModelActive(), heat.hpp -> the btplayer.cpp
|
||||
// bridge) and FUN_004ac9c8 is the player+0x274==0 NOVICE lockout
|
||||
// (MechSubsystem::IsDamaged() -> the same bridge family); call sites now use
|
||||
// the real members. See context/experience-levels.md.)
|
||||
// FUN_0049fb54 == Mech::IsDestroyed (movementMode 2||9; reconstructed as
|
||||
// Mech::IsDisabled). Was a mislabeled "cockpit/HUD query" no-op stub -- so a
|
||||
// live beam never CUT when its target mech died (@004ba8d0/@004baa20 check
|
||||
@@ -131,7 +137,6 @@ static int BTMechDestroyed(Entity *e)
|
||||
// TrackSeekVoltage never charged. The E7 one-frame force-charge that covered
|
||||
// for it made every emitter recycle in ~0.3s instead of the authored 2-6s
|
||||
// RechargeRate -- the actual root cause of the task-#10 heat runaway.)
|
||||
static int FUN_004ac9c8(void *) { return 0; } // heat-state query
|
||||
static int FUN_00421070(void *, void *) { return 0; } // damage source resolve
|
||||
static void *ResolveSource(void *) { return 0; } // named source registry lookup
|
||||
|
||||
@@ -281,7 +286,7 @@ void
|
||||
// E5: pendingHeat (HeatSink @0x1C8) is the field the heat sim absorbs each frame
|
||||
// (heatEnergy += pendingHeat -> temperature); the old Emitter-local heatAccumulator
|
||||
// was a SHADOW at the wrong offset, so firing never reached the heat model.
|
||||
if (FUN_004ad7d4(this)) // HeatableSubsystem active
|
||||
if (HeatModelActive()) // FUN_004ad7d4 -- player+0x260 heat-model experience gate (issue #2)
|
||||
{
|
||||
pendingHeat += heatPortion; // inherited HeatSink::pendingHeat @0x1c8
|
||||
}
|
||||
@@ -502,6 +507,26 @@ void
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// [aud-tail] (Gitea #5 verdict harness, additive): timestamped WeaponState
|
||||
// transitions. Leave-0 (Firing) == the beam-visual end (firingActive is
|
||||
// cleared on the same path); 3->2 (Loading->Loaded) is where the authored
|
||||
// charge-loop stop watcher fires StopNote and the release fade begins.
|
||||
// Correlate against the [aud-tail] logs in L4AUDLVL.cpp (same CRT clock()
|
||||
// ms). BT_AUD_TAIL=1 gates; instrumentation only, no behavior change.
|
||||
if (getenv("BT_AUD_TAIL"))
|
||||
{
|
||||
static std::map<const void *, int> s_prevState;
|
||||
int st = (int)weaponAlarm.GetState();
|
||||
std::map<const void *, int>::iterator it = s_prevState.find(this);
|
||||
if (it == s_prevState.end() || it->second != st)
|
||||
{
|
||||
DEBUG_STREAM << "[aud-tail] t=" << (long)clock() << "ms " << GetName()
|
||||
<< " state " << ((it == s_prevState.end()) ? -1 : it->second)
|
||||
<< " -> " << st << "\n" << std::flush;
|
||||
s_prevState[this] = st;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -530,7 +555,7 @@ void
|
||||
seekRate = (src->MeasuredVoltage() - currentLevel) / dtScale; // 0x45c = (src+0x1dc - 0x414)/..
|
||||
currentLevel = (seekRate / energyCoefficient) * time_slice + currentLevel; // 0x414
|
||||
|
||||
if (FUN_004ad7d4(this)) // heatable/online
|
||||
if (HeatModelActive()) // FUN_004ad7d4 -- player+0x260 heat-model experience gate (issue #2)
|
||||
{
|
||||
// @004ba838:7544 -- the charging I^2R loss lands in the GENERATOR's
|
||||
// pendingHeat (src+0x1c8): recharging weapons is what heats generators
|
||||
@@ -628,11 +653,11 @@ void
|
||||
int
|
||||
Emitter::AdvanceSeekVoltage(UpdateRecord *message)
|
||||
{
|
||||
if (FUN_004ac9c8(this)) // heat-state set -> skip
|
||||
if (MechSubsystem::IsDamaged()) // FUN_004ac9c8 -- NOVICE lockout (seek-voltage cycling is an advanced cockpit control; issue #2)
|
||||
{
|
||||
return /*non-zero status*/ 1;
|
||||
}
|
||||
if (!FUN_004ad7d4(this) || message->payloadCount <= 0) // message+0xc
|
||||
if (!HeatModelActive() || message->payloadCount <= 0) // FUN_004ad7d4 -- heat-model gate; message+0xc
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user