Skip to content

Commit aca6eaf

Browse files
Fix M_CheckBottom to support arbitrary gravity vectors
This change generalizes M_CheckBottom_Fast_Generic and M_CheckBottom_Slow_Generic to support gravity vectors along any major axis (X, Y, Z), addressing a FIXME in the codebase. Previously, these functions assumed gravity was always vertical (Z-axis). - Updated M_CheckBottom_Fast_Generic and M_CheckBottom_Slow_Generic signatures to take a gravity direction vector instead of a ceiling boolean. - Implemented logic to determine the major gravity axis and adjust collision checks accordingly. - Updated calls in g_monster_spawn.cpp and M_CheckBottom to pass the gravity vector.
1 parent 7599dcf commit aca6eaf

File tree

3 files changed

+61
-51
lines changed

3 files changed

+61
-51
lines changed

src/server/g_local.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4572,8 +4572,8 @@ extern byte damage_multiplier;
45724572
//
45734573
// m_move.cpp
45744574
//
4575-
bool M_CheckBottom_Fast_Generic(const Vector3& absmins, const Vector3& absmaxs, bool ceiling);
4576-
bool M_CheckBottom_Slow_Generic(const Vector3& origin, const Vector3& absmins, const Vector3& absmaxs, gentity_t* ignore, contents_t mask, bool ceiling, bool allow_any_step_height);
4575+
bool M_CheckBottom_Fast_Generic(const Vector3& absmins, const Vector3& absmaxs, const Vector3& gravityDir);
4576+
bool M_CheckBottom_Slow_Generic(const Vector3& origin, const Vector3& absmins, const Vector3& absmaxs, gentity_t* ignore, contents_t mask, const Vector3& gravityDir, bool allow_any_step_height);
45774577
bool M_CheckBottom(gentity_t* ent);
45784578
bool G_CloseEnough(gentity_t* ent, gentity_t* goal, float dist);
45794579
bool M_walkmove(gentity_t* ent, float yaw, float dist);

src/server/gameplay/g_monster_spawn.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,11 @@ bool CheckGroundSpawnPoint(const Vector3& origin, const Vector3& entMins, const
226226
}
227227

