]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/t_items.qc
Cleanse teamplay.qc of the looping horrors
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / t_items.qc
index f295777db791f581cc15e5a10ecdd4eb79cdea3b..8bce02ca18ede89a42cd2499168c550ea3fbd342 100644 (file)
 REGISTER_NET_LINKED(ENT_CLIENT_ITEM)
 
 #ifdef CSQC
-void ItemDraw(entity self)
+void ItemDraw(entity this)
 {
-    if(self.gravity)
+    if(this.gravity)
     {
-        Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
-        if(self.move_flags & FL_ONGROUND)
+        Movetype_Physics_MatchServer(this, false);
+        if(this.move_flags & FL_ONGROUND)
         { // For some reason move_avelocity gets set to '0 0 0' here ...
-            self.oldorigin = self.origin;
-            self.gravity = 0;
+            this.oldorigin = this.origin;
+            this.gravity = 0;
 
             if(autocvar_cl_animate_items)
             { // ... so reset it if animations are requested.
-                if(self.ItemStatus & ITS_ANIMATE1)
-                    self.move_avelocity = '0 180 0';
+                if(this.ItemStatus & ITS_ANIMATE1)
+                    this.move_avelocity = '0 180 0';
 
-                if(self.ItemStatus & ITS_ANIMATE2)
-                    self.move_avelocity = '0 -90 0';
+                if(this.ItemStatus & ITS_ANIMATE2)
+                    this.move_avelocity = '0 -90 0';
             }
         }
     }
     else if (autocvar_cl_animate_items)
     {
-        if(self.ItemStatus & ITS_ANIMATE1)
+        if(this.ItemStatus & ITS_ANIMATE1)
         {
-            self.angles += self.move_avelocity * frametime;
-            setorigin(self, '0 0 10' + self.oldorigin + '0 0 8' * sin(time * 2));
+            this.angles += this.move_avelocity * frametime;
+            setorigin(this, '0 0 10' + this.oldorigin + '0 0 8' * sin(time * 2));
         }
 
-        if(self.ItemStatus & ITS_ANIMATE2)
+        if(this.ItemStatus & ITS_ANIMATE2)
         {
-            self.angles += self.move_avelocity * frametime;
-            setorigin(self, '0 0 8' + self.oldorigin + '0 0 4' * sin(time * 3));
+            this.angles += this.move_avelocity * frametime;
+            setorigin(this, '0 0 8' + this.oldorigin + '0 0 4' * sin(time * 3));
         }
     }
 }
 
 void ItemDrawSimple(entity this)
 {
-    if(self.gravity)
+    if(this.gravity)
     {
-        Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+        Movetype_Physics_MatchServer(this, false);
 
-        if(self.move_flags & FL_ONGROUND)
-            self.gravity = 0;
+        if(this.move_flags & FL_ONGROUND)
+            this.gravity = 0;
     }
 }
 
@@ -96,6 +96,12 @@ void Item_PreDraw()
                self.drawmask = MASK_NORMAL;
 }
 
+void ItemRemove()
+{SELFPARAM();
+       if (self.mdl)
+               strunzone(self.mdl);
+}
+
 NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
 {
     int sf = ReadByte();
@@ -166,8 +172,12 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
     if(sf & ISF_MODEL)
     {
         self.drawmask  = MASK_NORMAL;
-               self.move_movetype = self.movetype = MOVETYPE_TOSS;
+               self.move_movetype = MOVETYPE_TOSS;
         self.draw       = ItemDraw;
+        self.solid = SOLID_TRIGGER;
+        //self.move_flags |= FL_ITEM;
+
+        bool use_bigsize = ReadByte();
 
         self.fade_end = ReadShort();
         self.fade_start = ReadShort();
@@ -205,10 +215,12 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
 
 
         if(self.mdl == "")
-            LOG_TRACE("^1WARNING!^7 self.mdl is unset for item ", self.classname, " tell tZork aboute this!\n");
+            LOG_TRACE("^1WARNING!^7 self.mdl is unset for item ", self.classname, ", tell tZork about this!\n");
 
         precache_model(self.mdl);
         _setmodel(self, self.mdl);
+
+        setsize(self, '-16 -16 0', (use_bigsize) ? '16 16 48' : '16 16 32');
     }
 
     if(sf & ISF_COLORMAP)
@@ -217,6 +229,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
     if(sf & ISF_DROP)
     {
         self.gravity = 1;
+        self.pushable = true;
         //self.move_angles = '0 0 0';
         self.move_movetype = MOVETYPE_TOSS;
         self.move_velocity_x = ReadCoord();
@@ -242,6 +255,9 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
         if(self.ItemStatus & ITS_ANIMATE2)
             self.move_avelocity = '0 -90 0';
     }
+
+    self.entremove = ItemRemove;
+
     return true;
 }
 
