//===========================================================================//
// File:	mechrecon.hpp                                                       //
// Project: BattleTech           Brick: Entity Manager                        //
// Contents: Reconstruction support shim for the "mech core" family           //
//           (mech / mech2..4 / mechsub / mechdmg / dmgtable).                //
//---------------------------------------------------------------------------//
// This header is NOT part of the shipped game.  It supplies the small set of //
// reconstruction helpers, decompiler-artifact globals and proxy stand-in     //
// types that the recovered mech-core bodies reference but the modern engine  //
// headers do not provide under those exact names.  It exists only so the     //
// reconstructed translation units COMPILE against the WinTesla engine; the   //
// proxies preserve the call structure of the recovered code (no logic is     //
// deleted).  Behaviour-equivalent semantics are filled where trivial.        //
//                                                                            //
// MUST be included AFTER <bt.hpp> / the engine headers (so Scalar, Quaternion //
// Vector3D, AffineMatrix, CString, Subsystem ... are already declared).      //
//===========================================================================//

#if !defined(MECHRECON_HPP)
#	define MECHRECON_HPP

#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
// Quaternion / Vector3D / AffineMatrix used below (kIdentityQuat etc.).  Include
// directly so mechrecon.hpp is self-sufficient regardless of the includer's order
// (myomers.cpp pulls this via mechsub.hpp BEFORE bt.hpp).  ROTATION.hpp DEFINES
// Quaternion (affnmtrx.hpp only forward-declares it).
#include <ROTATION.hpp>
#include <affnmtrx.hpp>

//===========================================================================//
// Universal decompiler-artifact value.
//
//   Stands in for the result of an unresolved FUN_/helper artifact.  Converts
//   to any scalar, pointer or default-constructible type so the recovered
//   expression typechecks.
//===========================================================================//
struct Recon
{
	Recon() {}
	template<class T> Recon(const T &) {}
	template<class T> operator T() const { return T(); }
};

//===========================================================================//
// Memory shim -- the decomp's "Memory::Allocate / Memory::Free" map onto the
// engine's per-object MemoryBlock allocators; for the offline reconstruction a
// plain heap allocation is behaviour-equivalent.
//===========================================================================//
namespace Memory
{
	inline void *Allocate(size_t bytes)		{ return ::operator new(bytes); }
	inline void *AllocateArray(size_t bytes){ return ::operator new(bytes); }
	inline void  Free(void *where)			{ ::operator delete(where); }
}

inline void  *Alloc(size_t bytes)		{ return ::operator new(bytes); }
inline void  *AllocateArray(size_t bytes){ return ::operator new(bytes); }

//===========================================================================//
// Ref-count / name helpers (decomp artifacts).
//===========================================================================//
template<class A>          inline void *NewRefCount(A)			{ return 0; }
                           inline void *NewRefCounted()			{ return 0; }
template<class A,class B>  inline void  BindName(A, B)			{}
template<class A,class B,class C> inline void BindName(A, B, C)	{}
template<class A>          inline void  ReleaseRefCounted(A)		{}
template<class A>          inline void  ZeroBlock(A, int)		{}
template<class A,class B>  inline void  Assign(A, B)			{}
template<class A>          inline Recon NewTableEntry(A)			{ return Recon(); }

//===========================================================================//
// Small dynamic string used by the resource-table builders
// ( TextString("Layer") + itoa(n) ).
//===========================================================================//
struct TextString
{
	char	buf[64];
	TextString()				{ buf[0] = 0; }
	TextString(const char *s)	{ buf[0] = 0; if (s) { strncpy(buf, s, 63); buf[63] = 0; } }
	TextString &operator+=(const char *s)	{ if (s) strncat(buf, s, 63 - strlen(buf)); return *this; }
	TextString  operator+ (const char *s) const	{ TextString t(*this); t += s; return t; }
	operator const char *() const	{ return buf; }
};

