icculus quake2 doxygen  1.0 dev
m_move.c File Reference
#include "g_local.h"

Go to the source code of this file.

Macros

#define STEPSIZE   18
 
#define DI_NODIR   -1
 

Functions

qboolean M_CheckBottom (edict_t *ent)
 
qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
 
void M_ChangeYaw (edict_t *ent)
 
qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
 
void SV_FixCheckBottom (edict_t *ent)
 
void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
 
qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
 
void M_MoveToGoal (edict_t *ent, float dist)
 
qboolean M_walkmove (edict_t *ent, float yaw, float dist)
 

Variables

int c_yes
 
int c_no
 

Macro Definition Documentation

◆ DI_NODIR

#define DI_NODIR   -1

Definition at line 402 of file m_move.c.

◆ STEPSIZE

#define STEPSIZE   18

Definition at line 24 of file m_move.c.

Function Documentation

◆ M_ChangeYaw()

void M_ChangeYaw ( edict_t ent)

Definition at line 304 of file m_move.c.

305 {
306  float ideal;
307  float current;
308  float move;
309  float speed;
310 
311  current = anglemod(ent->s.angles[YAW]);
312  ideal = ent->ideal_yaw;
313 
314  if (current == ideal)
315  return;
316 
317  move = ideal - current;
318  speed = ent->yaw_speed;
319  if (ideal > current)
320  {
321  if (move >= 180)
322  move = move - 360;
323  }
324  else
325  {
326  if (move <= -180)
327  move = move + 360;
328  }
329  if (move > 0)
330  {
331  if (move > speed)
332  move = speed;
333  }
334  else
335  {
336  if (move < -speed)
337  move = -speed;
338  }
339 
340  ent->s.angles[YAW] = anglemod (current + move);
341 }

Referenced by ai_charge(), ai_run_melee(), ai_run_missile(), ai_run_slide(), ai_stand(), ai_turn(), FindTarget(), and SV_StepDirection().

◆ M_CheckBottom()

qboolean M_CheckBottom ( edict_t ent)

Definition at line 37 of file m_move.c.

38 {
39  vec3_t mins, maxs, start, stop;
40  trace_t trace;
41  int x, y;
42  float mid, bottom;
43 
44  VectorAdd (ent->s.origin, ent->mins, mins);
45  VectorAdd (ent->s.origin, ent->maxs, maxs);
46 
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++)
53  {
54  start[0] = x ? maxs[0] : mins[0];
55  start[1] = y ? maxs[1] : mins[1];
56  if (gi.pointcontents (start) != CONTENTS_SOLID)
57  goto realcheck;
58  }
59 
60  c_yes++;
61  return true; // we got out easy
62 
63 realcheck:
64  c_no++;
65 //
66 // check it for real...
67 //
68  start[2] = mins[2];
69 
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 = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID);
75 
76  if (trace.fraction == 1.0)
77  return false;
78  mid = bottom = trace.endpos[2];
79 
80 // the corners must be within 16 of the midpoint
81  for (x=0 ; x<=1 ; x++)
82  for (y=0 ; y<=1 ; y++)
83  {
84  start[0] = stop[0] = x ? maxs[0] : mins[0];
85  start[1] = stop[1] = y ? maxs[1] : mins[1];
86 
87  trace = gi.trace (start, vec3_origin, vec3_origin, stop, ent, MASK_MONSTERSOLID);
88 
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;
93  }
94 
95  c_yes++;
96  return true;
97 }

Referenced by mutant_jump_touch(), SV_movestep(), SV_NewChaseDir(), and SV_Physics_Step().

◆ M_MoveToGoal()

void M_MoveToGoal ( edict_t ent,
float  dist 
)

Definition at line 515 of file m_move.c.

516 {
517  edict_t *goal;
518 
519  goal = ent->goalentity;
520 
521  if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)))
522  return;
523 
524 // if the next step hits the enemy, return immediately
525  if (ent->enemy && SV_CloseEnough (ent, ent->enemy, dist) )
526  return;
527 
528 // bump around...
529  if ( (rand()&3)==1 || !SV_StepDirection (ent, ent->ideal_yaw, dist))
530  {
531  if (ent->inuse)
532  SV_NewChaseDir (ent, goal, dist);
533  }
534 }