@@ -284,6 +300,8 @@ bool ItemSend(entity this, entity to, int sf)
 
        if(sf & ISF_MODEL)
        {
+               Pickup p = this.itemdef;
+               WriteByte(MSG_ENTITY, p.instanceOfPowerup || p.instanceOfHealth || p.instanceOfArmor);
                WriteShort(MSG_ENTITY, self.fade_end);
                WriteShort(MSG_ENTITY, self.fade_start);
 
@@ -307,9 +325,16 @@ bool ItemSend(entity this, entity to, int sf)
        return true;
 }
 
-void ItemUpdate(entity item)
+void ItemUpdate(entity this)
+{
+       this.oldorigin = this.origin;
+       this.SendFlags |= ISF_LOCATION;
+}
+
+void UpdateItemAfterTeleport(entity this)
 {
-       item.SendFlags |= ISF_LOCATION;
+       if(this.SendEntity3 == ItemSend)
+               ItemUpdate(this);
 }
 
 bool have_pickup_item(entity this)
@@ -427,10 +452,7 @@ void Item_Think()
 {SELFPARAM();
        self.nextthink = time;
        if(self.origin != self.oldorigin)
-       {
-               self.oldorigin = self.origin;
                ItemUpdate(self);
-       }
 }
 
 bool Item_ItemsTime_SpectatorOnly(GameItem it);
