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