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