File: game\g_chase.c

    1 /*
    2 Copyright (C) 1997-2001 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 #include "g_local.h"
   21 
   22 void UpdateChaseCam(edict_t *ent)
   23 {
   24         vec3_t o, ownerv, goal;
   25         edict_t *targ;
   26         vec3_t forward, right;
   27         trace_t trace;
   28         int i;
   29         vec3_t oldgoal;
   30         vec3_t angles;
   31 
   32         // is our chase target gone?
   33         if (!ent->client->chase_target->inuse
   34                 || ent->client->chase_target->client->resp.spectator) {
   35                 edict_t *old = ent->client->chase_target;
   36                 ChaseNext(ent);
   37                 if (ent->client->chase_target == old) {
   38                         ent->client->chase_target = NULL;
   39                         ent->client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
   40                         return;
   41                 }
   42         }
   43 
   44         targ = ent->client->chase_target;
   45 
   46         VectorCopy(targ->s.origin, ownerv);
   47         VectorCopy(ent->s.origin, oldgoal);
   48 
   49         ownerv[2] += targ->viewheight;
   50 
   51         VectorCopy(targ->client->v_angle, angles);
   52         if (angles[PITCH] > 56)
   53                 angles[PITCH] = 56;
   54         AngleVectors (angles, forward, right, NULL);
   55         VectorNormalize(forward);
   56         VectorMA(ownerv, -30, forward, o);
   57 
   58         if (o[2] < targ->s.origin[2] + 20)
   59                 o[2] = targ->s.origin[2] + 20;
   60 
   61         // jump animation lifts
   62         if (!targ->groundentity)
   63                 o[2] += 16;
   64 
   65         trace = gi.trace(ownerv, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
   66 
   67         VectorCopy(trace.endpos, goal);
   68 
   69         VectorMA(goal, 2, forward, goal);
   70 
   71         // pad for floors and ceilings
   72         VectorCopy(goal, o);
   73         o[2] += 6;
   74         trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
   75         if (trace.fraction < 1) {
   76                 VectorCopy(trace.endpos, goal);
   77                 goal[2] -= 6;
   78         }
   79 
   80         VectorCopy(goal, o);
   81         o[2] -= 6;
   82         trace = gi.trace(goal, vec3_origin, vec3_origin, o, targ, MASK_SOLID);
   83         if (trace.fraction < 1) {
   84                 VectorCopy(trace.endpos, goal);
   85                 goal[2] += 6;
   86         }
   87 
   88         if (targ->deadflag)
   89                 ent->client->ps.pmove.pm_type = PM_DEAD;
   90         else
   91                 ent->client->ps.pmove.pm_type = PM_FREEZE;
   92 
   93         VectorCopy(goal, ent->s.origin);
   94         for (i=0 ; i<3 ; i++)
   95                 ent->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(targ->client->v_angle[i] - ent->client->resp.cmd_angles[i]);
   96 
   97         if (targ->deadflag) {
   98                 ent->client->ps.viewangles[ROLL] = 40;
   99                 ent->client->ps.viewangles[PITCH] = -15;
  100                 ent->client->ps.viewangles[YAW] = targ->client->killer_yaw;
  101         } else {
  102                 VectorCopy(targ->client->v_angle, ent->client->ps.viewangles);
  103                 VectorCopy(targ->client->v_angle, ent->client->v_angle);
  104         }
  105 
  106         ent->viewheight = 0;
  107         ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;
  108         gi.linkentity(ent);
  109 }
  110 
  111 void ChaseNext(edict_t *ent)
  112 {
  113         int i;
  114         edict_t *e;
  115 
  116         if (!ent->client->chase_target)
  117                 return;
  118 
  119         i = ent->client->chase_target - g_edicts;
  120         do {
  121                 i++;
  122                 if (i > maxclients->value)
  123                         i = 1;
  124                 e = g_edicts + i;
  125                 if (!e->inuse)
  126                         continue;
  127                 if (!e->client->resp.spectator)
  128                         break;
  129         } while (e != ent->client->chase_target);
  130 
  131         ent->client->chase_target = e;
  132         ent->client->update_chase = true;
  133 }
  134 
  135 void ChasePrev(edict_t *ent)
  136 {
  137         int i;
  138         edict_t *e;
  139 
  140         if (!ent->client->chase_target)
  141                 return;
  142 
  143         i = ent->client->chase_target - g_edicts;
  144         do {
  145                 i--;
  146                 if (i < 1)
  147                         i = maxclients->value;
  148                 e = g_edicts + i;
  149                 if (!e->inuse)
  150                         continue;
  151                 if (!e->client->resp.spectator)
  152                         break;
  153         } while (e != ent->client->chase_target);
  154 
  155         ent->client->chase_target = e;
  156         ent->client->update_chase = true;
  157 }
  158 
  159 void GetChaseTarget(edict_t *ent)
  160 {
  161         int i;
  162         edict_t *other;
  163 
  164         for (i = 1; i <= maxclients->value; i++) {
  165                 other = g_edicts + i;
  166                 if (other->inuse && !other->client->resp.spectator) {
  167                         ent->client->chase_target = other;
  168                         ent->client->update_chase = true;
  169                         UpdateChaseCam(ent);
  170                         return;
  171                 }
  172         }
  173         gi.centerprintf(ent, "No other players to chase.");
  174 }
  175 
  176