]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Lyberta/StandaloneOverkillWeapons
authorLyberta <lyberta@lyberta.net>
Sat, 17 Feb 2018 05:43:10 +0000 (08:43 +0300)
committerLyberta <lyberta@lyberta.net>
Sat, 17 Feb 2018 05:43:10 +0000 (08:43 +0300)
1  2 
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/overkill/hmg.qc
qcsrc/common/mutators/mutator/overkill/okmachinegun.qc
qcsrc/common/mutators/mutator/overkill/oknex.qc
qcsrc/common/mutators/mutator/overkill/okshotgun.qc
qcsrc/common/mutators/mutator/overkill/rpc.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/wepent.qc
qcsrc/server/client.qc
qcsrc/server/defs.qh

index d4b061044ec617fca8ca8f99ca9151d6839f290a,f48a5d9e9500877599766082243dfc4afcd98cac..2b63a10e8ba0e0e984b46c05101e3241107e5757
@@@ -1,7 -1,5 +1,7 @@@
  #include "nades.qh"
  
 +#include "../overkill/okmachinegun.qh"
 +
  #ifdef SVQC
  bool autocvar_g_nades_nade_small;
  float autocvar_g_nades_spread = 0.04;
@@@ -399,7 -397,7 +399,7 @@@ void nade_ice_think(entity this
                        sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
  
                        RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
-                               autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, this.enemy);
+                               autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy);
                        Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
                                autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
                }
@@@ -637,7 -635,7 +637,7 @@@ void nade_heal_touch(entity this, entit
                }
                else if ( health_factor < 0 )
                {
-                       Damage(toucher,this,this.realowner,-health_factor,DEATH_NADE_HEAL.m_id,toucher.origin,'0 0 0');
+                       Damage(toucher,this,this.realowner,-health_factor,DEATH_NADE_HEAL.m_id,DMG_NOWEP,toucher.origin,'0 0 0');
                }
  
        }
@@@ -724,7 -722,7 +724,7 @@@ void nade_boom(entity this
        if(nade_blast)
        {
                RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
-                                autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, this.enemy);
+                                autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy);
                Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this);
        }
  
@@@ -817,7 -815,7 +817,7 @@@ void nade_beep(entity this
        this.nextthink = max(this.wait, time);
  }
  
