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
28 Returns false if any part of the bottom of the entity is off an edge that
35 qboolean SV_CheckBottom (edict_t *ent)
37 vec3_t mins, maxs, start, stop;
42 VectorAdd (ent->v->origin, ent->v->mins, mins);
43 VectorAdd (ent->v->origin, ent->v->maxs, maxs);
45 // if all of the points under the corners are solid world, don't bother
46 // with the tougher checks
47 // the corners must be within 16 of the midpoint
48 start[2] = mins[2] - 1;
49 for (x=0 ; x<=1 ; x++)
50 for (y=0 ; y<=1 ; y++)
52 start[0] = x ? maxs[0] : mins[0];
53 start[1] = y ? maxs[1] : mins[1];
54 if (!(SV_PointSuperContents(start) & SUPERCONTENTS_SOLID))
59 return true; // we got out easy
64 // check it for real...
68 // the midpoint must be within 16 of the bottom
69 start[0] = stop[0] = (mins[0] + maxs[0])*0.5;
70 start[1] = stop[1] = (mins[1] + maxs[1])*0.5;
71 stop[2] = start[2] - 2*sv_stepheight.value;
72 trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent);
74 if (trace.fraction == 1.0)
76 mid = bottom = trace.endpos[2];
78 // the corners must be within 16 of the midpoint
79 for (x=0 ; x<=1 ; x++)
80 for (y=0 ; y<=1 ; y++)
82 start[0] = stop[0] = x ? maxs[0] : mins[0];
83 start[1] = stop[1] = y ? maxs[1] : mins[1];
85 trace = SV_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent);
87 if (trace.fraction != 1.0 && trace.endpos[2] > bottom)
88 bottom = trace.endpos[2];
89 if (trace.fraction == 1.0 || mid - trace.endpos[2] > sv_stepheight.value)
102 Called by monster program code.
103 The move will be adjusted for slopes and stairs, but if the move isn't
104 possible, no move is done, false is returned, and
105 pr_global_struct->trace_normal is set to the normal of the blocking wall
108 qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
111 vec3_t oldorg, neworg, end, traceendpos;
117 VectorCopy (ent->v->origin, oldorg);
118 VectorAdd (ent->v->origin, move, neworg);
120 // flying monsters don't step up
121 if ( (int)ent->v->flags & (FL_SWIM | FL_FLY) )
123 // try one move with vertical motion, then one without
124 for (i=0 ; i<2 ; i++)
126 VectorAdd (ent->v->origin, move, neworg);
127 enemy = PROG_TO_EDICT(ent->v->enemy);
128 if (i == 0 && enemy != sv.edicts)
130 dz = ent->v->origin[2] - PROG_TO_EDICT(ent->v->enemy)->v->origin[2];
136 trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, neworg, MOVE_NORMAL, ent);
137 #if COLLISIONPARANOID >= 1
141 VectorCopy(trace.endpos, temp);
142 endstuck = SV_Move(temp, ent->v->mins, ent->v->maxs, temp, MOVE_WORLDONLY, ent).startsolid;
143 #if COLLISIONPARANOID < 2
144 if (trace.startsolid || endstuck)
147 Con_Printf("%s{e%i:%f %f %f:%f %f %f:%f:%f %f %f%s%s}\n", (trace.startsolid || endstuck) ? "\002" : "", ent - sv.edicts, ent->v->origin[0], ent->v->origin[1], ent->v->origin[2], neworg[0] - ent->v->origin[0], neworg[1] - ent->v->origin[1], neworg[2] - ent->v->origin[2], trace.fraction, trace.endpos[0] - ent->v->origin[0], trace.endpos[1] - ent->v->origin[1], trace.endpos[2] - ent->v->origin[2], trace.startsolid ? " startstuck" : "", endstuck ? " endstuck" : "");
148 //Con_Printf("trace %f %f %f : %f : %f %f %f\n", trace.endpos[0], trace.endpos[1], trace.endpos[2], trace.fraction, trace.plane.normal[0], trace.plane.normal[1], trace.plane.normal[2]);
150 Cbuf_AddText("disconnect\n");
155 if (trace.fraction == 1)
157 VectorCopy(trace.endpos, traceendpos);
158 if (((int)ent->v->flags & FL_SWIM) && !(SV_PointSuperContents(traceendpos) & SUPERCONTENTS_LIQUIDSMASK))
159 return false; // swim monster left water
161 VectorCopy (traceendpos, ent->v->origin);
163 SV_LinkEdict (ent, true);
167 if (enemy == sv.edicts)
174 // push down from a step height above the wished position
175 neworg[2] += sv_stepheight.value;
176 VectorCopy (neworg, end);
177 end[2] -= sv_stepheight.value*2;
179 trace = SV_Move (neworg, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
181 if (trace.startsolid)
183 neworg[2] -= sv_stepheight.value;
184 trace = SV_Move (neworg, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
185 if (trace.startsolid)
188 if (trace.fraction == 1)
190 // if monster had the ground pulled out, go ahead and fall
191 if ( (int)ent->v->flags & FL_PARTIALGROUND )
193 VectorAdd (ent->v->origin, move, ent->v->origin);
195 SV_LinkEdict (ent, true);
196 ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND;
200 return false; // walked off an edge
203 // check point traces down for dangling corners
204 VectorCopy (trace.endpos, ent->v->origin);
206 if (!SV_CheckBottom (ent))
208 if ( (int)ent->v->flags & FL_PARTIALGROUND )
209 { // entity had floor mostly pulled out from underneath it
210 // and is trying to correct
212 SV_LinkEdict (ent, true);
215 VectorCopy (oldorg, ent->v->origin);
219 if ( (int)ent->v->flags & FL_PARTIALGROUND )
220 ent->v->flags = (int)ent->v->flags & ~FL_PARTIALGROUND;
222 ent->v->groundentity = EDICT_TO_PROG(trace.ent);
226 SV_LinkEdict (ent, true);
231 //============================================================================
234 ======================
237 Turns to the movement direction, and walks the current distance if
240 ======================
242 void PF_changeyaw (void);
243 qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
245 vec3_t move, oldorigin;
248 ent->v->ideal_yaw = yaw;
251 yaw = yaw*M_PI*2 / 360;
252 move[0] = cos(yaw)*dist;
253 move[1] = sin(yaw)*dist;
256 VectorCopy (ent->v->origin, oldorigin);
257 if (SV_movestep (ent, move, false))
259 delta = ent->v->angles[YAW] - ent->v->ideal_yaw;
260 if (delta > 45 && delta < 315)
261 { // not turned far enough, so don't take the step
262 VectorCopy (oldorigin, ent->v->origin);
264 SV_LinkEdict (ent, true);
267 SV_LinkEdict (ent, true);
273 ======================
276 ======================
278 void SV_FixCheckBottom (edict_t *ent)
280 ent->v->flags = (int)ent->v->flags | FL_PARTIALGROUND;
292 void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
296 float tdir, olddir, turnaround;
298 olddir = ANGLEMOD((int)(actor->v->ideal_yaw/45)*45);
299 turnaround = ANGLEMOD(olddir - 180);
301 deltax = enemy->v->origin[0] - actor->v->origin[0];
302 deltay = enemy->v->origin[1] - actor->v->origin[1];
317 if (d[1] != DI_NODIR && d[2] != DI_NODIR)
320 tdir = d[2] == 90 ? 45 : 315;
322 tdir = d[2] == 90 ? 135 : 215;
324 if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
328 // try other directions
329 if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax))
336 if (d[1]!=DI_NODIR && d[1]!=turnaround
337 && SV_StepDirection(actor, d[1], dist))
340 if (d[2]!=DI_NODIR && d[2]!=turnaround
341 && SV_StepDirection(actor, d[2], dist))
344 /* there is no direct path to the player, so pick another direction */
346 if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
349 if (rand()&1) /*randomly determine direction of search*/
351 for (tdir=0 ; tdir<=315 ; tdir += 45)
352 if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
357 for (tdir=315 ; tdir >=0 ; tdir -= 45)
358 if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
362 if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
365 actor->v->ideal_yaw = olddir; // can't move
367 // if a bridge was pulled out from underneath a monster, it may not have
368 // a valid standing position at all
370 if (!SV_CheckBottom (actor))
371 SV_FixCheckBottom (actor);
376 ======================
379 ======================
381 qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
385 for (i=0 ; i<3 ; i++)
387 if (goal->v->absmin[i] > ent->v->absmax[i] + dist)
389 if (goal->v->absmax[i] < ent->v->absmin[i] - dist)
396 ======================
399 ======================
401 void SV_MoveToGoal (void)
406 ent = PROG_TO_EDICT(pr_global_struct->self);
407 goal = PROG_TO_EDICT(ent->v->goalentity);
408 dist = G_FLOAT(OFS_PARM0);
410 if ( !( (int)ent->v->flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
412 G_FLOAT(OFS_RETURN) = 0;
416 // if the next step hits the enemy, return immediately
417 if ( PROG_TO_EDICT(ent->v->enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) )
421 if ( (rand()&3)==1 ||
422 !SV_StepDirection (ent, ent->v->ideal_yaw, dist))
424 SV_NewChaseDir (ent, goal, dist);