From 01a958e0a69b113e5cae1d66ff7511effb373a3f Mon Sep 17 00:00:00 2001 From: Shpoike Date: Sun, 25 Jun 2023 15:49:09 +0100 Subject: [PATCH] Handle Hexen2's SOLID_PHASE more accurately, including warts, so corpses can be reliably whacked with melee weapons. --- engine/common/pr_common.h | 2 +- engine/server/sv_phys.c | 28 +++++++++++++++++++++++++++- engine/server/world.c | 4 ++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 0d4b1120a..897bad1fb 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -671,7 +671,7 @@ unsigned int FTEToDPContents(unsigned int contents); #define SOLID_BBOX 2 // touch on edge, block #define SOLID_SLIDEBOX 3 // touch on edge, but not an onground #define SOLID_BSP 4 // bsp clip, touch on edge, block -#define SOLID_PHASEH2 5 // hexen2 flag - these ents can be freely walked through or something +#define SOLID_PHASEH2 5 // hexen2 flag - this is apparently a modifier for movetype rather than solidity - passes through FL_MONSTER or MOVETYPE_WALK ents #define SOLID_CORPSE 5 // non-solid to solid_slidebox entities and itself. #define SOLID_LADDER 20 //spike: legacy. forces FTECONTENTS_LADDER. #define SOLID_PORTAL 21 //1: traces always use point-size. 2: various movetypes automatically transform entities. 3: traces that impact portal bbox use a union. 4. traces ignore part of the world within the portal's box diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 3e9252771..c9699eee4 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -649,6 +649,32 @@ static trace_t WPhys_PushEntity (world_t *w, wedict_t *ent, vec3_t push, unsigne trace.ent = w->edicts; } } +#if defined(HAVE_SERVER) && defined(HEXEN2) + else if (ent->v->solid == SOLID_PHASEH2 && progstype == PROG_H2 && w == &sv.world && trace.fraction != 1 && trace.ent && + (((int)((wedict_t*)trace.ent)->v->flags & FL_MONSTER) || (int)((wedict_t*)trace.ent)->v->movetype == MOVETYPE_WALK)) + { //hexen2's SOLID_PHASEH2 ents should pass through players+monsters, yet still trigger impacts. I would use MOVE_ENTCHAIN but that would corrupt .chain, perhaps that's okay though? + + //continue the trace on to where we wold be if there had been no impact + trace_t trace2 = World_Move (w, trace.endpos, ent->v->mins, ent->v->maxs, end, traceflags|MOVE_NOMONSTERS|MOVE_MISSILE|MOVE_RESERVED/*Don't fuck up in the face of dp's MOVE_WORLDONLY*/, (wedict_t*)ent); + + //do the first non-world impact + // if (trace.ent) + // VectorMA(trace.endpos, sv_impactpush.value, trace.plane.normal, ent->v->origin); + // else + VectorCopy (trace.endpos, ent->v->origin); + World_LinkEdict (w, ent, true); + + if (trace.ent) + { + WPhys_Impact (w, ent, &trace); + if (ent->ereftype != ER_ENTITY) + return trace; //someone remove()d it. don't do weird stuff. + } + + //and use our regular impact logic for the rest of it. + trace = trace2; + } +#endif // if (trace.ent) // VectorMA(trace.endpos, sv_impactpush.value, trace.plane.normal, ent->v->origin); @@ -1430,7 +1456,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent) if (ent->xv->bouncefactor) backoff = 1 + ent->xv->bouncefactor; // else if (progstype == PROG_H2 && ent->v->solid == SOLID_PHASEH2 && ((int)((wedict_t*)trace.ent)->v->flags & (FL_MONSTER|FL_CLIENT))) -// backoff = 0; +// backoff = 0; //don't bounce/slide, just pass straight through. else backoff = w->remasterlogic?1.5/*gib...*/:2; } diff --git a/engine/server/world.c b/engine/server/world.c index 2a233d985..0e9af561f 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -1029,7 +1029,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v trace.startsolid = false; hitmodel = false; } - else if (solid == SOLID_CORPSE) + else if (solid == SOLID_CORPSE && w->usesolidcorpse) goto scorpse; else if (ent->v->skin < 0) { //if forcedcontents is set, then ALL brushes in this model are forced to the specified contents value. @@ -2501,7 +2501,7 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e else clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY; //slidebox passes through corpses } - else if (passedict->v->solid == SOLID_CORPSE) + else if (passedict->v->solid == SOLID_CORPSE && w->usesolidcorpse) clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY; //corpses ignore corpses else if (passedict->v->solid == SOLID_TRIGGER||passedict->v->solid == SOLID_BSPTRIGGER) clip.hitcontentsmask = FTECONTENTS_SOLID|Q2CONTENTS_WINDOW | FTECONTENTS_BODY; //triggers ignore corpses too, apparently