@@ -482,8 +504,8 @@ void Item_RespawnCountdown ()
                        MUTATOR_CALLHOOK(Item_RespawnCountdown, string_null, '0 0 0');
                        do {
                                {
-                                       entity wi = get_weaponinfo(self.weapon);
-                                       if (wi.m_id) {
+                                       entity wi = Weapons_from(self.weapon);
+                                       if (wi != WEP_Null) {
                                                entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Weapon);
                                                wp.wp_extra = wi.m_id;
                                                break;
@@ -491,7 +513,7 @@ void Item_RespawnCountdown ()
                                }
                                {
                                        entity ii = self.itemdef;
-                                       if (ii.m_id) {
+                                       if (ii != NULL) {
                                                entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Item);
                                                wp.wp_extra = ii.m_id;
                                                break;
@@ -529,10 +551,7 @@ void Item_RespawnThink()
 {SELFPARAM();
        self.nextthink = time;
        if(self.origin != self.oldorigin)
-       {
-               self.oldorigin = self.origin;
                ItemUpdate(self);
-       }
 
        if(time >= self.wait)
                Item_Respawn();
@@ -623,8 +642,6 @@ float Item_GiveTo(entity item, entity player)
 {
        float _switchweapon;
        float pickedup;
-       float it;
-       float i;
 
        // if nothing happens to player, just return without taking the item
        pickedup = false;
@@ -633,10 +650,10 @@ float Item_GiveTo(entity item, entity player)
        // if the player is using their best weapon before items are given, they
        // probably want to switch to an even better weapon after items are given
        if (player.autoswitch)
-       if (player.switchweapon == w_getbestweapon(player))
+       if (PS(player).m_switchweapon == w_getbestweapon(player))
                _switchweapon = true;
 
-       if (!(player.weapons & WepSet_FromWeapon(player.switchweapon)))
+       if (!(player.weapons & WepSet_FromWeapon(PS(player).m_switchweapon)))
                _switchweapon = true;
 
        pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
@@ -650,26 +667,28 @@ float Item_GiveTo(entity item, entity player)
 
        if (item.itemdef.instanceOfWeaponPickup)
        {
-               WepSet it;
-               it = item.weapons;
-               it &= ~player.weapons;
+               WepSet w;
+               w = item.weapons;
+               w &= ~player.weapons;
 
-               if (it || (item.spawnshieldtime && item.pickup_anyway > 0))
+               if (w || (item.spawnshieldtime && item.pickup_anyway > 0))
                {
                        pickedup = true;
-                       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-                       if(it & WepSet_FromWeapon(i))
-                       {
-                               W_DropEvent(wr_pickup, player, i, item);
-                               W_GiveWeapon(player, i);
-                       }
+                       FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                               if(w & (it.m_wepset))
+                               {
+                                       W_DropEvent(wr_pickup, player, it.m_id, item);
+                                       W_GiveWeapon(player, it.m_id);
+                               }
+                       ));
                }
        }
 
-       if((it = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
+       int its;
+       if((its = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
        {
                pickedup = true;
-               player.items |= it;
+               player.items |= its;
                Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_ITEM_WEAPON_GOT, item.netname);
        }
 
@@ -701,12 +720,12 @@ float Item_GiveTo(entity item, entity player)
        // crude hack to enforce switching weapons
        if(g_cts && item.itemdef.instanceOfWeaponPickup)
        {
-               W_SwitchWeapon_Force(player, item.weapon);
+               W_SwitchWeapon_Force(player, Weapons_from(item.weapon));
                return 1;
        }
 
        if (_switchweapon)
-               if (player.switchweapon != w_getbestweapon(player))
+               if (PS(player).m_switchweapon != w_getbestweapon(player))
                        W_SwitchWeapon_Force(player, w_getbestweapon(player));
 
        return 1;
@@ -912,32 +931,28 @@ float weapon_pickupevalfunc(entity player, entity item)
 
 float commodity_pickupevalfunc(entity player, entity item)
 {
-       float c, i;
+       float c;
        float need_shells = false, need_nails = false, need_rockets = false, need_cells = false, need_plasma = false, need_fuel = false;
-       entity wi;
        c = 0;
 
        // Detect needed ammo
-       for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
-       {
-               wi = get_weaponinfo(i);
-
-               if (!(player.weapons & WepSet_FromWeapon(i)))
+       FOREACH(Weapons, it != WEP_Null, LAMBDA(
+               if(!(player.weapons & (it.m_wepset)))
                        continue;
 
-               if(wi.items & ITEM_Shells.m_itemid)
+               if(it.items & ITEM_Shells.m_itemid)
                        need_shells = true;
-               else if(wi.items & ITEM_Bullets.m_itemid)
+               else if(it.items & ITEM_Bullets.m_itemid)
                        need_nails = true;
-               else if(wi.items & ITEM_Rockets.m_itemid)
+               else if(it.items & ITEM_Rockets.m_itemid)
                        need_rockets = true;
-               else if(wi.items & ITEM_Cells.m_itemid)
+               else if(it.items & ITEM_Cells.m_itemid)
                        need_cells = true;
-               else if(wi.items & ITEM_Plasma.m_itemid)
+               else if(it.items & ITEM_Plasma.m_itemid)
                        need_plasma = true;
-               else if(wi.items & ITEM_JetpackFuel.m_itemid)
+               else if(it.items & ITEM_JetpackFuel.m_itemid)
                        need_fuel = true;
-       }
+       ));
 
        // TODO: figure out if the player even has the weapon this ammo is for?
        // may not affect strategy much though...
@@ -1014,7 +1029,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        }
 
        if(weaponid)
-               this.weapons = WepSet_FromWeapon(weaponid);
+               this.weapons = WepSet_FromWeapon(Weapons_from(weaponid));
 
        this.flags = FL_ITEM | itemflags;
 
@@ -1066,7 +1081,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                if(this.angles != '0 0 0')
                        this.SendFlags |= ISF_ANGLES;
 
-               this.reset = Item_Reset_self;
+               this.reset = Item_Reset;
                // it's a level item
                if(this.spawnflags & 1)
                        this.noalign = 1;
@@ -1117,7 +1132,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                        this.is_item = true;
                }
 
-               weaponsInMap |= WepSet_FromWeapon(weaponid);
+               weaponsInMap |= WepSet_FromWeapon(Weapons_from(weaponid));
 
                precache_model(this.model);
                precache_sound(this.item_pickupsound);
@@ -1199,10 +1214,10 @@ void StartItem(entity this, GameItem def)
 
 spawnfunc(item_rockets)
 {
-       if(!self.ammo_rockets)
-               self.ammo_rockets = g_pickup_rockets;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_ammo_anyway;
+       if(!this.ammo_rockets)
+               this.ammo_rockets = g_pickup_rockets;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_ammo_anyway;
     StartItem(this, ITEM_Rockets);
 }
 
@@ -1210,7 +1225,7 @@ spawnfunc(item_bullets)
 {
        if(!weaponswapping)
        if(autocvar_sv_q3acompat_machineshotgunswap)
-       if(self.classname != "droppedweapon")
+       if(this.classname != "droppedweapon")
        {
                weaponswapping = true;
                spawnfunc_item_shells(this);
@@ -1218,28 +1233,28 @@ spawnfunc(item_bullets)
                return;
        }
 
-       if(!self.ammo_nails)
-               self.ammo_nails = g_pickup_nails;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_ammo_anyway;
+       if(!this.ammo_nails)
+               this.ammo_nails = g_pickup_nails;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_ammo_anyway;
     StartItem(this, ITEM_Bullets);
 }
 
 spawnfunc(item_cells)
 {
-       if(!self.ammo_cells)
-               self.ammo_cells = g_pickup_cells;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_ammo_anyway;
+       if(!this.ammo_cells)
+               this.ammo_cells = g_pickup_cells;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_ammo_anyway;
        StartItem(this, ITEM_Cells);
 }
 
 spawnfunc(item_plasma)
 {
-       if(!self.ammo_plasma)
-               self.ammo_plasma = g_pickup_plasma;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_ammo_anyway;
+       if(!this.ammo_plasma)
+               this.ammo_plasma = g_pickup_plasma;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_ammo_anyway;
        StartItem(this, ITEM_Plasma);
 }
 
@@ -1247,7 +1262,7 @@ spawnfunc(item_shells)
 {
        if(!weaponswapping)
        if(autocvar_sv_q3acompat_machineshotgunswap)
-       if(self.classname != "droppedweapon")
+       if(this.classname != "droppedweapon")
        {
                weaponswapping = true;
                spawnfunc_item_bullets(this);
@@ -1255,98 +1270,98 @@ spawnfunc(item_shells)
                return;
        }
 
-       if(!self.ammo_shells)
-               self.ammo_shells = g_pickup_shells;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_ammo_anyway;
+       if(!this.ammo_shells)
+               this.ammo_shells = g_pickup_shells;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_ammo_anyway;
        StartItem(this, ITEM_Shells);
 }
 
 spawnfunc(item_armor_small)
 {
-       if(!self.armorvalue)
-               self.armorvalue = g_pickup_armorsmall;
-       if(!self.max_armorvalue)
-               self.max_armorvalue = g_pickup_armorsmall_max;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_armorsmall_anyway;
+       if(!this.armorvalue)
+               this.armorvalue = g_pickup_armorsmall;
+       if(!this.max_armorvalue)
+               this.max_armorvalue = g_pickup_armorsmall_max;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_armorsmall_anyway;
        StartItem(this, ITEM_ArmorSmall);
 }
 
 spawnfunc(item_armor_medium)
 {
-       if(!self.armorvalue)
-               self.armorvalue = g_pickup_armormedium;
-       if(!self.max_armorvalue)
-               self.max_armorvalue = g_pickup_armormedium_max;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_armormedium_anyway;
+       if(!this.armorvalue)
+               this.armorvalue = g_pickup_armormedium;
+       if(!this.max_armorvalue)
+               this.max_armorvalue = g_pickup_armormedium_max;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_armormedium_anyway;
        StartItem(this, ITEM_ArmorMedium);
 }
 
 spawnfunc(item_armor_big)
 {
-       if(!self.armorvalue)
-               self.armorvalue = g_pickup_armorbig;
-       if(!self.max_armorvalue)
-               self.max_armorvalue = g_pickup_armorbig_max;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_armorbig_anyway;
+       if(!this.armorvalue)
+               this.armorvalue = g_pickup_armorbig;
+       if(!this.max_armorvalue)
+               this.max_armorvalue = g_pickup_armorbig_max;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_armorbig_anyway;
        StartItem(this, ITEM_ArmorLarge);
 }
 
 spawnfunc(item_armor_large)
 {
-       if(!self.armorvalue)
-               self.armorvalue = g_pickup_armorlarge;
-       if(!self.max_armorvalue)
-               self.max_armorvalue = g_pickup_armorlarge_max;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_armorlarge_anyway;
+       if(!this.armorvalue)
+               this.armorvalue = g_pickup_armorlarge;
+       if(!this.max_armorvalue)
+               this.max_armorvalue = g_pickup_armorlarge_max;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_armorlarge_anyway;
        StartItem(this, ITEM_ArmorMega);
 }
 
 spawnfunc(item_health_small)
 {
-       if(!self.max_health)
-               self.max_health = g_pickup_healthsmall_max;
-       if(!self.health)
-               self.health = g_pickup_healthsmall;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_healthsmall_anyway;
+       if(!this.max_health)
+               this.max_health = g_pickup_healthsmall_max;
+       if(!this.health)
+               this.health = g_pickup_healthsmall;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_healthsmall_anyway;
        StartItem(this, ITEM_HealthSmall);
 }
 
 spawnfunc(item_health_medium)
 {
-       if(!self.max_health)
-               self.max_health = g_pickup_healthmedium_max;
-       if(!self.health)
-               self.health = g_pickup_healthmedium;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_healthmedium_anyway;
+       if(!this.max_health)
+               this.max_health = g_pickup_healthmedium_max;
+       if(!this.health)
+               this.health = g_pickup_healthmedium;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_healthmedium_anyway;
     StartItem(this, ITEM_HealthMedium);
 }
 
 spawnfunc(item_health_large)
 {
-       if(!self.max_health)
-               self.max_health = g_pickup_healthlarge_max;
-       if(!self.health)
-               self.health = g_pickup_healthlarge;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_healthlarge_anyway;
+       if(!this.max_health)
+               this.max_health = g_pickup_healthlarge_max;
+       if(!this.health)
+               this.health = g_pickup_healthlarge;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_healthlarge_anyway;
        StartItem(this, ITEM_HealthLarge);
 }
 
 spawnfunc(item_health_mega)
 {
-    if(!self.max_health)
-        self.max_health = g_pickup_healthmega_max;
-    if(!self.health)
-        self.health = g_pickup_healthmega;
-    if(!self.pickup_anyway)
-        self.pickup_anyway = g_pickup_healthmega_anyway;
+    if(!this.max_health)
+        this.max_health = g_pickup_healthmega_max;
+    if(!this.health)
+        this.health = g_pickup_healthmega;
+    if(!this.pickup_anyway)
+        this.pickup_anyway = g_pickup_healthmega_anyway;
     StartItem(this, ITEM_HealthMega);
 }
 
@@ -1359,20 +1374,20 @@ spawnfunc(item_health100) { spawnfunc_item_health_mega(this); }
 
 spawnfunc(item_strength)
 {
-               if(!self.strength_finished)
-                       self.strength_finished = autocvar_g_balance_powerup_strength_time;
+               if(!this.strength_finished)
+                       this.strength_finished = autocvar_g_balance_powerup_strength_time;
                StartItem(this, ITEM_Strength);
 }
 
 spawnfunc(item_invincible)
 {
-               if(!self.invincible_finished)
-                       self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
+               if(!this.invincible_finished)
+                       this.invincible_finished = autocvar_g_balance_powerup_invincible_time;
                StartItem(this, ITEM_Shield);
 }
 
 // compatibility:
-spawnfunc(item_quad) { self.classname = "item_strength";spawnfunc_item_strength(this);}
+spawnfunc(item_quad) { this.classname = "item_strength";spawnfunc_item_strength(this);}
 
 void target_items_use()
 {SELFPARAM();
@@ -1400,8 +1415,7 @@ void target_items_use()
 
 spawnfunc(target_items)
 {
-       float n, i, j;
-       entity e;
+       float n, i;
        string s;
 
        self.use = target_items_use;
@@ -1431,22 +1445,16 @@ spawnfunc(target_items)
                        else if(argv(i) == "fuel_regen")             self.items |= ITEM_JetpackRegen.m_itemid;
                        else
                        {
-                               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-                               {
-                                       e = get_weaponinfo(j);
+                               FOREACH(Weapons, it != WEP_Null, LAMBDA(
                                        s = W_UndeprecateName(argv(i));
-                                       if(s == e.netname)
+                                       if(s == it.netname)
                                        {
-                                               self.weapons |= WepSet_FromWeapon(j);
-                                               if(self.spawnflags == 0 || self.spawnflags == 2) {
-                                                       Weapon w = get_weaponinfo(e.weapon);
-                                                       w.wr_init(w);
-                                               }
+                                               self.weapons |= (it.m_wepset);
+                                               if(self.spawnflags == 0 || self.spawnflags == 2)
+                                                       it.wr_init(it);
                                                break;
                                        }
-                               }
-                               if(j > WEP_LAST)
-                                       LOG_INFO("target_items: invalid item ", argv(i), "\n");
+                               ));
                        }
                }
 
@@ -1478,13 +1486,13 @@ spawnfunc(target_items)
                }
 
                self.netname = "";
-               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_UNLIMITED_WEAPON_AMMO), "unlimited_weapon_ammo");
-               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
-               self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.strength_finished * !!(self.items & ITEM_Strength.m_itemid), "strength");
-               self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.invincible_finished * !!(self.items & ITEM_Shield.m_itemid), "invincible");
-               self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.superweapons_finished * !!(self.items & IT_SUPERWEAPON), "superweapons");
-               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & ITEM_Jetpack.m_itemid), "jetpack");
-               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & ITEM_JetpackRegen.m_itemid), "fuel_regen");
+               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, boolean(self.items & IT_UNLIMITED_WEAPON_AMMO), "unlimited_weapon_ammo");
+               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, boolean(self.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
+               self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.strength_finished * boolean(self.items & ITEM_Strength.m_itemid), "strength");
+               self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.invincible_finished * boolean(self.items & ITEM_Shield.m_itemid), "invincible");
+               self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.superweapons_finished * boolean(self.items & IT_SUPERWEAPON), "superweapons");
+               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, boolean(self.items & ITEM_Jetpack.m_itemid), "jetpack");
+               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, boolean(self.items & ITEM_JetpackRegen.m_itemid), "fuel_regen");
                if(self.ammo_shells != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_shells), "shells");
                if(self.ammo_nails != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_nails), "nails");
                if(self.ammo_rockets != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_rockets), "rockets");