- void nade_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+ void nade_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
  {
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
        {
                force *= 0.5; // too much
                damage = 0;
        }
 -      else if(DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER))
 +      else if(DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_NEX))
        {
                force *= 6;
                damage = this.max_health * 0.55;
        }
 -      else if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN))
 +      else if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_MACHINEGUN))
                damage = this.max_health * 0.1;
        else if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) // WEAPONTODO
        {
@@@ -901,7 -899,7 +901,7 @@@ void toss_nade(entity e, bool set_owner
        makevectors(e.v_angle);
  
        // NOTE: always throw from first weapon entity?
-       W_SetupShot(e, _nade.weaponentity_fld, false, false, SND_Null, CH_WEAPON_A, 0);
+       W_SetupShot(e, _nade.weaponentity_fld, false, false, SND_Null, CH_WEAPON_A, 0, DEATH_NADE.m_id);
  
        vector offset = (v_forward * autocvar_g_nades_throw_offset.x)
                      + (v_right * autocvar_g_nades_throw_offset.y)
index 02b7ccda2e1d469b83a26e44572078774dea1b77,b9e01bd9848bf2e937db67eafd90c69ed26e3561..28bc8c8b55930c347987b7a25bb0b3bb5ef338ff
@@@ -25,9 -25,9 +25,9 @@@ void W_HeavyMachineGun_Attack_Auto(Weap
                return;
        }
  
 -      W_DecreaseAmmo(WEP_HMG, actor, WEP_CVAR(hmg, ammo), weaponentity);
 +      W_DecreaseAmmo(WEP_HMG, actor, WEP_CVAR_PRI(hmg, ammo), weaponentity);
  
-       W_SetupShot (actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hmg, damage));
 -      W_SetupShot (actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(hmg, damage), WEP_HMG.m_id);
++      W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hmg, damage), WEP_HMG.m_id);
  
        if(!autocvar_g_norecoil)
        {
@@@ -35,8 -35,8 +35,8 @@@
                actor.punchangle_y = random () - 0.5;
        }
  
 -      float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR(hmg, spread_max));
 -      fireBullet(actor, weaponentity, w_shotorg, w_shotdir, hmg_spread, WEP_CVAR(hmg, solidpenetration), WEP_CVAR(hmg, damage), WEP_CVAR(hmg, force), WEP_HMG.m_id, 0);
 +      float hmg_spread = bound(WEP_CVAR_PRI(hmg, spread_min), WEP_CVAR_PRI(hmg, spread_min) + (WEP_CVAR_PRI(hmg, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR_PRI(hmg, spread_max));
 +      fireBullet(actor, weaponentity, w_shotorg, w_shotdir, hmg_spread, WEP_CVAR_PRI(hmg, solidpenetration), WEP_CVAR_PRI(hmg, damage), WEP_CVAR_PRI(hmg, force), WEP_HMG.m_id, 0);
  
        actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
  
@@@ -52,8 -52,8 +52,8 @@@
        }
  
        int slot = weaponslot(weaponentity);
 -      ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(hmg, refire) * W_WeaponRateFactor(actor);
 -      weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
 +      ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hmg, refire) * W_WeaponRateFactor(actor);
 +      weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hmg, refire), W_HeavyMachineGun_Attack_Auto);
  }
  
  METHOD(HeavyMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
  
  METHOD(HeavyMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
  {
 -    if(WEP_CVAR(hmg, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR(hmg, ammo)) { // forced reload
 +      if ((WEP_CVAR_SEC(hmg, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
 +      {
 +              // Secondary uses it's own refire timer if refire_type is 1.
 +              actor.jump_interval = time + WEP_CVAR_SEC(hmg, refire) * W_WeaponRateFactor(actor);
 +              // Ugly hack to reuse the fire mode of the blaster.
 +              makevectors(actor.v_angle);
 +              Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
 +              actor.(weaponentity).m_weapon = WEP_BLASTER;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(hmg, shotangle),
 +                      WEP_CVAR_SEC(hmg, damage),
 +                      WEP_CVAR_SEC(hmg, edgedamage),
 +                      WEP_CVAR_SEC(hmg, radius),
 +                      WEP_CVAR_SEC(hmg, force),
 +                      WEP_CVAR_SEC(hmg, speed),
 +                      WEP_CVAR_SEC(hmg, spread),
 +                      WEP_CVAR_SEC(hmg, delay),
 +                      WEP_CVAR_SEC(hmg, lifetime)
 +              );
 +              actor.(weaponentity).m_weapon = oldwep;
 +              if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
 +                      (actor.(weaponentity).wframe == WFRAME_FIRE2))
 +              {
 +                      // Set secondary fire animation.
 +                      vector a = '0 0 0';
 +                      actor.(weaponentity).wframe = WFRAME_FIRE2;
 +                      a = actor.(weaponentity).anim_fire2;
 +                      a.z *= g_weaponratefactor;
 +                      FOREACH_CLIENT(true, LAMBDA(
 +                              if (it == actor || (IS_SPEC(it) && it.enemy == actor))
 +                              {
 +                                      wframe_send(it, actor.(weaponentity), a, true);
 +                              }
 +                      ));
 +                      animdecide_setaction(actor, ANIMACTION_SHOOT, true);
 +              }
 +      }
 +    if (WEP_CVAR(hmg, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(hmg, ammo))
 +      {
 +              // Forced reload.
          thiswep.wr_reload(thiswep, actor, weaponentity);
 -    } else
 -    {
 -        if (fire & 1)
 -        if (weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
 -        {
 -            actor.(weaponentity).misc_bulletcounter = 0;
 -            W_HeavyMachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
 -        }
 -    }
 +              return;
 +      }
 +      if (fire & 1) // Primary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
 +              {
 +                      return;
 +              }
 +              actor.(weaponentity).misc_bulletcounter = 0;
 +              W_HeavyMachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
 +              return;
 +      }
 +      if ((fire & 2) && (WEP_CVAR_SEC(hmg, refire_type) == 0)) // Secondary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(hmg, refire)))
 +              {
 +                      return;
 +              }
 +              // ugly instagib hack to reuse the fire mode of the laser
 +              makevectors(actor.v_angle);
-               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
-               actor.(weaponentity).m_weapon = WEP_BLASTER;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(hmg, shotangle),
 +                      WEP_CVAR_SEC(hmg, damage),
 +                      WEP_CVAR_SEC(hmg, edgedamage),
 +                      WEP_CVAR_SEC(hmg, radius),
 +                      WEP_CVAR_SEC(hmg, force),
 +                      WEP_CVAR_SEC(hmg, speed),
 +                      WEP_CVAR_SEC(hmg, spread),
 +                      WEP_CVAR_SEC(hmg, delay),
 +                      WEP_CVAR_SEC(hmg, lifetime)
 +              );
-               actor.(weaponentity).m_weapon = oldwep;
 +              weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hmg, animtime), w_ready);
 +      }
  }
  
  METHOD(HeavyMachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
  {
 -    float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(hmg, ammo);
 -
 -    if(autocvar_g_balance_hmg_reload_ammo)
 -        ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
 -
 -    return ammo_amount;
 +      float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(hmg, ammo);
 +      if (autocvar_g_balance_hmg_reload_ammo)
 +      {
 +              ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR_PRI(hmg, ammo);
 +      }
 +      return ammo_amount;
  }
  
  METHOD(HeavyMachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
  {
 -    float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(hmg, ammo);
 -
 -    if(autocvar_g_balance_hmg_reload_ammo)
 -        ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
 -
 -    return ammo_amount;
 +      float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(hmg, ammo);
 +      if (autocvar_g_balance_hmg_reload_ammo)
 +      {
 +              ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR_SEC(hmg, ammo);
 +      }
 +      return ammo_amount;
  }
  
  METHOD(HeavyMachineGun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
  {
 -    W_Reload(actor, weaponentity, WEP_CVAR(hmg, ammo), SND_RELOAD);
 +    W_Reload(actor, weaponentity, WEP_CVAR_PRI(hmg, ammo), SND_RELOAD);
  }
  
  METHOD(HeavyMachineGun, wr_suicidemessage, Notification(entity thiswep))
index 60f916272609c498b9356065b3941d0d3df95274,0000000000000000000000000000000000000000..48c6634ddff28b695c9425927b6a9e3fffbbe342
mode 100644,000000..100644
--- /dev/null
@@@ -1,192 -1,0 +1,186 @@@
-       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(okmachinegun, damage));
 +#include "okmachinegun.qh"
 +
 +#ifdef SVQC
 +
 +void W_OverkillMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 +{
 +      float okmachinegun_spread;
 +
 +      if(!(fire & 1))
 +      {
 +              w_ready(thiswep, actor, weaponentity, fire);
 +              return;
 +      }
 +
 +      if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
 +      if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
 +      {
 +              W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
 +              w_ready(thiswep, actor, weaponentity, fire);
 +              return;
 +      }
 +
 +      W_DecreaseAmmo(WEP_OVERKILL_MACHINEGUN, actor, WEP_CVAR_PRI(okmachinegun, ammo), weaponentity);
 +
-               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
-               actor.(weaponentity).m_weapon = WEP_BLASTER;
++      W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(okmachinegun, damage), WEP_OVERKILL_MACHINEGUN.m_id);
 +      if(!autocvar_g_norecoil)
 +      {
 +              actor.punchangle_x = random() - 0.5;
 +              actor.punchangle_y = random() - 0.5;
 +      }
 +
 +      okmachinegun_spread = bound(WEP_CVAR_PRI(okmachinegun, spread_min), WEP_CVAR_PRI(okmachinegun, spread_min) + (WEP_CVAR_PRI(okmachinegun, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR_PRI(okmachinegun, spread_max));
 +      fireBullet(actor, weaponentity, w_shotorg, w_shotdir, okmachinegun_spread, WEP_CVAR_PRI(okmachinegun, solidpenetration), WEP_CVAR_PRI(okmachinegun, damage), WEP_CVAR_PRI(okmachinegun, force), WEP_OVERKILL_MACHINEGUN.m_id, 0);
 +
 +      actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
 +
 +      Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 +
 +      W_MachineGun_MuzzleFlash(actor, weaponentity);
 +      W_AttachToShotorg(actor, weaponentity, actor.(weaponentity).muzzle_flash, '5 0 0');
 +
 +      if(autocvar_g_casings >= 2) // casing code
 +      {
 +              makevectors(actor.v_angle); // for some reason, this is lost
 +              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, actor, weaponentity);
 +      }
 +
 +      int slot = weaponslot(weaponentity);
 +      ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(okmachinegun, refire) * W_WeaponRateFactor(actor);
 +      weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(okmachinegun, refire), W_OverkillMachineGun_Attack_Auto);
 +}
 +
 +METHOD(OverkillMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
 +              PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 +      else
 +              PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 +}
 +
 +METHOD(OverkillMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 +{
 +      if ((WEP_CVAR_SEC(okmachinegun, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
 +      {
 +              // Secondary uses it's own refire timer if refire_type is 1.
 +              actor.jump_interval = time + WEP_CVAR_SEC(okmachinegun, refire) * W_WeaponRateFactor(actor);
 +              // Ugly hack to reuse the fire mode of the blaster.
 +              makevectors(actor.v_angle);
-               actor.(weaponentity).m_weapon = oldwep;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(okmachinegun, shotangle),
 +                      WEP_CVAR_SEC(okmachinegun, damage),
 +                      WEP_CVAR_SEC(okmachinegun, edgedamage),
 +                      WEP_CVAR_SEC(okmachinegun, radius),
 +                      WEP_CVAR_SEC(okmachinegun, force),
 +                      WEP_CVAR_SEC(okmachinegun, speed),
 +                      WEP_CVAR_SEC(okmachinegun, spread),
 +                      WEP_CVAR_SEC(okmachinegun, delay),
 +                      WEP_CVAR_SEC(okmachinegun, lifetime)
 +              );
-               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
-               actor.(weaponentity).m_weapon = WEP_BLASTER;
 +              if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
 +                      (actor.(weaponentity).wframe == WFRAME_FIRE2))
 +              {
 +                      // Set secondary fire animation.
 +                      vector a = '0 0 0';
 +                      actor.(weaponentity).wframe = WFRAME_FIRE2;
 +                      a = actor.(weaponentity).anim_fire2;
 +                      a.z *= g_weaponratefactor;
 +                      FOREACH_CLIENT(true, LAMBDA(
 +                              if (it == actor || (IS_SPEC(it) && it.enemy == actor))
 +                              {
 +                                      wframe_send(it, actor.(weaponentity), a, true);
 +                              }
 +                      ));
 +                      animdecide_setaction(actor, ANIMACTION_SHOOT, true);
 +              }
 +      }
 +      if (WEP_CVAR(okmachinegun, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(okmachinegun, ammo))
 +      {
 +              // Forced reload
 +              thiswep.wr_reload(thiswep, actor, weaponentity);
 +              return;
 +      }
 +      if (fire & 1) // Primary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
 +              {
 +                      return;
 +              }
 +              actor.(weaponentity).misc_bulletcounter = 0;
 +              W_OverkillMachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
 +              return;
 +      }
 +      if ((fire & 2) && (WEP_CVAR_SEC(okmachinegun, refire_type) == 0)) // Secondary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(okmachinegun, refire)))
 +              {
 +                      return;
 +              }
 +              // Ugly hack to reuse the fire mode of the blaster.
 +              makevectors(actor.v_angle);
-               actor.(weaponentity).m_weapon = oldwep;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(okmachinegun, shotangle),
 +                      WEP_CVAR_SEC(okmachinegun, damage),
 +                      WEP_CVAR_SEC(okmachinegun, edgedamage),
 +                      WEP_CVAR_SEC(okmachinegun, radius),
 +                      WEP_CVAR_SEC(okmachinegun, force),
 +                      WEP_CVAR_SEC(okmachinegun, speed),
 +                      WEP_CVAR_SEC(okmachinegun, spread),
 +                      WEP_CVAR_SEC(okmachinegun, delay),
 +                      WEP_CVAR_SEC(okmachinegun, lifetime)
 +              );
 +              weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(okmachinegun, animtime), w_ready);
 +      }
 +}
 +
 +METHOD(OverkillMachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      float ammo_amount;
 +      ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(okmachinegun, ammo);
 +      if (WEP_CVAR(okmachinegun, reload_ammo))
 +      {
 +              ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_MACHINEGUN.m_id]) >= WEP_CVAR_PRI(okmachinegun, ammo);
 +      }
 +      return ammo_amount;
 +}
 +
 +METHOD(OverkillMachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      return true; // Blaster secondary is unlimited.
 +}
 +
 +METHOD(OverkillMachineGun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      W_Reload(actor, weaponentity, WEP_CVAR_PRI(okmachinegun, ammo), SND_RELOAD);
 +}
 +
 +METHOD(OverkillMachineGun, wr_suicidemessage, Notification(entity thiswep))
 +{
 +      return WEAPON_THINKING_WITH_PORTALS;
 +}
 +
 +METHOD(OverkillMachineGun, wr_killmessage, Notification(entity thiswep))
 +{
 +      return WEAPON_OVERKILL_MACHINEGUN_MURDER;
 +}
 +
 +#endif
 +#ifdef CSQC
 +
 +METHOD(OverkillMachineGun, wr_impacteffect, void(entity thiswep, entity actor))
 +{
 +      vector org2;
 +      org2 = w_org + w_backoff * 2;
 +      pointparticles(EFFECT_MACHINEGUN_IMPACT, org2, w_backoff * 1000, 1);
 +      if(!w_issilent)
 +              sound(actor, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTN_NORM);
 +}
 +
 +#endif
 +