//===========================================================================//
// Misc free-function artifacts (variadic -> Recon).
//===========================================================================//
template<class...A> inline Recon WorldTransform(A&&...)			{ return Recon(); }
template<class...A> inline Recon ResourceFind(A&&...)			{ return Recon(); }
template<class...A> inline Recon LoadSkeleton(A&&...)			{ return Recon(); }
template<class...A> inline int   ResourceManagerHas(A&&...)		{ return 0; }
template<class...A> inline void  GenerateFaultDefault(A&&...)	{}
// NOTE: renamed from Random() to avoid colliding with the engine's
// `extern RandomGenerator Random;` (RANDOM.h). Reconstructed code that wants the
// original zero-arg unit-random (FUN_00408050 -> Scalar in [0,1)) uses RandomUnit().
// Backed by the engine RNG: `RandomGenerator::operator Scalar()` returns a value
// in [0,1) (RANDOM.h), exactly matching FUN_00408050's contract.  Variadic tail
// kept so call sites (dmgtable: roll; theta*TwoPi) bind unchanged; Scalar return
// satisfies the dmgtable Scalar consumers.
#include <RANDOM.hpp>		// fwd/ -> engine RANDOM.h: extern RandomGenerator Random;
template<class...A> inline Scalar RandomUnit(A&&...)				{ return (Scalar)Random; }

//===========================================================================//
// String helpers (decomp inlined strcpy/strcat/stricmp etc.).
//===========================================================================//
inline void Strcpy(char *d, const char *s)	{ while ((*d++ = *s++) != 0) {} }
inline void Strcat(char *d, const char *s)	{ while (*d) ++d; while ((*d++ = *s++) != 0) {} }
inline int  Strcmp(const char *a, const char *b)	{ return strcmp(a, b); }

// Env gate with a DEFAULT: the authentic reconstructed paths (gait cutover/state
// machine, collision+gravity, real controls) are ON by default; set the var to
// "0" to fall back to the historical bring-up path (e.g. BT_GAIT_SM=0).
inline int BTEnvOn(const char *name, int on_by_default)
{
	const char *v = getenv(name);
	return v ? (v[0] != '0') : on_by_default;
}

// THE AUTHENTIC GROUND MODEL gate (task #15 -- the 1995 probe/snap/response
// ground block, ground-model-decode workflow).  ONE function so the Mech ctor
// (template lift, mech.cpp), the per-frame ground block and the ProcessCollision
// override (mech4.cpp) can never disagree: every TU reads the same env exactly
// once.  DEFAULT ON (verification passed: grass/arena/dbase census + anti-ladder
// soak + slope tracking + render-side screenshots + combat & heapcheck
// regressions -- see the task-#15 ground commit).  BT_GROUND_REAL=0 falls back
// to the bring-up gravity+push-out+clamp baseline.
inline int GroundReal()
{
	static const int v = BTEnvOn("BT_GROUND_REAL", 1);
	return v;
}
inline int GroundLog()
{
	static const int v = getenv("BT_GROUND_LOG") ? 1 : 0;
	return v;
}
inline int  Streq (const char *a, const char *b)	{ return strcmp(a, b) == 0; }

//===========================================================================//
// Multi-level status/alarm indicator.
//
//   The recovered code names this AlarmIndicator and drives it with a level
//   count ctor + SetLevel(level).  In the WinTesla engine the equivalent is
//   StateIndicator (SetState / GetState).  We provide a thin proxy that exposes
//   BOTH spellings so the recovered call sites compile unchanged.
//===========================================================================//
struct ReconAlarm
{
	unsigned	level;
	ReconAlarm()			: level(0) {}
	ReconAlarm(int n)		: level(0) { (void)n; }
	ReconAlarm(unsigned n)	: level(0) { (void)n; }
	ReconAlarm &operator=(const ReconAlarm &)	{ return *this; }
	void		SetLevel(int n)		{ level = (unsigned)n; }
	void		SetState(unsigned n){ level = n; }
	unsigned	GetLevel() const	{ return level; }
	unsigned	GetState() const	{ return level; }
	int			GetLevelCount() const { return 0; }
};

