]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/server/gamec/cl_weapons.c
- version number in FAQ is now 1.5
[divverent/nexuiz.git] / qcsrc / server / gamec / cl_weapons.c
1 // generic weapons table
2 // add new weapons here
3 void(float wpn, float wrequest) weapon_action =
4 {
5         if (wpn == WEP_LASER)
6                 w_laser(wrequest);
7         else if (wpn == WEP_SHOTGUN)
8                 w_shotgun(wrequest);
9         else if (wpn == WEP_UZI)
10                 w_uzi(wrequest);
11         else if (wpn == WEP_GRENADE_LAUNCHER)
12                 w_glauncher(wrequest);
13         else if (wpn == WEP_ELECTRO)
14                 w_electro(wrequest);
15         else if (wpn == WEP_CRYLINK)
16                 w_crylink(wrequest);
17         else if (wpn == WEP_NEX)
18                 w_nex(wrequest);
19         else if (wpn == WEP_HAGAR)
20                 w_hagar(wrequest);
21         else if (wpn == WEP_ROCKET_LAUNCHER)
22                 w_rlauncher(wrequest);
23 };
24
25 // think function for tossed weapons
26 void() thrown_wep_think =
27 {
28         self.solid = SOLID_TRIGGER;
29         SUB_SetFade(self, time + 20, 1);
30         setorigin(self, self.origin);
31 };
32
33 // toss current weapon
34 void() W_ThrowWeapon
35 {
36         local float w;
37         local entity wep, e;
38
39         e = self;
40         wep = spawn();
41         self = wep;
42         w = e.weapon;
43         setorigin(wep, e.origin);
44         makevectors(e.angles);
45         wep.classname = "droppedweapon";
46         wep.velocity = e.velocity * 0.5 + v_forward * 750;
47         SUB_SetFade(wep, time + 20, 1);
48
49         if(w == WEP_SHOTGUN)
50         {
51                 w = IT_SHOTGUN;
52                 if(!(e.items & w))
53                 {
54                         remove(wep);
55                         return;
56                 }
57                 weapon_shotgun();
58                 wep.ammo_shells = 1;
59                 e.ammo_shells -= 1;
60         }
61         else if(w == WEP_UZI)
62         {
63                 w = IT_UZI;
64                 if(!(e.items & w))
65                 {
66                         remove(wep);
67                         return;
68                 }
69                 weapon_uzi();
70                 wep.ammo_nails = 1;
71                 e.ammo_nails -= 1;
72         }
73         else if(w == WEP_GRENADE_LAUNCHER)
74         {
75                 w = IT_GRENADE_LAUNCHER;
76                 if(!(e.items & w))
77                 {
78                         remove(wep);
79                         return;
80                 }
81                 weapon_grenadelauncher();
82                 wep.ammo_rockets = 1;
83                 e.ammo_rockets -= 1;
84         }
85         else if(w == WEP_ELECTRO)
86         {
87                 w = IT_ELECTRO;
88                 if(!(e.items & w))
89                 {
90                         remove(wep);
91                         return;
92                 }
93                 weapon_electro();
94                 wep.ammo_cells = 1;
95                 e.ammo_cells -= 1;
96         }
97         else if(w == WEP_CRYLINK)
98         {
99                 w = IT_CRYLINK;
100                 if(!(e.items & w))
101                 {
102                         remove(wep);
103                         return;
104                 }
105                 weapon_crylink();
106                 wep.ammo_cells = 1;
107                 e.ammo_cells -= 1;
108         }
109         else if(w == WEP_NEX)
110         {
111                 w = IT_NEX;
112                 if(!(e.items & w))
113                 {
114                         remove(wep);
115                         return;
116                 }
117                 weapon_nex();
118                 wep.ammo_cells = 1;
119                 e.ammo_cells -= 1;
120         }
121         else if(w == WEP_HAGAR)
122         {
123                 w = IT_HAGAR;
124                 if(!(e.items & w))
125                 {
126                         remove(wep);
127                         return;
128                 }
129                 weapon_hagar();
130                 wep.ammo_rockets = 1;
131                 e.ammo_rockets -= 1;
132         }
133         else if(w == WEP_ROCKET_LAUNCHER)
134         {
135                 w = IT_ROCKET_LAUNCHER;
136                 if(!(e.items & w))
137                 {
138                         remove(wep);
139                         return;
140                 }
141                 weapon_rocketlauncher();
142                 wep.ammo_rockets = 1;
143                 e.ammo_rockets -= 1;
144         }
145
146         if(e.items & w)
147                 sprint(e, strcat("You dropped the ^2", wep.netname, "\n"));
148         wep.solid = SOLID_NOT;
149         setorigin(wep, wep.origin);
150         wep.nextthink = time + 0.25;
151         wep.think = thrown_wep_think;
152         wep.classname = "droppedweapon";
153         e.items = e.items - (e.items & w);
154         e.switchweapon = w_getbestweapon(e);
155         self = e;
156 };
157
158 // switch between weapons
159 void(float imp) W_SwitchWeapon
160 {
161         weapon_hasammo = TRUE;
162         if (!client_hasweapon(self, imp, TRUE))
163         {
164                 if (!weapon_hasammo)
165                         sprint(self, "You don't have any ammo for that weapon\n");
166                 else
167                         sprint(self, "You don't own that weapon\n");
168         }
169         else
170         {
171                 self.cnt = self.weapon;
172                 self.switchweapon = imp;
173         }
174 };
175
176 // next weapon
177 void() W_NextWeapon =
178 {
179         local float weaponwant, maxtries;
180
181         maxtries = WEP_LAST;
182
183         weaponwant = self.switchweapon + 1;
184         if (weaponwant < WEP_FIRST)
185                 weaponwant = WEP_LAST;
186         if (weaponwant > WEP_LAST)
187                 weaponwant = WEP_FIRST;
188         weapon_hasammo = TRUE;
189         while(!client_hasweapon(self, weaponwant, TRUE))
190         {
191                 if(!maxtries)
192                         return;
193                 
194                 maxtries -= 1;
195                 weaponwant = weaponwant + 1;
196                 if (weaponwant < WEP_FIRST)
197                         weaponwant = WEP_LAST;
198                 if (weaponwant > WEP_LAST)
199                         weaponwant = WEP_FIRST;
200         }
201         self.cnt = self.weapon;
202         self.switchweapon = weaponwant;
203 };
204
205 // prev weapon
206 void() W_PreviousWeapon =
207 {
208         local float weaponwant, maxtries;
209
210         maxtries = WEP_LAST;
211         
212         weaponwant = self.switchweapon - 1;
213         if (weaponwant < WEP_FIRST)
214                 weaponwant = WEP_LAST;
215         if (weaponwant > WEP_LAST)
216                 weaponwant = WEP_FIRST;
217         weapon_hasammo = TRUE;
218         while(!client_hasweapon(self, weaponwant, TRUE))
219         {
220                 if(!maxtries)
221                         return;
222                         
223                 maxtries -= 1;
224                 weaponwant = weaponwant - 1;
225                 if (weaponwant < WEP_FIRST)
226                         weaponwant = WEP_LAST;
227                 if (weaponwant > WEP_LAST)
228                         weaponwant = WEP_FIRST;
229         }
230         self.cnt = self.weapon;
231         self.switchweapon = weaponwant;
232 };
233
234 // Bringed back weapon frame
235 void() W_WeaponFrame =
236 {
237         if (!self.weaponentity || self.health <= 0)
238                 return; // Dead player can't use weapons and injure impulse commands
239
240         makevectors(self.v_angle);
241
242         // Change weapon
243         if (self.weapon != self.switchweapon)
244         {
245                 if (self.weaponentity.state == WS_CLEAR)
246                 {
247                         self.weaponentity.state = WS_RAISE;
248                         weapon_action(self.switchweapon, WR_SETUP);
249                         // VorteX: add player model weapon select frame here
250                         // setcustomframe(PlayerWeaponRaise);
251                         weapon_action(self.weapon, WR_UPDATECOUNTS);
252                         weapon_action(self.weapon, WR_RAISE);
253                 }
254                 else if (self.weaponentity.state == WS_READY)
255                 {
256                         sound (self, CHAN_WEAPON, "weapons/weapon_switch.ogg", 1, ATTN_NORM);
257                         self.weaponentity.state = WS_DROP;
258                         // VorteX: add player model weapon deselect frame here
259                         // setcustomframe(PlayerWeaponDrop);
260                         weapon_action(self.weapon, WR_DROP);
261                 }
262         }
263
264         if (self.button0)
265                 weapon_action(self.weapon, WR_FIRE1);
266         if (self.button3)
267                 weapon_action(self.weapon, WR_FIRE2);
268
269         // do weapon think
270         if (time >= self.weapon_nextthink)
271                 if (self.weapon_nextthink > 0)
272                         self.weapon_think();
273
274         // weapon bobbing and script actions
275         local float bobintensity, q1pitching, framespeed, diff;
276         local vector vel, realorg, layer1, boblayer;
277
278         bobintensity = cvar("g_viewweapon_bobintensity"); // weapon bob intensity
279         q1pitching = fabs(cvar("g_viewweapon_q1pitching")); // q1 style of "bob" when looking up and down
280
281         realorg = self.weaponentity.origin + self.weaponentity.view_ofs;
282         realorg = realorg - self.weaponentity.finaldest; // finaldest is last bob position
283
284         // VorteX: actually this is needed for weapon screen offset
285         if (q1pitching)
286         {
287                 self.weaponentity.view_ofs_x = q1pitching*bound(-5.5, self.v_angle_x/45, 5.5);
288                 self.weaponentity.view_ofs_z = q1pitching*bound(-1.5, self.v_angle_x/60, 1.5);
289         }
290
291         // weapon origin interpolation, layer 1
292         if (realorg != self.weaponentity.pos1)
293         {
294                 framespeed = frametime*self.weaponentity.lip*10; // lip is speed of origin changing (of layer1)
295                 diff = vlen(realorg - self.weaponentity.pos1);
296                 // VorteX: add speed modifier (haste)?
297                 layer1 = frametime*10*self.weaponentity.lip*normalize(self.weaponentity.pos1 - realorg);
298                 if (diff <= vlen(layer1))
299                         layer1 = normalize(self.weaponentity.pos1 - realorg)*diff;
300         }
301
302         // weapon bobbing (q3-style)
303         if (self.flags & FL_ONGROUND && self.waterlevel < 2)
304         {
305                 // VorteX: only xy velocity matters
306                 vel_x = self.velocity_x;
307                 vel_y = self.velocity_y;
308                 framespeed = vlen(vel);
309                 // Y axis
310                 diff = bobintensity*framespeed/300;
311                 self.weaponentity.destvec_y = self.weaponentity.destvec_y + frametime*10;
312                 boblayer_y = diff*cos(self.weaponentity.destvec_y + 90);
313                 // Z axis
314                 diff = bobintensity*framespeed/540;
315                 self.weaponentity.destvec_z = self.weaponentity.destvec_z + frametime*20;
316                 boblayer_z = diff*cos(self.weaponentity.destvec_z);
317                 self.weaponentity.finaldest = boblayer;
318         }
319         else if (self.waterlevel > 0)
320         {// swim, all velocity matters
321                 // X axis
322                 framespeed = vlen(self.velocity);
323                 diff = bobintensity*framespeed/100;
324                 self.weaponentity.destvec_x = self.weaponentity.destvec_x + frametime*6;
325                 boblayer_x = diff*cos(self.weaponentity.destvec_x);
326                 self.weaponentity.finaldest = boblayer;
327         }
328         else
329                 self.weaponentity.finaldest = '0 0 0';
330         self.weaponentity.origin = realorg + boblayer + layer1 - self.weaponentity.view_ofs;
331 };