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 //
21 // cg_weapon.c
22 // View weapon stuff
23 //
24 
25 #include "cg_local.h"
26 
27 static int					cg_gunFrame;
28 static struct refModel_s	*cg_gunModel;
29 
30 /*
31 =======================================================================
32 
33 	VIEW WEAPON
34 
35 =======================================================================
36 */
37 
38 /*
39 ==============
40 CG_AddViewWeapon
41 ==============
42 */
CG_AddViewWeapon(void)43 void CG_AddViewWeapon (void)
44 {
45 	refEntity_t			gun;
46 	entityState_t		*state;
47 	playerStateNew_t	*ps, *ops;
48 	cgEntity_t			*ent;
49 	vec3_t				angles;
50 	int					pnum;
51 
52 	// don't draw the weapon in third person
53 	if (cg.thirdPerson)
54 		return;
55 
56 	// allow the gun to be completely removed
57 	if (!cl_gun->intVal || hand->intVal == 2)
58 		return;
59 
60 	// find the previous frame to interpolate from
61 	ps = &cg.frame.playerState;
62 	if (cg.oldFrame.serverFrame != cg.frame.serverFrame-1 || !cg.oldFrame.valid)
63 		ops = &cg.frame.playerState;		// previous frame was dropped or invalid
64 	else
65 		ops = &cg.oldFrame.playerState;
66 
67 	memset (&gun, 0, sizeof (gun));
68 
69 	if (cg_gunModel) {
70 		// development tool
71 		gun.model = cg_gunModel;
72 	}
73 	else
74 		gun.model = cg.modelCfgDraw[ps->gunIndex];
75 
76 	if (!gun.model)
77 		return;
78 
79 	// set up gun position
80 	gun.origin[0] = cg.refDef.viewOrigin[0] + ops->gunOffset[0] + cg.lerpFrac * (ps->gunOffset[0] - ops->gunOffset[0]);
81 	gun.origin[1] = cg.refDef.viewOrigin[1] + ops->gunOffset[1] + cg.lerpFrac * (ps->gunOffset[1] - ops->gunOffset[1]);
82 	gun.origin[2] = cg.refDef.viewOrigin[2] + ops->gunOffset[2] + cg.lerpFrac * (ps->gunOffset[2] - ops->gunOffset[2]);
83 
84 	angles[0] = cg.refDef.viewAngles[0] + LerpAngle (ops->gunAngles[0], ps->gunAngles[0], cg.lerpFrac);
85 	angles[1] = cg.refDef.viewAngles[1] + LerpAngle (ops->gunAngles[1], ps->gunAngles[1], cg.lerpFrac);
86 	angles[2] = cg.refDef.viewAngles[2] + LerpAngle (ops->gunAngles[2], ps->gunAngles[2], cg.lerpFrac);
87 
88 	Angles_Matrix3 (angles, gun.axis);
89 
90 	if (cg_gunFrame) {
91 		// development tool
92 		gun.frame = cg_gunFrame;
93 		gun.oldFrame = cg_gunFrame;
94 	}
95 	else {
96 		gun.frame = ps->gunFrame;
97 		// just changed weapons, don't lerp from old
98 		if (gun.frame == 0)
99 			gun.oldFrame = 0;
100 		else
101 			gun.oldFrame = ops->gunFrame;
102 	}
103 
104 	ent = &cg_entityList[cg.playerNum+1];
105 	gun.flags = RF_MINLIGHT|RF_DEPTHHACK|RF_WEAPONMODEL;
106 	for (pnum = 0 ; pnum<cg.frame.numEntities ; pnum++) {
107 		state = &cg_parseEntities[(cg.frame.parseEntities+pnum)&(MAX_PARSEENTITIES_MASK)];
108 		if (state->number != cg.playerNum + 1)
109 			continue;
110 
111 		gun.flags |= state->renderFx;
112 		if (state->effects & EF_PENT)
113 			gun.flags |= RF_SHELL_RED;
114 		if (state->effects & EF_QUAD)
115 			gun.flags |= RF_SHELL_BLUE;
116 		if (state->effects & EF_DOUBLE)
117 			gun.flags |= RF_SHELL_DOUBLE;
118 		if (state->effects & EF_HALF_DAMAGE)
119 			gun.flags |= RF_SHELL_HALF_DAM;
120 
121 		if (state->renderFx & RF_TRANSLUCENT)
122 			gun.color[3] = 255 * 0.70f;
123 
124 		if (state->effects & EF_BFG) {
125 			gun.flags |= RF_TRANSLUCENT;
126 			gun.color[3] = 255 * 0.30f;
127 		}
128 
129 		if (state->effects & EF_PLASMA) {
130 			gun.flags |= RF_TRANSLUCENT;
131 			gun.color[3] = 255 * 0.6f;
132 		}
133 
134 		if (state->effects & EF_SPHERETRANS) {
135 			gun.flags |= RF_TRANSLUCENT;
136 
137 			if (state->effects & EF_TRACKERTRAIL)
138 				gun.color[3] = 255 * 0.6f;
139 			else
140 				gun.color[3] = 255 * 0.3f;
141 		}
142 		break;
143 	}
144 
145 	gun.scale = 1.0f;
146 	gun.backLerp = 1.0f - cg.lerpFrac;
147 	Vec3Copy (gun.origin, gun.oldOrigin);	// don't lerp origins at all
148 	Vec4Set (gun.color, 255, 255, 255, 255);
149 
150 	if (hand->intVal == 1) {
151 		gun.flags |= RF_CULLHACK;
152 		Vec3Negate (gun.axis[1], gun.axis[1]);
153 	}
154 
155 	cgi.R_AddEntity (&gun);
156 
157 	gun.skinNum = 0;
158 	gun.flags |= RF_DEPTHHACK;
159 	if (gun.flags & RF_SHELLMASK) {
160 		if (gun.flags & RF_SHELL_DOUBLE) {
161 			gun.skin = cgMedia.modelShellDouble;
162 			cgi.R_AddEntity (&gun);
163 		}
164 		if (gun.flags & RF_SHELL_HALF_DAM) {
165 			gun.skin = cgMedia.modelShellHalfDam;
166 			cgi.R_AddEntity (&gun);
167 		}
168 
169 		if (gun.flags & RF_SHELL_RED && gun.flags & RF_SHELL_GREEN && gun.flags & RF_SHELL_BLUE) {
170 			gun.skin = cgMedia.modelShellGod;
171 			cgi.R_AddEntity (&gun);
172 		}
173 		else {
174 			if (gun.flags & RF_SHELL_RED) {
175 				gun.skin = cgMedia.modelShellRed;
176 				cgi.R_AddEntity (&gun);
177 			}
178 			if (gun.flags & RF_SHELL_GREEN) {
179 				gun.skin = cgMedia.modelShellGreen;
180 				cgi.R_AddEntity (&gun);
181 			}
182 			if (gun.flags & RF_SHELL_BLUE) {
183 				gun.skin = cgMedia.modelShellBlue;
184 				cgi.R_AddEntity (&gun);
185 			}
186 		}
187 	}
188 }
189 
190 /*
191 =======================================================================
192 
193 	CONSOLE FUNCTIONS
194 
195 =======================================================================
196 */
197 
198 /*
199 =============
200 CG_Gun_FrameNext_f
201 =============
202 */
CG_Gun_FrameNext_f(void)203 static void CG_Gun_FrameNext_f (void)
204 {
205 	Com_Printf (0, "Gun frame %i\n", ++cg_gunFrame);
206 }
207 
208 
209 /*
210 =============
211 CG_Gun_FramePrev_f
212 =============
213 */
CG_Gun_FramePrev_f(void)214 static void CG_Gun_FramePrev_f (void)
215 {
216 	if (--cg_gunFrame < 0)
217 		cg_gunFrame = 0;
218 	Com_Printf (0, "Gun frame %i\n", cg_gunFrame);
219 }
220 
221 
222 /*
223 =============
224 CG_Gun_Model_f
225 =============
226 */
CG_Gun_Model_f(void)227 static void CG_Gun_Model_f (void)
228 {
229 	char	name[MAX_QPATH];
230 
231 	if (cgi.Cmd_Argc () != 2) {
232 		cg_gunModel = NULL;
233 		return;
234 	}
235 
236 	Q_snprintfz (name, sizeof (name), "models/%s/tris.md2", cgi.Cmd_Argv (1));
237 	cg_gunModel = cgi.R_RegisterModel (name);
238 }
239 
240 /*
241 =======================================================================
242 
243 	INIT / SHUTDOWN
244 
245 =======================================================================
246 */
247 
248 static void		*cmd_gunNext;
249 static void		*cmd_gunPrev;
250 static void		*cmd_gunModel;
251 
252 /*
253 =============
254 CG_WeapRegister
255 =============
256 */
CG_WeapRegister(void)257 void CG_WeapRegister (void)
258 {
259 	cmd_gunNext		= cgi.Cmd_AddCommand ("gun_next",		CG_Gun_FrameNext_f,	"Increments view weapon frame number");
260 	cmd_gunPrev		= cgi.Cmd_AddCommand ("gun_prev",		CG_Gun_FramePrev_f,	"Decrements view weapon frame number");
261 	cmd_gunModel	= cgi.Cmd_AddCommand ("gun_model",	CG_Gun_Model_f,		"Changes the view weapon model");
262 }
263 
264 
265 /*
266 =============
267 CG_WeapUnregister
268 =============
269 */
CG_WeapUnregister(void)270 void CG_WeapUnregister (void)
271 {
272 	cgi.Cmd_RemoveCommand ("gun_next", cmd_gunNext);
273 	cgi.Cmd_RemoveCommand ("gun_prev", cmd_gunPrev);
274 	cgi.Cmd_RemoveCommand ("gun_model", cmd_gunModel);
275 }
276