//===========================================================================//
// Filtered (running-average) scalar -- decomp uses Initialize(n, value).
//===========================================================================//
struct ReconFiltered
{
	ReconFiltered() {}
	template<class...A> void	Initialize(A&&...)	{}
	template<class...A> void	Add(A&&...)			{}
	Scalar						Value() const		{ return Scalar(0); }
	// static-style accumulator verbs:  FilteredScalar::Push(filter, sample) etc.
	template<class...A> static void		Push(A&&...)	{}
	template<class...A> static Scalar	Sum(A&&...)		{ return Scalar(0); }
	template<class...A> static Scalar	Average(A&&...)	{ return Scalar(0); }
};

typedef unsigned int uint;

//===========================================================================//
// Universal word-cell proxy + word accessor.
//
//   The recovered mech-core bodies address the object as an int[] and assign
//   raw words by index ( this[0xNN] = ... ).  Pointer-subscripting `this`
//   cannot be made an assignable scalar lvalue, so each `this[0xNN]` is
//   rewritten to Wword(0xNN), which hands back a distinct, universally
//   assignable/convertible cell (one per word index).  This preserves the
//   per-offset write structure of the decomp while compiling against the
//   modern engine; the cell is behaviour-neutral storage for the offline
//   reconstruction (it is NOT aliased onto the real member at that offset).
//===========================================================================//
struct BTVal
{
	Scalar	max, min, field8;					// named sub-fields used by the decomp

	BTVal() : max(0), min(0), field8(0) {}
	template<class T> BTVal(const T &) : max(0), min(0), field8(0) {}

	BTVal &operator=(const BTVal &)			{ return *this; }	// real copy-assign
	template<class T> BTVal &operator=(const T &)	{ return *this; }
	template<class T> operator T() const	{ return T(); }

	// member-call passthrough (this[]-proxy + pose-member verbs)
	template<class...A> BTVal &Construct(A&&...)		{ return *this; }
	template<class...A> BTVal &LinkTo(A&&...)		{ return *this; }
	template<class...A> BTVal &SetIdentity(A&&...)	{ return *this; }
	template<class...A> BTVal &Mul(A&&...)			{ return *this; }
	template<class...A> BTVal &Copy(A&&...)			{ return *this; }

	// arithmetic kept closed over BTVal (avoids operator T() ambiguity)
	friend BTVal operator+(const BTVal &, const BTVal &)	{ return BTVal(); }
	friend BTVal operator-(const BTVal &, const BTVal &)	{ return BTVal(); }
	BTVal &operator+=(const BTVal &)				{ return *this; }
	template<class T> BTVal &operator+=(const T &)	{ return *this; }

	// comparisons (exact-match friends beat the templated operator T())
	friend bool operator==(const BTVal &, const BTVal &)	{ return false; }
	friend bool operator!=(const BTVal &, const BTVal &)	{ return false; }
	friend bool operator==(const BTVal &, int)			{ return false; }
	friend bool operator!=(const BTVal &, int)			{ return false; }
	friend bool operator==(int, const BTVal &)			{ return false; }
	friend bool operator!=(int, const BTVal &)			{ return false; }
};

inline BTVal &Wword(int i)		{ static BTVal bank[0x400]; return bank[i & 0x3ff]; }

static Vector3D	ZeroVector;		// neutral zero vector (decomp ZeroVector datum)

//===========================================================================//
// Affine-matrix proxy -- adds the SetRotation / FromRotation / FromQuaternion
// spellings the decomp uses (the engine AffineMatrix expresses these through
// operator= / dedicated helpers).
//===========================================================================//
struct ReconMatrix
{
	AffineMatrix	m;
	ReconMatrix() {}
	template<class T>   ReconMatrix &operator=(const T &)	{ return *this; }
	template<class...A> void	FromRotation(A&&...)			{}
	// P3 GAIT CUTOVER: backed by the real engine AffineMatrix (was no-op stubs, so
	// IntegrateMotion's world-step committed nothing).  Identity == BuildIdentity;
	// FromQuaternion/SetRotation == AffineMatrix::operator=(const Quaternion&) (the
	// engine's build-rotation-from-quaternion).  Signatures match every call site
	// (mech4.cpp IntegrateMotion + Simulate).
	static void SetRotation(ReconMatrix *dst, const Quaternion *q)	{ dst->m = *q; }
	static void FromQuaternion(ReconMatrix *dst, const Quaternion *q)	{ dst->m = *q; }
	static void Identity(ReconMatrix *dst)							{ dst->m.BuildIdentity(); }
	operator AffineMatrix &()	{ return m; }
};

