Fix for the problem that SDL applications exited
[AROS-Contrib.git] / Games / Quake / sv_move.c
bloba0078b941a0586d99846beef770d7313687c04b7
1 /*
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
22 #include "quakedef.h"
24 #define STEPSIZE 18
27 =============
28 SV_CheckBottom
30 Returns false if any part of the bottom of the entity is off an edge that
31 is not a staircase.
33 =============
35 int c_yes, c_no;
37 qboolean SV_CheckBottom (edict_t *ent)
39 vec3_t mins, maxs, start, stop;
40 trace_t trace;
41 int x, y;
42 float mid, bottom;
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)
57 goto realcheck;
60 c_yes++;
61 return true; // we got out easy
63 realcheck:
64 c_no++;
66 // check it for real...
68 start[2] = mins[2];
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)
77 return false;
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)
92 return false;
95 c_yes++;
96 return true;
101 =============
102 SV_movestep
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
108 =============
110 qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
112 float dz;
113 vec3_t oldorg, neworg, end;
114 trace_t trace;
115 int i;
116 edict_t *enemy;
118 // try the move
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];
133 if (dz > 40)
134 neworg[2] -= 8;
135 if (dz < 30)
136 neworg[2] += 8;
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);
146 if (relink)
147 SV_LinkEdict (ent, true);
148 return true;
151 if (enemy == sv.edicts)
152 break;
155 return false;
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);
165 if (trace.allsolid)
166 return false;
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)
173 return false;
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);
181 if (relink)
182 SV_LinkEdict (ent, true);
183 ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
184 // Con_Printf ("fall down\n");
185 return true;
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
199 if (relink)
200 SV_LinkEdict (ent, true);
201 return true;
203 VectorCopy (oldorg, ent->v.origin);
204 return false;
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);
214 // the move is ok
215 if (relink)
216 SV_LinkEdict (ent, true);
217 return true;
221 //============================================================================
224 ======================
225 SV_StepDirection
227 Turns to the movement direction, and walks the current distance if
228 facing it.
230 ======================
232 void PF_changeyaw (void);
233 qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
235 vec3_t move, oldorigin;
236 float delta;
238 ent->v.ideal_yaw = yaw;
239 PF_changeyaw();
241 yaw = yaw*M_PI*2 / 360;
242 move[0] = cos(yaw)*dist;
243 move[1] = sin(yaw)*dist;
244 move[2] = 0;
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);
255 return true;
257 SV_LinkEdict (ent, true);
259 return false;
263 ======================
264 SV_FixCheckBottom
266 ======================
268 void SV_FixCheckBottom (edict_t *ent)
270 // Con_Printf ("SV_FixCheckBottom\n");
272 ent->v.flags = (int)ent->v.flags | FL_PARTIALGROUND;
278 ================
279 SV_NewChaseDir
281 ================
283 #define DI_NODIR -1
284 void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
286 float deltax,deltay;
287 float d[3];
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];
295 if (deltax>10)
296 d[1]= 0;
297 else if (deltax<-10)
298 d[1]= 180;
299 else
300 d[1]= DI_NODIR;
301 if (deltay<-10)
302 d[2]= 270;
303 else if (deltay>10)
304 d[2]= 90;
305 else
306 d[2]= DI_NODIR;
308 // try direct route
309 if (d[1] != DI_NODIR && d[2] != DI_NODIR)
311 if (d[1] == 0)
312 tdir = d[2] == 90 ? 45 : 315;
313 else
314 tdir = d[2] == 90 ? 135 : 215;
316 if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
317 return;
320 // try other directions
321 if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax))
323 tdir=d[1];
324 d[1]=d[2];
325 d[2]=tdir;
328 if (d[1]!=DI_NODIR && d[1]!=turnaround
329 && SV_StepDirection(actor, d[1], dist))
330 return;
332 if (d[2]!=DI_NODIR && d[2]!=turnaround
333 && SV_StepDirection(actor, d[2], dist))
334 return;
336 /* there is no direct path to the player, so pick another direction */
338 if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
339 return;
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) )
345 return;
347 else
349 for (tdir=315 ; tdir >=0 ; tdir -= 45)
350 if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
351 return;
354 if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
355 return;
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 ======================
369 SV_CloseEnough
371 ======================
373 qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
375 int i;
377 for (i=0 ; i<3 ; i++)
379 if (goal->v.absmin[i] > ent->v.absmax[i] + dist)
380 return false;
381 if (goal->v.absmax[i] < ent->v.absmin[i] - dist)
382 return false;
384 return true;
388 ======================
389 SV_MoveToGoal
391 ======================
393 void SV_MoveToGoal (void)
395 edict_t *ent, *goal;
396 float dist;
397 #ifdef QUAKE2
398 edict_t *enemy;
399 #endif
401 ent = PROG_TO_EDICT(pr_global_struct->self);
402 goal = PROG_TO_EDICT(ent->v.goalentity);
403 dist = G_FLOAT(OFS_PARM0);
405 if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
407 G_FLOAT(OFS_RETURN) = 0;
408 return;
411 // if the next step hits the enemy, return immediately
412 #ifdef QUAKE2
413 enemy = PROG_TO_EDICT(ent->v.enemy);
414 if (enemy != sv.edicts && SV_CloseEnough (ent, enemy, dist) )
415 #else
416 if ( PROG_TO_EDICT(ent->v.enemy) != sv.edicts && SV_CloseEnough (ent, goal, dist) )
417 #endif
418 return;
420 // bump around...
421 if ( (rand()&3)==1 ||
422 !SV_StepDirection (ent, ent->v.ideal_yaw, dist))
424 SV_NewChaseDir (ent, goal, dist);