Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  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.
  8.  
  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.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  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.
  18.  
  19. */
  20. // sv_move.c -- monster movement
  21.  
  22. #include "quakedef.h"
  23.  
  24. #define STEPSIZE        18
  25.  
  26. /*
  27. =============
  28. SV_CheckBottom
  29.  
  30. Returns false if any part of the bottom of the entity is off an edge that
  31. is not a staircase.
  32.  
  33. =============
  34. */
  35. int c_yes, c_no;
  36.  
  37. qboolean SV_CheckBottom (edict_t *ent)
  38. {
  39.         vec3_t  mins, maxs, start, stop;
  40.         trace_t trace;
  41.         int             x, y;
  42.         float   mid, bottom;
  43.        
  44.         VectorAdd (ent->v.origin, ent->v.mins, mins);
  45.         VectorAdd (ent->v.origin, ent->v.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 (SV_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 = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
  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 = SV_Move (start, vec3_origin, vec3_origin, stop, true, ent);
  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. }
  98.  
  99.  
  100. /*
  101. =============
  102. SV_movestep
  103.  
  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. =============
  109. */
  110. qboolean SV_movestep (edict_t *ent, vec3_t move, qboolean relink)
  111. {
  112.         float           dz;
  113.         vec3_t          oldorg, neworg, end;
  114.         trace_t         trace;
  115.         int                     i;
  116.         edict_t         *enemy;
  117.  
  118. // try the move
  119.         VectorCopy (ent->v.origin, oldorg);
  120.         VectorAdd (ent->v.origin, move, neworg);
  121.  
  122. // flying monsters don't step up
  123.         if ( (int)ent->v.flags & (FL_SWIM | FL_FLY) )
  124.         {
  125.         // try one move with vertical motion, then one without
  126.                 for (i=0 ; i<2 ; i++)
  127.                 {
  128.                         VectorAdd (ent->v.origin, move, neworg);
  129.                         enemy = PROG_TO_EDICT(ent->v.enemy);
  130.                         if (i == 0 && enemy != sv.edicts)
  131.                         {
  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;
  137.                         }
  138.                         trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, neworg, false, ent);
  139.        
  140.                         if (trace.fraction == 1)
  141.                         {
  142.                                 if ( ((int)ent->v.flags & FL_SWIM) && SV_PointContents(trace.endpos) == CONTENTS_EMPTY )
  143.                                         return false;   // swim monster left water
  144.        
  145.                                 VectorCopy (trace.endpos, ent->v.origin);
  146.                                 if (relink)
  147.                                         SV_LinkEdict (ent, true);
  148.                                 return true;
  149.                         }
  150.                        
  151.                         if (enemy == sv.edicts)
  152.                                 break;
  153.                 }
  154.                
  155.                 return false;
  156.         }
  157.  
  158. // push down from a step height above the wished position
  159.         neworg[2] += STEPSIZE;
  160.         VectorCopy (neworg, end);
  161.         end[2] -= STEPSIZE*2;
  162.  
  163.         trace = SV_Move (neworg, ent->v.mins, ent->v.maxs, end, false, ent);
  164.  
  165.         if (trace.allsolid)
  166.                 return false;
  167.  
  168.         if (trace.startsolid)
  169.         {
  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;
  174.         }
  175.         if (trace.fraction == 1)
  176.         {
  177.         // if monster had the ground pulled out, go ahead and fall
  178.                 if ( (int)ent->v.flags & FL_PARTIALGROUND )
  179.                 {
  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;
  186.                 }
  187.        
  188.                 return false;           // walked off an edge
  189.         }
  190.  
  191. // check point traces down for dangling corners
  192.         VectorCopy (trace.endpos, ent->v.origin);
  193.        
  194.         if (!SV_CheckBottom (ent))
  195.         {
  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;
  202.                 }
  203.                 VectorCopy (oldorg, ent->v.origin);
  204.                 return false;
  205.         }
  206.  
  207.         if ( (int)ent->v.flags & FL_PARTIALGROUND )
  208.         {
  209. //              Con_Printf ("back on ground\n");
  210.                 ent->v.flags = (int)ent->v.flags & ~FL_PARTIALGROUND;
  211.         }
  212.         ent->v.groundentity = EDICT_TO_PROG(trace.ent);
  213.  
  214. // the move is ok
  215.         if (relink)
  216.                 SV_LinkEdict (ent, true);
  217.         return true;
  218. }
  219.  
  220.  
  221. //============================================================================
  222.  
  223. /*
  224. ======================
  225. SV_StepDirection
  226.  
  227. Turns to the movement direction, and walks the current distance if
  228. facing it.
  229.  
  230. ======================
  231. */
  232. void PF_changeyaw (void);
  233. qboolean SV_StepDirection (edict_t *ent, float yaw, float dist)
  234. {
  235.         vec3_t          move, oldorigin;
  236.         float           delta;
  237.        
  238.         ent->v.ideal_yaw = yaw;
  239.         PF_changeyaw();
  240.        
  241.         yaw = yaw*M_PI*2 / 360;
  242.         move[0] = cos(yaw)*dist;
  243.         move[1] = sin(yaw)*dist;
  244.         move[2] = 0;
  245.  
  246.         VectorCopy (ent->v.origin, oldorigin);
  247.         if (SV_movestep (ent, move, false))
  248.         {
  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);
  253.                 }
  254.                 SV_LinkEdict (ent, true);
  255.                 return true;
  256.         }
  257.         SV_LinkEdict (ent, true);
  258.                
  259.         return false;
  260. }
  261.  
  262. /*
  263. ======================
  264. SV_FixCheckBottom
  265.  
  266. ======================
  267. */
  268. void SV_FixCheckBottom (edict_t *ent)
  269. {
  270. //      Con_Printf ("SV_FixCheckBottom\n");
  271.        
  272.         ent->v.flags = (int)ent->v.flags | FL_PARTIALGROUND;
  273. }
  274.  
  275.  
  276.  
  277. /*
  278. ================
  279. SV_NewChaseDir
  280.  
  281. ================
  282. */
  283. #define DI_NODIR        -1
  284. void SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist)
  285. {
  286.         float           deltax,deltay;
  287.         float                   d[3];
  288.         float           tdir, olddir, turnaround;
  289.  
  290.         olddir = anglemod( (int)(actor->v.ideal_yaw/45)*45 );
  291.         turnaround = anglemod(olddir - 180);
  292.  
  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;
  307.  
  308. // try direct route
  309.         if (d[1] != DI_NODIR && d[2] != DI_NODIR)
  310.         {
  311.                 if (d[1] == 0)
  312.                         tdir = d[2] == 90 ? 45 : 315;
  313.                 else
  314.                         tdir = d[2] == 90 ? 135 : 215;
  315.                        
  316.                 if (tdir != turnaround && SV_StepDirection(actor, tdir, dist))
  317.                         return;
  318.         }
  319.  
  320. // try other directions
  321.         if ( ((rand()&3) & 1) ||  abs(deltay)>abs(deltax))
  322.         {
  323.                 tdir=d[1];
  324.                 d[1]=d[2];
  325.                 d[2]=tdir;
  326.         }
  327.  
  328.         if (d[1]!=DI_NODIR && d[1]!=turnaround
  329.         && SV_StepDirection(actor, d[1], dist))
  330.                         return;
  331.  
  332.         if (d[2]!=DI_NODIR && d[2]!=turnaround
  333.         && SV_StepDirection(actor, d[2], dist))
  334.                         return;
  335.  
  336. /* there is no direct path to the player, so pick another direction */
  337.  
  338.         if (olddir!=DI_NODIR && SV_StepDirection(actor, olddir, dist))
  339.                         return;
  340.  
  341.         if (rand()&1)   /*randomly determine direction of search*/
  342.         {
  343.                 for (tdir=0 ; tdir<=315 ; tdir += 45)
  344.                         if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
  345.                                         return;
  346.         }
  347.         else
  348.         {
  349.                 for (tdir=315 ; tdir >=0 ; tdir -= 45)
  350.                         if (tdir!=turnaround && SV_StepDirection(actor, tdir, dist) )
  351.                                         return;
  352.         }
  353.  
  354.         if (turnaround != DI_NODIR && SV_StepDirection(actor, turnaround, dist) )
  355.                         return;
  356.  
  357.         actor->v.ideal_yaw = olddir;            // can't move
  358.  
  359. // if a bridge was pulled out from underneath a monster, it may not have
  360. // a valid standing position at all
  361.  
  362.         if (!SV_CheckBottom (actor))
  363.                 SV_FixCheckBottom (actor);
  364.  
  365. }
  366.  
  367. /*
  368. ======================
  369. SV_CloseEnough
  370.  
  371. ======================
  372. */
  373. qboolean SV_CloseEnough (edict_t *ent, edict_t *goal, float dist)
  374. {
  375.         int             i;
  376.        
  377.         for (i=0 ; i<3 ; i++)
  378.         {
  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;
  383.         }
  384.         return true;
  385. }
  386.  
  387. /*
  388. ======================
  389. SV_MoveToGoal
  390.  
  391. ======================
  392. */
  393. void SV_MoveToGoal (void)
  394. {
  395.         edict_t         *ent, *goal;
  396.         float           dist;
  397. #ifdef QUAKE2
  398.         edict_t         *enemy;
  399. #endif
  400.  
  401.         ent = PROG_TO_EDICT(pr_global_struct->self);
  402.         goal = PROG_TO_EDICT(ent->v.goalentity);
  403.         dist = G_FLOAT(OFS_PARM0);
  404.  
  405.         if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
  406.         {
  407.                 G_FLOAT(OFS_RETURN) = 0;
  408.                 return;
  409.         }
  410.  
  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;
  419.  
  420. // bump around...
  421.         if ( (rand()&3)==1 ||
  422.         !SV_StepDirection (ent, ent->v.ideal_yaw, dist))
  423.         {
  424.                 SV_NewChaseDir (ent, goal, dist);
  425.         }
  426. }
  427.  
  428.