//===========================================================================//
// SequenceController -- the BT-specific keyframe animation player embedded in the
// Mech as legAnimation (@0x65c) / bodyAnimation (@0x6bc).  RECONSTRUCTED from the
// binary (part_003.c: ctor @00427768, SelectSequence @004277a8, Advance @0042790c,
// Reset @004283b8).  NOT in the RP411 engine.  Plays a gait clip: walks keyframes,
// interpolates each joint's rotation, writes it through the engine Joint API
// (same as gyro/torso), and returns the root-translation distance advanced.
// Modelled as a plain struct (accessed only by name; no Plug base needed).  The
// keyframeCount/keyframeTimes/keyframeData accessors are preserved for mech3's
// LoadLocomotionClips/MeasureClipStride; full spec in btbuild/P3_LOCOMOTION.md.
//===========================================================================//
class Mech;		// owner (forward decl -- mechrecon.hpp precedes the Mech class)

struct SequenceController
{
	// rootTranslation entry (binary 0xC/frame); ".stride" == the .z the gait reads.
	struct Keyframe { Scalar x, y, stride; };

	// --- clip data parsed by SelectSequence (keyframe accessors read by mech3) ---
	int			keyframeCount;		// frameCount             (binary +0x14)
	int			jointCount;			// animated joints        (binary +0x18)
	int			*jointIndices;		// keyframe->skeleton map  (binary +0x1c)
	Scalar		*keyframeTimes;		// frameTimes[frameCount]  (binary +0x24)
	void		*keyframeBase;		// keyframe pose data base (binary +0x28)
	void		*keyframeCursor;	// current pose cursor     (binary +0x2c)
	Keyframe	*keyframeData;		// rootTranslations[]      (binary +0x34)

	// --- runtime state / links ---
	int			currentFrame;		// (binary +0x3c)
	Scalar		currentTime;		// clip playback time      (binary +0x54)
	void		*jointSubsystem;	// resolved owner joint subsystem (binary +0x38)
	Mech		*owner;				// (binary +0x40)
	void		*clipResource;		// locked clip resource handle    (binary +0x44)
	void		*cbCode;			// finished-callback code ptr     (binary +0x48)
	unsigned	cbArg2, cbArg3;		// finished-callback context words (binary +0x4c/0x50)

	SequenceController()
		: keyframeCount(0), jointCount(0), jointIndices(0), keyframeTimes(0),
		  keyframeBase(0), keyframeCursor(0), keyframeData(0), currentFrame(0),
		  currentTime(0.0f), jointSubsystem(0), owner(0), clipResource(0),
		  cbCode(0), cbArg2(0), cbArg3(0) {}

	void	Init(Mech *owner_mech);								// @00427768 (ctor logic)
	void	SelectSequence(int clip_id, void *cb, unsigned a2, unsigned a3);	// @004277a8
	Scalar	Advance(Scalar time_slice, int move_joints);		// @0042790c
	void	Reset(int loop);									// @004283b8
	~SequenceController();										// @004278d4 (release clip)
};
typedef SequenceController ReconSeq;

//===========================================================================//
// Controls motion source -- the controls subsystem the Mech reads its live
// commanded ground speed from (this[0x128] -> +0x128).
//===========================================================================//
struct ReconMotionSource
{
	Scalar	commandedSpeed;		// +0x128
};

// Gait-state name table ( <AnimationNames> + state*0x3c ); display data only.
static char	AnimationNames[0x1e * 0x3c] = { 0 };

