]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/cl_weapons.qc
"fall out of bluesky" fixed
[divverent/nexuiz.git] / data / qcsrc / server / cl_weapons.qc
1
2 // generic weapons table
3 // add new weapons here
4 float(float wpn, float wrequest) weapon_action =
5 {
6         if (wpn == WEP_LASER)
7                 return w_laser(wrequest);
8         else if (wpn == WEP_SHOTGUN)
9                 return w_shotgun(wrequest);
10         else if (wpn == WEP_UZI)
11                 return w_uzi(wrequest);
12         else if (wpn == WEP_GRENADE_LAUNCHER)
13                 return w_glauncher(wrequest);
14         else if (wpn == WEP_ELECTRO)
15                 return w_electro(wrequest);
16         else if (wpn == WEP_CRYLINK)
17                 return w_crylink(wrequest);
18         else if (wpn == WEP_NEX)
19                 return w_nex(wrequest);
20         else if (wpn == WEP_HAGAR)
21                 return w_hagar(wrequest);
22         else if (wpn == WEP_ROCKET_LAUNCHER)
23                 return w_rlauncher(wrequest);
24         return FALSE;
25 };
26
27 // think function for tossed weapons
28 void() thrown_wep_think
29 {
30         self.solid = SOLID_TRIGGER;
31         self.owner = world;
32         SUB_SetFade(self, time + 20, 1);
33         setorigin(self, self.origin);
34 };
35
36 // toss current weapon
37 void(vector velo, vector delta, float doreduce) W_ThrowWeapon
38 {
39         local float w, ammo;
40         local entity wep, e;
41
42         w = self.weapon;
43         if(w == WEP_LASER)
44                 return;
45         if(w == 0)
46                 return; // just in case
47
48         e = self;
49         wep = spawn();
50         self = wep;
51
52         setorigin(wep, e.origin + delta);
53         makevectors(e.angles);
54         wep.classname = "droppedweapon";
55         wep.velocity = velo; // e.velocity * 0.5 + v_forward * 750;
56         SUB_SetFade(wep, time + 20, 1);
57
58         if(w == WEP_SHOTGUN)
59         {
60                 w = IT_SHOTGUN;
61                 if(!(e.items & w))
62                 {
63                         remove(wep);
64                         self = e;
65                         return;
66                 }
67                 weapon_shotgun();
68                 if(startitem_failed)
69                 {
70                         self = e;
71                         return;
72                 }
73                 if(doreduce)
74                 {
75                         ammo = min(e.ammo_shells, wep.ammo_shells);
76                         wep.ammo_shells = ammo;
77                         e.ammo_shells -= ammo;
78                 }
79         }
80         else if(w == WEP_UZI)
81         {
82                 w = IT_UZI;
83                 if(!(e.items & w))
84                 {
85                         remove(wep);
86                         self = e;
87                         return;
88                 }
89                 weapon_uzi();
90                 if(startitem_failed)
91                 {
92                         self = e;
93                         return;
94                 }
95                 if(doreduce)
96                 {
97                         ammo = min(e.ammo_nails, wep.ammo_nails);
98                         wep.ammo_nails = ammo;
99                         e.ammo_nails -= ammo;
100                 }
101         }
102         else if(w == WEP_GRENADE_LAUNCHER)
103         {
104                 w = IT_GRENADE_LAUNCHER;
105                 if(!(e.items & w))
106                 {
107                         self = e;
108                         remove(wep);
109                         return;
110                 }
111                 weapon_grenadelauncher();
112                 if(startitem_failed)
113                 {
114                         self = e;
115                         return;
116                 }
117                 if(doreduce)
118                 {
119                         ammo = min(e.ammo_rockets, wep.ammo_rockets);
120                         wep.ammo_rockets = ammo;
121                         e.ammo_rockets -= ammo;
122                 }
123         }
124         else if(w == WEP_ELECTRO)
125         {
126                 w = IT_ELECTRO;
127                 if(!(e.items & w))
128                 {
129                         self = e;
130                         remove(wep);
131                         return;
132                 }
133                 weapon_electro();
134                 if(startitem_failed)
135                 {
136                         self = e;
137                         return;
138                 }
139                 if(doreduce)
140                 {
141                         ammo = min(e.ammo_cells, wep.ammo_cells);
142                         wep.ammo_cells = ammo;
143                         e.ammo_cells -= ammo;
144                 }
145         }
146         else if(w == WEP_CRYLINK)
147         {
148                 w = IT_CRYLINK;
149                 if(!(e.items & w))
150                 {
151                         self = e;
152                         remove(wep);
153                         return;
154                 }
155                 weapon_crylink();
156                 if(startitem_failed)
157                 {
158                         self = e;
159                         return;
160                 }
161                 if(doreduce)
162                 {
163                         ammo = min(e.ammo_cells, wep.ammo_cells);
164                         wep.ammo_cells = ammo;
165                         e.ammo_cells -= ammo;
166                 }
167         }
168         else if(w == WEP_NEX)
169         {
170                 w = IT_NEX;
171                 if(!(e.items & w))
172                 {
173                         self = e;
174                         remove(wep);
175                         return;
176                 }
177                 weapon_nex();
178                 if(startitem_failed)
179                 {
180                         self = e;
181                         return;
182                 }
183                 if(doreduce)
184                 {
185                         ammo = min(e.ammo_cells, wep.ammo_cells);
186                         wep.ammo_cells = ammo;
187                         e.ammo_cells -= ammo;
188                 }
189         }
190         else if(w == WEP_HAGAR)
191         {
192                 w = IT_HAGAR;
193                 if(!(e.items & w))
194                 {
195                         self = e;
196                         remove(wep);
197                         return;
198                 }
199                 weapon_hagar();
200                 if(startitem_failed)
201                 {
202                         self = e;
203                         return;
204                 }
205                 if(doreduce)
206                 {
207                         ammo = min(e.ammo_rockets, wep.ammo_rockets);
208                         wep.ammo_rockets = ammo;
209                         e.ammo_rockets -= ammo;
210                 }
211         }
212         else if(w == WEP_ROCKET_LAUNCHER)
213         {
214                 w = IT_ROCKET_LAUNCHER;
215                 if(!(e.items & w))
216                 {
217                         self = e;
218                         remove(wep);
219                         return;
220                 }
221                 weapon_rocketlauncher();
222                 if(startitem_failed)
223                 {
224                         self = e;
225                         return;
226                 }
227                 if(doreduce)
228                 {
229                         ammo = min(e.ammo_rockets, wep.ammo_rockets);
230                         wep.ammo_rockets = ammo;
231                         e.ammo_rockets -= ammo;
232                 }
233         }
234
235         if(e.items & w)
236                 if(e.health >= 1)
237                         sprint(e, strcat("You dropped the ^2", wep.netname, "\n"));
238         wep.owner = e;
239         setorigin(wep, wep.origin);
240         wep.nextthink = time + 0.5;
241         wep.think = thrown_wep_think;
242         wep.classname = "droppedweapon";
243         wep.flags = wep.flags | FL_TOSSED;
244         e.items = e.items - (e.items & w);
245         e.switchweapon = w_getbestweapon(e);
246         wep.colormap = e.colormap;
247         if (e.switchweapon != e.weapon)
248                 e.cnt = e.weapon;
249         self = e;
250 };
251
252 // switch between weapons
253 void(float imp) W_SwitchWeapon
254 {
255         if (self.weapon != imp)
256         if (client_hasweapon(self, imp, TRUE, TRUE))
257         {
258                 self.cnt = self.weapon;
259                 self.switchweapon = imp;
260         }
261 };
262
263 // next weapon
264 void() W_NextWeapon =
265 {
266         local float weaponwant, maxtries;
267
268         maxtries = WEP_LAST;
269
270         weaponwant = self.switchweapon + 1;
271         if (weaponwant < WEP_FIRST)
272                 weaponwant = WEP_LAST;
273         if (weaponwant > WEP_LAST)
274                 weaponwant = WEP_FIRST;
275         while(!client_hasweapon(self, weaponwant, TRUE, FALSE))
276         {
277                 if(!maxtries)
278                         return;
279
280                 maxtries -= 1;
281                 weaponwant = weaponwant + 1;
282                 if (weaponwant < WEP_FIRST)
283                         weaponwant = WEP_LAST;
284                 if (weaponwant > WEP_LAST)
285                         weaponwant = WEP_FIRST;
286         }
287         self.cnt = self.weapon;
288         self.switchweapon = weaponwant;
289 };
290
291 // prev weapon
292 void() W_PreviousWeapon =
293 {
294         local float weaponwant, maxtries;
295
296         maxtries = WEP_LAST;
297
298         weaponwant = self.switchweapon - 1;
299         if (weaponwant < WEP_FIRST)
300                 weaponwant = WEP_LAST;
301         if (weaponwant > WEP_LAST)
302                 weaponwant = WEP_FIRST;
303         while(!client_hasweapon(self, weaponwant, TRUE, FALSE))
304         {
305                 if(!maxtries)
306                         return;
307
308                 maxtries -= 1;
309                 weaponwant = weaponwant - 1;
310                 if (weaponwant < WEP_FIRST)
311                         weaponwant = WEP_LAST;
312                 if (weaponwant > WEP_LAST)
313                         weaponwant = WEP_FIRST;
314         }
315         self.cnt = self.weapon;
316         self.switchweapon = weaponwant;
317 };
318
319 // Bringed back weapon frame
320 void() W_WeaponFrame =
321 {
322         if(arena_roundbased)
323         if(time < warmup)
324                 return;
325
326         if (!self.weaponentity || self.health < 1)
327                 return; // Dead player can't use weapons and injure impulse commands
328
329         if(!self.switchweapon)
330         {
331                 self.weapon = 0;
332                 self.weaponentity.state = WS_CLEAR;
333                 return;
334         }
335
336         makevectors(self.v_angle);
337
338         // Change weapon
339         if (self.weapon != self.switchweapon)
340         {
341                 if (self.weaponentity.state == WS_CLEAR)
342                 {
343                         self.weaponentity.state = WS_RAISE;
344                         weapon_action(self.switchweapon, WR_SETUP);
345                         // VorteX: add player model weapon select frame here
346                         // setcustomframe(PlayerWeaponRaise);
347                         weapon_thinkf(WFRAME_IDLE, cvar("g_balance_weaponswitchdelay"), w_ready);
348                         weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, '0 0 0');
349                 }
350                 else if (self.weaponentity.state == WS_READY)
351                 {
352                         sound (self, CHAN_WEAPON, "weapons/weapon_switch.ogg", 1, ATTN_NORM);
353                         self.weaponentity.state = WS_DROP;
354                         // set up weapon switch think in the future, and start drop anim
355                         weapon_thinkf(WFRAME_IDLE, cvar("g_balance_weaponswitchdelay"), w_clear);
356                         weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, PLAYER_WEAPONSELECTION_RANGE);
357                 }
358         }
359
360         // call the think code which may fire the weapon
361         // and do so multiple times to resolve framerate dependency issues if the
362         // server framerate is very low and the weapon fire rate very high
363         local float c;
364         c = 0;
365         while (c < 5)
366         {
367                 c = c + 1;
368                 weapon_action(self.weapon, WR_THINK);
369                 if (self.weapon_nextthink > 0 && time >= self.weapon_nextthink)
370                 {
371                         self.weapon_nextthink_lastframe = self.weapon_nextthink;
372                         self.weapon_think();
373                 }
374         }
375
376         // don't let attack_finished fall behind when not firing
377         if (self.attack_finished < time)
378                 self.attack_finished = time;
379
380         // update currentammo incase it has changed
381         if (self.items & IT_CELLS)
382                 self.currentammo = self.ammo_cells;
383         else if (self.items & IT_ROCKETS)
384                 self.currentammo = self.ammo_rockets;
385         else if (self.items & IT_NAILS)
386                 self.currentammo = self.ammo_nails;
387         else if (self.items & IT_SHELLS)
388                 self.currentammo = self.ammo_shells;
389         else
390                 self.currentammo = 1;
391
392 };
393
394 float nixnex_weapon;
395 float nixnex_nextchange;
396 float nixnex_nextweapon;
397 .float nixnex_lastchange_id;
398 .float nixnex_lastinfotime;
399 .float nixnex_nextincr;
400
401 void Nixnex_ChooseNextWeapon()
402 {
403         float numberof, id;
404         numberof = WEP_LAST - WEP_FIRST; // all but the current one
405         if(cvar("g_nixnex_with_laser"))
406                 numberof = numberof - 1;
407         id = WEP_FIRST + ceil(random() * numberof) - 1;
408
409         if(cvar("g_nixnex_with_laser")) // skip the laser if needed
410                 id = id + 1;
411
412         if(id >= nixnex_weapon) // skip the current weapon
413                 id = id + 1;
414
415         if(id < WEP_FIRST) // can't happen, but to be sure...
416         {
417                 dprint("Won't happen (id < WEP_FIRST)\n");
418                 id = WEP_FIRST;
419         }
420         if(id > WEP_LAST) // either
421         {
422                 dprint("Won't happen (id > WEP_LAST)\n");
423                 id = WEP_LAST;
424         }
425
426         nixnex_nextweapon = id;
427 }
428
429 string W_Name(float weaponid)
430 {
431         if(weaponid == WEP_LASER)             return "Laser";
432         if(weaponid == WEP_UZI)               return "Machine Gun";
433         if(weaponid == WEP_SHOTGUN)           return "Shotgun";
434         if(weaponid == WEP_GRENADE_LAUNCHER)  return "Mortar";
435         if(weaponid == WEP_ELECTRO)           return "Electro";
436         if(weaponid == WEP_NEX)               return "Nex";
437         if(weaponid == WEP_HAGAR)             return "Hagar";
438         if(weaponid == WEP_ROCKET_LAUNCHER)   return "Rocket Launcher";
439         if(weaponid == WEP_CRYLINK)           return "Crylink";
440         return "@!#%'n Tuba";
441 }
442
443 void Nixnex_GiveCurrentWeapon()
444 {
445         float dt;
446         if(cvar("g_nixnex"))
447         {
448                 if(!nixnex_nextweapon)
449                         Nixnex_ChooseNextWeapon();
450
451                 dt = ceil(nixnex_nextchange - time);
452
453                 if(dt <= 0)
454                 {
455                         nixnex_weapon = nixnex_nextweapon;
456                         nixnex_nextweapon = 0;
457                         nixnex_nextchange = time + cvar("g_balance_nixnex_roundtime");
458                 }
459
460                 if(nixnex_nextchange != self.nixnex_lastchange_id) // this shall only be called once per round!
461                 {
462                         self.nixnex_lastchange_id = nixnex_nextchange;
463                         if (cvar("g_use_ammunition"))
464                         {
465                                 self.ammo_shells = cvar("g_balance_nixnex_ammo_shells");
466                                 self.ammo_nails = cvar("g_balance_nixnex_ammo_nails");
467                                 self.ammo_rockets = cvar("g_balance_nixnex_ammo_rockets");
468                                 self.ammo_cells = cvar("g_balance_nixnex_ammo_cells");
469                         }
470                         else
471                         {
472                                 self.ammo_shells = 999;
473                                 self.ammo_nails = 999;
474                                 self.ammo_rockets = 999;
475                                 self.ammo_cells = 999;
476                         }
477                         self.nixnex_nextincr = time + cvar("g_balance_nixnex_incrtime");
478                         if(dt >= 1 && dt <= 5)
479                                 self.nixnex_lastinfotime = -42;
480                         else
481                         {
482                                 centermsg_free(CENTERMSG_NIXNEXCOUNT);
483                                 centermsg_set(CENTERMSG_NIXNEX, strcat("^2Active weapon: ^3", W_Name(nixnex_weapon)));
484                         }
485                 }
486                 if(self.nixnex_lastinfotime != dt)
487                 {
488                         self.nixnex_lastinfotime = dt; // initial value 0 should count as "not seen"
489                         if(dt >= 1 && dt <= 5)
490                         {
491                                 centermsg_set(CENTERMSG_NIXNEXCOUNT, strcat("^3", ftos(dt), "^2 seconds until weapon change..."));
492                                 centermsg_set(CENTERMSG_NIXNEX, strcat("Next weapon: ^3", W_Name(nixnex_nextweapon)));
493                         }
494                 }
495
496                 if(cvar("g_use_ammunition") && time > self.nixnex_nextincr)
497                 {
498                         self.ammo_shells = self.ammo_shells + cvar("g_balance_nixnex_ammoincr_shells");
499                         self.ammo_nails = self.ammo_nails + cvar("g_balance_nixnex_ammoincr_nails");
500                         self.ammo_rockets = self.ammo_rockets + cvar("g_balance_nixnex_ammoincr_rockets");
501                         self.ammo_cells = self.ammo_cells + cvar("g_balance_nixnex_ammoincr_cells");
502                         self.nixnex_nextincr = time + cvar("g_balance_nixnex_incrtime");
503                 }
504
505                 self.items = self.items - (self.items & (IT_LASER | IT_SHOTGUN | IT_UZI | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER));
506                 if(cvar("g_nixnex_with_laser"))
507                         self.items = self.items + IT_LASER;
508                 self.items = self.items - (self.items & weapon_translateindextoflag(nixnex_weapon)) + weapon_translateindextoflag(nixnex_weapon);
509
510                 if(self.switchweapon != nixnex_weapon)
511                         if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
512                                 if(client_hasweapon(self, nixnex_weapon, TRUE, FALSE))
513                                         W_SwitchWeapon(nixnex_weapon);
514         }
515 }
516