Files
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00

159 lines
3.1 KiB
C++

#pragma once
#include <memory.h>
#include <d3d9.h>
#include <d3dx9.h>
#include "../munga/time.h"
#include "l4d3d.h"
#define COLOR_POINT_COUNT 10
#define MAX_PARTICLE_EFFECTS 32
#define EFFECT_GROUPING_EPSILON 1.0f
#define L4BASICVERTEX_FVF (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE | D3DFVF_NORMAL)
struct L4BASICVERTEX
{
float x, y, z;
float nx, ny, nz;
DWORD color;
float u, v;
};
union L4COLOR
{
DWORD argb;
struct
{
unsigned char b;
unsigned char g;
unsigned char r;
unsigned char a;
};
};
struct COLOR_POINT
{
bool active;
Scalar time;
L4COLOR color;
};
struct PARTICLE_EFFECT
{
int id;
struct
{
float left, top, right, bottom;
} textureBounds;
bool rotate;
float fragSize;
float velocity;
COLOR_POINT colors[COLOR_POINT_COUNT];
float gravity;
float varianceX;
float varianceY;
float varianceZ;
int fragCount;
float fragLifetime;
float maxRepeat;
};
struct INDIE_EFFECT : public PARTICLE_EFFECT
{
int maxIssue;
float releasePeriod;
float duration;
};
class ParticleEngine;
class ParticleEmitter;
class Particle
{
friend class ParticleEngine;
public:
Particle(PARTICLE_EFFECT *effect);
void Execute(Scalar dT);
inline bool IsAlive() { return (mEffect && ( mAge < mEffect->fragLifetime)); }
inline Particle *Next() { return mNextParticle; }
inline Particle *Prev() { return mPrevParticle; }
private:
float mX, mY, mZ;
L4COLOR mColor;
D3DXVECTOR3 mVelocity;
D3DXVECTOR3 mAcceleration;
D3DXMATRIX mTextureTransform;
PARTICLE_EFFECT *mEffect;
Scalar mAge;
Particle *mNextParticle;
Particle *mPrevParticle;
friend int compare(const Particle *, const Particle *, const D3DXMATRIX *);
friend void mergesort(Particle **, Particle **, const D3DXMATRIX *);
};
class ParticleEmitter
{
public:
ParticleEmitter();
bool IsActive() { return mActive; }
void SetEffect(int effect);
void SetEffect(INDIE_EFFECT *effect) { mEffect = effect; }
float GetMaxRepeat() { return mEffect->maxRepeat; }
void Execute();
void Fire() { mActive = true; }
void Start()
{
mActive = true;
mActivated = (Scalar)Now();
}
void SetPosition(float x, float y, float z)
{
mPosition.x = x;
mPosition.y = y;
mPosition.z = z;
}
private:
PARTICLE_EFFECT *mEffect;
bool mActive;
Scalar mActivated;
D3DXVECTOR3 mPosition;
};
class ParticleEngine
{
friend class ParticleEmitter;
public:
static void Destroy();
static void Initialize(LPDIRECT3DDEVICE9 device);
static void InstallEffect(int effectNumber, PARTICLE_EFFECT effect);
static void RenderParticles(const D3DXMATRIX *view_matrix, Scalar timeSlice);
private:
static void CreateParticle(D3DXVECTOR3 position, PARTICLE_EFFECT *effect);
static int BuildParticleVertices(const Particle *p, L4BASICVERTEX *verts, D3DXMATRIX *view_matrix);
static void ExecuteParticles(const D3DXMATRIX *view_matrix, Scalar timeSlice);
static LPDIRECT3DDEVICE9 mDevice;
static PARTICLE_EFFECT mInstalledEffects[];
static LPDIRECT3DTEXTURE9 mParticleTexture;
static bool mActiveParticles;
static LPDIRECT3DVERTEXBUFFER9 mVertBuffer;
static Particle *mParticlesHead;
static Particle *mParticlesTail;
static long mTotalParticleCount;
static long mMaxParticleCount;
};