index a52ac30e14b21455fc1fc1c60611ab49d895dda2,0000000000000000000000000000000000000000..cbfa1216d8206a70849a0360d927a650dc0f6347
mode 100644,000000..100644
--- /dev/null
@@@ -1,397 -1,0 +1,391 @@@
-       W_SetupShot(actor, weaponentity, true, 5, SND_NEXFIRE, CH_WEAPON_A, mydmg);
 +#include "oknex.qh"
 +
 +#ifdef SVQC
 +
 +.float oknex_lasthit;
 +#endif
 +
 +#if defined(GAMEQC)
 +
 +METHOD(OverkillNex, wr_glow, vector(OverkillNex this, entity actor, entity wepent))
 +{
 +      if (!WEP_CVAR(oknex, charge)) return '0 0 0';
 +      float charge = wepent.oknex_charge;
 +      float animlimit = WEP_CVAR(oknex, charge_animlimit);
 +      vector g;
 +      g.x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, charge / animlimit);
 +      g.y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, charge / animlimit);
 +      g.z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, charge / animlimit);
 +      if (charge > animlimit)
 +      {
 +              g.x += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (charge - animlimit) / (1 - animlimit);
 +              g.y += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (charge - animlimit) / (1 - animlimit);
 +              g.z += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (charge - animlimit) / (1 - animlimit);
 +      }
 +      return g;
 +}
 +#endif
 +
 +#ifdef SVQC
 +REGISTER_MUTATOR(oknex_charge, true);
 +
 +MUTATOR_HOOKFUNCTION(oknex_charge, GetPressedKeys)
 +{
 +      entity player = M_ARGV(0, entity);
 +
 +      // WEAPONTODO
 +      if(!WEP_CVAR(oknex, charge) || !WEP_CVAR(oknex, charge_velocity_rate))
 +              return;
 +
 +      for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
 +      {
 +              .entity weaponentity = weaponentities[slot];
 +
 +              if (player.(weaponentity).m_weapon == WEP_OVERKILL_NEX && WEP_CVAR(oknex, charge) && WEP_CVAR(oknex, charge_velocity_rate) && vdist(vec2(player.velocity), >, WEP_CVAR(oknex, charge_minspeed)))
 +              {
 +                      float xyspeed = vlen(vec2(player.velocity));
 +                      // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
 +                              xyspeed = min(xyspeed, WEP_CVAR(oknex, charge_maxspeed));
 +                      float f = (xyspeed - WEP_CVAR(oknex, charge_minspeed)) / (WEP_CVAR(oknex, charge_maxspeed) - WEP_CVAR(oknex, charge_minspeed));
 +                      // add the extra charge
 +                      player.(weaponentity).oknex_charge = min(1, player.(weaponentity).oknex_charge + WEP_CVAR(oknex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
 +              }
 +      }
 +}
 +
 +void W_OverkillNex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float issecondary)
 +{
 +      float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
 +
 +      mydmg = WEP_CVAR_BOTH(oknex, !issecondary, damage);
 +      myforce = WEP_CVAR_BOTH(oknex, !issecondary, force);
 +      mymindist = WEP_CVAR_BOTH(oknex, !issecondary, damagefalloff_mindist);
 +      mymaxdist = WEP_CVAR_BOTH(oknex, !issecondary, damagefalloff_maxdist);
 +      myhalflife = WEP_CVAR_BOTH(oknex, !issecondary, damagefalloff_halflife);
 +      myforcehalflife = WEP_CVAR_BOTH(oknex, !issecondary, damagefalloff_forcehalflife);
 +      myammo = WEP_CVAR_BOTH(oknex, !issecondary, ammo);
 +
 +      float flying;
 +      flying = IsFlying(actor); // do this BEFORE to make the trace values from FireRailgunBullet last
 +
 +      if (WEP_CVAR(oknex, charge))
 +      {
 +              charge = WEP_CVAR(oknex, charge_mindmg) / mydmg + (1 - WEP_CVAR(oknex, charge_mindmg) / mydmg) * actor.(weaponentity).oknex_charge;
 +              actor.(weaponentity).oknex_charge *= WEP_CVAR(oknex, charge_shot_multiplier); // do this AFTER setting mydmg/myforce
 +              // O RLY? -- divVerent
 +              // YA RLY -- FruitieX
 +      }
 +      else
 +      {
 +              charge = 1;
 +      }
 +      mydmg *= charge;
 +      myforce *= charge;
 +
-               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
-               actor.(weaponentity).m_weapon = WEP_BLASTER;
++      W_SetupShot(actor, weaponentity, true, 5, SND_NEXFIRE, CH_WEAPON_A, mydmg, WEP_OVERKILL_NEX.m_id);
 +      if(charge > WEP_CVAR(oknex, charge_animlimit) && WEP_CVAR(oknex, charge_animlimit)) // if the OverkillNex is overcharged, we play an extra sound
 +      {
 +              sound(actor, CH_WEAPON_B, SND_NEXCHARGE, VOL_BASE * (charge - 0.5 * WEP_CVAR(oknex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(oknex, charge_animlimit)), ATTN_NORM);
 +      }
 +
 +      yoda = 0;
 +      damage_goodhits = 0;
 +      FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_OVERKILL_NEX.m_id);
 +
 +      if(yoda && flying)
 +              Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
 +      if(damage_goodhits && actor.oknex_lasthit)
 +      {
 +              Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
 +              damage_goodhits = 0; // only every second time
 +      }
 +
 +      actor.oknex_lasthit = damage_goodhits;
 +
 +      //beam and muzzle flash done on client
 +      SendCSQCVortexBeamParticle(charge);
 +
 +      W_DecreaseAmmo(thiswep, actor, myammo, weaponentity);
 +}
 +
 +.float oknex_chargepool_pauseregen_finished;
 +
 +METHOD(OverkillNex, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      if(bot_aim(actor, weaponentity, 1000000, 0, 1, false))
 +              PHYS_INPUT_BUTTON_ATCK(actor) = true;
 +      else
 +      {
 +              if(WEP_CVAR(oknex, charge))
 +                      PHYS_INPUT_BUTTON_ATCK2(actor) = true;
 +      }
 +}
 +
 +METHOD(OverkillNex, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 +{
 +      if (WEP_CVAR(oknex, charge) && actor.(weaponentity).oknex_charge < WEP_CVAR(oknex, charge_limit))
 +      {
 +              actor.(weaponentity).oknex_charge = min(1, actor.(weaponentity).oknex_charge + WEP_CVAR(oknex, charge_rate) * frametime / W_TICSPERFRAME);
 +      }
 +
 +      if (WEP_CVAR_SEC(oknex, chargepool))
 +              if (actor.(weaponentity).oknex_chargepool_ammo < 1)
 +              {
 +                      if (actor.oknex_chargepool_pauseregen_finished < time)
 +                              actor.(weaponentity).oknex_chargepool_ammo = min(1, actor.(weaponentity).oknex_chargepool_ammo + WEP_CVAR_SEC(oknex, chargepool_regen) * frametime / W_TICSPERFRAME);
 +                      actor.pauseregen_finished = max(actor.pauseregen_finished, time + WEP_CVAR_SEC(oknex, chargepool_pause_regen));
 +              }
 +
 +      if ((WEP_CVAR_SEC(oknex, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
 +      {
 +              // Secondary uses it's own refire timer if refire_type is 1.
 +              actor.jump_interval = time + WEP_CVAR_SEC(oknex, refire) * W_WeaponRateFactor(actor);
 +              // Ugly hack to reuse the fire mode of the blaster.
 +              makevectors(actor.v_angle);
-               actor.(weaponentity).m_weapon = oldwep;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(oknex, shotangle),
 +                      WEP_CVAR_SEC(oknex, damage),
 +                      WEP_CVAR_SEC(oknex, edgedamage),
 +                      WEP_CVAR_SEC(oknex, radius),
 +                      WEP_CVAR_SEC(oknex, force),
 +                      WEP_CVAR_SEC(oknex, speed),
 +                      WEP_CVAR_SEC(oknex, spread),
 +                      WEP_CVAR_SEC(oknex, delay),
 +                      WEP_CVAR_SEC(oknex, lifetime)
 +              );
-               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
-               actor.(weaponentity).m_weapon = WEP_BLASTER;
 +              if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
 +                      (actor.(weaponentity).wframe == WFRAME_FIRE2))
 +              {
 +                      // Set secondary fire animation.
 +                      vector a = '0 0 0';
 +                      actor.(weaponentity).wframe = WFRAME_FIRE2;
 +                      a = actor.(weaponentity).anim_fire2;
 +                      a.z *= g_weaponratefactor;
 +                      FOREACH_CLIENT(true, LAMBDA(
 +                              if (it == actor || (IS_SPEC(it) && it.enemy == actor))
 +                              {
 +                                      wframe_send(it, actor.(weaponentity), a, true);
 +                              }
 +                      ));
 +                      animdecide_setaction(actor, ANIMACTION_SHOOT, true);
 +              }
 +      }
 +
 +      if (autocvar_g_balance_oknex_reload_ammo && actor.(weaponentity).clip_load < WEP_CVAR_PRI(oknex, ammo))
 +      {
 +              // Rorced reload
 +              thiswep.wr_reload(thiswep, actor, weaponentity);
 +              return;
 +      }
 +      if (fire & 1) // Primary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(oknex, refire)))
 +              {
 +                      return;
 +              }
 +              W_OverkillNex_Attack(thiswep, actor, weaponentity, 0);
 +              weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(oknex, animtime), w_ready);
 +              return;
 +      }
 +      if ((fire & 2) && (WEP_CVAR(oknex, secondary) == 2) && (WEP_CVAR_SEC(oknex, refire_type) == 0))
 +      {
 +              // Secondary attack
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(oknex, refire)))
 +              {
 +                      return;
 +              }
 +              // ugly instagib hack to reuse the fire mode of the laser
 +              makevectors(actor.v_angle);
-               actor.(weaponentity).m_weapon = oldwep;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(oknex, shotangle),
 +                      WEP_CVAR_SEC(oknex, damage),
 +                      WEP_CVAR_SEC(oknex, edgedamage),
 +                      WEP_CVAR_SEC(oknex, radius),
 +                      WEP_CVAR_SEC(oknex, force),
 +                      WEP_CVAR_SEC(oknex, speed),
 +                      WEP_CVAR_SEC(oknex, spread),
 +                      WEP_CVAR_SEC(oknex, delay),
 +                      WEP_CVAR_SEC(oknex, lifetime)
 +              );
 +              weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(oknex, animtime), w_ready);
 +              return;
 +      }
 +      //if ((WEP_CVAR(oknex, charge) && (WEP_CVAR(oknex, secondary) == 1)) ? (PHYS_INPUT_BUTTON_ZOOM(actor) | PHYS_INPUT_BUTTON_ZOOMSCRIPT(actor)) : (fire & 2))
 +      //{
 +      //      if(WEP_CVAR(oknex, charge))
 +      //      {
 +      //              actor.(weaponentity).oknex_charge_rottime = time + WEP_CVAR(oknex, charge_rot_pause);
 +      //              float dt = frametime / W_TICSPERFRAME;
 +      //
 +      //              if(actor.(weaponentity).oknex_charge < 1)
 +      //              {
 +      //                      if(WEP_CVAR_SEC(oknex, chargepool))
 +      //                      {
 +      //                              if(WEP_CVAR_SEC(oknex, ammo))
 +      //                              {
 +      //                                      // always deplete if secondary is held
 +      //                                      actor.(weaponentity).oknex_chargepool_ammo = max(0, actor.(weaponentity).oknex_chargepool_ammo - WEP_CVAR_SEC(oknex, ammo) * dt);
 +
 +      //                                      dt = min(dt, (1 - actor.(weaponentity).oknex_charge) / WEP_CVAR(oknex, charge_rate));
 +      //                                      actor.oknex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(oknex, chargepool_pause_regen);
 +      //                                      dt = min(dt, actor.(weaponentity).oknex_chargepool_ammo);
 +      //                                      dt = max(0, dt);
 +
 +      //                                      actor.(weaponentity).oknex_charge += dt * WEP_CVAR(oknex, charge_rate);
 +      //                              }
 +      //                      }
 +
 +      //                      else if(WEP_CVAR_SEC(oknex, ammo))
 +      //                      {
 +      //                              if(fire & 2) // only eat ammo when the button is pressed
 +      //                              {
 +      //                                      dt = min(dt, (1 - actor.(weaponentity).oknex_charge) / WEP_CVAR(oknex, charge_rate));
 +      //                                      if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
 +      //                                      {
 +      //                                              // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
 +      //                                              if(autocvar_g_balance_vortex_reload_ammo)
 +      //                                              {
 +      //                                                      dt = min(dt, (actor.(weaponentity).clip_load - WEP_CVAR_PRI(oknex, ammo)) / WEP_CVAR_SEC(oknex, ammo));
 +      //                                                      dt = max(0, dt);
 +      //                                                      if(dt > 0)
 +      //                                                      {
 +      //                                                              actor.(weaponentity).clip_load = max(WEP_CVAR_SEC(oknex, ammo), actor.(weaponentity).clip_load - WEP_CVAR_SEC(oknex, ammo) * dt);
 +      //                                                      }
 +      //                                                      actor.(weaponentity).(weapon_load[WEP_OVERKILL_NEX.m_id]) = actor.(weaponentity).clip_load;
 +      //                                              }
 +      //                                              else
 +      //                                              {
 +      //                                                      dt = min(dt, (actor.(thiswep.ammo_field) - WEP_CVAR_PRI(oknex, ammo)) / WEP_CVAR_SEC(oknex, ammo));
 +      //                                                      dt = max(0, dt);
 +      //                                                      if(dt > 0)
 +      //                                                      {
 +      //                                                              actor.(thiswep.ammo_field) = max(WEP_CVAR_SEC(oknex, ammo), actor.(thiswep.ammo_field) - WEP_CVAR_SEC(oknex, ammo) * dt);
 +      //                                                      }
 +      //                                              }
 +      //                                      }
 +      //                                      actor.(weaponentity).oknex_charge += dt * WEP_CVAR(oknex, charge_rate);
 +      //                              }
 +      //                      }
 +
 +      //                      else
 +      //                      {
 +      //                              dt = min(dt, (1 - actor.(weaponentity).oknex_charge) / WEP_CVAR(oknex, charge_rate));
 +      //                              actor.(weaponentity).oknex_charge += dt * WEP_CVAR(oknex, charge_rate);
 +      //                      }
 +      //              }
 +      //      }
 +      //      else if(WEP_CVAR(oknex, secondary))
 +      //      {
 +      //              if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(oknex, refire)))
 +      //              {
 +      //                      W_OverkillNex_Attack(thiswep, actor, weaponentity, 1);
 +      //                      weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(oknex, animtime), w_ready);
 +      //              }
 +      //      }
 +      //}
 +}
 +
 +METHOD(OverkillNex, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      actor.oknex_lasthit = 0;
 +}
 +
 +METHOD(OverkillNex, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(oknex, ammo);
 +      ammo_amount += (autocvar_g_balance_oknex_reload_ammo && actor.(weaponentity).(weapon_load[WEP_OVERKILL_NEX.m_id]) >= WEP_CVAR_PRI(oknex, ammo));
 +      return ammo_amount;
 +}
 +
 +METHOD(OverkillNex, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      if (WEP_CVAR(oknex, secondary))
 +      {
 +              // don't allow charging if we don't have enough ammo
 +              float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(oknex, ammo);
 +              ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_NEX.m_id]) >= WEP_CVAR_SEC(oknex, ammo);
 +              return ammo_amount;
 +      }
 +      else
 +      {
 +              return false; // zoom is not a fire mode
 +      }
 +}
 +
 +METHOD(OverkillNex, wr_resetplayer, void(entity thiswep, entity actor))
 +{
 +      if (WEP_CVAR(oknex, charge)) {
 +              for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
 +              {
 +                      .entity weaponentity = weaponentities[slot];
 +                      actor.(weaponentity).oknex_charge = WEP_CVAR(oknex, charge_start);
 +              }
 +      }
 +      actor.oknex_lasthit = 0;
 +}
 +
 +METHOD(OverkillNex, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      W_Reload(actor, weaponentity, WEP_CVAR_PRI(oknex, ammo), SND_RELOAD);
 +}
 +
 +METHOD(OverkillNex, wr_suicidemessage, Notification(entity thiswep))
 +{
 +      return WEAPON_THINKING_WITH_PORTALS;
 +}
 +
 +METHOD(OverkillNex, wr_killmessage, Notification(entity thiswep))
 +{
 +      return WEAPON_OVERKILL_NEX_MURDER;
 +}
 +
 +METHOD(OverkillNex, wr_zoom, bool(entity thiswep, entity actor))
 +{
 +      return PHYS_INPUT_BUTTON_ATCK2(actor) && !WEP_CVAR(oknex, secondary);
 +}
 +
 +#endif
 +#ifdef CSQC
 +
 +METHOD(OverkillNex, wr_impacteffect, void(entity thiswep, entity actor))
 +{
 +      entity this = actor;
 +      vector org2 = w_org + w_backoff * 6;
 +      pointparticles(EFFECT_VORTEX_IMPACT, org2, '0 0 0', 1);
 +      if(!w_issilent)
 +              sound(this, CH_SHOTS, SND_NEXIMPACT, VOL_BASE, ATTN_NORM);
 +}
 +
 +METHOD(OverkillNex, wr_init, void(entity thiswep))
 +{
 +      if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
 +      {
 +              precache_pic("gfx/reticle_nex");
 +      }
 +}
 +
 +METHOD(OverkillNex, wr_zoom, bool(entity thiswep, entity actor))
 +{
 +      if(button_zoom || zoomscript_caught || (!WEP_CVAR(oknex, secondary) && button_attack2))
 +      {
 +              return true;
 +      }
 +      else
 +      {
 +              // no weapon specific image for this weapon
 +              return false;
 +      }
 +}
 +
 +METHOD(OverkillNex, wr_zoomdir, bool(entity thiswep))
 +{
 +    return button_attack2 && !WEP_CVAR(oknex, secondary);
 +}
 +
 +#endif
