1 /*
2 Copyright (C) 20?? COR Entertainment, LLC.
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 along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "g_local.h"
25
26 /*#define DEBUG_DEATHCAM*/ /* Uncomment this or set as a CFLAG at build time */
27
28 void DeathcamTrack (edict_t *ent);
29
30 /* The ent is the owner of the chasecam */
DeathcamStart(edict_t * ent)31 void DeathcamStart (edict_t *ent)
32 {
33
34 /* This creates a tempory entity we can manipulate within this
35 * function */
36 edict_t *chasecam;
37
38 /* Tell everything that looks at the toggle that our chasecam is on
39 * and working */
40 ent->client->chasetoggle = 1;
41
42 /* Make out gun model "non-existent" so it's more realistic to the
43 * player using the chasecam */
44 ent->client->ps.gunindex = 0;
45
46 chasecam = G_Spawn ();
47 chasecam->owner = ent;
48 chasecam->solid = SOLID_NOT;
49 chasecam->movetype = MOVETYPE_FLYMISSILE;
50
51 /* Stop movement prediction */
52 ent->client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;
53
54 /* Don't send camera info to other players */
55 ent->svflags |= SVF_NOCLIENT;
56
57 /* Now, make the angles of the player model, (!NOT THE HUMAN VIEW!) be
58 * copied to the same angle of the chasecam entity */
59 VectorCopy (ent->s.angles, chasecam->s.angles);
60
61 /*alt fire of zoom weapons-- reset some things.*/
62 ent->client->ps.fov = atoi(Info_ValueForKey(ent->client->pers.userinfo, "fov")); //alt fire - reset the fov;
63 ent->client->ps.stats[STAT_ZOOMED] = 0;
64
65 /* Clear the size of the entity, so it DOES technically have a size,
66 * but that of '0 0 0'-'0 0 0'. (xyz, xyz). mins = Minimum size,
67 * maxs = Maximum size */
68 VectorClear (chasecam->mins);
69 VectorClear (chasecam->maxs);
70 VectorClear (chasecam->velocity);
71
72 /* Make the chasecam's origin (position) be the same as the player
73 * entity's because as the camera starts, it will force itself out
74 * slowly backwards from the player model */
75 VectorCopy (ent->s.origin, chasecam->s.origin);
76 VectorCopy (ent->s.origin, chasecam->death_origin);
77
78 chasecam->classname = "chasecam";
79 chasecam->nextthink = level.time + 0.100;
80 chasecam->think = DeathcamTrack;
81 ent->client->chasecam = chasecam;
82 ent->client->oldplayer = G_Spawn();
83
84 }
85
DeathcamRemove(edict_t * ent,char * opt)86 void DeathcamRemove (edict_t *ent, char *opt)
87 {
88 if(ent->client->chasetoggle == 1) /* Safety check */
89 {
90 ent->client->chasetoggle = 0;
91
92 /* Stop the chasecam from moving */
93 VectorClear (ent->client->chasecam->velocity);
94
95 /* Re-enable sending entity info to other clients */
96 ent->svflags &= ~SVF_NOCLIENT;
97
98 if(ent->client->oldplayer->client != NULL)
99 {
100 #ifdef DEBUG_DEATHCAM
101 printf("--- Deathcam = %p\n", ent->client->oldplayer->client);
102 #endif
103 free(ent->client->oldplayer->client);
104 }
105
106 G_FreeEdict (ent->client->oldplayer);
107 G_FreeEdict (ent->client->chasecam);
108 }
109 }
110
111 /* The "ent" is the chasecam */
DeathcamTrack(edict_t * ent)112 void DeathcamTrack (edict_t *ent)
113 {
114
115
116 trace_t tr;
117 vec3_t spot1, spot2;
118 vec3_t forward, right, up;
119
120 ent->nextthink = level.time + 0.100;
121
122 AngleVectors (ent->s.angles, forward, right, up);
123
124 //JKD - 7/16/06 - tweaked this slightly so that it's a little closer to the body
125 /* find position for camera to end up */
126 VectorMA (ent->death_origin, -150, forward, spot1);
127
128 /* Move camera destination up slightly too */
129 spot1[2] += 30;
130
131 /* Make sure we don't go outside the level */
132 tr = gi.trace (ent->s.origin, NULL, NULL, spot1, ent, false);
133
134 /* subtract the endpoint from the start point for length and
135 * direction manipulation */
136 VectorSubtract (tr.endpos, ent->s.origin, spot2);
137
138 /* Use this to modify camera velocity */
139 VectorCopy(spot2, ent->velocity);
140
141 }
142
143
CheckDeathcam_Viewent(edict_t * ent)144 void CheckDeathcam_Viewent (edict_t *ent)
145 {
146 gclient_t *cl;
147 int tmp;
148
149 if (!ent->client->oldplayer->client)
150 {
151 cl = (gclient_t *) malloc(sizeof(gclient_t));
152 ent->client->oldplayer->client = cl;
153 #ifdef DEBUG_DEATHCAM
154 printf("+++ Deathcam = %p\n", cl);
155 #endif
156 }
157
158 if (ent->client->oldplayer)
159 {
160 ent->client->oldplayer->s.frame = ent->s.frame;
161 /* Copy the origin, the speed, and the model angle, NOT
162 * literal angle to the display entity */
163 VectorCopy (ent->s.origin, ent->client->oldplayer->s.origin);
164 VectorCopy (ent->velocity, ent->client->oldplayer->velocity);
165 VectorCopy (ent->s.angles, ent->client->oldplayer->s.angles);
166 }
167 tmp = ent->client->oldplayer->s.number;
168 ent->client->oldplayer->s = ent->s;
169 ent->client->oldplayer->s.number = tmp; // keep same s.number, not client's
170
171 gi.linkentity (ent->client->oldplayer);
172
173 }
174