g_chase.c (4142B)
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