2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // sv_move.c -- monster movement
30 Returns false if any part of the bottom of the entity is off an edge that
37 qboolean SV_CheckBottom (edict_t *ent)
39 vec3_t mins, maxs, start, stop;
44 VectorAdd (ent->v.origin, ent->v.mins, mins);
45 VectorAdd (ent->v.origin, ent->v.maxs, maxs);
47 // if all of the points under the corners are solid world, don't bother
48 // with the tougher checks
49 // the corners must be within 16 of the midpoint
50 start[2] = mins[2] - 1;
51 for (x=0 ; x<=1 ; x++)
52 for (y=0 ; y<=1 ; y++)
54 start[0] = x ? maxs[0] : mins[0];
55 start[1] = y ? maxs[1] : mins[1];
56 if (SV_PointContents (start) != CONTENTS_SOLID)
61 return true; // we got out easy
66 // check it for real...
70 // the midpoint must be within 16 of the bottom
71 start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
72 start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
73 stop[2] = start[2] - 2*STEPSIZE;
74 trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
76 if (trace.fraction == 1.0)
78 mid = bottom = trace.endpos[2];
80 // the corners must be within 16 of the midpoint
81 for (x=0 ; x<=1 ; x++)
82 for (y=0 ; y<=1 ; y++)
84 start[0] = stop[0] = x ? maxs[0] : mins[0];
85 start[1] = stop[1] = y ? maxs[1] : mins[1];
87 trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
89 if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
90 bottom = trace.endpos[2];
91 if (trace.fraction == 1.0 || mid - trace.endpos[2] > STEPSIZE)
104 Called by monster program code.
105 The move will be adjusted for slopes and stairs, but if the move isn't
106 possible, no move is done, false is returned, and
107 pr_global_struct->trace_normal is set to the normal of the blocking wall
110 qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
113 vec3_t oldorg, neworg, end;
119 VectorCopy (ent->v.origin, oldorg);
120 VectorAdd (ent->v.origin, move, neworg);
122 // flying monsters don't step up
123 if ( (int)ent->v.flags & (FL_SWIM | FL_FLY) )
125 // try one move with vertical motion, then one without
126 for (i=0 ; i<2 ; i++)
128 VectorAdd (ent->v.origin, move, neworg);
129 enemy = PROG_TO_EDICT(ent->v.enemy);
130 if (i == 0 && enemy != sv.edicts)
132 dz = ent->v.origin[2] - PROG_TO_EDICT(ent->v.enemy)->v.origin[2];
138 trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);
140 if (trace.fraction == 1)
142 if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == CONTENTS_EMPTY )
143 return false; // swim monster left water
145 VectorCopy (trace.endpos, ent->v.origin);
147 SV_LinkEdict (ent, true);
151 if (enemy == sv.edicts)
158 // push down from a step height above the wished position
159 neworg[2] += STEPSIZE;
160 VectorCopy (neworg, end);
161 end[2] -= STEPSIZE*2;
163 trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
168 if (trace.startsolid)
170 neworg[2] -= STEPSIZE;
171 trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
172 if (trace.allsolid || trace.startsolid)
175 if (trace.fraction == 1)
177 // if monster had the ground pulled out, go ahead and fall
178 if ( (int)ent->v.flags & FL_PARTIALGROUND )
180 VectorAdd (ent->v.origin, move, ent->v.origin);
182 SV_LinkEdict (ent, true);
183 ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
184 // Con_Printf ("fall down\n");
188 return false; // walked off an edge
191 // check point traces down for dangling corners
192 VectorCopy (trace.endpos, ent->v.origin);
194 if (!SV_CheckBottom (ent))
196 if ( (int)ent->v.flags & FL_PARTIALGROUND )
197 { // entity had floor mostly pulled out from underneath it
198 // and is trying to correct
200 SV_LinkEdict (ent, true);
203 VectorCopy (oldorg, ent->v.origin);
207 if ( (int)ent->v.flags & FL_PARTIALGROUND )
209 // Con_Printf ("back on ground\n");
210 ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
212 ent->v.groundentity = EDICT_TO_PROG(trace.ent);
216 SV_LinkEdict (ent, true);
221 //============================================================================
224 ======================
227 Turns to the movement direction, and walks the current distance if
230 ======================
232 void PF_changeyaw (void);
233 qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
235 vec3_t move, oldorigin;
238 ent->v.ideal_yaw = yaw;
241 yaw = yaw*M_PI*2 / 360;
242 move[0] = cos(yaw)*dist;
243 move[1] = sin(yaw)*dist;
246 VectorCopy (ent->v.origin, oldorigin);
247 if (SV_movestep (ent, move, false))
249 delta = ent->v.angles[YAW] - ent->v.ideal_yaw;
250 if (delta > 45 && delta < 315)
251 { // not turned far enough, so don't take the step
252 VectorCopy (oldorigin, ent->v.origin);
254 SV_LinkEdict (ent, true);
257 SV_LinkEdict (ent, true);
263 ======================
266 ======================
268 void SV_FixCheckBottom (edict_t *ent)
270 // Con_Printf ("SV_FixCheckBottom\n");
272 ent->v.flags = (int)ent->v.flags | FL_PARTIALGROUND;
284 void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
288 float tdir, olddir, turnaround;
290 olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 );
291 turnaround = anglemod(olddir - 180);
293 deltax = enemy->v.origin[0] - actor->v.origin[0];
294 deltay = enemy->v.origin[1] - actor->v.origin[1];
309 if (d[1] != DI_NODIR && d[2] != DI_NODIR)
312 tdir = d[2] == 90 ? 45 : 315;
314 tdir = d[2] == 90 ? 135 : 215;
316 if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
320 // try other directions
321 if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax))
328 if (d[1]!=DI_NODIR && d[1]!=turnaround
329 && SV_StepDirection(actor, d[1], dist))
332 if (d[2]!=DI_NODIR && d[2]!=turnaround
333 && SV_StepDirection(actor, d[2], dist))
336 /* there is no direct path to the player, so pick another direction */
338 if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
341 if (rand()&1) /*randomly determine direction of search*/
343 for (tdir=0 ; tdir<=315 ; tdir += 45)
344 if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
349 for (tdir=315 ; tdir >=0 ; tdir -= 45)
350 if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
354 if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
357 actor->v.ideal_yaw = olddir; // can't move
359 // if a bridge was pulled out from underneath a monster, it may not have
360 // a valid standing position at all
362 if (!SV_CheckBottom (actor))
363 SV_FixCheckBottom (actor);
368 ======================
371 ======================
373 qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
377 for (i=0 ; i<3 ; i++)
379 if (goal->v.absmin[i] > ent->v.absmax[i] + dist)
381 if (goal->v.absmax[i] < ent->v.absmin[i] - dist)
388 ======================
391 ======================
393 void SV_MoveToGoal (void)
398 ent = PROG_TO_EDICT(pr_global_struct->self);
399 goal = PROG_TO_EDICT(ent->v.goalentity);
400 dist = G_FLOAT(OFS_PARM0);
402 if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
404 G_FLOAT(OFS_RETURN) = 0;
408 // if the next step hits the enemy, return immediately
409 if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) )
413 if ( (rand()&3)==1 ||
414 !SV_StepDirection (ent, ent->v.ideal_yaw, dist))
416 SV_NewChaseDir (ent, goal, dist);