index c71263aee4b47b79658bfb6949de6335bcf3f8f9,0000000000000000000000000000000000000000..a0c80f25ec7457787b926a700a79af76ce9d6f09
mode 100644,000000..100644
--- /dev/null
@@@ -1,152 -1,0 +1,146 @@@
-               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
-               actor.(weaponentity).m_weapon = WEP_BLASTER;
 +#include "okshotgun.qh"
 +
 +#ifdef SVQC
 +METHOD(OverkillShotgun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      if (vdist(actor.origin - actor.enemy.origin, >, WEP_CVAR_PRI(okshotgun, bot_range)))
 +      {
 +              PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 +      }
 +      else
 +      {
 +              PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 +      }
 +}
 +
 +METHOD(OverkillShotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 +{
 +      if ((WEP_CVAR_SEC(okshotgun, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
 +      {
 +              // Secondary uses it's own refire timer if refire_type is 1.
 +              actor.jump_interval = time + WEP_CVAR_SEC(okshotgun, refire) * W_WeaponRateFactor(actor);
 +              // Ugly hack to reuse the fire mode of the blaster.
 +              makevectors(actor.v_angle);
-               actor.(weaponentity).m_weapon = oldwep;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(okshotgun, shotangle),
 +                      WEP_CVAR_SEC(okshotgun, damage),
 +                      WEP_CVAR_SEC(okshotgun, edgedamage),
 +                      WEP_CVAR_SEC(okshotgun, radius),
 +                      WEP_CVAR_SEC(okshotgun, force),
 +                      WEP_CVAR_SEC(okshotgun, speed),
 +                      WEP_CVAR_SEC(okshotgun, spread),
 +                      WEP_CVAR_SEC(okshotgun, delay),
 +                      WEP_CVAR_SEC(okshotgun, lifetime)
 +              );
-               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
-               actor.(weaponentity).m_weapon = WEP_BLASTER;
 +              if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
 +                      (actor.(weaponentity).wframe == WFRAME_FIRE2))
 +              {
 +                      // Set secondary fire animation.
 +                      vector a = '0 0 0';
 +                      actor.(weaponentity).wframe = WFRAME_FIRE2;
 +                      a = actor.(weaponentity).anim_fire2;
 +                      a.z *= g_weaponratefactor;
 +                      FOREACH_CLIENT(true, LAMBDA(
 +                              if (it == actor || (IS_SPEC(it) && it.enemy == actor))
 +                              {
 +                                      wframe_send(it, actor.(weaponentity), a, true);
 +                              }
 +                      ));
 +                      animdecide_setaction(actor, ANIMACTION_SHOOT, true);
 +              }
 +      }
 +      if (WEP_CVAR(okshotgun, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(okshotgun, ammo))
 +      {
 +              // Forced reload
 +              thiswep.wr_reload(thiswep, actor, weaponentity);
 +              return;
 +      }
 +      if (fire & 1) // Primary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(okshotgun, animtime)))
 +              {
 +                      return;
 +              }
 +              W_Shotgun_Attack(thiswep, actor, weaponentity, true,
 +                      WEP_CVAR_PRI(okshotgun, ammo),
 +                      WEP_CVAR_PRI(okshotgun, damage),
 +                      WEP_CVAR_PRI(okshotgun, bullets),
 +                      WEP_CVAR_PRI(okshotgun, spread),
 +                      WEP_CVAR_PRI(okshotgun, solidpenetration),
 +                      WEP_CVAR_PRI(okshotgun, force));
 +              weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(okshotgun, animtime), w_ready);
 +              return;
 +      }
 +      if ((fire & 2) && (WEP_CVAR_SEC(okshotgun, refire_type) == 0)) // Secondary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(okshotgun, refire)))
 +              {
 +                      return;
 +              }
 +              // Ugly hack to reuse the fire mode of the blaster.
 +              makevectors(actor.v_angle);
-               actor.(weaponentity).m_weapon = oldwep;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(okshotgun, shotangle),
 +                      WEP_CVAR_SEC(okshotgun, damage),
 +                      WEP_CVAR_SEC(okshotgun, edgedamage),
 +                      WEP_CVAR_SEC(okshotgun, radius),
 +                      WEP_CVAR_SEC(okshotgun, force),
 +                      WEP_CVAR_SEC(okshotgun, speed),
 +                      WEP_CVAR_SEC(okshotgun, spread),
 +                      WEP_CVAR_SEC(okshotgun, delay),
 +                      WEP_CVAR_SEC(okshotgun, lifetime)
 +              );
 +              weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(okshotgun, animtime), w_ready);
 +      }
 +}
 +
 +METHOD(OverkillShotgun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(okshotgun, ammo);
 +      ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_SHOTGUN.m_id]) >= WEP_CVAR_PRI(okshotgun, ammo);
 +      return ammo_amount;
 +}
 +
 +METHOD(OverkillShotgun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      return true; // Blaster secondary is unlimited.
 +}
 +
 +METHOD(OverkillShotgun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 +{
 +      W_Reload(actor, weaponentity, WEP_CVAR_PRI(okshotgun, ammo), SND_RELOAD); // WEAPONTODO
 +}
 +
 +METHOD(OverkillShotgun, wr_suicidemessage, Notification(entity thiswep))
 +{
 +      return WEAPON_THINKING_WITH_PORTALS;
 +}
 +
 +METHOD(OverkillShotgun, wr_killmessage, Notification(entity thiswep))
 +{
 +      return WEAPON_OVERKILL_SHOTGUN_MURDER;
 +}
 +
 +#endif
 +#ifdef CSQC
 +.float prevric;
 +
 +METHOD(OverkillShotgun, wr_impacteffect, void(entity thiswep, entity actor))
 +{
 +      vector org2 = w_org + w_backoff * 2;
 +      pointparticles(EFFECT_SHOTGUN_IMPACT, org2, w_backoff * 1000, 1);
 +      if(!w_issilent && time - actor.prevric > 0.25)
 +      {
 +              if(w_random < 0.05)
 +                      sound(actor, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM);
 +              actor.prevric = time;
 +      }
 +}
 +
 +#endif
index 7f80268d8d7ddd9c4e49a1854262b24cace48cbd,09e6ce29e4f75aea8ea609f476430cb79a37c6db..f42a55f65e012aa8f54f55a5377f8fe8fd60dccc
@@@ -7,7 -7,7 +7,7 @@@ void W_RocketPropelledChainsaw_Explode(
        this.event_damage = func_null;
        this.takedamage = DAMAGE_NO;
  
-       RadiusDamage (this, this.realowner, WEP_CVAR_PRI(rpc, damage), WEP_CVAR_PRI(rpc, edgedamage), WEP_CVAR_PRI(rpc, radius), NULL, NULL, WEP_CVAR_PRI(rpc, force), this.projectiledeathtype, directhitentity);
 -      RadiusDamage (this, this.realowner, WEP_CVAR(rpc, damage), WEP_CVAR(rpc, edgedamage), WEP_CVAR(rpc, radius), NULL, NULL, WEP_CVAR(rpc, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
++      RadiusDamage(this, this.realowner, WEP_CVAR_PRI(rpc, damage), WEP_CVAR_PRI(rpc, edgedamage), WEP_CVAR_PRI(rpc, radius), NULL, NULL, WEP_CVAR_PRI(rpc, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
  
        delete(this);
  }
@@@ -26,7 -26,7 +26,7 @@@ void W_RocketPropelledChainsaw_Touch (e
        W_RocketPropelledChainsaw_Explode(this, toucher);
  }
  
- void W_RocketPropelledChainsaw_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+ void W_RocketPropelledChainsaw_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
  {
        if (this.health <= 0)
                return;
@@@ -54,9 -54,9 +54,9 @@@ void W_RocketPropelledChainsaw_Think(en
  
        tracebox(this.origin, this.mins, this.maxs, this.origin + mydir * (2 * myspeed_accel), MOVE_NORMAL, this);
        if(IS_PLAYER(trace_ent))
-               Damage (trace_ent, this, this.realowner, WEP_CVAR_PRI(rpc, damage2), this.projectiledeathtype, this.origin, normalize(this.origin - other.origin) * WEP_CVAR_PRI(rpc, force));
 -              Damage (trace_ent, this, this.realowner, WEP_CVAR(rpc, damage2), this.projectiledeathtype, this.weaponentity_fld, this.origin, normalize(this.origin - trace_ent.origin) * WEP_CVAR(rpc, force));
++              Damage(trace_ent, this, this.realowner, WEP_CVAR_PRI(rpc, damage2), this.projectiledeathtype, this.weaponentity_fld, this.origin, normalize(this.origin - trace_ent.origin) * WEP_CVAR_PRI(rpc, force));
  
 -      this.velocity = mydir * (myspeed + (WEP_CVAR(rpc, speedaccel) * sys_frametime));
 +      this.velocity = mydir * (myspeed + (WEP_CVAR_PRI(rpc, speedaccel) * sys_frametime));
  
        UpdateCSQCProjectile(this);
        this.nextthink = time;
@@@ -67,33 -67,34 +67,34 @@@ void W_RocketPropelledChainsaw_Attack (
        entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(actor);
        entity flash = spawn ();
  
 -      W_DecreaseAmmo(thiswep, actor, WEP_CVAR(rpc, ammo), weaponentity);
 -      W_SetupShot_ProjectileSize (actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(rpc, damage), WEP_RPC.m_id);
 +      W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(rpc, ammo), weaponentity);
-       W_SetupShot_ProjectileSize (actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(rpc, damage));
++      W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(rpc, damage), WEP_RPC.m_id);
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
        PROJECTILE_MAKETRIGGER(missile);
  
        missile.owner = missile.realowner = actor;
        missile.bot_dodge = true;
 -      missile.bot_dodgerating = WEP_CVAR(rpc, damage) * 2;
 +      missile.bot_dodgerating = WEP_CVAR_PRI(rpc, damage) * 2;
  
        missile.takedamage = DAMAGE_YES;
 -      missile.damageforcescale = WEP_CVAR(rpc, damageforcescale);
 -      missile.health = WEP_CVAR(rpc, health);
 +      missile.damageforcescale = WEP_CVAR_PRI(rpc, damageforcescale);
 +      missile.health = WEP_CVAR_PRI(rpc, health);
        missile.event_damage = W_RocketPropelledChainsaw_Damage;
        missile.damagedbycontents = true;
        IL_PUSH(g_damagedbycontents, missile);
        set_movetype(missile, MOVETYPE_FLY);
  
        missile.projectiledeathtype = WEP_RPC.m_id;
+       missile.weaponentity_fld = weaponentity;
        setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
  
        setorigin(missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
 -      W_SetupProjVelocity_Basic(missile, WEP_CVAR(rpc, speed), 0);
 +      W_SetupProjVelocity_Basic(missile, WEP_CVAR_PRI(rpc, speed), 0);
  
        settouch(missile, W_RocketPropelledChainsaw_Touch);
  
        setthink(missile, W_RocketPropelledChainsaw_Think);
 -      missile.cnt = time + WEP_CVAR(rpc, lifetime);
 +      missile.cnt = time + WEP_CVAR_PRI(rpc, lifetime);
        missile.nextthink = time;
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
  
  METHOD(RocketPropelledChainsaw, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
  {
 -    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(rpc, speed), 0, WEP_CVAR(rpc, lifetime), false);
 +    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(rpc, speed), 0, WEP_CVAR_PRI(rpc, lifetime), false);
  }
  
  METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
  {
 -    if(WEP_CVAR(rpc, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR(rpc, ammo)) {
 -        thiswep.wr_reload(thiswep, actor, weaponentity);
 -    } else
 -    {
 -        if (fire & 1)
 -        {
 -            if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(rpc, refire)))
 -            {
 -                W_RocketPropelledChainsaw_Attack(thiswep, actor, weaponentity);
 -                weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(rpc, animtime), w_ready);
 -            }
 -        }
 -
 -        if (fire & 2)
 -        {
 -            // to-do
 -        }
 -    }
 +      if ((WEP_CVAR_SEC(rpc, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
 +      {
 +              // Secondary uses it's own refire timer if refire_type is 1.
 +              actor.jump_interval = time + WEP_CVAR_SEC(rpc, refire) * W_WeaponRateFactor(actor);
 +              // Ugly hack to reuse the fire mode of the blaster.
 +              makevectors(actor.v_angle);
 +              Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
 +              actor.(weaponentity).m_weapon = WEP_BLASTER;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(rpc, shotangle),
 +                      WEP_CVAR_SEC(rpc, damage),
 +                      WEP_CVAR_SEC(rpc, edgedamage),
 +                      WEP_CVAR_SEC(rpc, radius),
 +                      WEP_CVAR_SEC(rpc, force),
 +                      WEP_CVAR_SEC(rpc, speed),
 +                      WEP_CVAR_SEC(rpc, spread),
 +                      WEP_CVAR_SEC(rpc, delay),
 +                      WEP_CVAR_SEC(rpc, lifetime)
 +              );
 +              actor.(weaponentity).m_weapon = oldwep;
 +              if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
 +                      (actor.(weaponentity).wframe == WFRAME_FIRE2))
 +              {
 +                      // Set secondary fire animation.
 +                      vector a = '0 0 0';
 +                      actor.(weaponentity).wframe = WFRAME_FIRE2;
 +                      a = actor.(weaponentity).anim_fire2;
 +                      a.z *= g_weaponratefactor;
 +                      FOREACH_CLIENT(true, LAMBDA(
 +                              if (it == actor || (IS_SPEC(it) && it.enemy == actor))
 +                              {
 +                                      wframe_send(it, actor.(weaponentity), a, true);
 +                              }
 +                      ));
 +                      animdecide_setaction(actor, ANIMACTION_SHOOT, true);
 +              }
 +      }
 +      if (WEP_CVAR(rpc, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(rpc, ammo))
 +      {
 +              // Forced reload
 +              thiswep.wr_reload(thiswep, actor, weaponentity);
 +              return;
 +      }
 +      if (fire & 1) // Primary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(rpc, refire)))
 +              {
 +                      return;
 +              }
 +              W_RocketPropelledChainsaw_Attack(thiswep, actor, weaponentity);
 +              weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(rpc, animtime), w_ready);
 +              return;
 +      }
 +      if ((fire & 2) && (WEP_CVAR_SEC(rpc, refire_type) == 0)) // Secondary attack
 +      {
 +              if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(rpc, refire)))
 +              {
 +                      return;
 +              }
 +              // ugly instagib hack to reuse the fire mode of the laser
 +              makevectors(actor.v_angle);
-               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
-               actor.(weaponentity).m_weapon = WEP_BLASTER;
 +              W_Blaster_Attack(
 +                      actor,
 +                      weaponentity,
 +                      WEP_BLASTER.m_id | HITTYPE_SECONDARY,
 +                      WEP_CVAR_SEC(rpc, shotangle),
 +                      WEP_CVAR_SEC(rpc, damage),
 +                      WEP_CVAR_SEC(rpc, edgedamage),
 +                      WEP_CVAR_SEC(rpc, radius),
 +                      WEP_CVAR_SEC(rpc, force),
 +                      WEP_CVAR_SEC(rpc, speed),
 +                      WEP_CVAR_SEC(rpc, spread),
 +                      WEP_CVAR_SEC(rpc, delay),
 +                      WEP_CVAR_SEC(rpc, lifetime)
 +              );
-               actor.(weaponentity).m_weapon = oldwep;
 +              weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(rpc, animtime), w_ready);
 +      }
  }
  
  METHOD(RocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
  {
 -    float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR(rpc, ammo);
 -    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR(rpc, ammo);
 -    return ammo_amount;
 +      float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(rpc, ammo);
 +      ammo_amount += actor.(weaponentity).(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR_PRI(rpc, ammo);
 +      return ammo_amount;
  }
  
  METHOD(RocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
  {
 -    return false;
 +      float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(rpc, ammo);
 +      ammo_amount += actor.(weaponentity).(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR_SEC(rpc, ammo);
 +      return ammo_amount;
  }
  
  METHOD(RocketPropelledChainsaw, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
  {
 -    W_Reload(actor, weaponentity, WEP_CVAR(rpc, ammo), SND_RELOAD);
 +    W_Reload(actor, weaponentity, WEP_CVAR_PRI(rpc, ammo), SND_RELOAD);
  }
  
  METHOD(RocketPropelledChainsaw, wr_suicidemessage, Notification(entity thiswep))
index a3f9c111a8bbb71792158331cf547e7dc24d15f8,7cabd77103b4a3032c73b409ad3768176243b2ed..057ef3f03a756b6c3d337a7257fada47c88ebd51
@@@ -2,15 -2,15 +2,16 @@@
  
  #ifdef SVQC
  
 -void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary)
 +void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary, float ammocount, float damage, float bullets, float spread, float solidpenetration, float force)
  {
 -      W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(shotgun, ammo), weaponentity);
 +      W_DecreaseAmmo(thiswep, actor, ammocount, weaponentity);
  
-       W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), damage * bullets);
 -      W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets), WEP_SHOTGUN.m_id);
 -      for(int sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
 -              fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN.m_id, 0);