//===========================================================================//
// MechSubsystem-coupled damage zone view.
//
//   The recovered MechSubsystem code addresses its DamageZone through a small
//   set of fields (structure level, per-facing armour, structure reference and
//   the zone's own alarm) that are reconstruction names rather than the modern
//   engine DamageZone member spellings; this proxy carries them so the bodies
//   compile.  damageZone is stored through it.
//===========================================================================//
struct ReconDamageZone
{
	Scalar		structureLevel;
	Scalar		structureReference;
	Scalar		armour[5];
	ReconAlarm	alarm;
};

//===========================================================================//
// Subsystem proxy + critical-subsystem chain (DistributeCriticalHit support).
//===========================================================================//
struct ReconSub
{
	template<class...A> Recon	GetName(A&&...)		{ return Recon(); }
	template<class...A> void	TakeDamage(A&&...)	{}
};

struct CriticalEntry
{
	ReconSub	*sub;
	ReconSub	*Subsystem()	{ return sub; }
};

struct CriticalChain
{
	template<class A> CriticalChain(A) {}
	int				CountOfType(int)	{ return 1; }
	CriticalEntry	*First()			{ return 0; }
	CriticalEntry	*Next()				{ return 0; }
};

//===========================================================================//
// Callable returned by the "base vtable slot 0x18" thunk:  (*BaseSlot0x18())(...)
//===========================================================================//
struct ReconCallable
{
	template<class...A> Recon	operator()(A&&...)	{ return Recon(); }
};
inline ReconCallable *BaseSlot0x18()	{ static ReconCallable c; return &c; }

//===========================================================================//
// Resource-table proxies (dmgtable).
//
//   The recovered damage-table classes drive their entry pools through a small
//   verb set (Init / Insert / Lookup / count) and a forward iterator
//   (First / Next / Current) that differ from the modern TableOf/TableIterator
//   API, so the table members are declared with these proxies instead.
//===========================================================================//
template<class T> struct ReconTable
{
	int	count;
	ReconTable() : count(0) {}
	void				Init()				{ count = 0; }
	template<class...A> void	Insert(A&&...)	{}
	template<class...A> void	*Lookup(A&&...) const	{ return 0; }
};

struct ReconTableIter
{
	template<class A> ReconTableIter(const A &) {}
	void	*First()	{ return 0; }
	void	*Next()		{ return 0; }
	void	*Current()	{ return 0; }
};

//===========================================================================//
// Generic object stream + notation-line + skeleton proxies (dmgtable parsers).
//===========================================================================//
struct GenericObjectStream
{
	template<class...A> void	Read(A&&...)	{}
	template<class...A> void	Write(A&&...)	{}
};

struct NotationLine
{
	NotationLine	*Next()		{ return 0; }
	const char		*Format()	{ return ""; }
	const char		*Value()	{ return ""; }
	int				 Count()	{ return 0; }
	template<class...A> void	Parse(A&&...)	{}
};

struct Skeleton
{
	int	SegmentCount()	{ return 1; }
};

template<class...A> inline NotationLine	*ReconGetPage(A&&...)	{ static NotationLine l; return &l; }
template<class...A> inline Recon			 ReconDir(A&&...)		{ return Recon(); }
template<class A,class B> inline int		 ReconSegIndex(A, B)	{ return 0; }

//===========================================================================//
// Vector math namespace artifact ( Vector::Add / AddScaled / Scale / Dot ... ).
// (The decomp emits free vector ops under a "Vector" qualifier; the engine uses
// Vector3D member ops.  Behaviour-neutral stand-ins for the reconstruction.)
//===========================================================================//
namespace Vector
{
	template<class...A> inline void	Add(A&&...)			{}
	template<class...A> inline void	AddScaled(A&&...)	{}
	template<class...A> inline void	Scale(A&&...)		{}
	template<class...A> inline void	Copy(A&&...)		{}
	template<class...A> inline void	Subtract(A&&...)	{}
	template<class...A> inline Scalar	Dot(A&&...)		{ return Scalar(0); }
	template<class...A> inline Scalar	Sum(A&&...)		{ return Scalar(0); }
}