Referenced by ai_run(), and ai_walk().

◆ M_walkmove()

qboolean M_walkmove ( edict_t ent,
float  yaw,
float  dist 
)

Definition at line 542 of file m_move.c.

543 {
544  vec3_t move;
545 
546  if (!ent->groundentity && !(ent->flags & (FL_FLY|FL_SWIM)))
547  return false;
548 
549  yaw = yaw*M_PI*2 / 360;
550 
551  move[0] = cos(yaw)*dist;
552  move[1] = sin(yaw)*dist;
553  move[2] = 0;
554 
555  return SV_movestep(ent, move, true);
556 }

Referenced by ai_charge(), ai_move(), ai_run_slide(), ai_stand(), ai_turn(), barrel_touch(), flymonster_start_go(), and walkmonster_start_go().

◆ SV_CloseEnough()

qboolean SV_CloseEnough ( edict_t ent,
edict_t goal,
float  dist 
)

Definition at line 495 of file m_move.c.

496 {
497  int i;
498 
499  for (i=0 ; i<3 ; i++)
500  {
501  if (goal->absmin[i] > ent->absmax[i] + dist)
502  return false;
503  if (goal->absmax[i] < ent->absmin[i] - dist)
504  return false;
505  }
506  return true;
507 }

Referenced by M_MoveToGoal().

◆ SV_FixCheckBottom()

void SV_FixCheckBottom ( edict_t ent)

Definition at line 389 of file m_move.c.

390 {
391  ent->flags |= FL_PARTIALGROUND;
392 }

Referenced by SV_NewChaseDir().

◆ SV_movestep()

qboolean SV_movestep ( edict_t ent,
vec3_t  move,
qboolean  relink 
)

Definition at line 112 of file m_move.c.