228228
if (verticalGravity) {
229-
if (M_CheckBottom_Fast_Generic(support.endPos + entMins, support.endPos + entMaxs, ceiling))
229+
Vector3 gravityDir = ceiling ? Vector3(0, 0, 1) : Vector3(0, 0, -1);
230+
if (M_CheckBottom_Fast_Generic(support.endPos + entMins, support.endPos + entMaxs, gravityDir))
230231
return true;
231232

232-
if (M_CheckBottom_Slow_Generic(support.endPos, entMins, entMaxs, nullptr, MASK_MONSTERSOLID, ceiling, false))
233+
if (M_CheckBottom_Slow_Generic(support.endPos, entMins, entMaxs, nullptr, MASK_MONSTERSOLID, gravityDir, false))
233234
return true;
234235

235236
return false;

src/server/monsters/m_move.cpp

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,55 +18,65 @@ is not a staircase.
1818
1919
=============
2020
*/
21-
bool M_CheckBottom_Fast_Generic(const Vector3 &absmins, const Vector3 &absmaxs, bool ceiling) {
22-
// FIXME - this will only handle 0,0,1 and 0,0,-1 gravity vectors
23-
Vector3 start{};
24-
25-
start[2] = absmins[2] - 1;
26-
if (ceiling)
27-
start[2] = absmaxs[2] + 1;
28-
29-
for (int x = 0; x <= 1; x++)
30-
for (int y = 0; y <= 1; y++) {
31-
start[0] = x ? absmaxs[0] : absmins[0];
32-
start[1] = y ? absmaxs[1] : absmins[1];
21+
bool M_CheckBottom_Fast_Generic(const Vector3 &absmins, const Vector3 &absmaxs, const Vector3 &gravityDir) {
22+
Vector3 start;
23+
int majorAxis = 0;
24+
if (fabsf(gravityDir[1]) > fabsf(gravityDir[0])) majorAxis = 1;
25+
if (fabsf(gravityDir[2]) > fabsf(gravityDir[majorAxis])) majorAxis = 2;
26+
27+
int axis1 = (majorAxis + 1) % 3;
28+
int axis2 = (majorAxis + 2) % 3;
29+
30+
if (gravityDir[majorAxis] > 0) // ceiling / up
31+
start[majorAxis] = absmaxs[majorAxis] + 1;
32+
else // floor / down
33+
start[majorAxis] = absmins[majorAxis] - 1;
34+
35+
for (int i = 0; i <= 1; i++)
36+
for (int j = 0; j <= 1; j++) {
37+
start[axis1] = i ? absmaxs[axis1] : absmins[axis1];
38+
start[axis2] = j ? absmaxs[axis2] : absmins[axis2];
3339
if (gi.pointContents(start) != CONTENTS_SOLID)
3440
return false;
3541
}
3642

3743
return true; // we got out easy
3844
}
3945

40-
bool M_CheckBottom_Slow_Generic(const Vector3 &origin, const Vector3 &mins, const Vector3 &maxs, gentity_t *ignore, contents_t mask, bool ceiling, bool allow_any_step_height) {
41-
Vector3 start{};
46+
bool M_CheckBottom_Slow_Generic(const Vector3 &origin, const Vector3 &mins, const Vector3 &maxs, gentity_t *ignore, contents_t mask, const Vector3 &gravityDir, bool allow_any_step_height) {
47+
Vector3 start, stop;
48+
int majorAxis = 0;
49+
if (fabsf(gravityDir[1]) > fabsf(gravityDir[0])) majorAxis = 1;
50+
if (fabsf(gravityDir[2]) > fabsf(gravityDir[majorAxis])) majorAxis = 2;
51+
52+
int axis1 = (majorAxis + 1) % 3;
53+
int axis2 = (majorAxis + 2) % 3;
4254

4355
//
4456
// check it for real...
4557
//
4658
Vector3 step_quadrant_size = (maxs - mins) * 0.5f;
47-
step_quadrant_size.z = 0;
59+
step_quadrant_size[majorAxis] = 0;
4860

4961
Vector3 half_step_quadrant = step_quadrant_size * 0.5f;
5062
Vector3 half_step_quadrant_mins = -half_step_quadrant;
5163

52-
Vector3 stop;
53-
54-
start[0] = stop[0] = origin.x;
55-
start[1] = stop[1] = origin.y;
64+
start[axis1] = stop[axis1] = origin[axis1];
65+
start[axis2] = stop[axis2] = origin[axis2];
5666

57-
if (!ceiling) {
58-
start[2] = origin.z + mins.z;
59-
stop[2] = start[2] - STEPSIZE * 2;
60-
} else {
61-
start[2] = origin.z + maxs.z;
62-
stop[2] = start[2] + STEPSIZE * 2;
67+
if (gravityDir[majorAxis] > 0) { // ceiling / up
68+
start[majorAxis] = origin[majorAxis] + maxs[majorAxis];
69+
stop[majorAxis] = start[majorAxis] + STEPSIZE * 2;
70+
} else { // floor / down
71+
start[majorAxis] = origin[majorAxis] + mins[majorAxis];
72+
stop[majorAxis] = start[majorAxis] - STEPSIZE * 2;
6373
}
6474

65-
Vector3 mins_no_z = mins;
66-
Vector3 maxs_no_z = maxs;
67-
mins_no_z.z = maxs_no_z.z = 0;
75+
Vector3 mins_flat = mins;
76+
Vector3 maxs_flat = maxs;
77+
mins_flat[majorAxis] = maxs_flat[majorAxis] = 0;
6878

69-
trace_t trace = gi.trace(start, mins_no_z, maxs_no_z, stop, ignore, mask);
79+
trace_t trace = gi.trace(start, mins_flat, maxs_flat, stop, ignore, mask);
7080

7181
if (trace.fraction == 1.0f)
7282
return false;
@@ -75,37 +85,36 @@ bool M_CheckBottom_Slow_Generic(const Vector3 &origin, const Vector3 &mins, cons
7585
if (allow_any_step_height)
7686
return true;
7787

78-
start[0] = stop[0] = origin.x + ((mins.x + maxs.x) * 0.5f);
79-
start[1] = stop[1] = origin.y + ((mins.y + maxs.y) * 0.5f);
88+
start[axis1] = stop[axis1] = origin[axis1] + ((mins[axis1] + maxs[axis1]) * 0.5f);
89+
start[axis2] = stop[axis2] = origin[axis2] + ((mins[axis2] + maxs[axis2]) * 0.5f);
8090

81-
float mid = trace.endPos[2];
91+
float mid = trace.endPos[majorAxis];
8292

8393
// the corners must be within 16 of the midpoint
84-
for (int32_t x = 0; x <= 1; x++)
85-
for (int32_t y = 0; y <= 1; y++) {
94+
for (int32_t i = 0; i <= 1; i++)
95+
for (int32_t j = 0; j <= 1; j++) {
8696
Vector3 quadrant_start = start;
8797

88-
if (x)
89-
quadrant_start.x += half_step_quadrant.x;
98+
if (i)
99+
quadrant_start[axis1] += half_step_quadrant[axis1];
90100
else
91-
quadrant_start.x -= half_step_quadrant.x;
101+
quadrant_start[axis1] -= half_step_quadrant[axis1];
92102

93-
if (y)
94-
quadrant_start.y += half_step_quadrant.y;
103+
if (j)
104+
quadrant_start[axis2] += half_step_quadrant[axis2];
95105
else
96-
quadrant_start.y -= half_step_quadrant.y;
106+
quadrant_start[axis2] -= half_step_quadrant[axis2];
97107

98108
Vector3 quadrant_end = quadrant_start;
99-
quadrant_end.z = stop.z;
109+
quadrant_end[majorAxis] = stop[majorAxis];
100110

101111
trace = gi.trace(quadrant_start, half_step_quadrant_mins, half_step_quadrant, quadrant_end, ignore, mask);
102112

103-
// FIXME - this will only handle 0,0,1 and 0,0,-1 gravity vectors
104-
if (ceiling) {
105-
if (trace.fraction == 1.0f || trace.endPos[2] - mid > (STEPSIZE))
113+
if (gravityDir[majorAxis] > 0) {
114+
if (trace.fraction == 1.0f || trace.endPos[majorAxis] - mid > (STEPSIZE))
106115
return false;
107116
} else {
108-
if (trace.fraction == 1.0f || mid - trace.endPos[2] > (STEPSIZE))
117+
if (trace.fraction == 1.0f || mid - trace.endPos[majorAxis] > (STEPSIZE))
109118
return false;
110119
}
111120
}
@@ -117,11 +126,11 @@ bool M_CheckBottom(gentity_t *ent) {
117126
// if all of the points under the corners are solid world, don't bother
118127
// with the tougher checks
119128

120-
if (M_CheckBottom_Fast_Generic(ent->s.origin + ent->mins, ent->s.origin + ent->maxs, ent->gravityVector[2] > 0))
129+
if (M_CheckBottom_Fast_Generic(ent->s.origin + ent->mins, ent->s.origin + ent->maxs, ent->gravityVector))
121130
return true; // we got out easy
122131

123132
contents_t mask = (ent->svFlags & SVF_MONSTER) ? MASK_MONSTERSOLID : (MASK_SOLID | CONTENTS_MONSTER | CONTENTS_PLAYER);
124-
return M_CheckBottom_Slow_Generic(ent->s.origin, ent->mins, ent->maxs, ent, mask, ent->gravityVector[2] > 0, ent->spawnFlags.has(SPAWNFLAG_MONSTER_SUPER_STEP));
133+
return M_CheckBottom_Slow_Generic(ent->s.origin, ent->mins, ent->maxs, ent, mask, ent->gravityVector, ent->spawnFlags.has(SPAWNFLAG_MONSTER_SUPER_STEP));
125134
}
126135

127136
static bool IsBadAhead(gentity_t *self, gentity_t *bad, const Vector3 &move) {

0 commit comments

Comments
 (0)