//
// Quaternion free-function artifacts (the decomp writes these as
// Quaternion::Identity(dst,&id) / Quaternion::IntegrateInto(...) -- calling the
// engine's static const Identity datum as a function; routed to free shims).
//
// P3 GAIT CUTOVER: backed by the real engine Quaternion (were no-op stubs).
//   ReconQuatIdentity(q, &id)      -> q = Quaternion::Identity
//   ReconQuatIntegrate(out,in,d)   -> out = in integrated by angular delta d
//                                     (engine Quaternion::Add(source, Vector3D) == FUN_00409f58)
// All callers pass (Quaternion*,Quaternion*) / (Quaternion*,Quaternion*,Vector3D*).
inline void	ReconQuatIdentity(Quaternion *q, const Quaternion * /*id*/)	{ *q = Quaternion::Identity; }
inline void	ReconQuatIntegrate(Quaternion *out, const Quaternion *in, const Vector3D *delta)	{ out->Add(*in, *delta); }
template<class...A> inline Recon	ReconQuatSlerp(A&&...)		{ return Recon(); }
template<class...A> inline Recon	ComputeImpactDamage(A&&...)	{ return Recon(); }

//
// Raw FUN_ helper artifacts referenced in code (vector/matrix/transform glue).
//
template<class...A> inline Recon	FUN_00408644(A&&...)	{ return Recon(); }
// FUN_00408744 (part_000.c:8331) -- rotate a 3-vector by a matrix's 3x3 rotation:
//   out[i] = v[0]*M(i,0) + v[1]*M(i,1) + v[2]*M(i,2)   (row i . v).
// Backed by the engine AffineMatrix column basis: GetFromAxis(j) returns the "from"
// axis = column j = (M(0,j),M(1,j),M(2,j)), so out = v.x*colX + v.y*colY + v.z*colZ
// reproduces the raw row-dot formula EXACTLY (out[i] = sum_j v[j]*M(i,j)).  This is
// IntegrateMotion's world-step: worldVelocity = bodyOrientation * localVelocity.  The
// same GetFromAxis convention the drive facing uses (mech4.cpp), so it is sign-consistent.
inline Vector3D	*FUN_00408744(Vector3D *out, const Scalar *v, ReconMatrix *m)
{
	Vector3D colX, colY, colZ;
	m->m.GetFromAxis(X_Axis, &colX);
	m->m.GetFromAxis(Y_Axis, &colY);
	m->m.GetFromAxis(Z_Axis, &colZ);
	out->x = v[0]*colX.x + v[1]*colY.x + v[2]*colZ.x;
	out->y = v[0]*colX.y + v[1]*colY.y + v[2]*colZ.y;
	out->z = v[0]*colX.z + v[1]*colY.z + v[2]*colZ.z;
	return out;
}
template<class...A> inline Recon	FUN_00408848(A&&...)	{ return Recon(); }
template<class...A> inline Recon	FUN_00433ed4(A&&...)	{ return Recon(); }
template<class...A> inline Recon	FUN_0040e5f0(A&&...)	{ return Recon(); }
template<class...A> inline Recon	FUN_0040e36c(A&&...)	{ return Recon(); }
template<class...A> inline Recon	FUN_00406ff8(A&&...)	{ return Recon(); }

// Free vector op + pose/notify artifacts used unqualified in mech4.
template<class...A> inline Scalar	Dot(A&&...)			{ return Scalar(0); }
template<class...A> inline Recon	Build(A&&...)		{ return Recon(); }
template<class...A> inline void		ReconBeginPose(A&&...)	{}
template<class...A> inline void		ReconEndPose(A&&...)	{}
template<class...A> inline int		ReconIsDerived(A&&...)	{ return 0; }

//
// Damage notification message (DamageMessage msg; DamageMessage::Build(&msg,...)).
//
struct DamageMessage
{
	template<class...A> static void	Build(A&&...)	{}
};

// Geometry / pose constants.
static Quaternion	kIdentityQuat;
static Vector3D		kZeroVector;
static Scalar		_DAT_004ac048	= 0;
static Scalar		_DAT_004ab9c8	= 0;
static Scalar		_DAT_004ab9d0	= 0;
static Scalar		_DAT_004ab9d4	= 0;
static Recon		vtable_0050bb90;

