diff --git a/src/k_objects.h b/src/k_objects.h index fe3e17783..c5e7dba5b 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -17,6 +17,7 @@ void Obj_HyudoroDeploy(mobj_t *master); void Obj_HyudoroThink(mobj_t *actor); void Obj_HyudoroCenterThink(mobj_t *actor); void Obj_HyudoroCollide(mobj_t *special, mobj_t *toucher); +boolean Obj_HyudoroShadowZ(mobj_t *actor, fixed_t *return_z, pslope_t **return_slope); /* Garden Top */ void Obj_GardenTopDeploy(mobj_t *rider); @@ -218,6 +219,7 @@ void Obj_SetEmeraldAwardee(mobj_t *emerald, mobj_t *awardee); /* Fake Shadow */ mobj_t *Obj_SpawnFakeShadow(mobj_t *from); void Obj_FakeShadowThink(mobj_t *shadow); +boolean Obj_FakeShadowZ(const mobj_t *shadow, fixed_t *return_z, pslope_t **return_slope); /* Checkpoints */ void Obj_ResetCheckpoints(void); diff --git a/src/objects/hyudoro.c b/src/objects/hyudoro.c index 51b87627e..552b77bfa 100644 --- a/src/objects/hyudoro.c +++ b/src/objects/hyudoro.c @@ -882,3 +882,21 @@ Obj_HyudoroCollide break; } } + +boolean +Obj_HyudoroShadowZ +( mobj_t * hyu, + fixed_t * return_z, + pslope_t ** return_slope) +{ + if (hyudoro_mode(hyu) != HYU_PATROL) + return false; + + if (P_MobjWasRemoved(hyudoro_center(hyu))) + return false; + + *return_z = hyu->z; + *return_slope = hyudoro_center(hyu)->standingslope; + + return true; +} diff --git a/src/objects/shadow.cpp b/src/objects/shadow.cpp index 9aa88213c..58c670ca0 100644 --- a/src/objects/shadow.cpp +++ b/src/objects/shadow.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "../info.h" #include "../k_objects.h" #include "../p_local.h" @@ -19,6 +22,28 @@ struct Shadow : mobj_t bool valid() const { return !P_MobjWasRemoved(this) && !P_MobjWasRemoved(follow()); } + std::optional> z_position() const + { + switch (follow()->type) + { + case MT_HYUDORO: { + fixed_t z; + pslope_t* slope; + + if (Obj_HyudoroShadowZ(follow(), &z, &slope)) + { + return {{z, slope}}; + } + break; + } + + default: + break; + } + + return {}; + } + void destroy() { P_RemoveMobj(this); } void move() @@ -58,3 +83,27 @@ void Obj_FakeShadowThink(mobj_t* shadow) x->move(); } + +boolean Obj_FakeShadowZ(const mobj_t* shadow, fixed_t* return_z, pslope_t** return_slope) +{ + auto x = static_cast(shadow); + + if (!x->valid()) + { + return false; + } + + auto pair = x->z_position(); + + if (!pair) + { + return false; + } + + auto [z, slope] = *pair; + + *return_z = z; + *return_slope = slope; + + return true; +} diff --git a/src/r_spritefx.cpp b/src/r_spritefx.cpp index 756e0a96e..ff0713bc8 100644 --- a/src/r_spritefx.cpp +++ b/src/r_spritefx.cpp @@ -10,6 +10,7 @@ #include "d_player.h" #include "info.h" +#include "k_objects.h" #include "p_tick.h" #include "r_splats.h" #include "r_things.h" @@ -59,3 +60,21 @@ boolean R_SplatSlope(mobj_t* mobj, vector3_t position, pslope_t* slope) return false; } + +boolean R_CustomShadowZ(mobj_t* thing, fixed_t *z, pslope_t** slope) +{ + switch (thing->type) + { + case MT_SHADOW: + if (Obj_FakeShadowZ(thing, z, slope)) + { + return true; + } + break; + + default: + break; + } + + return false; +} diff --git a/src/r_things.c b/src/r_things.c index 967006041..d94ed27af 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1315,6 +1315,14 @@ fixed_t R_GetShadowZ( sector_t *sector; ffloor_t *rover; + if (R_CustomShadowZ(thing, &groundz, &groundslope)) + { + if (shadowslope != NULL) + *shadowslope = groundslope; + + return groundz; + } + // for frame interpolation interpmobjstate_t interp = {0}; diff --git a/src/r_things.h b/src/r_things.h index 642f788d9..8f74f5135 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -95,6 +95,7 @@ boolean R_ThingIsFlashing(mobj_t *thing); INT32 R_ThingLightLevel(mobj_t *thing); boolean R_SplatSlope(mobj_t *thing, vector3_t position, pslope_t *slope); +boolean R_CustomShadowZ(mobj_t *thing, fixed_t *return_z, pslope_t **return_slope); // -------------- // MASKED DRAWING