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
UpdateChaseCam(edict_t * ent)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
ChaseNext(edict_t * ent)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
ChasePrev(edict_t * ent)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
GetChaseTarget(edict_t * ent)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