//===========================================================================//
// Subsystem-roster chain proxy.
//
//   The Mech keeps several ChainOf<Subsystem*> capability views.  The engine
//   ChainOf has no default ctor / SetOwner / Construct / iterate-in-place verbs
//   that the recovered ctor uses, so the roster members are declared with this
//   proxy instead.
//===========================================================================//
template<class T> struct ReconChain
{
	ReconChain() {}
	ReconChain(void *) {}
	template<class...A> void	SetOwner(A&&...)	{}
	template<class...A> void	Construct(A&&...)	{}
	template<class...A> void	Reset(A&&...)		{}
	void	Add(T)			{}
	T		First()			{ return T(); }
	T		Next()			{ return T(); }
};

//===========================================================================//
// Debug-stream artifact ( DebugStream << x << endl; ).
//===========================================================================//
struct ReconStream
{
	template<class T> ReconStream &operator<<(const T &)	{ return *this; }
	void Flush() {}
	void Emit() {}
};

//===========================================================================//
// Resolve-able connection slot proxy (e.g. the power-bus / death-effect slot).
//===========================================================================//
struct ReconSlot
{
	template<class...A> Recon	Resolve(A&&...)	{ return Recon(); }
	template<class...A> void	LinkTo(A&&...)	{}
	template<class...A> void	Construct(A&&...){}
};
static ReconStream	DebugStream;
static int			endl		= 0;

//===========================================================================//
// Type aliases consumed by the recovered headers.  Defining the guard here
// suppresses the (now superseded) in-header alias blocks.
//===========================================================================//
#if !defined(BT_RECON_TYPE_ALIASES)
#	define BT_RECON_TYPE_ALIASES
	typedef ReconMatrix		Matrix34;		// orientation matrix proxy
	typedef ReconAlarm		AlarmIndicator;	// multi-level status indicator
	typedef ReconFiltered	FilteredScalar;	// running-average scalar
#endif

//===========================================================================//
// Decompiler-artifact globals actually referenced by mech-core code.
//   *  .data pointers used in address arithmetic  -> char*
//   *  scalar tuning constants                    -> Scalar
//   *  opaque label/vtable/handle operands         -> Recon
//===========================================================================//
static char		*DAT_004efc94	= 0;	// TheApp base (App*)
static Scalar	 DAT_005209d0	= 0;	// FLT_MAX seed
static Scalar	 DAT_0052140c	= 1;	// runtime frame time scale (divisor)
static char		 DAT_004e0f8c[1] = { 0 };	// "" empty string literal
static Scalar	 _DAT_004ab9cc	= 0;

//===========================================================================//
// Shared empty handler / attribute sets used to satisfy the 4-arg
// Simulation::SharedData ctor for the reconstructed DefaultData objects (the
// shipped game passes each class's own generated sets; an empty shared set is
// structurally correct for the offline reconstruction).
//===========================================================================//
static Receiver::MessageHandlerSet		ReconMessageHandlers;
static Simulation::AttributeIndexSet	ReconAttributeIndex;

static Recon	PTR_FUN_0050cfa8;		// Mech vtable
static Recon	PTR_LAB_0050c0e8;		// copy Performance
static Recon	PTR_LAB_0050c0f4;		// master Performance

// Animation SelectSequence operand triples (label + 2 floats per gait clip).
static Recon	PTR_LAB_0050d6f0, DAT_0050d6f4, DAT_0050d6f8;
static Recon	PTR_LAB_0050d6fc, DAT_0050d700, DAT_0050d704;
static Recon	PTR_LAB_0050d708, DAT_0050d70c, DAT_0050d710;
static Recon	PTR_LAB_0050d714, DAT_0050d718, DAT_0050d71c;
static Recon	PTR_LAB_0050d720, DAT_0050d724, DAT_0050d728;
static Recon	PTR_LAB_0050d72c, DAT_0050d730, DAT_0050d734;
static Recon	PTR_LAB_0050d738, DAT_0050d73c, DAT_0050d740;
static Recon	PTR_LAB_0050d744, DAT_0050d748, DAT_0050d74c;

#endif // MECHRECON_HPP