113 {
114  float dz;
115  vec3_t oldorg, neworg, end;
116  trace_t trace;
117  int i;
118  float stepsize;
119  vec3_t test;
120  int contents;
121 
122 // try the move
123  VectorCopy (ent->s.origin, oldorg);
124  VectorAdd (ent->s.origin, move, neworg);
125 
126 // flying monsters don't step up
127  if ( ent->flags & (FL_SWIM | FL_FLY) )
128  {
129  // try one move with vertical motion, then one without
130  for (i=0 ; i<2 ; i++)
131  {
132  VectorAdd (ent->s.origin, move, neworg);
133  if (i == 0 && ent->enemy)
134  {
135  if (!ent->goalentity)
136  ent->goalentity = ent->enemy;
137  dz = ent->s.origin[2] - ent->goalentity->s.origin[2];
138  if (ent->goalentity->client)
139  {
140  if (dz > 40)
141  neworg[2] -= 8;
142  if (!((ent->flags & FL_SWIM) && (ent->waterlevel < 2)))
143  if (dz < 30)
144  neworg[2] += 8;
145  }
146  else
147  {
148  if (dz > 8)
149  neworg[2] -= 8;
150  else if (dz > 0)
151  neworg[2] -= dz;
152  else if (dz < -8)
153  neworg[2] += 8;
154  else
155  neworg[2] += dz;
156  }
157  }
158  trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, neworg, ent, MASK_MONSTERSOLID);
159 
160  // fly monsters don't enter water voluntarily
161  if (ent->flags & FL_FLY)
162  {
163  if (!ent->waterlevel)
164  {
165  test[0] = trace.endpos[0];
166  test[1] = trace.endpos[1];
167  test[2] = trace.endpos[2] + ent->mins[2] + 1;
168  contents = gi.pointcontents(test);
169  if (contents & MASK_WATER)
170  return false;
171  }
172  }
173 
174  // swim monsters don't exit water voluntarily
175  if (ent->flags & FL_SWIM)
176  {
177  if (ent->waterlevel < 2)
178  {
179  test[0] = trace.endpos[0];
180  test[1] = trace.endpos[1];
181  test[2] = trace.endpos[2] + ent->mins[2] + 1;
182  contents = gi.pointcontents(test);
183  if (!(contents & MASK_WATER))
184  return false;
185  }
186  }
187 
188  if (trace.fraction == 1)
189  {
190  VectorCopy (trace.endpos, ent->s.origin);
191  if (relink)
192  {
193  gi.linkentity (ent);
194  G_TouchTriggers (ent);
195  }
196  return true;
197  }
198 
199  if (!ent->enemy)
200  break;
201  }
202 
203  return false;
204  }
205 
206 // push down from a step height above the wished position
207  if (!(ent->monsterinfo.aiflags & AI_NOSTEP))
208  stepsize = STEPSIZE;
209  else
210  stepsize = 1;
211 
212  neworg[2] += stepsize;
213  VectorCopy (neworg, end);
214  end[2] -= stepsize*2;
215 
216  trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);
217 
218  if (trace.allsolid)
219  return false;
220 
221  if (trace.startsolid)
222  {
223  neworg[2] -= stepsize;
224  trace = gi.trace (neworg, ent->mins, ent->maxs, end, ent, MASK_MONSTERSOLID);
225  if (trace.allsolid || trace.startsolid)
226  return false;
227  }
228 
229 
230  // don't go in to water
231  if (ent->waterlevel == 0)
232  {
233  test[0] = trace.endpos[0];
234  test[1] = trace.endpos[1];
235  test[2] = trace.endpos[2] + ent->mins[2] + 1;
236  contents = gi.pointcontents(test);
237 
238  if (contents & MASK_WATER)
239  return false;
240  }
241 
242  if (trace.fraction == 1)
243  {
244  // if monster had the ground pulled out, go ahead and fall
245  if ( ent->flags & FL_PARTIALGROUND )
246  {
247  VectorAdd (ent->s.origin, move, ent->s.origin);
248  if (relink)
249  {
250  gi.linkentity (ent);
251  G_TouchTriggers (ent);
252  }
253  ent->groundentity = NULL;
254  return true;
255  }
256 
257  return false; // walked off an edge
258  }
259 
260 // check point traces down for dangling corners
261  VectorCopy (trace.endpos, ent->s.origin);
262 
263  if (!M_CheckBottom (ent))
264  {
265  if ( ent->flags & FL_PARTIALGROUND )
266  { // entity had floor mostly pulled out from underneath it
267  // and is trying to correct
268  if (relink)
269  {
270  gi.linkentity (ent);
271  G_TouchTriggers (ent);
272  }
273  return true;
274  }
275  VectorCopy (oldorg, ent->s.origin);
276  return false;
277  }
278 
279  if ( ent->flags & FL_PARTIALGROUND )
280  {
281  ent->flags &= ~FL_PARTIALGROUND;
282  }
283  ent->groundentity = trace.ent;
284  ent->groundentity_linkcount = trace.ent->linkcount;
285 
286 // the move is ok
287  if (relink)
288  {
289  gi.linkentity (ent);
290  G_TouchTriggers (ent);
291  }
292  return true;
293 }

Referenced by M_walkmove(), and SV_StepDirection().

◆ SV_NewChaseDir()

void SV_NewChaseDir ( edict_t actor,
edict_t enemy,
float  dist 
)

Definition at line 403 of file m_move.c.

