#87: mech armour PANELS now darken with damage -- the .DZM material system was loaded and unused
Players: "the actual enemy mech in external view is not showing darkened armor panels". We swapped destroyed LIMB meshes but never darkened a panel. The 1995 game darkens armour through the MATERIALS. MakeMechRenderables (FUN_004cef28) built, per (damage zone, material), a watcher FUN_004573e4(material, &zone->damageLevel, 0.1f) that snapshotted the materials
This commit is contained in:
@@ -393,6 +393,17 @@ d3d_OBJECT* d3d_OBJECT::LoadObjectBGF(LPDIRECT3DDEVICE9 device, char *fileName)
|
||||
object->mDrawOps[i].lodNear = data.batches[i].lodNear;
|
||||
object->mDrawOps[i].lodFar = data.batches[i].lodFar;
|
||||
object->mDrawOps[i].lodDepthBias = data.batches[i].lodBias;
|
||||
// MECH ARMOUR DAMAGE (issue #87): carry the authored material name so the
|
||||
// mech's .DZM zone->material lists can drive this batch's darkening.
|
||||
{
|
||||
const std::string &mn = data.batches[i].matName;
|
||||
size_t n = mn.size();
|
||||
if (n >= sizeof(object->mDrawOps[i].dzMatName))
|
||||
n = sizeof(object->mDrawOps[i].dzMatName) - 1;
|
||||
memcpy(object->mDrawOps[i].dzMatName, mn.c_str(), n);
|
||||
object->mDrawOps[i].dzMatName[n] = '\0';
|
||||
object->mDrawOps[i].dzDamageLevel = 0.0f;
|
||||
}
|
||||
|
||||
const bool useRamp = (s_ramp && data.batches[i].hasRamp);
|
||||
uint32_t c = data.batches[i].color;
|
||||
@@ -1198,6 +1209,33 @@ void d3d_OBJECT::DrawMesh(int pass, const D3DXMATRIX *viewTransform, Time target
|
||||
|
||||
mDevice->SetMaterial(&drawOp->material);
|
||||
|
||||
// MECH ARMOUR DAMAGE (issue #87): the 1995 renderer kept a per-material
|
||||
// watcher that lerped the material's colour terms from the authored values
|
||||
// toward 0.1x as the owning damage zone's damageLevel ran 0->1
|
||||
// (FUN_004573e4 precomputed pristine*0.1; FUN_00457784 re-pushed
|
||||
// lerp(pristine, damaged, level) on every change, constant @0x4579a4 = 1.0).
|
||||
//
|
||||
// We cannot express that by scaling this op's D3DMATERIAL9: D3D9 defaults
|
||||
// DIFFUSEMATERIALSOURCE to D3DMCS_COLOR1, and every BGF vertex carries a
|
||||
// baked colour, so the material's Diffuse is never consulted for this
|
||||
// geometry -- scaling it renders identically (measured: 0 changed pixels).
|
||||
// Instead modulate the FINAL colour by k on texture stage 1, which darkens
|
||||
// the result whatever the diffuse source was, and equally covers the
|
||||
// ramp-baked-texture path (the mech's own case) and pure-emissive batches.
|
||||
const bool damageTint = (drawOp->dzDamageLevel > 0.0f);
|
||||
if (damageTint)
|
||||
{
|
||||
float d = drawOp->dzDamageLevel;
|
||||
if (d > 1.0f) d = 1.0f;
|
||||
const float k = 1.0f - (1.0f - kDamagedMaterialScale) * d; // lerp(1, 0.1, d)
|
||||
mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_COLORVALUE(k, k, k, 1.0f));
|
||||
mDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
mDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
||||
mDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
|
||||
mDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
mDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
|
||||
}
|
||||
|
||||
#ifndef RP3_EMULATE
|
||||
SetTextureScrolling(&(drawOp->texture), targetRenderFrame);
|
||||
SetTexture(drawOp->texture.texture);
|
||||
@@ -1337,6 +1375,13 @@ void d3d_OBJECT::DrawMesh(int pass, const D3DXMATRIX *viewTransform, Time target
|
||||
mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, sVAop);
|
||||
mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, sVAa2);
|
||||
}
|
||||
if (damageTint)
|
||||
{
|
||||
// stage 1 is otherwise unused in this draw path -- put it back to
|
||||
// DISABLE so the next (undamaged) op is not tinted too.
|
||||
mDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
mDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
}
|
||||
if (drawOp->lodDepthBias != 0.0f)
|
||||
mDevice->SetRenderState(D3DRS_DEPTHBIAS, sDB);
|
||||
}
|
||||
|
||||
@@ -619,6 +619,9 @@ struct Builder {
|
||||
uint32_t currentColor = 0xFFB0B0B8u;
|
||||
bool currentHasDiffuse = false; // material carried an explicit diffuse tag
|
||||
std::string currentTex;
|
||||
// authored (pre-substitution) "library:material_mtl" of the material in force --
|
||||
// the .DZM armour-damage lists key on this (issue #87)
|
||||
std::string currentMatName;
|
||||
int currentTexChannel = 0; // BSL bit-slice (BMF tag 0x18)
|
||||
bool currentTexScroll = false; // TEXTURE SPECIAL " SCROLL" (tag 0x2037)
|
||||
float currentTexScrollU = 0.0f, currentTexScrollV = 0.0f;
|
||||
@@ -872,6 +875,7 @@ struct Builder {
|
||||
batch.color = pureEmissive ? currentColor // keep BLACK: L4D3D's
|
||||
: (useRamp ? rampTint : currentColor); // pure-emissive test keys on it
|
||||
batch.texPath = currentTex;
|
||||
batch.matName = currentMatName; // .DZM armour-damage key (issue #87)
|
||||
batch.texChannel = currentTexChannel;
|
||||
batch.texScroll = currentTexScroll;
|
||||
batch.texScrollU = currentTexScrollU;
|
||||
@@ -1185,6 +1189,9 @@ struct Builder {
|
||||
size_t maxn = ch.len - 1, n = 0;
|
||||
while (n < maxn && s[n]) ++n;
|
||||
std::string full(s, n);
|
||||
// remember the AUTHORED name (before the paint callback rewrites
|
||||
// it) -- the .DZM zone material lists are authored against it
|
||||
currentMatName = full;
|
||||
// baked ground-shadow material (basev:shadow_mtl etc.)
|
||||
currentShadowMat = false;
|
||||
for (size_t si = 0; si + 6 <= full.size(); ++si)
|
||||
|
||||
@@ -106,6 +106,17 @@ struct BgfDrawBatch {
|
||||
// routed through the mech-shadow pipeline (translucent dark, depth-biased,
|
||||
// no z-write) instead.
|
||||
bool shadowMat = false;
|
||||
// AUTHORED MATERIAL NAME ("library:material_mtl", e.g. "avaskin:avat2_dz_ltorso_mtl"),
|
||||
// recorded PRE-substitution -- the per-pilot paint callback rewrites names, but the
|
||||
// .DZM damage-zone material lists are authored against these base names.
|
||||
//
|
||||
// This is the key the mech ARMOUR-DARKENING system matches on (issue #87): the 1995
|
||||
// BTL4VideoRenderer built one material-damage watcher per (zone, material) pair
|
||||
// (FUN_004573e4) that lerped the material's colour terms from pristine toward 0.1x
|
||||
// as that zone's damageLevel ran 0->1. Our draw path bakes colour into a
|
||||
// D3DMATERIAL9 at load, so the equivalent modulation is applied per draw op --
|
||||
// see L4D3D d3d_OBJECT::SetDamageScaleForMaterials.
|
||||
std::string matName;
|
||||
};
|
||||
|
||||
struct BgfData {
|
||||
|
||||
@@ -71,6 +71,12 @@ struct L4RAMP
|
||||
float r1, g1, b1;
|
||||
};
|
||||
|
||||
// MECH ARMOUR DAMAGE (issue #87): the factor the 1995 material-damage watcher
|
||||
// (FUN_004573e4) precomputed as the FULLY-DAMAGED colour -- pristine x 0.1, the
|
||||
// literal 0x3dcccccd passed at every construction site. A zone at damageLevel 1
|
||||
// renders its panels at 10% of the authored brightness.
|
||||
const float kDamagedMaterialScale = 0.1f;
|
||||
|
||||
struct L4DRAWOP
|
||||
{
|
||||
D3DMATERIAL9 material;
|
||||
@@ -112,6 +118,18 @@ struct L4DRAWOP
|
||||
// coplanar duplicated surfaces resolve to the detail layer instead of
|
||||
// venetian-blind z-fighting (the board's submission-order rule, in D3D terms).
|
||||
float lodDepthBias;
|
||||
// MECH ARMOUR DAMAGE (issue #87). The 1995 BTL4VideoRenderer bound one
|
||||
// material-damage watcher per (damage zone, material) pair -- FUN_004573e4 --
|
||||
// which lerped that material's colour terms from their authored values toward
|
||||
// 0.1x as the zone's damageLevel ran 0->1 (FUN_00457784 re-pushed them whenever
|
||||
// the level changed). The zone->material lists come from the per-mech .DZM
|
||||
// files, already parsed into DamageZone::materialTable (MUNGA DAMAGE.cpp).
|
||||
//
|
||||
// Our draw path bakes colour into this D3DMATERIAL9 at load, so the equivalent
|
||||
// modulation is applied at SetMaterial time from the level cached here.
|
||||
// Both fields are memset-0 safe: empty name = not zone-mapped, level 0 = pristine.
|
||||
char dzMatName[64]; // authored "library:material_mtl" for this batch
|
||||
float dzDamageLevel; // owning zone's damageLevel [0..1] (0 = undamaged)
|
||||
};
|
||||
|
||||
class d3d_OBJECT
|
||||
|
||||
Reference in New Issue
Block a user