]> 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 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)
        {
@@@ -66,89 -66,17 +66,86 @@@ METHOD(HeavyMachineGun, wr_aim, void(en
  
  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))
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);
  }
@@@ -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,8 -67,8 +67,8 @@@ 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);
  
@@@ -116,89 -117,24 +117,86 @@@ METHOD(RocketPropelledChainsaw, wr_aim
  
  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))
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)
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(); }) \
Simple merge
Simple merge