++      W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), damage * bullets, WEP_SHOTGUN.m_id);
 +      for(int sc = 0;sc < bullets;sc = sc + 1)
 +              fireBullet(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, WEP_SHOTGUN.m_id, 0);
  
 -      Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo));
++
 +      Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, ammocount);
  
        // casing code
        if(autocvar_g_casings >= 1)
@@@ -91,7 -91,7 +92,7 @@@ void W_Shotgun_Melee_Think(entity this
                        //print(strcat(this.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n"));
  
                        Damage(target_victim, this.realowner, this.realowner,
-                               swing_damage, WEP_SHOTGUN.m_id | HITTYPE_SECONDARY,
+                               swing_damage, WEP_SHOTGUN.m_id | HITTYPE_SECONDARY, this.weaponentity_fld,
                                this.realowner.origin + this.realowner.view_ofs,
                                v_forward * WEP_CVAR_SEC(shotgun, force));
  
@@@ -136,7 -136,8 +137,8 @@@ void W_Shotgun_Attack2(Weapon thiswep, 
        meleetemp.realowner = actor;
        setthink(meleetemp, W_Shotgun_Melee_Think);
        meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor(actor);
-       W_SetupShot_Range(actor, weaponentity, true, 0, SND_Null, 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
+       meleetemp.weaponentity_fld = weaponentity;
+       W_SetupShot_Range(actor, weaponentity, true, 0, SND_Null, 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range), WEP_SHOTGUN.m_id | HITTYPE_SECONDARY);
  }
  
  // alternate secondary weapon frames
@@@ -151,13 -152,7 +153,13 @@@ void W_Shotgun_Attack3_Frame2(Weapon th
        }
  
        sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound
 -      W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, true); // actually is secondary, but we trick the last shot into playing full reload sound
 +      W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, true,
 +              WEP_CVAR_PRI(shotgun, ammo),
 +              WEP_CVAR_PRI(shotgun, damage),
 +              WEP_CVAR_PRI(shotgun, bullets),
 +              WEP_CVAR_PRI(shotgun, spread),
 +              WEP_CVAR_PRI(shotgun, solidpenetration),
 +              WEP_CVAR_PRI(shotgun, force)); // actually is secondary, but we trick the last shot into playing full reload sound
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready);
  }
  void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
                return;
        }
  
 -      W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, false);
 +      W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, false,
 +              WEP_CVAR_PRI(shotgun, ammo),
 +              WEP_CVAR_PRI(shotgun, damage),
 +              WEP_CVAR_PRI(shotgun, bullets),
 +              WEP_CVAR_PRI(shotgun, spread),
 +              WEP_CVAR_PRI(shotgun, solidpenetration),
 +              WEP_CVAR_PRI(shotgun, force));
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
  }
  
