1 #include "g_local.h"
2
3 void ChasecamTrack (edict_t *ent);
4 void CheckChasecam_Viewent (edict_t *ent);
5
6
ChasecamStart(edict_t * ent)7 void ChasecamStart (edict_t *ent)
8 {
9 edict_t *chasecam;
10
11 if (ent->client->oldplayer)
12 {
13 if (ent->client->oldplayer->client)
14 free(ent->client->oldplayer->client);
15 G_FreeEdict (ent->client->oldplayer);
16 }
17 if (ent->client->chasecam)
18 G_FreeEdict (ent->client->chasecam);
19
20 ent->client->chasetoggle = 1;
21
22 ent->client->ps.gunindex = 0;
23
24 chasecam = G_Spawn ();
25 chasecam->owner = ent;
26 chasecam->solid = SOLID_NOT;
27 chasecam->movetype = MOVETYPE_NONE;
28
29 ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;
30 ent->svflags |= SVF_NOCLIENT;
31
32 VectorCopy (ent->s.angles, chasecam->s.angles);
33
34 VectorClear (chasecam->mins);
35 VectorClear (chasecam->maxs);
36 VectorCopy (ent->s.origin, chasecam->s.origin);
37
38 chasecam->classname = "chasecam";
39 chasecam->nextthink = level.time + 0.100;
40 chasecam->think = ChasecamTrack;
41 chasecam->prethink = ChasecamTrack;
42
43 ent->client->chasecam = chasecam;
44 ent->client->oldplayer = G_Spawn();
45 }
46
47
ChasecamRestart(edict_t * ent)48 void ChasecamRestart (edict_t *ent)
49 {
50 if (ent->owner->health <= 0)
51 {
52 G_FreeEdict(ent);
53 return;
54 }
55
56 ChasecamStart (ent->owner);
57 G_FreeEdict (ent);
58 }
59
ChasecamRemove(edict_t * ent,int opt)60 void ChasecamRemove (edict_t *ent, int opt)
61 {
62
63 VectorClear (ent->client->chasecam->velocity);
64
65 if (!level.intermissiontime)
66 ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
67
68 ent->s.modelindex = ent->client->oldplayer->s.modelindex;
69 ent->svflags &= ~SVF_NOCLIENT;
70
71 if (opt == OPTION_BACKGROUND)
72 {
73 ent->client->oldplayer->client = NULL;
74 ent->client->chasetoggle = 0;
75 G_FreeEdict (ent->client->chasecam);
76 G_FreeEdict (ent->client->oldplayer);
77 ent->client->oldplayer = NULL;
78 ent->client->chasecam = G_Spawn ();
79 ent->client->chasecam->owner = ent;
80 ent->client->chasecam->solid = SOLID_NOT;
81 ent->client->chasecam->movetype = MOVETYPE_FLYMISSILE;
82 VectorClear (ent->client->chasecam->mins);
83 VectorClear (ent->client->chasecam->maxs);
84 ent->client->chasecam->classname = "chasecam";
85 ent->client->chasecam->prethink = ChasecamRestart; // begin checking for emergence from the water
86 }
87 else if (opt == OPTION_OFF)
88 {
89 ent->client->oldplayer->client = NULL;
90 G_FreeEdict (ent->client->oldplayer);
91 ent->client->oldplayer = NULL;
92 ent->client->chasetoggle = 0;
93 G_FreeEdict (ent->client->chasecam);
94 ent->client->chasecam = NULL;
95 }
96 }
97
98 /* The "ent" is the chasecam */
ChasecamTrack(edict_t * ent)99 void ChasecamTrack (edict_t *ent)
100 {
101 trace_t tr;
102 vec3_t spot2, headorg, angle;
103 vec3_t forward, right, up, end;
104 float dist;
105
106 ent->nextthink = level.time + 0.100;
107
108 VectorCopy(ent->owner->s.origin, headorg);
109 if(!(ent->owner->client->ps.pmove.pm_flags & PMF_DUCKED))
110 headorg[2] += 25;
111 else
112 headorg[2] += 10;
113
114 if(ent->owner->chasedist1 <= 0)
115 ent->owner->chasedist1 = 50;
116
117 VectorCopy(ent->owner->client->v_angle, angle);
118 AngleVectors (ent->owner->client->ps.viewangles, forward, right, up);
119
120 dist = ent->chasedist2 / ent->owner->chasedist1;
121
122 VectorScale(forward, -ent->owner->chasedist1, spot2); // Find the max
123 spot2[2] += 5.00;
124 VectorScale(spot2, dist, spot2); // Calculate the current distance
125
126 VectorAdd(headorg, spot2, spot2);
127 tr = gi.trace (headorg, NULL, NULL, spot2, ent->owner, CONTENTS_SOLID);
128 VectorSubtract(spot2, headorg, spot2);
129
130 VectorScale(spot2, tr.fraction - 0.05, spot2);
131
132 VectorAdd(spot2, headorg, spot2);
133 VectorCopy(spot2, ent->s.origin);
134 // VectorCopy(angle, ent->s.angles);
135
136 VectorCopy (ent->s.origin, ent->movedir);
137
138 if(ent->owner->client->chasetoggle == 2)
139 {
140 ent->chasedist2 -= 20;
141 if (ent->chasedist2 <= 50)
142 ent->chasedist2 = 50;
143
144 }
145 else
146 {
147 ent->chasedist2 += 30;
148 if (ent->chasedist2 > ent->owner->chasedist1)
149 ent->chasedist2 = ent->owner->chasedist1;
150 }
151 }
152
Cmd_Chasecam_Toggle(edict_t * ent)153 void Cmd_Chasecam_Toggle (edict_t *ent)
154 {
155 if (!ent->deadflag)
156 {
157 if (ent->client->chasetoggle)
158 ChasecamRemove (ent, OPTION_OFF);
159 else
160 ChasecamStart (ent);
161 }
162 }
163
CheckChasecam_Viewent(edict_t * ent)164 void CheckChasecam_Viewent (edict_t *ent)
165 {
166 gclient_t *cl;
167
168 if ((ent->client->chasetoggle >= 1) && (ent->client->oldplayer))
169 {
170 ent->client->oldplayer->s.frame = ent->s.frame;
171
172 VectorCopy (ent->s.origin, ent->client->oldplayer->s.origin);
173 VectorCopy (ent->velocity, ent->client->oldplayer->velocity);
174 VectorCopy (ent->s.angles, ent->client->oldplayer->s.angles);
175
176 ent->client->oldplayer->waterlevel = ent->waterlevel;
177 ent->client->oldplayer->client = ent->client;
178 ent->client->oldplayer->s = ent->s;
179
180 gi.linkentity (ent->client->oldplayer);
181 }
182 }
P_ProjectSource(gclient_t * client,vec3_t point,vec3_t distance,vec3_t forward,vec3_t right,vec3_t result)183 static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
184 {
185 vec3_t _distance;
186
187 VectorCopy (distance, _distance);
188 if (client->pers.hand == LEFT_HANDED)
189 _distance[1] *= -1;
190 else if (client->pers.hand == CENTER_HANDED)
191 _distance[1] = 0;
192 G_ProjectSource (point, _distance, forward, right, result);
193 }
194