404 {
405  float deltax,deltay;
406  float d[3];
407  float tdir, olddir, turnaround;
408 
409  //FIXME: how did we get here with no enemy
410  if (!enemy)
411  return;
412 
413  olddir = anglemod( (int)(actor->ideal_yaw/45)*45 );
414  turnaround = anglemod(olddir - 180);
415 
416  deltax = enemy->s.origin[0] - actor->s.origin[0];
417  deltay = enemy->s.origin[1] - actor->s.origin[1];
418  if (deltax>10)
419  d[1]= 0;
420  else if (deltax<-10)
421  d[1]= 180;
422  else
423  d[1]= DI_NODIR;
424  if (deltay<-10)
425  d[2]= 270;
426  else if (deltay>10)
427  d[2]= 90;
428  else
429  d[2]= DI_NODIR;
430 
431 // try direct route
432  if (d[1] != DI_NODIR && d[2] != DI_NODIR)
433  {
434  if (d[1] == 0)
435  tdir = d[2] == 90 ? 45 : 315;
436  else
437  tdir = d[2] == 90 ? 135 : 215;
438 
439  if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
440  return;
441  }
442 
443 // try other directions
444  if ( ((rand()&3) & 1) || abs(deltay)>abs(deltax))
445  {
446  tdir=d[1];
447  d[1]=d[2];
448  d[2]=tdir;
449  }
450 
451  if (d[1]!=DI_NODIR && d[1]!=turnaround
452  && SV_StepDirection(actor, d[1], dist))
453  return;
454 
455  if (d[2]!=DI_NODIR && d[2]!=turnaround
456  && SV_StepDirection(actor, d[2], dist))
457  return;
458 
459 /* there is no direct path to the player, so pick another direction */
460 
461  if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
462  return;
463 
464  if (rand()&1) /*randomly determine direction of search*/
465  {
466  for (tdir=0 ; tdir<=315 ; tdir += 45)
467  if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
468  return;
469  }
470  else
471  {
472  for (tdir=315 ; tdir >=0 ; tdir -= 45)
473  if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
474  return;
475  }
476 
477  if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
478  return;
479 
480  actor->ideal_yaw = olddir; // can't move
481 
482 // if a bridge was pulled out from underneath a monster, it may not have
483 // a valid standing position at all
484 
485  if (!M_CheckBottom (actor))
486  SV_FixCheckBottom (actor);
487 }

Referenced by M_MoveToGoal().

◆ SV_StepDirection()

qboolean SV_StepDirection ( edict_t ent,
float  yaw,
float  dist 
)

Definition at line 353 of file m_move.c.

354 {
355  vec3_t move, oldorigin;
356  float delta;
357 
358  ent->ideal_yaw = yaw;
359  M_ChangeYaw (ent);
360 
361  yaw = yaw*M_PI*2 / 360;
362  move[0] = cos(yaw)*dist;
363  move[1] = sin(yaw)*dist;
364  move[2] = 0;
365 
366  VectorCopy (ent->s.origin, oldorigin);
367  if (SV_movestep (ent, move, false))
368  {
369  delta = ent->s.angles[YAW] - ent->ideal_yaw;
370  if (delta > 45 && delta < 315)
371  { // not turned far enough, so don't take the step
372  VectorCopy (oldorigin, ent->s.origin);
373  }
374  gi.linkentity (ent);
375  G_TouchTriggers (ent);
376  return true;
377  }
378  gi.linkentity (ent);
379  G_TouchTriggers (ent);
380  return false;
381 }

Referenced by M_MoveToGoal(), and SV_NewChaseDir().

Variable Documentation

◆ c_no

int c_no

Definition at line 35 of file m_move.c.

Referenced by M_CheckBottom().

◆ c_yes

int c_yes

Definition at line 35 of file m_move.c.

Referenced by M_CheckBottom().