@@@ -189,7 -178,6 +191,7 @@@ METHOD(Shotgun, wr_aim, void(entity thi
      else
          PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
  }
 +
  METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
  {
      if(WEP_CVAR(shotgun, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
              {
                  if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(shotgun, animtime)))
                  {
 -                    W_Shotgun_Attack(thiswep, actor, weaponentity, true);
 +                    W_Shotgun_Attack(thiswep, actor, weaponentity, true,
 +                                              WEP_CVAR_PRI(shotgun, ammo),
 +                                              WEP_CVAR_PRI(shotgun, damage),
 +                                              WEP_CVAR_PRI(shotgun, bullets),
 +                                              WEP_CVAR_PRI(shotgun, spread),
 +                                              WEP_CVAR_PRI(shotgun, solidpenetration),
 +                                              WEP_CVAR_PRI(shotgun, force));
                      actor.(weaponentity).shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(actor);
                      weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
                  }
              {
                  if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(shotgun, alt_animtime)))
                  {
 -                    W_Shotgun_Attack(thiswep, actor, weaponentity, false);
 +                    W_Shotgun_Attack(thiswep, actor, weaponentity, false,
 +                                              WEP_CVAR_PRI(shotgun, ammo),
 +                                              WEP_CVAR_PRI(shotgun, damage),
 +                                              WEP_CVAR_PRI(shotgun, bullets),
 +                                              WEP_CVAR_PRI(shotgun, spread),
 +                                              WEP_CVAR_PRI(shotgun, solidpenetration),
 +                                              WEP_CVAR_PRI(shotgun, force));
                      actor.(weaponentity).shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(actor);
                      weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
                  }
diff --combined qcsrc/common/wepent.qc
index 37694987063c9d613d40d3ca8c2ebe8e4761fb51,3da8b8939a48ca1e649e611f5e8d036939c4104c..8927c70a67548f60ff2be28b8c909129f509295d
@@@ -23,13 -23,9 +23,13 @@@ MACRO_EN
        { (viewmodels[this.m_wepent_slot]).alpha = (ReadByte() + -1) / 254; }) \
      \
      PROP(false, vortex_charge, WEPENT_SET_NORMAL, \
-       { WriteByte(chan, this.vortex_charge * 16); }, \
-       { (viewmodels[this.m_wepent_slot]).vortex_charge = ReadByte() / 16; }) \
+       { WriteByte(chan, this.vortex_charge * 255); }, \
+       { (viewmodels[this.m_wepent_slot]).vortex_charge = ReadByte() / 255; }) \
      \
 +    PROP(false, oknex_charge, WEPENT_SET_NORMAL, \
 +      { WriteByte(chan, this.oknex_charge * 16); }, \
 +      { (viewmodels[this.m_wepent_slot]).oknex_charge = ReadByte() / 16; }) \
 +    \
      PROP(false, m_gunalign, WEPENT_SET_NORMAL, \
        { WriteByte(chan, this.m_gunalign); }, \
        { (viewmodels[this.m_wepent_slot]).m_gunalign = ReadByte(); }) \
        { WriteByte(chan, this.vortex_chargepool_ammo * 16); }, \
        { (viewmodels[this.m_wepent_slot]).vortex_chargepool_ammo = ReadByte() / 16; }) \
      \
 -    PROP(false, clip_load, WEPENT_SET_NORMAL, \
 +      PROP(false, oknex_chargepool_ammo, WEPENT_SET_NORMAL, \
 +      { WriteByte(chan, this.oknex_chargepool_ammo * 16); }, \
 +      { (viewmodels[this.m_wepent_slot]).oknex_chargepool_ammo = ReadByte() / 16; }) \
 +    \
 +      PROP(false, clip_load, WEPENT_SET_NORMAL, \
        { WriteShort(chan, this.clip_load); }, \
        { (viewmodels[this.m_wepent_slot]).clip_load = ReadShort(); }) \
      \
diff --combined qcsrc/server/client.qc
index ade2e388215f2dfb7b9c03a9a119a2b49c51706b,77f863f37eafcf6f0f06489390ad3f4be65fa8bf..8493bf380774cdcc142eaad5ce26d605e4969784
@@@ -62,8 -62,6 +62,8 @@@
  
  #include "../lib/warpzone/server.qh"
  
 +#include <common/mutators/mutator/overkill/oknex.qh>
 +
  STATIC_METHOD(Client, Add, void(Client this, int _team))
  {
      ClientConnect(this);
@@@ -922,7 -920,7 +922,7 @@@ void ClientKill_Now(entity this
            if(!this.killindicator_teamchange)
            {
              this.vehicle_health = -1;
-             Damage(this, this, this, 1 , DEATH_KILL.m_id, this.origin, '0 0 0');
+             Damage(this, this, this, 1 , DEATH_KILL.m_id, DMG_NOWEP, this.origin, '0 0 0');
            }
        }
  
  
        if (!IS_SPEC(this) && !IS_OBSERVER(this) && MUTATOR_CALLHOOK(ClientKill_Now, this) == false)
        {
-               Damage(this, this, this, 100000, DEATH_KILL.m_id, this.origin, '0 0 0');
+               Damage(this, this, this, 100000, DEATH_KILL.m_id, DMG_NOWEP, this.origin, '0 0 0');
        }
  
        // now I am sure the player IS dead
@@@ -1689,7 -1687,7 +1689,7 @@@ void player_regen(entity this
                if(this.vehicle)
                        vehicles_exit(this.vehicle, VHEF_RELEASE);
                if(this.event_damage)
-                       this.event_damage(this, this, this, 1, DEATH_ROT.m_id, this.origin, '0 0 0');
+                       this.event_damage(this, this, this, 1, DEATH_ROT.m_id, DMG_NOWEP, this.origin, '0 0 0');
        }
  
        if (!(this.items & IT_UNLIMITED_WEAPON_AMMO))
@@@ -2558,7 -2556,7 +2558,7 @@@ void PlayerPreThink (entity this
                                if (this.vehicle)
                                        vehicles_exit(this.vehicle, VHEF_RELEASE);
                                if(this.event_damage)
-                                       this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, this.origin, '0 0 0');
+                                       this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, DMG_NOWEP, this.origin, '0 0 0');
                        }
                        else if (this.revive_progress <= 0)
                                Unfreeze(this);
