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