gi
game_import_t gi
Definition: g_main.c:25
SV_CloseEnough
qboolean SV_CloseEnough(edict_t *ent, edict_t *goal, float dist)
Definition: m_move.c:495
edict_s::ideal_yaw
float ideal_yaw
Definition: g_local.h:1034
edict_s::s
entity_state_t s
Definition: g_local.h:964
edict_s::groundentity
edict_t * groundentity
Definition: g_local.h:1073
YAW
#define YAW
Definition: q_shared.h:66
MASK_MONSTERSOLID
#define MASK_MONSTERSOLID
Definition: q_shared.h:394
game_import_t::trace
trace_t(* trace)(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passent, int contentmask)
Definition: game.h:128
c_no
int c_no
Definition: m_move.c:35
trace_t::fraction
float fraction
Definition: q_shared.h:453
edict_s::absmax
vec3_t absmax
Definition: g_local.h:985
bottom
GLdouble GLdouble bottom
Definition: qgl_win.c:159
M_ChangeYaw
void M_ChangeYaw(edict_t *ent)
Definition: m_move.c:304
entity_state_s::origin
vec3_t origin
Definition: q_shared.h:1173
edict_s::linkcount
int linkcount
Definition: g_local.h:971
MASK_WATER
#define MASK_WATER
Definition: q_shared.h:395
x
GLint GLenum GLint x
Definition: qgl_win.c:116
edict_s::inuse
qboolean inuse
Definition: g_local.h:970
trace_t
Definition: q_shared.h:449
i
int i
Definition: q_shared.c:305
G_TouchTriggers
void G_TouchTriggers(edict_t *ent)
Definition: g_utils.c:475
edict_s::client
struct gclient_s * client
Definition: g_local.h:965
CONTENTS_SOLID
#define CONTENTS_SOLID
Definition: qfiles.h:333
edict_s::mins
vec3_t mins
Definition: g_local.h:984
M_PI
#define M_PI
Definition: q_shared.h:135
edict_s::groundentity_linkcount
int groundentity_linkcount
Definition: g_local.h:1074
anglemod
float anglemod(float a)
Definition: q_shared.c:293
FL_SWIM
#define FL_SWIM
Definition: g_local.h:58
trace_t::allsolid
qboolean allsolid
Definition: q_shared.h:451
edict_s
Definition: g_local.h:962
game_import_t::pointcontents
int(* pointcontents)(vec3_t point)
Definition: game.h:129
FL_PARTIALGROUND
#define FL_PARTIALGROUND
Definition: g_local.h:65
NULL
#define NULL
Definition: q_shared.h:60
current
static int current
Definition: cl_scrn.c:131
monsterinfo_t::aiflags
int aiflags
Definition: g_local.h:419
M_CheckBottom
qboolean M_CheckBottom(edict_t *ent)
Definition: m_move.c:37
edict_s::goalentity
edict_t * goalentity
Definition: g_local.h:1031
VectorAdd
#define VectorAdd(a, b, c)
Definition: q_shared.h:157
y
GLint y
Definition: qgl_win.c:115
DI_NODIR
#define DI_NODIR
Definition: m_move.c:402
edict_s::yaw_speed
float yaw_speed
Definition: g_local.h:1033
VectorCopy
#define VectorCopy(a, b)
Definition: q_shared.h:158
SV_FixCheckBottom
void SV_FixCheckBottom(edict_t *ent)
Definition: m_move.c:389
edict_s::monsterinfo
monsterinfo_t monsterinfo
Definition: g_local.h:1108
trace_t::endpos
vec3_t endpos
Definition: q_shared.h:454
vec3_origin
vec3_t vec3_origin
Definition: q_shared.c:24
SV_movestep
qboolean SV_movestep(edict_t *ent, vec3_t move, qboolean relink)
Definition: m_move.c:112
c_yes
int c_yes
Definition: m_move.c:35
SV_NewChaseDir
void SV_NewChaseDir(edict_t *actor, edict_t *enemy, float dist)
Definition: m_move.c:403
edict_s::flags
int flags
Definition: g_local.h:996
edict_s::maxs
vec3_t maxs
Definition: g_local.h:984
trace_t::startsolid
qboolean startsolid
Definition: q_shared.h:452
trace_t::ent
struct edict_s * ent
Definition: q_shared.h:458
SV_StepDirection
qboolean SV_StepDirection(edict_t *ent, float yaw, float dist)
Definition: m_move.c:353
FL_FLY
#define FL_FLY
Definition: g_local.h:57
STEPSIZE
#define STEPSIZE
Definition: m_move.c:24
edict_s::waterlevel
int waterlevel
Definition: g_local.h:1094
edict_s::enemy
edict_t * enemy
Definition: g_local.h:1070
game_import_t::linkentity
void(* linkentity)(edict_t *ent)
Definition: game.h:138
entity_state_s::angles
vec3_t angles
Definition: q_shared.h:1174
vec3_t
vec_t vec3_t[3]
Definition: q_shared.h:127
edict_s::absmin
vec3_t absmin
Definition: g_local.h:985
AI_NOSTEP
#define AI_NOSTEP
Definition: g_local.h:137