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