]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'martin-t/AMMO' into 'master'
authorMario <mario.mario@y7mail.com>
Thu, 26 Sep 2019 04:49:24 +0000 (04:49 +0000)
committerMario <mario.mario@y7mail.com>
Thu, 26 Sep 2019 04:49:24 +0000 (04:49 +0000)
Rename misleading const, fix overkill

See merge request xonotic/xonotic-data.pk3dir!692

1  2 
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/t_items.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/machinegun.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/weapons/weaponsystem.qc
ruleset-overkill.cfg
xonotic-server.cfg

index 27e0697daed09771616c51021d08790764706b56,7dc4461df87b5f99c4aa1ed41555072202da91e5..256af90affb3650cfc444b0e9d33827af1504ab1
@@@ -212,7 -212,7 +212,7 @@@ float buff_Available(entity buff
  {
        if (buff == BUFF_Null)
                return false;
-       if (buff == BUFF_AMMO && ((start_items & IT_UNLIMITED_WEAPON_AMMO) || (start_items & IT_UNLIMITED_AMMO) || (cvar("g_melee_only"))))
+       if (buff == BUFF_AMMO && ((start_items & IT_UNLIMITED_AMMO) || cvar("g_melee_only")))
                return false;
        if (buff == BUFF_VAMPIRE && cvar("g_vampire"))
                return false;
@@@ -576,6 -576,7 +576,6 @@@ MUTATOR_HOOKFUNCTION(buffs, PlayerSpawn
        entity player = M_ARGV(0, entity);
  
        player.oldbuffs = 0;
 -      PS(player).buff_shield = time + 0.5; // prevent picking up buffs immediately
        // reset timers here to prevent them continuing after re-spawn
        player.buff_disability_time = 0;
        player.buff_disability_effect_time = 0;
@@@ -917,8 -918,8 +917,8 @@@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreTh
  
                BUFF_ONADD(BUFF_AMMO)
                {
-                       player.buff_ammo_prev_infitems = (player.items & IT_UNLIMITED_WEAPON_AMMO);
-                       player.items |= IT_UNLIMITED_WEAPON_AMMO;
+                       player.buff_ammo_prev_infitems = (player.items & IT_UNLIMITED_AMMO);
+                       player.items |= IT_UNLIMITED_AMMO;
  
                        if(STAT(BUFFS, player) & BUFF_AMMO.m_itemid)
                        {
                BUFF_ONREM(BUFF_AMMO)
                {
                        if(player.buff_ammo_prev_infitems)
-                               player.items |= IT_UNLIMITED_WEAPON_AMMO;
+                               player.items |= IT_UNLIMITED_AMMO;
                        else
-                               player.items &= ~IT_UNLIMITED_WEAPON_AMMO;
+                               player.items &= ~IT_UNLIMITED_AMMO;
  
                        if(STAT(BUFFS, player) & BUFF_AMMO.m_itemid)
                        {
diff --combined qcsrc/common/t_items.qc
index d349f48c54653ef954d32c56ce7c0c3653d2a963,a1476ae14c9a13d0e9158f0f303db2676b5d47c0..9d595b9591df90326e8d188c17ef2abfdc94f6ee
@@@ -780,14 -780,14 +780,14 @@@ bool Item_GiveTo(entity item, entity pl
                }
        }
        bool pickedup = false;
 -      pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_HEALTH, item.max_health));
 -      pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_ARMOR, item.max_armorvalue));
 -      pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_SHELLS, g_pickup_shells_max));
 -      pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_BULLETS, g_pickup_nails_max));
 -      pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_ROCKETS, g_pickup_rockets_max));
 -      pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_CELLS, g_pickup_cells_max));
 -      pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_PLASMA, g_pickup_plasma_max));
 -      pickedup = (pickedup || Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max));
 +      pickedup |= Item_GiveAmmoTo(item, player, RES_HEALTH, item.max_health);
 +      pickedup |= Item_GiveAmmoTo(item, player, RES_ARMOR, item.max_armorvalue);
 +      pickedup |= Item_GiveAmmoTo(item, player, RES_SHELLS, g_pickup_shells_max);
 +      pickedup |= Item_GiveAmmoTo(item, player, RES_BULLETS, g_pickup_nails_max);
 +      pickedup |= Item_GiveAmmoTo(item, player, RES_ROCKETS, g_pickup_rockets_max);
 +      pickedup |= Item_GiveAmmoTo(item, player, RES_CELLS, g_pickup_cells_max);
 +      pickedup |= Item_GiveAmmoTo(item, player, RES_PLASMA, g_pickup_plasma_max);
 +      pickedup |= Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max);
        if (item.itemdef.instanceOfWeaponPickup)
        {
                WepSet w;
@@@ -1477,9 -1477,6 +1477,6 @@@ void target_items_use(entity this, enti
  
  spawnfunc(target_items)
  {
-       int n;
-       string s;
        this.use = target_items_use;
        if(!this.strength_finished)
                this.strength_finished = autocvar_g_balance_powerup_strength_time;
        if(!this.superweapons_finished)
                this.superweapons_finished = autocvar_g_balance_superweapons_time;
  
-       n = tokenize_console(this.netname);
+       int n = tokenize_console(this.netname);
        if(argv(0) == "give")
        {
                this.netname = substring(this.netname, argv_start_index(1), argv_end_index(-1) - argv_start_index(1));
        {
                for(int j = 0; j < n; ++j)
                {
-                       if     (argv(j) == "unlimited_ammo")         this.items |= IT_UNLIMITED_AMMO;
-                       else if(argv(j) == "unlimited_weapon_ammo")  this.items |= IT_UNLIMITED_WEAPON_AMMO;
+                       // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
+                       if     (argv(j) == "unlimited_ammo")         this.items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
+                       else if(argv(j) == "unlimited_weapon_ammo")  this.items |= IT_UNLIMITED_AMMO;
                        else if(argv(j) == "unlimited_superweapons") this.items |= IT_UNLIMITED_SUPERWEAPONS;
                        else if(argv(j) == "strength")               this.items |= ITEM_Strength.m_itemid;
                        else if(argv(j) == "invincible")             this.items |= ITEM_Shield.m_itemid;
                        {
                                FOREACH(Buffs, it != BUFF_Null,
                                {
-                                       s = Buff_UndeprecateName(argv(j));
+                                       string s = Buff_UndeprecateName(argv(j));
                                        if(s == it.netname)
                                        {
                                                STAT(BUFFS, this) |= (it.m_itemid);
                                        }
                                });
                                FOREACH(Weapons, it != WEP_Null, {
-                                       s = W_UndeprecateName(argv(j));
+                                       string s = W_UndeprecateName(argv(j));
                                        if(s == it.netname)
                                        {
                                                STAT(WEAPONS, this) |= (it.m_wepset);
                }
  
                this.netname = "";
-               this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, boolean(this.items & IT_UNLIMITED_WEAPON_AMMO), "unlimited_weapon_ammo");
+               this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, boolean(this.items & IT_UNLIMITED_AMMO), "unlimited_weapon_ammo");
                this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, boolean(this.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
                this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, this.strength_finished * boolean(this.items & ITEM_Strength.m_itemid), "strength");
                this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, this.invincible_finished * boolean(this.items & ITEM_Shield.m_itemid), "invincible");
@@@ -1763,7 -1761,7 +1761,7 @@@ float GiveItems(entity e, float beginar
                                got += GiveValue(e, strength_finished, op, val);
                                got += GiveValue(e, invincible_finished, op, val);
                                got += GiveValue(e, superweapons_finished, op, val);
-                               got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
+                               got += GiveBit(e, items, IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS, op, val);
                        case "all":
                                got += GiveBit(e, items, ITEM_Jetpack.m_itemid, op, val);
                                got += GiveResourceValue(e, RES_HEALTH, op, val);
                                got += GiveResourceValue(e, RES_FUEL, op, val);
                                break;
                        case "unlimited_ammo":
-                               got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
+                               // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
+                               got += GiveBit(e, items, IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS, op, val);
                                break;
                        case "unlimited_weapon_ammo":
-                               got += GiveBit(e, items, IT_UNLIMITED_WEAPON_AMMO, op, val);
+                               got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
                                break;
                        case "unlimited_superweapons":
                                got += GiveBit(e, items, IT_UNLIMITED_SUPERWEAPONS, op, val);
  
        POSTGIVE_BIT(e, items, ITEM_JetpackRegen.m_itemid, SND_ITEMPICKUP, SND_Null);
        POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, SND_POWERUP, SND_POWEROFF);
-       POSTGIVE_BIT(e, items, IT_UNLIMITED_WEAPON_AMMO, SND_POWERUP, SND_POWEROFF);
+       POSTGIVE_BIT(e, items, IT_UNLIMITED_AMMO, SND_POWERUP, SND_POWEROFF);
        POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND_ITEMPICKUP, SND_Null);
        FOREACH(Weapons, it != WEP_Null, {
                POSTGIVE_WEAPON(e, it, SND_WEAPONPICKUP, SND_Null);
index db14a603068f47d3b9c267cad6369b2573359dd7,2a42f475b4cd1e094f15c931af5e21ff941fabe9..a69f43fbd3f7afbdd01bca9d88707ee5255c5729
@@@ -43,15 -43,9 +43,15 @@@ void W_Crylink_Dequeue(entity e
        W_Crylink_Dequeue_Raw(e.crylink_owner, e.queueprev, e, e.queuenext);
  }
  
 +void W_Crylink_DeleteLink(entity this)
 +{
 +      if(this.classname != "spike_oktoremove")
 +              W_Crylink_Dequeue(this);
 +      delete_fn(this);
 +}
 +
  void W_Crylink_Reset(entity this)
  {
 -      W_Crylink_Dequeue(this);
        delete(this);
  }
  
@@@ -269,6 -263,7 +269,6 @@@ void W_Crylink_Touch(entity this, entit
        else if(finalhit)
        {
                // just unlink
 -              W_Crylink_Dequeue(this);
                delete(this);
                return;
        }
  
  void W_Crylink_Fadethink(entity this)
  {
 -      W_Crylink_Dequeue(this);
        delete(this);
  }
  
@@@ -312,7 -308,6 +312,7 @@@ void W_Crylink_Attack(Weapon thiswep, e
        for(counter = 0; counter < shots; ++counter)
        {
                proj = new(spike);
 +              proj.dtor = W_Crylink_DeleteLink;
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = actor;
                proj.crylink_owner = actor;
@@@ -425,7 -420,6 +425,7 @@@ void W_Crylink_Attack2(Weapon thiswep, 
        for(counter = 0; counter < shots; ++counter)
        {
                proj = new(spike);
 +              proj.dtor = W_Crylink_DeleteLink;
                proj.weaponentity_fld = weaponentity;
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = actor;
@@@ -574,7 -568,7 +574,7 @@@ METHOD(Crylink, wr_think, void(entity t
              }
              actor.(weaponentity).crylink_waitrelease = 0;
              if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity) && !thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-             if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+             if(!(actor.items & IT_UNLIMITED_AMMO))
              {
                  // ran out of ammo!
                  actor.cnt = thiswep.m_id;
index fc42f39d71763909615daaedb2c6790445f1aa51,62b7b556f29b7d35acb1c9b4a8f184af775ba992..fce84c3b8eb88cc3d0b36a37861a361e5810f103
@@@ -47,7 -47,7 +47,7 @@@ void W_Devastator_Explode(entity this, 
        if(this.realowner.(weaponentity).m_weapon == thiswep)
        {
                if(GetResource(this.realowner, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
-               if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!(this.realowner.items & IT_UNLIMITED_AMMO))
                {
                        this.realowner.cnt = thiswep.m_id;
                        ATTACK_FINISHED(this.realowner, weaponentity) = time;
@@@ -71,11 -71,8 +71,11 @@@ void W_Devastator_DoRemoteExplode(entit
  
        bool handled_as_rocketjump = false;
        entity head = NULL;
 +      bool allow_rocketjump = WEP_CVAR(devastator, remote_jump);
 +      MUTATOR_CALLHOOK(AllowRocketJumping, allow_rocketjump);
 +      allow_rocketjump = M_ARGV(0, bool);
  
 -      if(WEP_CVAR(devastator, remote_jump_radius))
 +      if(allow_rocketjump && WEP_CVAR(devastator, remote_jump_radius))
        {
                head = WarpZone_FindRadius(
                        this.origin,
        if(this.realowner.(weaponentity).m_weapon == thiswep)
        {
                if(GetResource(this.realowner, thiswep.ammo_type) < WEP_CVAR(devastator, ammo))
-               if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!(this.realowner.items & IT_UNLIMITED_AMMO))
                {
                        this.realowner.cnt = thiswep.m_id;
                        ATTACK_FINISHED(this.realowner, weaponentity) = time;
@@@ -317,7 -314,7 +317,7 @@@ void W_Devastator_Attack(Weapon thiswep
        if(WEP_CVAR(devastator, detonatedelay) >= 0)
                missile.spawnshieldtime = time + WEP_CVAR(devastator, detonatedelay);
        else
 -              missile.spawnshieldtime = -1;
 +              missile.spawnshieldtime = -1; // NOTE: proximity based when rocket jumping
        missile.pushltime = time + WEP_CVAR(devastator, guidedelay);
        missile.classname = "rocket";
        missile.bot_dodge = true;
index e16ffe66bd451b1a7a4927aaa047417cd3d645db,8aed354348dcc6cd7f02f493faab75052a9cad13..86de79f600603d02f84bab06858b5dc533b42508
@@@ -84,7 -84,7 +84,7 @@@ void W_MachineGun_Attack_Frame(Weapon t
        if(PHYS_INPUT_BUTTON_ATCK(actor))
        {
                if(!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(!(actor.items & IT_UNLIMITED_AMMO))
                {
                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                        w_ready(thiswep, actor, weaponentity, fire);
@@@ -110,7 -110,7 +110,7 @@@ void W_MachineGun_Attack_Auto(Weapon th
        }
  
        if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
-       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       if(!(actor.items & IT_UNLIMITED_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
@@@ -190,14 -190,10 +190,14 @@@ METHOD(MachineGun, wr_aim, void(entity 
  }
  METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
  {
 -    if(WEP_CVAR(machinegun, reload_ammo) && actor.(weaponentity).clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) { // forced reload
 +    // forced reload - wait until the bulletcounter is 0 so a burst loop can finish
 +    if(WEP_CVAR(machinegun, reload_ammo)
 +        && actor.(weaponentity).clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))
 +        && actor.(weaponentity).misc_bulletcounter >= 0)
 +    {
          thiswep.wr_reload(thiswep, actor, weaponentity);
 -    } else
 -    if(WEP_CVAR(machinegun, mode) == 1)
 +    }
 +    else if(WEP_CVAR(machinegun, mode) == 1)
      {
          if(fire & 1)
          if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
              W_MachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
          }
  
 +        // You can "shoot" more rounds than what's "used", and vice versa.
          if(fire & 2)
          if(weapon_prepareattack(thiswep, actor, weaponentity, true, 0))
          {
              if(!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-             if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+             if(!(actor.items & IT_UNLIMITED_AMMO))
              {
                  W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                  w_ready(thiswep, actor, weaponentity, fire);
                  return;
              }
  
 -            W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, burst_ammo), weaponentity);
 +            float ammo_available;
 +            if (WEP_CVAR(machinegun, reload_ammo) > 0)
 +            {
 +                ammo_available = actor.(weaponentity).clip_load;
 +            }
 +            else
 +            {
 +                ammo_available = GetResource(actor, thiswep.ammo_type);
 +            }
 +
 +            // We don't want to shoot 3 rounds if there's 2 left in the mag, so we'll use a fraction.
 +            // Also keep the fraction <= 1 otherwise we'd mag dump in one burst.
 +            float burst_fraction = min(1, ammo_available / WEP_CVAR(machinegun, burst_ammo));
 +            int to_shoot = floor(WEP_CVAR(machinegun, burst) * burst_fraction);
  
 -            actor.(weaponentity).misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
 +            // We also don't want to use 3 rounds if there's only 2 left.
 +            int to_use = min(WEP_CVAR(machinegun, burst_ammo), ammo_available);
 +            W_DecreaseAmmo(thiswep, actor, to_use, weaponentity);
 +
 +            // Bursting counts up to 0 from a negative.
 +            actor.(weaponentity).misc_bulletcounter = -to_shoot;
              W_MachineGun_Attack_Burst(thiswep, actor, weaponentity, fire);
          }
      }
@@@ -282,16 -259,15 +282,16 @@@ METHOD(MachineGun, wr_checkammo1, bool(
  METHOD(MachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
  {
      float ammo_amount;
 +    float burst_ammo_per_shot = WEP_CVAR(machinegun, burst_ammo) / WEP_CVAR(machinegun, burst);
      if(WEP_CVAR(machinegun, mode) == 1)
 -        ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR(machinegun, burst_ammo);
 +        ammo_amount = GetResource(actor, thiswep.ammo_type) >= burst_ammo_per_shot;
      else
          ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR(machinegun, first_ammo);
  
      if(WEP_CVAR(machinegun, reload_ammo))
      {
          if(WEP_CVAR(machinegun, mode) == 1)
 -            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(machinegun, burst_ammo);
 +            ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= burst_ammo_per_shot;
          else
              ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR(machinegun, first_ammo);
      }
  }
  METHOD(MachineGun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
  {
 +      if(actor.(weaponentity).misc_bulletcounter < 0)
 +              return;
      W_Reload(actor, weaponentity, min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), SND_RELOAD);
  }
  METHOD(MachineGun, wr_suicidemessage, Notification(entity thiswep))
index 18e75fad26e54aba8eed9cf6269ff6a5ecd9a29a,1eee25a05cc1d0992a587d6304856f327f7f6f26..e2f4b640aa1b818f3a6b7640c9cf7be2d61c93b2
@@@ -16,17 -16,8 +16,17 @@@ void W_Shotgun_Attack(Weapon thiswep, e
        W_DecreaseAmmo(thiswep, actor, ammocount, weaponentity);
  
        W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), damage * bullets, thiswep.m_id);
 +
 +      // TRICK: do the antilag outside the regular fireBullet function, so it isn't performed unnecessarily on every single bullet!
 +      float lag = antilag_getlag(actor);
 +      if(lag && bullets > 0)
 +              antilag_takeback_all(actor, lag);
 +
        for(int sc = 0;sc < bullets;sc = sc + 1)
 -              fireBullet(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, thiswep.m_id, bullet_trail_effect);
 +              fireBullet_antilag(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, thiswep.m_id, bullet_trail_effect, false);
 +      
 +      if(lag && bullets > 0)
 +              antilag_restore_all(actor);
  
        Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, ammocount);
  
@@@ -162,7 -153,7 +162,7 @@@ void W_Shotgun_Attack2(Weapon thiswep, 
  void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity, int fire)
  {
        if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       if (!(actor.items & IT_UNLIMITED_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
  void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
  {
        if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
-       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       if (!(actor.items & IT_UNLIMITED_AMMO))
        {
                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
@@@ -263,7 -254,7 +263,7 @@@ METHOD(Shotgun, wr_think, void(entity t
      }
      if(actor.(weaponentity).clip_load >= 0) // we are not currently reloading
      if(WEP_CVAR(shotgun, secondary) == 1)
-     if(((fire & 1) && GetResource(actor, thiswep.ammo_type) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (fire & 2))
+     if(((fire & 1) && GetResource(actor, thiswep.ammo_type) <= 0 && !(actor.items & IT_UNLIMITED_AMMO)) || (fire & 2))
      if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(shotgun, refire)))
      {
          // attempt forcing playback of the anim by switching to another anim (that we never play) here...
index 026e1d7ceb9e9fa190633702e12f819a09526f49,5fb0c7b94fef530a28b5e57288569185edbb7f5a..ded47a6387f97920ce32f2fa41851a7b8ec32dea
@@@ -715,7 -715,7 +715,7 @@@ void readplayerstartcvars(
        {
                g_weapon_stay = 0; // incompatible
                start_weapons = g_weaponarena_weapons;
-               start_items |= IT_UNLIMITED_AMMO;
+               start_items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
        }
        else
        {
        if(!cvar("g_use_ammunition"))
                start_items |= IT_UNLIMITED_AMMO;
  
-       if(start_items & IT_UNLIMITED_WEAPON_AMMO)
+       if(start_items & IT_UNLIMITED_AMMO)
        {
                start_ammo_shells = 999;
                start_ammo_nails = 999;
@@@ -1196,6 -1196,11 +1196,6 @@@ bool WarpZone_Projectile_Touch_ImpactFi
                        return false; // no checks here
                else if(this.classname == "grapplinghook")
                        RemoveHook(this);
 -              else if(this.classname == "spike")
 -              {
 -                      W_Crylink_Dequeue(this);
 -                      delete(this);
 -              }
                else
                        delete(this);
                return true;
index f1655b632269bb79a4c6b4ae732b2886f928c77d,f2eec236c9a51b137a418cba35331c4ce1fd3d3b..d593658a3d2a5bac7b265ebe06331dfa16f508a4
@@@ -224,7 -224,7 +224,7 @@@ void w_ready(Weapon thiswep, entity act
  .float prevwarntime;
  bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary, .entity weaponentity)
  {
-       if ((actor.items & IT_UNLIMITED_WEAPON_AMMO)) return true;
+       if ((actor.items & IT_UNLIMITED_AMMO)) return true;
        bool ammo = false;
        if (secondary) ammo = thiswep.wr_checkammo2(thiswep, actor, weaponentity);
        else ammo = thiswep.wr_checkammo1(thiswep, actor, weaponentity);
@@@ -688,7 -688,7 +688,7 @@@ void W_AttachToShotorg(entity actor, .e
  void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity)
  {
        if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor, actor.(weaponentity), ammo_use)) return;
-       if ((actor.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo) return;
+       if ((actor.items & IT_UNLIMITED_AMMO) && !wep.reloading_ammo) return;
  
        ammo_use = M_ARGV(2, float);
  
@@@ -735,7 -735,7 +735,7 @@@ void W_ReloadedAndReady(Weapon thiswep
        w_ent.clip_load = w_ent.old_clip_load;  // restore the ammo counter, in case we still had ammo in the weapon before reloading
  
        // if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
-       if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_WEAPON_AMMO) || wpn.ammo_type == RES_NONE)
+       if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_AMMO) || wpn.ammo_type == RES_NONE)
        {
                w_ent.clip_load = w_ent.reload_ammo_amount;
        }
@@@ -791,7 -791,7 +791,7 @@@ void W_Reload(entity actor, .entity wea
        {
                if (!GetResource(actor, e.ammo_type) && this.reload_ammo_min)
                {
-                       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+                       if (!(actor.items & IT_UNLIMITED_AMMO))
                        {
                                if (IS_REAL_CLIENT(actor) && actor.reload_complain < time)
                                {
                        }
                }
        }
 -
        if (this)
        {
                if (this.wframe == WFRAME_RELOAD) return;
diff --combined ruleset-overkill.cfg
index f74c1e9b0249467f0a66aec39360c27aec0ea326,5b71bb60a0576d40959a59b0a91d7e3404dc61f4..cb39b2a10ce1a16c1b5cb554be256a42e01c52f5
@@@ -10,8 -10,6 +10,6 @@@ if_dedicated exec help-overkill.cf
  
  g_overkill 1
  
- g_use_ammunition 0
  // hack - eventually, we should be able to choose overkill models in menu like for vanilla
  sv_defaultcharacter 1
  sv_defaultplayermodel "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
@@@ -36,3 -34,5 +34,3 @@@ g_spawn_near_teammate "!g_assault !g_fr
  g_spawn_near_teammate_ignore_spawnpoint 1
  g_spawnshieldtime 0.5
  g_respawn_delay_forced 2
 -
 -g_buffs_resistance_blockpercent 0.5
diff --combined xonotic-server.cfg
index d17ba5c3118b58937cfa8f51982379bafd74067c,13f790714f96ecaa413cc4f0af9f0f293576c7a8..6d1f427725a18e9e691decb7e9631dc13478b44d
@@@ -32,8 -32,6 +32,8 @@@ set g_warmup_allow_timeout 0  "allow cal
  set g_warmup_allguns 1        "provide more weapons on start while in warmup: 0 = normal start weapons, 1 = all guns available on the map, 2 = all normal weapons"
  set g_warmup_majority_factor 0.8 "minimum percentage of players ready needed for warmup to end"
  
 +alias sv_hook_warmupend
 +
  set g_chat_nospectators 0     "if 0 spec/observer chat is always visible to the player, if 1 it is never visible to players, if 2 it is only visible to players during warmup stage"
  set sv_vote_nospectators 0    "only players can call a vote (thus spectators and observers can't call a vote): 0 = all people can vote, 1 = spectators can vote in warmup stage, 2 = only players can vote (no exceptions)."
  
@@@ -114,7 -112,6 +114,7 @@@ set bot_usemodelnames 0    "Use player mod
  set bot_nofire 0      "When set, bots never fire. Mainly for testing in g_waypointeditor mode"
  set bot_prefix [BOT]  "Prefix in front of the bot names"
  set bot_suffix ""     "Suffix behind the bot names"
 +skill 8
  set skill_auto 0      "when 1, \"skill\" gets adjusted to match the best player on the map"
  set bot_debug_tracewalk 0 "Enable visual indicators for short-term navigation. Green: Goal Reached / Yellow: Obstacle found / Red: Unsolvable obstacle found"
  set bot_debug_goalstack 0 "Visualize the current path that each bot is following. Use with as few bots as possible."
@@@ -193,7 -190,7 +193,7 @@@ set g_pinata 0 "if set to 1 you will no
  set g_weapon_stay 0 "1: ghost weapons can be picked up too but give no ammo, 2: ghost weapons refill ammo to one pickup size, thrown guns have no ammo"
  set g_weapon_throwable 1 "if set to 1, weapons can be dropped"
  set g_powerups -1 "if set to 0 the strength and shield (invincibility) will not spawn on the map, if 1 they will spawn in all game modes, -1 is game mode default"
- set g_use_ammunition 1 "if set to 0 all weapons have unlimited ammunition"
+ set g_use_ammunition 1 "if set to 0 all weapons have unlimited ammo"
  set g_pickup_items -1 "if set to 0 all items (health, armor, ammo, weapons...) are removed from the map, if 1 they are forced to spawn"
  set g_pickup_respawntime_scaling_reciprocal 0 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to 0) can be used to achieve a constant number of items spawned *per player*"
  set g_pickup_respawntime_scaling_offset 0 "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `offset` offsets the curve left or right - the results are not intuitive and I recommend plotting the respawn time and the number of items per player to see what's happening"
@@@ -424,11 -421,15 +424,11 @@@ set g_ban_sync_trusted_servers_verify 
  
  set g_showweaponspawns 1 "1: display waypoints for weapon spawns found on the map when a weapon key is pressed and the weapon is not owned; 2: for dropped weapons too; 3: for all the weapons sharing the same impulse"
  
 -// ballistics use physical units, but qu based
 -//   Quake-Newton: 1 qN  = 1 qu * 1 g / 1 s^2
 -//   Quake-Joule:  1 qJ  = 1 qN * 1 qu
 -//   Quake-Pascal: 1 qPa = 1 qN / 1 qu^2
 -
 -set g_ballistics_mindistance 2 "enable ballistics starting from 2 qu"
 -set g_ballistics_density_player 0.50 "players are 2x as easy to pass through as walls"
 -set g_ballistics_density_corpse 0.10 "corpses are 10x as easy to pass through as walls"
 -set g_ballistics_penetrate_clips 0 "allow ballistics to pass through weapon clips"
 +set g_ballistics_mindistance 2 "when shooting through walls thinner than this, treat them as this thick (useful because patches (curved surfaces) have no thickness)"
 +set g_ballistics_density_player 0.50 "how hard players are to shoot through compared to walls"
 +set g_ballistics_density_corpse 0.10 "how hard corpses are to shoot through compared to walls"
 +set g_ballistics_penetrate_clips 1 "allow ballistics to pass through weapon clips"
 +set g_ballistics_solidpenetration_exponent 0.25 "how fast damage falls off when bullets pass through walls - 1 means linear, lower values mean slower initial falloff but faster once there's little solidpenetration left (damage_fraction = solidpen_fraction^exp for solidpen_fraction between 0 and 1)"
  
  sv_status_show_qcstatus 1     "Xonotic uses this field instead of frags"
  set g_full_getstatus_responses 0      "this currently breaks qstat"
@@@ -493,8 -494,6 +493,8 @@@ set g_maxspeed 0 "player speed limit, f
  
  // sv_cullentities_trace is 1, so the client doesn't have to
  sv_cullentities_trace 1
 +// due to a bug in the engine, the default setting of this (16) spams the network with item updates
 +sv_cullentities_trace_eyejitter 0
  
  // less "lagging" of other players, but also less PL tolerant... let's try this
  sv_clmovement_inputtimeout 0.066 // slightly less than 2 frames, so only one frame can be compensated
@@@ -566,4 -565,3 +566,4 @@@ set sv_showspectators 1 "Show who's spe
  set sv_damagetext 2 "<= 0: disabled, >= 1: visible to spectators, >= 2: visible to attacker, >= 3: all players see everyone's damage"
  
  set sv_showfps 5 "Show player's FPS counters in the scoreboard. This setting acts as a delay in seconds between updates"
 +set autocvar_sv_doors_always_open 0 "If set to 1 don't close doors which after they were open"