]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/w_uzi.qc
Set weapons to fully loaded on respawn in each weapon file instead of cl_client....
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / w_uzi.qc
1 #ifdef REGISTER_WEAPON
2 REGISTER_WEAPON(UZI, w_uzi, IT_NAILS, 3, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_MID, "uzi", "uzi", _("Machine Gun"))
3 #else
4 #ifdef SVQC
5
6 void W_UZI_SetAmmoCounter()
7 {
8         // set clip_load to the weapon we have switched to, if the gun uses reloading
9         if(!autocvar_g_balance_uzi_reload_ammo)
10                 self.clip_load = 0; // also keeps crosshair ammo from displaying
11         else
12         {
13                 self.clip_load = self.uzi_load;
14                 self.clip_size = autocvar_g_balance_uzi_reload_ammo; // for the crosshair ammo display
15         }
16 }
17
18 void W_UZI_ReloadedAndReady()
19 {
20         float t;
21
22         // now do the ammo transfer
23         self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
24         while(self.clip_load < autocvar_g_balance_uzi_reload_ammo && self.ammo_nails) // make sure we don't add more ammo than we have
25         {
26                 self.clip_load += 1;
27                 self.ammo_nails -= 1;
28         }
29         self.uzi_load = self.clip_load;
30
31         t = ATTACK_FINISHED(self) - autocvar_g_balance_uzi_reload_time - 1;
32         ATTACK_FINISHED(self) = t;
33         w_ready();
34 }
35
36 void W_UZI_Reload()
37 {
38         // return if reloading is disabled for this weapon
39         if(!autocvar_g_balance_uzi_reload_ammo)
40                 return;
41
42         if(!W_ReloadCheck(self.ammo_nails, min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo)))
43                 return;
44
45         float t;
46
47         sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
48
49         t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_uzi_reload_time + 1;
50         ATTACK_FINISHED(self) = t;
51
52         weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_uzi_reload_time, W_UZI_ReloadedAndReady);
53
54         self.old_clip_load = self.clip_load;
55         self.clip_load = -1;
56 }
57
58 // leilei's fancy muzzleflash stuff
59 void UZI_Flash_Go() 
60 {       
61         self.frame = self.frame + 2;
62         self.scale = self.scale * 0.5;
63         self.alpha = self.alpha - 0.25;
64         self.nextthink = time + 0.05;
65
66         if (self.alpha <= 0)
67         {
68                 self.think = SUB_Remove;
69                 self.nextthink = time;
70                 self.owner.muzzle_flash = world;
71                 return;
72         }
73         
74 }
75
76 void UziFlash()
77 {       
78         if (self.muzzle_flash == world)
79                 self.muzzle_flash = spawn();    
80         
81         // muzzle flash for 1st person view
82         setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below
83         
84         self.muzzle_flash.scale = 0.75;
85         self.muzzle_flash.think = UZI_Flash_Go;
86         self.muzzle_flash.nextthink = time + 0.02;
87         self.muzzle_flash.frame = 2;
88         self.muzzle_flash.alpha = 0.75;
89         self.muzzle_flash.angles_z = random() * 180;
90         self.muzzle_flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
91         self.muzzle_flash.owner = self;
92 }
93
94 void W_UZI_Attack (float deathtype)
95 {
96         W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CHAN_WEAPON, ((self.misc_bulletcounter == 1) ? autocvar_g_balance_uzi_first_damage : autocvar_g_balance_uzi_sustained_damage));
97         if (!g_norecoil)
98         {
99                 self.punchangle_x = random () - 0.5;
100                 self.punchangle_y = random () - 0.5;
101         }
102
103         // this attack_finished just enforces a cooldown at the end of a burst
104         ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor();
105
106         if (self.misc_bulletcounter == 1)
107                 fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_first_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_first_damage, 0, autocvar_g_balance_uzi_first_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant);
108         else
109                 fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_sustained_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, 0, autocvar_g_balance_uzi_sustained_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant);
110         endFireBallisticBullet();
111
112         pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
113
114         UziFlash();
115         W_AttachToShotorg(self.muzzle_flash, '5 0 0');
116
117         // casing code
118         if (autocvar_g_casings >= 2)
119                 SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
120
121         // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
122         if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
123         {
124                 if(autocvar_g_balance_uzi_reload_ammo)
125                 {
126                         if (self.misc_bulletcounter == 1)
127                                 self.clip_load -= autocvar_g_balance_uzi_first_ammo;
128                         else
129                                 self.clip_load -= autocvar_g_balance_uzi_sustained_ammo;
130                         self.uzi_load = self.clip_load;
131                 }
132                 else
133                 {
134                         if (self.misc_bulletcounter == 1)
135                                 self.ammo_nails -= autocvar_g_balance_uzi_first_ammo;
136                         else
137                                 self.ammo_nails -= autocvar_g_balance_uzi_sustained_ammo;
138                 }
139         }
140 }
141
142 // weapon frames
143 void uzi_fire1_02()
144 {
145         if(self.weapon != self.switchweapon) // abort immediately if switching
146         {
147                 w_ready();
148                 return;
149         }
150         if (self.BUTTON_ATCK)
151         {
152                 if (!weapon_action(self.weapon, WR_CHECKAMMO2))
153                 {
154                         W_SwitchWeapon_Force(self, w_getbestweapon(self));
155                         w_ready();
156                         return;
157                 }
158                 self.misc_bulletcounter = self.misc_bulletcounter + 1;
159                 W_UZI_Attack(WEP_UZI);
160                 weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02);
161         }
162         else
163                 weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, w_ready);
164 }
165
166
167 void uzi_mode1_fire_auto()
168 {
169         float uzi_spread;
170
171         // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
172         if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
173         {
174                 if(autocvar_g_balance_uzi_reload_ammo)
175                 {
176                         self.clip_load -= autocvar_g_balance_uzi_sustained_ammo;
177                         self.uzi_load = self.clip_load;
178                 }
179                 else
180                         self.ammo_nails -= autocvar_g_balance_uzi_sustained_ammo;
181         }
182         
183         if (self.BUTTON_ATCK)
184                 weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_mode1_fire_auto);
185         else
186         {
187                 ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor();
188                 weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, w_ready);
189                 return;
190         }
191
192         if (!weapon_action(self.weapon, WR_CHECKAMMO1))
193         {
194                 W_SwitchWeapon_Force(self, w_getbestweapon(self));
195                 w_ready();
196                 return;
197         }
198         
199         W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CHAN_WEAPON, autocvar_g_balance_uzi_sustained_damage);
200         if (!g_norecoil)
201         {
202                 self.punchangle_x = random () - 0.5;
203                 self.punchangle_y = random () - 0.5;
204         }
205         
206         uzi_spread = bound(autocvar_g_balance_uzi_spread_min, autocvar_g_balance_uzi_spread_min + (autocvar_g_balance_uzi_spread_add * self.misc_bulletcounter), autocvar_g_balance_uzi_spread_max);
207         fireBallisticBullet(w_shotorg, w_shotdir, uzi_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, 0, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant);
208         endFireBallisticBullet();
209         
210         self.misc_bulletcounter = self.misc_bulletcounter + 1;
211         
212         pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
213
214         UziFlash();
215         W_AttachToShotorg(self.muzzle_flash, '5 0 0');
216         
217         if (autocvar_g_casings >= 2) // casing code
218                 SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
219 }
220
221 void uzi_mode1_fire_burst()
222 {
223         W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CHAN_WEAPON, autocvar_g_balance_uzi_sustained_damage);
224         if (!g_norecoil)
225         {
226                 self.punchangle_x = random () - 0.5;
227                 self.punchangle_y = random () - 0.5;
228         }
229         
230         fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_burst_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, 0, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant);
231         endFireBallisticBullet();
232         
233         
234         pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
235
236         UziFlash();
237         W_AttachToShotorg(self.muzzle_flash, '5 0 0');
238         
239         if (autocvar_g_casings >= 2) // casing code
240                 SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
241
242         self.misc_bulletcounter = self.misc_bulletcounter + 1;
243         if (self.misc_bulletcounter == 0)
244         {
245                 ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_burst_refire2 * W_WeaponRateFactor();
246                 weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_animtime, w_ready);
247         }
248         else
249         {
250                 weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_refire, uzi_mode1_fire_burst);
251         }
252                 
253 }
254
255 void spawnfunc_weapon_machinegun(); // defined in t_items.qc
256
257 float w_uzi(float req)
258 {
259         float ammo_amount;
260         if (req == WR_AIM)
261                 if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200)
262                         self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
263                 else
264                 {
265                         self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE);
266                 }
267         else if (req == WR_THINK)
268         {
269                 if(autocvar_g_balance_uzi_reload_ammo && self.clip_load < min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo)) // forced reload
270                         W_UZI_Reload();
271                 else if(autocvar_g_balance_uzi_mode == 1)
272                 {
273                         if (self.BUTTON_ATCK)
274                         if (weapon_prepareattack(0, 0))
275                         {                               
276                                 self.misc_bulletcounter = 0;
277                                 uzi_mode1_fire_auto();
278                         }
279                         
280                         if(self.BUTTON_ATCK2)
281                         if(weapon_prepareattack(1, 0))
282                         {
283                                 if (!weapon_action(self.weapon, WR_CHECKAMMO2))
284                                 {
285                                         W_SwitchWeapon_Force(self, w_getbestweapon(self));
286                                         w_ready();
287                                         return FALSE;
288                                 }
289
290                                 // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
291                                 if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
292                                 {
293                                         if(autocvar_g_balance_uzi_reload_ammo)
294                                         {
295                                                 self.clip_load -= autocvar_g_balance_uzi_burst_ammo;
296                                                 self.uzi_load = self.clip_load;
297                                         }
298                                         else
299                                                 self.ammo_nails -= autocvar_g_balance_uzi_burst_ammo;
300                                 }
301
302                                 self.misc_bulletcounter = autocvar_g_balance_uzi_burst * -1;
303                                 uzi_mode1_fire_burst();
304                         }
305                 }
306                 else
307                 {
308                         
309                         if (self.BUTTON_ATCK)
310                         if (weapon_prepareattack(0, 0))
311                         {
312                                 self.misc_bulletcounter = 1;
313                                 W_UZI_Attack(WEP_UZI); // sets attack_finished
314                                 weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02);
315                         }
316
317                         if (self.BUTTON_ATCK2 && autocvar_g_balance_uzi_first)
318                         if (weapon_prepareattack(1, 0))
319                         {
320                                 self.misc_bulletcounter = 1;
321                                 W_UZI_Attack(WEP_UZI | HITTYPE_SECONDARY); // sets attack_finished
322                                 weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_first_refire, w_ready);
323                         }
324                 }
325         }
326         else if (req == WR_PRECACHE)
327         {
328                 precache_model ("models/uziflash.md3");
329                 precache_model ("models/weapons/g_uzi.md3");
330                 precache_model ("models/weapons/v_uzi.md3");
331                 precache_model ("models/weapons/h_uzi.iqm");
332                 precache_sound ("weapons/uzi_fire.wav");
333                 precache_sound ("weapons/reload.wav");
334         }
335         else if (req == WR_SETUP)
336         {
337                 weapon_setup(WEP_UZI);
338                 W_UZI_SetAmmoCounter();
339         }
340         else if (req == WR_CHECKAMMO1)
341         {
342                 if(autocvar_g_balance_uzi_mode == 1)
343                         ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_sustained_ammo;
344                 else
345                         ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo;
346
347                 if(autocvar_g_balance_uzi_reload_ammo)
348                 {
349                         if(autocvar_g_balance_uzi_mode == 1)
350                                 ammo_amount += self.uzi_load >= autocvar_g_balance_uzi_sustained_ammo;
351                         else
352                                 ammo_amount += self.uzi_load >= autocvar_g_balance_uzi_first_ammo;
353                 }
354                 return ammo_amount;
355         }
356         else if (req == WR_CHECKAMMO2)
357         {
358                 if(autocvar_g_balance_uzi_mode == 1)
359                         ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_burst_ammo;
360                 else
361                         ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo;
362
363                 if(autocvar_g_balance_uzi_reload_ammo)
364                 {
365                         if(autocvar_g_balance_uzi_mode == 1)
366                                 ammo_amount += self.uzi_load >= autocvar_g_balance_uzi_burst_ammo;
367                         else
368                                 ammo_amount += self.uzi_load >= autocvar_g_balance_uzi_first_ammo;
369                 }
370                 return ammo_amount;
371         }
372         else if (req == WR_RESETPLAYER)
373         {
374                 // all weapons must be fully loaded when we spawn
375                 self.uzi_load = autocvar_g_balance_uzi_reload_ammo;
376         }
377         else if (req == WR_RELOAD)
378         {
379                 W_UZI_Reload();
380         }
381         return TRUE;
382 };
383 #endif
384 #ifdef CSQC
385 float w_uzi(float req)
386 {
387         if(req == WR_IMPACTEFFECT)
388         {
389                 vector org2;
390                 org2 = w_org + w_backoff * 2;
391                 pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1);
392                 if(!w_issilent)
393                         if(w_random < 0.05)
394                                 sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM);
395                         else if(w_random < 0.1)
396                                 sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM);
397                         else if(w_random < 0.2)
398                                 sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM);
399         }
400         else if(req == WR_PRECACHE)
401         {
402                 precache_sound("weapons/ric1.wav");
403                 precache_sound("weapons/ric2.wav");
404                 precache_sound("weapons/ric3.wav");
405         }
406         else if (req == WR_SUICIDEMESSAGE)
407                 w_deathtypestring = "%s did the impossible";
408         else if (req == WR_KILLMESSAGE)
409         {
410                 if(w_deathtype & HITTYPE_SECONDARY)
411                         w_deathtypestring = "%s was sniped by %s";
412                 else
413                         w_deathtypestring = "%s was riddled full of holes by %s";
414         }
415         return TRUE;
416 }
417 #endif
418 #endif