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