]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/w_electro.qc
Remove the switchable check and do all checks in the WR_CHECKAMMO checks. Only fixed...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / w_electro.qc
1 #ifdef REGISTER_WEAPON
2 REGISTER_WEAPON(ELECTRO, w_electro, IT_CELLS, 5, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "electro", "electro", _("Electro"));
3 #else
4 #ifdef SVQC
5 .float electro_count;
6 .float electro_secondarytime;
7
8 void W_Electro_SetAmmoCounter()
9 {
10         // set clip_load to the weapon we have switched to, if the gun uses reloading
11         if(!autocvar_g_balance_electro_reload_ammo)
12                 self.clip_load = 0; // also keeps crosshair ammo from displaying
13         else
14         {
15                 self.clip_load = self.electro_load;
16                 self.clip_size = autocvar_g_balance_electro_reload_ammo; // for the crosshair ammo display
17         }
18 }
19
20 void W_Electro_ReloadedAndReady()
21 {
22         float t;
23
24         // now do the ammo transfer
25         self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
26         while(self.clip_load < autocvar_g_balance_electro_reload_ammo && self.ammo_cells) // make sure we don't add more ammo than we have
27         {
28                 self.clip_load += 1;
29                 self.ammo_cells -= 1;
30         }
31         self.electro_load = self.clip_load;
32
33         t = ATTACK_FINISHED(self) - autocvar_g_balance_electro_reload_time - 1;
34         ATTACK_FINISHED(self) = t;
35         w_ready();
36 }
37
38 void W_Electro_Reload()
39 {
40         // return if reloading is disabled for this weapon
41         if(!autocvar_g_balance_electro_reload_ammo)
42                 return;
43
44         if(!W_ReloadCheck(self.ammo_cells, min(autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_secondary_ammo)))
45                 return;
46
47         float t;
48
49         sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
50
51         t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_electro_reload_time + 1;
52         ATTACK_FINISHED(self) = t;
53
54         weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_electro_reload_time, W_Electro_ReloadedAndReady);
55
56         self.old_clip_load = self.clip_load;
57         self.clip_load = -1;
58 }
59
60 void W_Plasma_Explode_Combo (void);
61
62 void W_Plasma_TriggerCombo(vector org, float rad, entity own)
63 {
64         local entity e;
65         e = WarpZone_FindRadius(org, rad, TRUE);
66         while (e)
67         {
68                 if (e.classname == "plasma")
69                 {
70                         // change owner to whoever caused the combo explosion
71                         e.owner = own;
72                         e.takedamage = DAMAGE_NO;
73                         e.classname = "plasma_chain";
74                         e.think = W_Plasma_Explode_Combo;
75                         e.nextthink = time + vlen(e.WarpZone_findradius_dist) / autocvar_g_balance_electro_combo_speed; // delay combo chains, looks cooler
76                 }
77                 e = e.chain;
78         }
79 }
80
81 void W_Plasma_Explode (void)
82 {
83         if(other.takedamage == DAMAGE_AIM)
84                 if(other.classname == "player")
85                         if(IsDifferentTeam(self.owner, other))
86                                 if(other.deadflag == DEAD_NO)
87                                         if(IsFlying(other))
88                                                 AnnounceTo(self.owner, "electrobitch");
89
90         self.event_damage = SUB_Null;
91         self.takedamage = DAMAGE_NO;
92         if (self.movetype == MOVETYPE_BOUNCE)
93         {
94                 RadiusDamage (self, self.owner, autocvar_g_balance_electro_secondary_damage, autocvar_g_balance_electro_secondary_edgedamage, autocvar_g_balance_electro_secondary_radius, world, autocvar_g_balance_electro_secondary_force, self.projectiledeathtype, other);
95         }
96         else
97         {
98                 W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_primary_comboradius, self.owner);
99                 RadiusDamage (self, self.owner, autocvar_g_balance_electro_primary_damage, autocvar_g_balance_electro_primary_edgedamage, autocvar_g_balance_electro_primary_radius, world, autocvar_g_balance_electro_primary_force, self.projectiledeathtype, other);
100         }
101
102         remove (self);
103 }
104
105 void W_Plasma_Explode_Combo (void)
106 {
107         W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_combo_comboradius, self.owner);
108
109         self.event_damage = SUB_Null;
110         RadiusDamage (self, self.owner, autocvar_g_balance_electro_combo_damage, autocvar_g_balance_electro_combo_edgedamage, autocvar_g_balance_electro_combo_radius, world, autocvar_g_balance_electro_combo_force, WEP_ELECTRO | HITTYPE_BOUNCE, world); // use THIS type for a combo because primary can't bounce
111         remove (self);
112 }
113
114 void W_Plasma_Touch (void)
115 {
116         //self.velocity = self.velocity  * 0.1;
117
118         PROJECTILE_TOUCH;
119         if (other.takedamage == DAMAGE_AIM) {
120                 W_Plasma_Explode ();
121         } else {
122                 //UpdateCSQCProjectile(self);
123                 spamsound (self, CHAN_PROJECTILE, "weapons/electro_bounce.wav", VOL_BASE, ATTN_NORM);
124                 self.projectiledeathtype |= HITTYPE_BOUNCE;
125         }
126 }
127
128 void W_Plasma_TouchExplode (void)
129 {
130         PROJECTILE_TOUCH;
131         W_Plasma_Explode ();
132 }
133
134 void W_Plasma_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
135 {
136         if(self.health <= 0)
137                 return;
138         // note: combos are usually triggered by W_Plasma_TriggerCombo, not damage
139         self.health = self.health - damage;
140         if (self.health <= 0)
141         {
142                 self.takedamage = DAMAGE_NO;
143                 self.nextthink = time;
144                 if (inflictor.classname == "plasma_chain" || inflictor.classname == "plasma_prim")
145                 {
146                         // change owner to whoever caused the combo explosion
147                         self.owner = inflictor.owner;
148                         self.classname = "plasma_chain";
149                         self.think = W_Plasma_Explode_Combo;
150                         self.nextthink = time + min(autocvar_g_balance_electro_combo_radius, vlen(self.origin - inflictor.origin)) / autocvar_g_balance_electro_combo_speed; // delay combo chains, looks cooler
151                                 //                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bounding the length, because inflictor may be in a galaxy far far away (warpzones)
152                 }
153                 else
154                 {
155                         self.use = W_Plasma_Explode;
156                         self.think = adaptor_think2use; // not _hittype_splash, as this runs "immediately"
157                 }
158         }
159 }
160
161 void W_Electro_Attack()
162 {
163         local entity proj;
164
165         // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
166         if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
167         {
168                 if(autocvar_g_balance_electro_reload_ammo)
169                 {
170                         self.clip_load -= autocvar_g_balance_electro_primary_ammo;
171                         self.electro_load = self.clip_load;
172                 }
173                 else
174                         self.ammo_cells -= autocvar_g_balance_electro_primary_ammo;
175         }
176
177         W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', FALSE, 2, "weapons/electro_fire.wav", CHAN_WEAPON, autocvar_g_balance_electro_primary_damage);
178
179         pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
180
181         proj = spawn ();
182         proj.classname = "plasma_prim";
183         proj.owner = self;
184         proj.bot_dodge = TRUE;
185         proj.bot_dodgerating = autocvar_g_balance_electro_primary_damage;
186         proj.use = W_Plasma_Explode;
187         proj.think = adaptor_think2use_hittype_splash;
188         proj.nextthink = time + autocvar_g_balance_electro_primary_lifetime;
189         PROJECTILE_MAKETRIGGER(proj);
190         proj.projectiledeathtype = WEP_ELECTRO;
191         setorigin(proj, w_shotorg);
192
193         proj.movetype = MOVETYPE_FLY;
194         W_SETUPPROJECTILEVELOCITY(proj, g_balance_electro_primary);
195         proj.angles = vectoangles(proj.velocity);
196         proj.touch = W_Plasma_TouchExplode;
197         setsize(proj, '0 0 -3', '0 0 -3');
198         proj.flags = FL_PROJECTILE;
199
200         //sound (proj, CHAN_PAIN, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM);
201         //sounds bad
202
203         CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
204
205         other = proj; MUTATOR_CALLHOOK(EditProjectile);
206 }
207
208 void W_Electro_Attack2()
209 {
210         local entity proj;
211
212         // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
213         if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
214         {
215                 if(autocvar_g_balance_electro_reload_ammo)
216                 {
217                         self.clip_load -= autocvar_g_balance_electro_secondary_ammo;
218                         self.electro_load = self.clip_load;
219                 }
220                 else
221                         self.ammo_cells -= autocvar_g_balance_electro_secondary_ammo;
222         }
223
224         W_SetupShot_ProjectileSize (self, '0 0 -4', '0 0 -4', FALSE, 2, "weapons/electro_fire2.wav", CHAN_WEAPON, autocvar_g_balance_electro_secondary_damage);
225
226         w_shotdir = v_forward; // no TrueAim for grenades please
227
228         pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
229
230         proj = spawn ();
231         proj.classname = "plasma";
232         proj.owner = self;
233         proj.use = W_Plasma_Explode;
234         proj.think = adaptor_think2use_hittype_splash;
235         proj.bot_dodge = TRUE;
236         proj.bot_dodgerating = autocvar_g_balance_electro_secondary_damage;
237         proj.nextthink = time + autocvar_g_balance_electro_secondary_lifetime;
238         PROJECTILE_MAKETRIGGER(proj);
239         proj.projectiledeathtype = WEP_ELECTRO | HITTYPE_SECONDARY;
240         setorigin(proj, w_shotorg);
241
242         //proj.glow_size = 50;
243         //proj.glow_color = 45;
244         proj.movetype = MOVETYPE_BOUNCE;
245         W_SETUPPROJECTILEVELOCITY_UP(proj, g_balance_electro_secondary);
246         proj.touch = W_Plasma_Touch;
247         setsize(proj, '0 0 -4', '0 0 -4');
248         proj.takedamage = DAMAGE_YES;
249         proj.damageforcescale = autocvar_g_balance_electro_secondary_damageforcescale;
250         proj.health = autocvar_g_balance_electro_secondary_health;
251         proj.event_damage = W_Plasma_Damage;
252         proj.flags = FL_PROJECTILE;
253
254         proj.bouncefactor = autocvar_g_balance_electro_secondary_bouncefactor;
255         proj.bouncestop = autocvar_g_balance_electro_secondary_bouncestop;
256
257 #if 0
258         entity p2;
259         p2 = spawn();
260         copyentity(proj, p2);
261         setmodel(p2, "models/ebomb.mdl");
262         setsize(p2, proj.mins, proj.maxs);
263 #endif
264
265         CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO, FALSE); // no culling, it has sound
266
267         other = proj; MUTATOR_CALLHOOK(EditProjectile);
268 }
269
270 .vector hook_start, hook_end;
271 float lgbeam_send(entity to, float sf)
272 {
273         WriteByte(MSG_ENTITY, ENT_CLIENT_LGBEAM);
274         sf = sf & 0x7F;
275         if(sound_allowed(MSG_BROADCAST, self.owner))
276                 sf |= 0x80;
277         WriteByte(MSG_ENTITY, sf);
278         if(sf & 1)
279         {
280                 WriteByte(MSG_ENTITY, num_for_edict(self.owner));
281                 WriteCoord(MSG_ENTITY, autocvar_g_balance_electro_primary_range);
282         }
283         if(sf & 2)
284         {
285                 WriteCoord(MSG_ENTITY, self.hook_start_x);
286                 WriteCoord(MSG_ENTITY, self.hook_start_y);
287                 WriteCoord(MSG_ENTITY, self.hook_start_z);
288         }
289         if(sf & 4)
290         {
291                 WriteCoord(MSG_ENTITY, self.hook_end_x);
292                 WriteCoord(MSG_ENTITY, self.hook_end_y);
293                 WriteCoord(MSG_ENTITY, self.hook_end_z);
294         }
295         return TRUE;
296 }
297 .entity lgbeam;
298 .float prevlgfire;
299 float lgbeam_checkammo()
300 {
301         if(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)
302                 return TRUE;
303         else if(autocvar_g_balance_electro_reload_ammo)
304                 return self.owner.clip_load > 0;
305         else
306                 return self.owner.ammo_cells > 0;
307 }
308
309 void lgbeam_think()
310 {
311         self.owner.prevlgfire = time;
312         if (self != self.owner.lgbeam)
313         {
314                 remove(self);
315                 return;
316         }
317
318         if (self.owner.weaponentity.state != WS_INUSE || !lgbeam_checkammo() || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK || self.owner.freezetag_frozen)
319         {
320                 if(self == self.owner.lgbeam)
321                         self.owner.lgbeam = world;
322                 remove(self);
323                 return;
324         }
325
326         self.nextthink = time;
327
328         makevectors(self.owner.v_angle);
329
330         float dt, f;
331         dt = frametime;
332         // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
333         if not(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)
334         {
335                 if(autocvar_g_balance_electro_primary_ammo)
336                 {
337                         if(autocvar_g_balance_electro_reload_ammo)
338                         {
339                                 dt = min(dt, self.owner.clip_load / autocvar_g_balance_electro_primary_ammo);
340                                 self.owner.clip_load = max(0, self.owner.clip_load - autocvar_g_balance_electro_primary_ammo * frametime);
341                                 self.owner.electro_load = self.owner.clip_load;
342                         }
343                         else
344                         {
345                                 dt = min(dt, self.owner.ammo_cells / autocvar_g_balance_electro_primary_ammo);
346                                 self.owner.ammo_cells = max(0, self.owner.ammo_cells - autocvar_g_balance_electro_primary_ammo * frametime);
347                         }
348                 }
349         }
350
351         W_SetupShot_Range(self.owner, TRUE, 0, "", 0, autocvar_g_balance_electro_primary_damage * dt, autocvar_g_balance_electro_primary_range);
352         WarpZone_traceline_antilag(self.owner, w_shotorg, w_shotend, MOVE_NORMAL, self.owner, ANTILAG_LATENCY(self.owner));
353
354         // apply the damage
355         if(trace_ent)
356         {
357                 vector force;
358                 force = w_shotdir * autocvar_g_balance_electro_primary_force + '0 0 1' * autocvar_g_balance_electro_primary_force_up;
359
360                 f = ExponentialFalloff(autocvar_g_balance_electro_primary_falloff_mindist, autocvar_g_balance_electro_primary_falloff_maxdist, autocvar_g_balance_electro_primary_falloff_halflifedist, vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - w_shotorg));
361
362                 if(accuracy_isgooddamage(self.owner, trace_ent))
363                         accuracy_add(self.owner, WEP_ELECTRO, 0, autocvar_g_balance_electro_primary_damage * dt * f);
364                 Damage (trace_ent, self.owner, self.owner, autocvar_g_balance_electro_primary_damage * dt * f, WEP_ELECTRO, trace_endpos, force * dt);
365         }
366         W_Plasma_TriggerCombo(trace_endpos, autocvar_g_balance_electro_primary_comboradius, self.owner);
367
368         // draw effect
369         if(w_shotorg != self.hook_start)
370         {
371                 self.SendFlags |= 2;
372                 self.hook_start = w_shotorg;
373         }
374         if(w_shotend != self.hook_end)
375         {
376                 self.SendFlags |= 4;
377                 self.hook_end = w_shotend;
378         }
379 }
380
381 // experimental lightning gun
382 void W_Electro_Attack3 (void)
383 {
384         // only play fire sound if 0.5 sec has passed since player let go the fire button
385         if(time - self.prevlgfire > 0.5)
386                 sound (self, CHAN_WEAPON, "weapons/lgbeam_fire.wav", VOL_BASE, ATTN_NORM);
387
388         entity beam, oldself;
389
390         self.lgbeam = beam = spawn();
391         beam.classname = "lgbeam";
392         beam.solid = SOLID_NOT;
393         beam.think = lgbeam_think;
394         beam.owner = self;
395         beam.movetype = MOVETYPE_NONE;
396         beam.shot_spread = 0;
397         beam.bot_dodge = TRUE;
398         beam.bot_dodgerating = autocvar_g_balance_electro_primary_damage;
399         Net_LinkEntity(beam, FALSE, 0, lgbeam_send);
400
401         oldself = self;
402         self = beam;
403         self.think();
404         self = oldself;
405 }
406
407 void ElectroInit()
408 {
409         weapon_action(WEP_ELECTRO, WR_PRECACHE);
410         electro_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ELECTRO), FALSE, FALSE, 1);
411         electro_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ELECTRO), FALSE, FALSE, 2);
412         electro_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ELECTRO), FALSE, FALSE, 3);
413         electro_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ELECTRO), FALSE, FALSE, 4);
414 }
415
416 void spawnfunc_weapon_electro (void)
417 {
418         weapon_defaultspawnfunc(WEP_ELECTRO);
419 }
420
421 void w_electro_checkattack()
422 {
423         if(self.electro_count > 1)
424         if(self.BUTTON_ATCK2)
425         if(weapon_prepareattack(1, -1))
426         {
427                 W_Electro_Attack2();
428                 self.electro_count -= 1;
429                 weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_electro_secondary_animtime, w_electro_checkattack);
430                 return;
431         }
432
433         w_ready();
434 }
435
436 .float bot_secondary_electromooth;
437 .float BUTTON_ATCK_prev;
438 float w_electro(float req)
439 {
440         if (req == WR_AIM)
441         {
442                 self.BUTTON_ATCK=FALSE;
443                 self.BUTTON_ATCK2=FALSE;
444                 if(vlen(self.origin-self.enemy.origin) > 1000)
445                         self.bot_secondary_electromooth = 0;
446                 if(self.bot_secondary_electromooth == 0)
447                 {
448                         float shoot;
449
450                         if(autocvar_g_balance_electro_primary_speed)
451                                 shoot = bot_aim(autocvar_g_balance_electro_primary_speed, 0, autocvar_g_balance_electro_primary_lifetime, FALSE);
452                         else
453                                 shoot = bot_aim(1000000, 0, 0.001, FALSE);
454
455                         if(shoot)
456                         {
457                                 self.BUTTON_ATCK = TRUE;
458                                 if(random() < 0.01) self.bot_secondary_electromooth = 1;
459                         }
460                 }
461                 else
462                 {
463                         if(bot_aim(autocvar_g_balance_electro_secondary_speed, autocvar_g_balance_grenadelauncher_secondary_speed_up, autocvar_g_balance_electro_secondary_lifetime, TRUE))
464                         {
465                                 self.BUTTON_ATCK2 = TRUE;
466                                 if(random() < 0.03) self.bot_secondary_electromooth = 0;
467                         }
468                 }
469         }
470         else if (req == WR_THINK)
471         {
472                 if(autocvar_g_balance_electro_reload_ammo && self.clip_load < min(autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_secondary_ammo)) // forced reload
473                         W_Electro_Reload();
474                 else if (self.BUTTON_ATCK)
475                 {
476                         if(autocvar_g_balance_electro_lightning)
477                                 if(self.BUTTON_ATCK_prev)
478                                 {
479                                         // prolong the animtime while the gun is being fired
480                                         if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y)
481                                                 weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_electro_primary_animtime, w_ready);
482                                         else
483                                                 weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready);
484                                 }
485                         if (weapon_prepareattack(0, (autocvar_g_balance_electro_lightning ? 0 : autocvar_g_balance_electro_primary_refire)))
486                         {
487                                 if(autocvar_g_balance_electro_lightning)
488                                 {
489                                         if ((!self.lgbeam) || wasfreed(self.lgbeam))
490                                         {
491                                                 W_Electro_Attack3();
492                                         }
493                                         if(!self.BUTTON_ATCK_prev)
494                                         {
495                                                 weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready);
496                                                 self.BUTTON_ATCK_prev = 1;
497                                         }
498                                 }
499                                 else
500                                 {
501                                         W_Electro_Attack();
502                                         weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready);
503                                 }
504                         }
505                 } else {
506                         if(autocvar_g_balance_electro_lightning)
507                         {
508                                 if (self.BUTTON_ATCK_prev != 0)
509                                 {
510                                         weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready);
511                                         ATTACK_FINISHED(self) = time + autocvar_g_balance_electro_primary_refire * W_WeaponRateFactor();
512                                 }
513                                 self.BUTTON_ATCK_prev = 0;
514                         }
515
516                         if (self.BUTTON_ATCK2)
517                         {
518                                 if (time >= self.electro_secondarytime)
519                                 if (weapon_prepareattack(1, autocvar_g_balance_electro_secondary_refire))
520                                 {
521                                         W_Electro_Attack2();
522                                         self.electro_count = autocvar_g_balance_electro_secondary_count;
523                                         weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_electro_secondary_animtime, w_electro_checkattack);
524                                         self.electro_secondarytime = time + autocvar_g_balance_electro_secondary_refire2 * W_WeaponRateFactor();
525                                 }
526                         }
527                 }
528
529         if(self.wish_reload)
530         {
531             if(self.switchweapon == self.weapon)
532             {
533                 if(self.weaponentity.state == WS_READY)
534                 {
535                     self.wish_reload = 0;
536                     W_Electro_Reload();
537                 }
538             }
539         }
540         }
541         else if (req == WR_PRECACHE)
542         {
543                 precache_model ("models/weapons/g_electro.md3");
544                 precache_model ("models/weapons/v_electro.md3");
545                 precache_model ("models/weapons/h_electro.iqm");
546                 precache_sound ("weapons/electro_bounce.wav");
547                 precache_sound ("weapons/electro_fire.wav");
548                 precache_sound ("weapons/electro_fire2.wav");
549                 precache_sound ("weapons/electro_impact.wav");
550                 precache_sound ("weapons/electro_impact_combo.wav");
551                 precache_sound ("weapons/reload.wav");
552                 if(autocvar_g_balance_electro_lightning)
553                 {
554                         precache_sound ("weapons/lgbeam_fire.wav");
555                 }
556         }
557         else if (req == WR_SETUP)
558         {
559                 weapon_setup(WEP_ELECTRO);
560                 W_Electro_SetAmmoCounter();
561         }
562         else if (req == WR_CHECKAMMO1)
563         {
564                 if(autocvar_g_balance_electro_reload_ammo)
565                 {
566                         if(autocvar_g_balance_electro_lightning)
567                                 return !autocvar_g_balance_electro_primary_ammo || (self.electro_load > 0);
568                         else
569                                 return self.electro_load >= autocvar_g_balance_electro_primary_ammo;
570                 }
571                 else
572                 {
573                         if(autocvar_g_balance_electro_lightning)
574                                 return !autocvar_g_balance_electro_primary_ammo || (self.ammo_cells > 0);
575                         else
576                                 return self.ammo_cells >= autocvar_g_balance_electro_primary_ammo;
577                 }
578         }
579         else if (req == WR_CHECKAMMO2)
580         {
581                 if(autocvar_g_balance_electro_reload_ammo)
582                         return self.electro_load >= autocvar_g_balance_electro_secondary_ammo;
583                 else
584                         return self.ammo_cells >= autocvar_g_balance_electro_secondary_ammo;
585         }
586         else if (req == WR_RESETPLAYER)
587         {
588                 self.electro_secondarytime = time;
589         }
590         else if (req == WR_RELOAD)
591         {
592                 W_Shotgun_Reload();
593         }
594         return TRUE;
595 };
596 #endif
597 #ifdef CSQC
598 float w_electro(float req)
599 {
600         if(req == WR_IMPACTEFFECT)
601         {
602                 vector org2;
603                 org2 = w_org + w_backoff * 6;
604                 if(w_deathtype & HITTYPE_SECONDARY)
605                 {
606                         pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1);
607                         if(!w_issilent)
608                                 sound(self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
609                 }
610                 else
611                 {
612                         if(w_deathtype & HITTYPE_BOUNCE)
613                         {
614                                 // this is sent as "primary (w_deathtype & HITTYPE_BOUNCE)" to distinguish it from (w_deathtype & HITTYPE_SECONDARY) bounced balls
615                                 pointparticles(particleeffectnum("electro_combo"), org2, '0 0 0', 1);
616                                 if(!w_issilent)
617                                         sound(self, CHAN_PROJECTILE, "weapons/electro_impact_combo.wav", VOL_BASE, ATTN_NORM);
618                         }
619                         else
620                         {
621                                 pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1);
622                                 if(!w_issilent)
623                                         sound(self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
624                         }
625                 }
626         }
627         else if(req == WR_PRECACHE)
628         {
629                 precache_sound("weapons/electro_impact.wav");
630                 precache_sound("weapons/electro_impact_combo.wav");
631         }
632         else if (req == WR_SUICIDEMESSAGE)
633         {
634                 if(w_deathtype & HITTYPE_SECONDARY)
635                         w_deathtypestring = "%s could not remember where they put plasma";
636                 else
637                         w_deathtypestring = "%s played with plasma";
638         }
639         else if (req == WR_KILLMESSAGE)
640         {
641                 if(w_deathtype & HITTYPE_SECONDARY)
642                 {
643                         if(w_deathtype & HITTYPE_SPLASH) // unchecked: BOUNCE
644                                 w_deathtypestring = "%s just noticed %s's blue ball";
645                         else // unchecked: BOUNCE
646                                 w_deathtypestring = "%s got in touch with %s's blue ball";
647                 }
648                 else
649                 {
650                         if(w_deathtype & HITTYPE_BOUNCE) // combo
651                                 w_deathtypestring = "%s felt the electrifying air of %s's combo";
652                         else if(w_deathtype & HITTYPE_SPLASH)
653                                 w_deathtypestring = "%s got too close to %s's blue beam";
654                         else
655                                 w_deathtypestring = "%s was blasted by %s's blue beam";
656                 }
657         }
658         return TRUE;
659 }
660 #endif
661 #endif