@@@ -2671,7 -2669,7 +2671,7 @@@ void DrownPlayer(entity this
        {       // drown!
                if (this.pain_finished < time)
                {
-                       Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, this.origin, '0 0 0');
+                       Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, DMG_NOWEP, this.origin, '0 0 0');
                        this.pain_finished = time + 0.5;
                }
        }
diff --combined qcsrc/server/defs.qh
index 7a71ff1e7bda3c0d997e9bbb20fd5dfcc6643492,185a68a85341763984db7e8e798b2e4f8cddfe6a..69dac94a81ecc5d695aea52fbcddb25cce09632a
@@@ -34,7 -34,7 +34,7 @@@ float server_is_dedicated
  
  // Fields
  
- .void(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) event_damage;
+ .void(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) event_damage;
  
  //.string     wad;
  //.string     map;
@@@ -228,7 -228,10 +228,10 @@@ int have_team_spawns_forteams; // if Xt
  
  .bool canteamdamage;
  
- void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
+ void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
+ // WEAPONTODO
+ #define DMG_NOWEP (weaponentities[0])
  
  float lockteams;
  
@@@ -332,9 -335,6 +335,9 @@@ float client_cefc_accumulatortime
  .float vortex_charge;
  .float vortex_charge_rottime;
  .float vortex_chargepool_ammo;
 +.float oknex_charge;
 +.float oknex_charge_rottime;
 +.float oknex_chargepool_ammo;
  .int hagar_load;
  
  .int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab