From 4a4448a1282e7e9481a5bf43189e6d092a48c501 Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Sat, 15 Jul 2023 22:28:27 +1000 Subject: [PATCH] droptofloor(): refactor and use correct conditions for each BSP format Behaviour changes: Although startsolid is used by Q3 and Q2, it's too strict for Quake which used allsolid, so we now use the correct conditions for each BSP format. The downtrace endpoint is now calculated after sv_gameplayfix_droptofloorstartsolid_nudgetocorrect. The downtrace endpoint is now offset when using the sv_gameplayfix_droptofloorstartsolid fallback path, otherwise it would trace a diagonal line for entities whose origin is not horizontally centred in their bbox. Signed-off-by: bones_was_here --- svvm_cmds.c | 104 ++++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/svvm_cmds.c b/svvm_cmds.c index b3992c47..4cccd0f4 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -1178,12 +1178,18 @@ VM_SV_droptofloor void() droptofloor =============== */ - +inline static qbool droptofloor_bsp_failcond(trace_t *trace) +{ + if (sv.worldmodel->brush.isq3bsp || sv.worldmodel->brush.isq2bsp) + return trace->startsolid; + else + return trace->allsolid || trace->fraction == 1; +} static void VM_SV_droptofloor(prvm_prog_t *prog) { - prvm_edict_t *ent; - vec3_t end, entorigin, entmins, entmaxs; - trace_t trace; + prvm_edict_t *ent; + vec3_t end; + trace_t trace; VM_SAFEPARMCOUNTRANGE(0, 2, VM_SV_droptofloor); // allow 2 parameters because the id1 defs.qc had an incorrect prototype @@ -1202,14 +1208,6 @@ static void VM_SV_droptofloor(prvm_prog_t *prog) return; } - VectorCopy (PRVM_serveredictvector(ent, origin), end); - if (sv.worldmodel->brush.isq3bsp) - end[2] -= 4096; - else if (sv.worldmodel->brush.isq2bsp) - end[2] -= 128; - else - end[2] -= 256; // Quake, QuakeWorld - if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer) { int n = PHYS_NudgeOutOfSolid(prog, ent); @@ -1219,6 +1217,14 @@ static void VM_SV_droptofloor(prvm_prog_t *prog) VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid_nudgetocorrect FIXED badly placed entity \"%s\" before drop\n", PRVM_gameedictvector(ent, origin)[0], PRVM_gameedictvector(ent, origin)[1], PRVM_gameedictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname))); } + VectorCopy (PRVM_serveredictvector(ent, origin), end); + if (sv.worldmodel->brush.isq3bsp) + end[2] -= 4096; + else if (sv.worldmodel->brush.isq2bsp) + end[2] -= 128; + else + end[2] -= 256; // Quake, QuakeWorld + /* bones_was_here: not using SV_GenericHitSuperContentsMask(ent) anymore because it was setting: * items: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY * monsters: SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_PLAYERCLIP @@ -1226,55 +1232,47 @@ static void VM_SV_droptofloor(prvm_prog_t *prog) * which caused (startsolid == true) when, for example, a health was touching a monster. * Changing MOVE_NORMAL also fixes that, but other engines are using MOVE_NORMAL here. */ - VectorCopy(PRVM_serveredictvector(ent, origin), entorigin); - VectorCopy(PRVM_serveredictvector(ent, mins), entmins); - VectorCopy(PRVM_serveredictvector(ent, maxs), entmaxs); - trace = SV_TraceBox(entorigin, entmins, entmaxs, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value); - if (trace.startsolid && sv_gameplayfix_droptofloorstartsolid.integer) - { - vec3_t offset, org; - VectorSet(offset, 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]), 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]), PRVM_serveredictvector(ent, mins)[2]); - VectorAdd(PRVM_serveredictvector(ent, origin), offset, org); - trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value); - VectorSubtract(trace.endpos, offset, trace.endpos); - if (trace.startsolid) - { - VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid COULD NOT FIX badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname))); - SV_LinkEdict(ent); - PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND; - PRVM_serveredictedict(ent, groundentity) = 0; - PRVM_G_FLOAT(OFS_RETURN) = 1; - } - else if (trace.fraction < 1) + trace = SV_TraceBox(PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value); + if (droptofloor_bsp_failcond(&trace)) + { + if (sv_gameplayfix_droptofloorstartsolid.integer) { + vec3_t offset, org; + + offset[0] = 0.5f * (PRVM_serveredictvector(ent, mins)[0] + PRVM_serveredictvector(ent, maxs)[0]); + offset[1] = 0.5f * (PRVM_serveredictvector(ent, mins)[1] + PRVM_serveredictvector(ent, maxs)[1]); + offset[2] = PRVM_serveredictvector(ent, mins)[2]; + VectorAdd(PRVM_serveredictvector(ent, origin), offset, org); + VectorAdd(end, offset, end); + + trace = SV_TraceLine(org, end, MOVE_NORMAL, ent, SUPERCONTENTS_SOLID, 0, 0, collision_extendmovelength.value); + if (droptofloor_bsp_failcond(&trace)) + { + VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid COULD NOT FIX badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname))); + return; + } VM_Warning(prog, "droptofloor at \"%f %f %f\": sv_gameplayfix_droptofloorstartsolid FIXED badly placed entity \"%s\"\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname))); - VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin)); + VectorSubtract(trace.endpos, offset, PRVM_serveredictvector(ent, origin)); + + // only because we dropped it without considering its bbox if (sv_gameplayfix_droptofloorstartsolid_nudgetocorrect.integer) PHYS_NudgeOutOfSolid(prog, ent); - SV_LinkEdict(ent); - PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND; - PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent); - PRVM_G_FLOAT(OFS_RETURN) = 1; - // if support is destroyed, keep suspended (gross hack for floating items in various maps) - ent->priv.server->suspendedinairflag = true; } - } - else - { - if (trace.startsolid) - VM_Warning(prog, "droptofloor at \"%f %f %f\": badly placed entity \"%s\", startsolid: %d allsolid: %d\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)), trace.startsolid, trace.allsolid); - - if (!trace.allsolid && trace.fraction < 1) + else { - VectorCopy (trace.endpos, PRVM_serveredictvector(ent, origin)); - SV_LinkEdict(ent); - PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND; - PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent); - PRVM_G_FLOAT(OFS_RETURN) = 1; - // if support is destroyed, keep suspended (gross hack for floating items in various maps) - ent->priv.server->suspendedinairflag = true; + VM_Warning(prog, "droptofloor at \"%f %f %f\": badly placed entity \"%s\", startsolid: %d allsolid: %d\n", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2], PRVM_GetString(prog, PRVM_gameedictstring(ent, classname)), trace.startsolid, trace.allsolid); + return; } } + else + VectorCopy(trace.endpos, PRVM_serveredictvector(ent, origin)); + + SV_LinkEdict(ent); + PRVM_serveredictfloat(ent, flags) = (int)PRVM_serveredictfloat(ent, flags) | FL_ONGROUND; + PRVM_serveredictedict(ent, groundentity) = PRVM_EDICT_TO_PROG(trace.ent); + PRVM_G_FLOAT(OFS_RETURN) = 1; + // if support is destroyed, keep suspended (gross hack for floating items in various maps) + ent->priv.server->suspendedinairflag = true; } /* -- 2.39.2