@@ -1493,12 +1501,7 @@ spawnfunc(target_items)
                if(self.ammo_fuel != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_fuel), "fuel");
                if(self.health != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.health), "health");
                if(self.armorvalue != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.health), "armor");
-               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-               {
-                       e = get_weaponinfo(j);
-                       if(e.weapon)
-                               self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.weapons & WepSet_FromWeapon(j)), e.netname);
-               }
+               FOREACH(Weapons, it != WEP_Null, LAMBDA(self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.weapons & (it.m_wepset)), it.netname)));
        }
        self.netname = strzone(self.netname);
        //print(self.netname, "\n");
@@ -1506,25 +1509,22 @@ spawnfunc(target_items)
        n = tokenize_console(self.netname);
        for(i = 0; i < n; ++i)
        {
-               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-               {
-                       e = get_weaponinfo(j);
-                       if(argv(i) == e.netname)
+               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                       if(argv(i) == it.netname)
                        {
-                               Weapon w = get_weaponinfo(e.weapon);
-                               w.wr_init(w);
+                               it.wr_init(it);
                                break;
                        }
-               }
+               ));
        }
 }
 
 spawnfunc(item_fuel)
 {
-       if(!self.ammo_fuel)
-               self.ammo_fuel = g_pickup_fuel;
-       if(!self.pickup_anyway)
-               self.pickup_anyway = g_pickup_ammo_anyway;
+       if(!this.ammo_fuel)
+               this.ammo_fuel = g_pickup_fuel;
+       if(!this.pickup_anyway)
+               this.pickup_anyway = g_pickup_ammo_anyway;
        StartItem(this, ITEM_JetpackFuel);
 }
 
