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