]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/cl_weaponsystem.c
Added function for "+use" with teslas -- also added semi-support for railgun
[divverent/nexuiz.git] / TeamNexuiz / game / gamec / cl_weaponsystem.c
1 /*\r
2 ===========================================================================\r
3 \r
4   CLIENT WEAPONSYSTEM CODE\r
5   Bring back W_Weaponframe\r
6 \r
7 ===========================================================================\r
8 */\r
9 \r
10 void() CL_Weaponentity_Think =\r
11 {\r
12         self.nextthink = time;\r
13         if (self.owner.weaponentity != self)\r
14         {\r
15                 remove(self);\r
16                 return;\r
17         }\r
18         self.effects = self.owner.effects;\r
19         if(!(self.class == CLASS_SPY && self.special_active))\r
20                 self.alpha = self.owner.alpha;\r
21 };\r
22 \r
23 void() CL_ExteriorWeaponentity_Think =\r
24 {\r
25         self.nextthink = time;\r
26         if (self.owner.exteriorweaponentity != self)\r
27         {\r
28                 remove(self);\r
29                 return;\r
30         }\r
31         if (self.cnt != self.owner.weaponentity.modelindex || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)\r
32         {\r
33                 self.cnt = self.owner.weaponentity.modelindex;\r
34                 self.dmg = self.owner.modelindex;\r
35                 self.deadflag = self.owner.deadflag;\r
36                 if (self.owner.deadflag) self.model = "";\r
37                 else if (self.owner.wpn == WEP_LASER) setmodel(self, "models/weapons/v_laser.md3");\r
38                 else if (self.owner.wpn == WEP_SHOTGUN) setmodel(self, "models/weapons/v_shotgun.md3");\r
39                 else if (self.owner.wpn == WEP_UZI) setmodel(self, "models/weapons/v_uzi.md3");\r
40                 else if (self.owner.wpn == WEP_GRENADE_LAUNCHER) setmodel(self, "models/weapons/v_gl.md3");\r
41                 else if (self.owner.wpn == WEP_ELECTRO) setmodel(self, "models/weapons/v_electro.md3");\r
42                 else if (self.owner.wpn == WEP_CRYLINK) setmodel(self, "models/weapons/v_crylink.md3");\r
43                 else if (self.owner.wpn == WEP_NEX) setmodel(self, "models/weapons/v_nex.md3");\r
44                 else if (self.owner.wpn == WEP_HAGAR) setmodel(self, "models/weapons/v_hagar.md3");\r
45                 else if (self.owner.wpn == WEP_ROCKET_LAUNCHER) setmodel(self, "models/weapons/v_rl.md3");\r
46                 else if (self.owner.wpn == WEP_BOMBLETTS) setmodel(self, "models/weapons/v_bombletts.md3");\r
47                 else if (self.owner.wpn == WEP_ROCKET_INCENDIARY) setmodel(self, "models/weapons/v_rli.md3");\r
48                 else if (self.owner.wpn == WEP_HOTBOMBS) setmodel(self, "models/weapons/v_hotbombs.md3");\r
49                 else if (self.owner.wpn == WEP_GRAPPLE) setmodel(self, "models/weapons/v_grapple.md3");\r
50                 else if (self.owner.wpn == WEP_NAMEK) setmodel(self, "models/weapons/v_namek.md3");\r
51                 else if (self.owner.wpn == WEP_RAILGUN) setmodel(self, "models/weapons/v_railgun.md3");\r
52                 setattachment(self, self.owner, "bip01 r hand");\r
53                 // if that didn't find a tag, hide the exterior weapon model\r
54                 if (!self.tag_index)\r
55                         self.model = "";\r
56         }\r
57         self.effects = self.owner.weaponentity.effects;\r
58 };\r
59 \r
60 // spawning weaponentity for client\r
61 void() CL_SpawnWeaponentity =\r
62 {\r
63         if (self.weaponentity)\r
64         {\r
65                 w_clear();\r
66                 return;\r
67         }\r
68         self.weaponentity = spawn();\r
69         self.weaponentity.solid = SOLID_NOT;\r
70         self.weaponentity.owner = self;\r
71         self.weaponentity.weaponentity = self.weaponentity;\r
72         setmodel(self.weaponentity, "");\r
73         self.weaponentity.origin = '0 0 0';\r
74         self.weaponentity.angles = '0 0 0';\r
75         self.weaponentity.viewmodelforclient = self;\r
76         self.weaponentity.flags = 0;\r
77         self.weaponentity.think = CL_Weaponentity_Think;\r
78         self.weaponentity.nextthink = time;\r
79 \r
80         self.exteriorweaponentity = spawn();\r
81         self.exteriorweaponentity.solid = SOLID_NOT;\r
82         self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;\r
83         self.exteriorweaponentity.owner = self;\r
84         self.exteriorweaponentity.origin = '0 0 0';\r
85         self.exteriorweaponentity.angles = '0 0 0';\r
86         self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;\r
87         self.exteriorweaponentity.nextthink = time;\r
88 };\r
89 \r
90 // convertion from index (= impulse) to flag in .items\r
91 float(float index) weapon_translateindextoflag =\r
92 {\r
93         if (index == WEP1)\r
94                 return IT_WEP1;\r
95         else if (index == WEP2)\r
96                 return IT_WEP2;\r
97         else if (index == WEP3)\r
98                 return IT_WEP3;\r
99         else if (index == WEP4)\r
100                 return IT_WEP4;\r
101         else if (index == WEP5)\r
102                 return IT_WEP5;\r
103         return IT_WEP1;\r
104 };\r
105 \r
106 float(entity cl, float wpn, float andammo) client_hasweapon =\r
107 {\r
108         local float itemcode;\r
109         local entity oldself;\r
110 \r
111         weapon_hasammo = TRUE;\r
112         if (wpn < WEP_FIRST || wpn > WEP_LAST)\r
113                 return FALSE;\r
114         itemcode = weapon_translateindextoflag(wpn);\r
115         if (cl.items & itemcode)\r
116         {\r
117                 if (andammo)\r
118                 {\r
119                         oldself = self;\r
120                         self = cl;\r
121                         weapon_action(wpn, WR_CHECKAMMO);\r
122                         self = oldself;\r
123                         if (weapon_hasammo)\r
124                                 return TRUE;\r
125                         return FALSE;\r
126                 }\r
127                 return TRUE;\r
128         }\r
129         return FALSE;\r
130 };\r
131 \r
132 // Weapon subs\r
133 void() w_clear =\r
134 {\r
135         weapon_action(self.weapon, WR_CLEAR);\r
136         if (self.weapon != -1)\r
137                 self.weapon = 0;\r
138         if (self.weaponentity)\r
139         {\r
140                 self.weaponentity.state = WS_CLEAR;\r
141                 setmodel(self.weaponentity, "");\r
142                 self.weaponentity.effects = 0;\r
143         }\r
144 };\r
145 \r
146 void() w_ready =\r
147 {\r
148         self.weaponentity.state = WS_READY;\r
149         weapon_action(self.weapon, WR_IDLE);\r
150 };\r
151 \r
152 // FIXME: add qw-style client-custom weaponrating (cl_weaponrating)?\r
153 float(entity e) w_getbestweapon\r
154 {// add new weapons here\r
155         if(e.class == CLASS_SCOUT)\r
156         {\r
157                 if (client_hasweapon(e, WEP5, TRUE))\r
158                         return WEP5;\r
159                 else if (client_hasweapon(e, WEP3, TRUE))\r
160                         return WEP3;\r
161                 else if (client_hasweapon(e, WEP2, TRUE))\r
162                         return WEP2;\r
163                 weapon_hasammo = TRUE;\r
164                 return WEP1;\r
165         }\r
166         if(e.class == CLASS_SPY)\r
167         {\r
168                 if (client_hasweapon(e, WEP5, TRUE))\r
169                         return WEP5;\r
170                 else if (client_hasweapon(e, WEP2, TRUE))\r
171                         return WEP2;\r
172                 weapon_hasammo = TRUE;\r
173                 return WEP1;\r
174         }\r
175         if(e.class == CLASS_SOLDIER)\r
176         {\r
177                 if (client_hasweapon(e, WEP5, TRUE))\r
178                         return WEP5;\r
179                 else if (client_hasweapon(e, WEP4, TRUE))\r
180                         return WEP4;\r
181                 else if (client_hasweapon(e, WEP3, TRUE))\r
182                         return WEP3;\r
183                 else if (client_hasweapon(e, WEP2, TRUE))\r
184                         return WEP2;\r
185                 weapon_hasammo = TRUE;\r
186                 return WEP1;\r
187         }\r
188         if(e.class == CLASS_PYRO)\r
189         {\r
190                 if (client_hasweapon(e, WEP5, TRUE))\r
191                         return WEP5;\r
192                 else if (client_hasweapon(e, WEP3, TRUE))\r
193                         return WEP3;\r
194                 else if (client_hasweapon(e, WEP2, TRUE))\r
195                         return WEP2;\r
196                 else if (client_hasweapon(e, WEP4, TRUE))\r
197                         return WEP4;\r
198                 weapon_hasammo = TRUE;\r
199                 return WEP1;\r
200         }\r
201         if(e.class == CLASS_MEDIC)\r
202         {\r
203                 if (client_hasweapon(e, WEP5, TRUE))\r
204                         return WEP5;\r
205                 else if (client_hasweapon(e, WEP4, TRUE))\r
206                         return WEP4;\r
207                 else if (client_hasweapon(e, WEP3, TRUE))\r
208                         return WEP3;\r
209                 else if (client_hasweapon(e, WEP2, TRUE))\r
210                         return WEP2;\r
211                 weapon_hasammo = TRUE;\r
212                 return WEP1;\r
213         }\r
214         if(e.class == CLASS_ENGINEER)\r
215         {\r
216                 if (client_hasweapon(e, WEP5, TRUE))\r
217                         return WEP5;\r
218                 else if (client_hasweapon(e, WEP4, TRUE))\r
219                         return WEP4;\r
220                 else if (client_hasweapon(e, WEP3, TRUE))\r
221                         return WEP3;\r
222                 else if (client_hasweapon(e, WEP2, TRUE))\r
223                         return WEP2;\r
224                 weapon_hasammo = TRUE;\r
225                 return WEP1;\r
226         }\r
227         weapon_hasammo = TRUE;\r
228         return WEP1;\r
229 };\r
230 \r
231 // Setup weapon for client (after this raise frame will be launched)\r
232 void(float new_wep, string wmodel, float hudammo) weapon_setup =\r
233 {\r
234         local string weaponmdl;\r
235 \r
236         self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));\r
237         self.items = self.items | hudammo;\r
238 \r
239         self.weapon = self.switchweapon;\r
240         //self.weapon = weapon_translateindextoflag(new_wep);\r
241         self.wpn = new_wep;\r
242 \r
243         if (wmodel != "")\r
244         {\r
245                 weaponmdl = strzone(strcat("models/weapons/", wmodel));\r
246                 setmodel(self.weaponentity, weaponmdl);\r
247         }\r
248         // VorteX: update visible weapon\r
249         // CL_ViswepUpdate();\r
250 };\r
251 \r
252 /*void(float new_wep, string wmodel, float hudammo, void spfunciton()) weapon_setup_special =\r
253 {\r
254         weapon_setup(new_wep, wmodel, hudammo);\r
255         spfunction();\r
256 }*/\r
257 \r
258 // shot direction\r
259 float WEAPON_MAXRELX = 14; // if more, shot can be spawned after wall surface (in empty worldspace) or inside other entity if client stands close to it\r
260 void(float x, float y, float z) weapon_shotdir =\r
261 {\r
262         makevectors(self.v_angle);\r
263         self.shotorg  = self.origin + self.view_ofs + v_forward*bound(0, x, WEAPON_MAXRELX) + v_right*(y + self.weaponentity.view_ofs_y) + v_up*z;\r
264         self.shotdir = aim(self, 1000);\r
265 };\r
266 \r
267 // perform weapon to attack (weaponstate and attack_finished check is here)\r
268 void(float() checkfunc1, float() checkfunc2, void() firefunc, float atktime) weapon_prepareattack =\r
269 {\r
270         // fixme: does spy need to decloak here?\r
271         //if(self.class == CLASS_SPY)\r
272         //{\r
273         //      SpyDecloak();\r
274         //}\r
275         // Change to best weapon if failed\r
276         if ((cvar("g_instagib") == 0) && (cvar("g_rocketarena") == 0))\r
277         {\r
278                 if (!checkfunc1())\r
279                 {\r
280                         if (!checkfunc2())\r
281                                 self.switchweapon = w_getbestweapon(self);\r
282                         return;\r
283                 }\r
284         }\r
285         // Don't do shot if previos attack  not finished\r
286                 if (time < self.attack_finished)\r
287                         return;\r
288         // Can't do shot if changing weapon\r
289                 if (self.weaponentity.state != WS_READY)\r
290                         return;\r
291 \r
292         self.attack_finished = time + atktime;\r
293         firefunc();\r
294 };\r
295 \r
296 void SpyDecloak();\r
297 // perform weapon attack\r
298 void(float() checkfunc1, float() checkfunc2, void() firefunc) weapon_doattack\r
299 {\r
300         if(self.class == CLASS_SPY)\r
301         {\r
302                 SpyDecloak();\r
303         }\r
304 \r
305 \r
306         // Change to best weapon if failed\r
307         if ((cvar("g_instagib") == 0) && (cvar("g_rocketarena") == 0))\r
308         {\r
309                 if (!checkfunc1())\r
310                 {\r
311                         if (!checkfunc2())\r
312                                 self.switchweapon = w_getbestweapon(self);\r
313                         return;\r
314                 }\r
315         }\r
316         self.weaponentity.state = WS_INUSE;\r
317         firefunc();\r
318         weapon_action(self.weapon, WR_UPDATECOUNTS); // update ammo now\r
319 };\r
320 \r
321 void(entity ent, float recoil) weapon_recoil =\r
322 {\r
323         ent.punchangle = (randomvec() + '-1 0 0')*recoil;\r
324         ent.punchangle_z = 0; // don't want roll\r
325         if (recoil > 3) // push back if large recoil\r
326                 ent.velocity = ent.velocity - normalize(ent.shotdir)*recoil*25;\r
327 };\r
328 \r
329 void(float fr, float t, void() func) weapon_thinkf =\r
330 {\r
331         if (fr >= 0)\r
332                 if (self.weaponentity != world)\r
333                         self.weaponentity.frame = fr;\r
334         // VorteX: haste can be added here\r
335         self.weapon_nextthink = time + t;\r
336         self.weapon_think = func;\r
337 };\r
338 \r
339 void(float spd, vector org) weapon_boblayer1 =\r
340 {\r
341         // VorteX: haste can be added here\r
342         self.weaponentity.pos1 =org;\r
343         self.weaponentity.lip = spd;\r
344 };\r