@@ -1540,8 +1540,8 @@ spawnfunc(item_fuel_regen)
 
 spawnfunc(item_jetpack)
 {
-       if(!self.ammo_fuel)
-               self.ammo_fuel = g_pickup_fuel_jetpack;
+       if(!this.ammo_fuel)
+               this.ammo_fuel = g_pickup_fuel_jetpack;
        if(start_items & ITEM_Jetpack.m_itemid)
        {
                spawnfunc_item_fuel(this);
@@ -1553,30 +1553,31 @@ spawnfunc(item_jetpack)
 float GiveWeapon(entity e, float wpn, float op, float val)
 {
        WepSet v0, v1;
-       v0 = (e.weapons & WepSet_FromWeapon(wpn));
+       WepSet s = WepSet_FromWeapon(Weapons_from(wpn));
+       v0 = (e.weapons & s);
        switch(op)
        {
                case OP_SET:
                        if(val > 0)
-                               e.weapons |= WepSet_FromWeapon(wpn);
+                               e.weapons |= s;
                        else
-                               e.weapons &= ~WepSet_FromWeapon(wpn);
+                               e.weapons &= ~s;
                        break;
                case OP_MIN:
                case OP_PLUS:
                        if(val > 0)
-                               e.weapons |= WepSet_FromWeapon(wpn);
+                               e.weapons |= s;
                        break;
                case OP_MAX:
                        if(val <= 0)
-                               e.weapons &= ~WepSet_FromWeapon(wpn);
+                               e.weapons &= ~s;
                        break;
                case OP_MINUS:
                        if(val > 0)
-                               e.weapons &= ~WepSet_FromWeapon(wpn);
+                               e.weapons &= ~s;
                        break;
        }
-       v1 = (e.weapons & WepSet_FromWeapon(wpn));
+       v1 = (e.weapons & s);
        return (v0 != v1);
 }
 
@@ -1605,9 +1606,8 @@ void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .floa
 }
 float GiveItems(entity e, float beginarg, float endarg)
 {SELFPARAM();
-       float got, i, j, val, op;
+       float got, i, val, op;
        float _switchweapon;
-       entity wi;
        string cmd;
 
        val = 999;
@@ -1617,7 +1617,7 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        _switchweapon = false;
        if (e.autoswitch)
-               if (e.switchweapon == w_getbestweapon(e))
+               if (PS(e).m_switchweapon == w_getbestweapon(e))
                        _switchweapon = true;
 
        e.strength_finished = max(0, e.strength_finished - time);
@@ -1676,13 +1676,10 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveValue(e, health, op, val);
                                got += GiveValue(e, armorvalue, op, val);
                        case "allweapons":
-                               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-                               {
-                                       wi = get_weaponinfo(j);
-                                       if(wi.weapon)
-                                               if (!(wi.spawnflags & WEP_FLAG_MUTATORBLOCKED))
-                                                       got += GiveWeapon(e, j, op, val);
-                               }
+                               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                                       if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
+                                               got += GiveWeapon(e, it.m_id, op, val);
+                               ));
                        case "allammo":
                                got += GiveValue(e, ammo_cells, op, val);
                                got += GiveValue(e, ammo_plasma, op, val);
@@ -1741,17 +1738,13 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveValue(e, ammo_fuel, op, val);
                                break;
                        default:
-                               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-                               {
-                                       wi = get_weaponinfo(j);
-                                       if(cmd == wi.netname)
+                               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                                       if(cmd == it.netname)
                                        {
-                                               got += GiveWeapon(e, j, op, val);
+                                               got += GiveWeapon(e, it.m_id, op, val);
                                                break;
                                        }
-                               }
-                               if(j > WEP_LAST)
-                                       LOG_INFO("give: invalid item ", cmd, "\n");
+                               ));
                                break;
                }
                val = 999;
@@ -1762,19 +1755,12 @@ float GiveItems(entity e, float beginarg, float endarg)
        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, ITEM_Jetpack.m_itemid, SND(ITEMPICKUP), string_null);
-       for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-       {
-               wi = get_weaponinfo(j);
-               if(wi.weapon)
-               {
-                       POSTGIVE_WEAPON(e, j, SND(WEAPONPICKUP), string_null);
-                       if (!(save_weapons & WepSet_FromWeapon(j)))
-                               if(e.weapons & WepSet_FromWeapon(j)) {
-                                       Weapon w = get_weaponinfo(wi.weapon);
-                                       w.wr_init(w);
-                               }
-               }
-       }
+       FOREACH(Weapons, it != WEP_Null, LAMBDA(
+               POSTGIVE_WEAPON(e, it, SND(WEAPONPICKUP), string_null);
+               if(!(save_weapons & (it.m_wepset)))
+                       if(e.weapons & (it.m_wepset))
+                               it.wr_init(it);
+       ));
        POSTGIVE_VALUE(e, strength_finished, 1, SND(POWERUP), SND(POWEROFF));
        POSTGIVE_VALUE(e, invincible_finished, 1, "misc/powerup_shield.wav", SND(POWEROFF));
        POSTGIVE_VALUE(e, ammo_nails, 0, SND(ITEMPICKUP), string_null);
@@ -1803,7 +1789,7 @@ float GiveItems(entity e, float beginarg, float endarg)
        else
                e.superweapons_finished += time;
 
-       if (!(e.weapons & WepSet_FromWeapon(e.switchweapon)))
+       if (!(e.weapons & WepSet_FromWeapon(PS(e).m_switchweapon)))
                _switchweapon = true;
        if(_switchweapon)
                W_SwitchWeapon_Force(e, w_getbestweapon(e));