]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/t_items.qc
Merge branch 'master' into Mario/wepent_experimental
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / t_items.qc
index 3147354ea5554f9bc001c9e536198209cb752eac..17fb9fce0cba011f19ed36f4bd5d0985199c5489 100644 (file)
@@ -1,13 +1,12 @@
 #include "t_items.qh"
 
-#include "items/all.qc"
+#include "items/_mod.qh"
 
 #if defined(SVQC)
 
-    #include "../server/bot/bot.qh"
-    #include "../server/bot/waypoints.qh"
+    #include "../server/bot/api.qh"
 
-    #include <server/mutators/all.qh>
+    #include <server/mutators/_mod.qh>
 
     #include "../server/weapons/common.qh"
     #include "../server/weapons/selection.qh"
        #include "triggers/subs.qh"
     #include "util.qh"
 
-    #include <common/monsters/all.qh>
+    #include <common/monsters/_mod.qh>
 
-    #include <common/weapons/all.qh>
+    #include <common/weapons/_all.qh>
 
     #include "../lib/warpzone/util_server.qh"
 #elif defined(CSQC)
        #include "physics/movetypes/movetypes.qh"
-       #include <common/weapons/all.qh>
+       #include <common/weapons/_all.qh>
        #include "../lib/csqcmodel/cl_model.qh"
        #include "../lib/csqcmodel/common.qh"
 #endif
@@ -35,6 +34,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_ITEM)
 
 #ifdef CSQC
 bool autocvar_cl_ghost_items_vehicle = true;
+.vector item_glowmod;
 void Item_SetAlpha(entity this)
 {
        bool veh_hud = (hud && autocvar_cl_ghost_items_vehicle);
@@ -42,7 +42,8 @@ void Item_SetAlpha(entity this)
        if(!veh_hud && (this.ItemStatus & ITS_AVAILABLE))
        {
                this.alpha = 1;
-               this.colormod = this.glowmod = '1 1 1';
+               this.colormod = '1 1 1';
+               this.glowmod = this.item_glowmod;
        }
        else
        {
@@ -182,7 +183,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
             if(this.ItemStatus & ITS_ALLOWFB)
                 this.effects |= EF_FULLBRIGHT;
 
-        if(this.ItemStatus & ITS_POWERUP)
+        if(this.ItemStatus & ITS_GLOW)
         {
             if(this.ItemStatus & ITS_AVAILABLE)
                 this.effects |= (EF_ADDITIVE | EF_FULLBRIGHT);
@@ -194,7 +195,8 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
     if(sf & ISF_MODEL)
     {
         this.drawmask  = MASK_NORMAL;
-               this.move_movetype = MOVETYPE_TOSS;
+               set_movetype(this, MOVETYPE_TOSS);
+               if (isnew) IL_PUSH(g_drawables, this);
         this.draw       = ItemDraw;
         this.solid = SOLID_TRIGGER;
         //this.flags |= FL_ITEM;
@@ -228,7 +230,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
             else
             {
                 this.draw = ItemDraw;
-                LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it\n");
+                LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it");
             }
         }
 
@@ -237,7 +239,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
 
 
         if(this.mdl == "")
-            LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, ", tell tZork about this!\n");
+            LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, ", tell tZork about this!");
 
         precache_model(this.mdl);
         _setmodel(this, this.mdl);
@@ -246,14 +248,19 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
     }
 
     if(sf & ISF_COLORMAP)
+    {
         this.colormap = ReadShort();
+        this.item_glowmod_x = ReadByte() / 255.0;
+        this.item_glowmod_y = ReadByte() / 255.0;
+        this.item_glowmod_z = ReadByte() / 255.0;
+    }
 
     if(sf & ISF_DROP)
     {
         this.gravity = 1;
         this.pushable = true;
         //this.angles = '0 0 0';
-        this.move_movetype = MOVETYPE_TOSS;
+        set_movetype(this, MOVETYPE_TOSS);
         this.velocity_x = ReadCoord();
         this.velocity_y = ReadCoord();
         this.velocity_z = ReadCoord();
@@ -327,14 +334,19 @@ bool ItemSend(entity this, entity to, int sf)
                WriteShort(MSG_ENTITY, this.fade_start);
 
                if(this.mdl == "")
-                       LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "exspect a crash just aboute now\n");
+                       LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "expect a crash just about now");
 
                WriteString(MSG_ENTITY, this.mdl);
        }
 
 
        if(sf & ISF_COLORMAP)
+       {
                WriteShort(MSG_ENTITY, this.colormap);
+               WriteByte(MSG_ENTITY, this.glowmod.x * 255.0);
+        WriteByte(MSG_ENTITY, this.glowmod.y * 255.0);
+        WriteByte(MSG_ENTITY, this.glowmod.z * 255.0);
+       }
 
        if(sf & ISF_DROP)
        {
@@ -411,6 +423,7 @@ void Item_Show (entity e, float mode)
 {
        e.effects &= ~(EF_ADDITIVE | EF_STARDUST | EF_FULLBRIGHT | EF_NODEPTHTEST);
        e.ItemStatus &= ~ITS_STAYWEP;
+       entity def = e.itemdef;
        if (mode > 0)
        {
                // make the item look normal, and be touchable
@@ -428,7 +441,6 @@ void Item_Show (entity e, float mode)
                e.ItemStatus &= ~ITS_AVAILABLE;
        }
        else {
-       entity def = e.itemdef;
        bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.weapons & WEPSET_SUPERWEAPONS) : false // no weapon-stay on superweapons
                || e.team // weapon stay isn't supported for teamed weapons
                ;
@@ -446,13 +458,13 @@ void Item_Show (entity e, float mode)
                //setmodel(e, "null");
                e.solid = SOLID_NOT;
                e.colormod = '0 0 0';
-               e.glowmod = e.colormod;
+               //e.glowmod = e.colormod;
                e.spawnshieldtime = 1;
                e.ItemStatus &= ~ITS_AVAILABLE;
        }}
 
-       if (e.items & ITEM_Strength.m_itemid || e.items & ITEM_Shield.m_itemid)
-               e.ItemStatus |= ITS_POWERUP;
+       if (def.m_glow)
+               e.ItemStatus |= ITS_GLOW;
 
        if (autocvar_g_nodepthtestitems)
                e.effects |= EF_NODEPTHTEST;
@@ -485,13 +497,7 @@ void Item_ItemsTime_SetTimesForAllPlayers();
 void Item_Respawn (entity this)
 {
        Item_Show(this, 1);
-       // this is ugly...
-       if(this.items == ITEM_Strength.m_itemid)
-               sound (this, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTEN_NORM);   // play respawn sound
-       else if(this.items == ITEM_Shield.m_itemid)
-               sound (this, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTEN_NORM);     // play respawn sound
-       else
-               sound (this, CH_TRIGGER, SND_ITEMRESPAWN, VOL_BASE, ATTEN_NORM);        // play respawn sound
+       sound(this, CH_TRIGGER, this.itemdef.m_respawnsound, VOL_BASE, ATTEN_NORM);     // play respawn sound
        setorigin(this, this.origin);
 
     if (Item_ItemsTime_Allow(this.itemdef) || this.weapons & WEPSET_SUPERWEAPONS)
@@ -660,21 +666,30 @@ LABEL(YEAH)
 
 float Item_GiveTo(entity item, entity player)
 {
-       float _switchweapon;
        float pickedup;
 
        // if nothing happens to player, just return without taking the item
        pickedup = false;
-       _switchweapon = false;
+       int _switchweapon = 0;
        // in case the player has autoswitch enabled do the following:
        // 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 (PS(player).m_switchweapon == w_getbestweapon(player))
-               _switchweapon = true;
 
-       if (!(player.weapons & WepSet_FromWeapon(PS(player).m_switchweapon)))
-               _switchweapon = true;
+       if(player.autoswitch)
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                       {
+                               if(player.(weaponentity).m_switchweapon == w_getbestweapon(player, weaponentity))
+                                       _switchweapon |= BIT(slot);
+
+                               if(!(player.weapons & WepSet_FromWeapon(player.(weaponentity).m_switchweapon)))
+                                       _switchweapon |= BIT(slot);
+                       }
+               }
+       }
 
        pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
        pickedup |= Item_GiveAmmoTo(item, player, ammo_shells, g_pickup_shells_max, ITEM_MODE_NONE);
@@ -697,7 +712,12 @@ float Item_GiveTo(entity item, entity player)
                        FOREACH(Weapons, it != WEP_Null, {
                                if(w & (it.m_wepset))
                                {
-                                       W_DropEvent(wr_pickup, player, it.m_id, item);
+                                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                                       {
+                                               .entity weaponentity = weaponentities[slot];
+                                               if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                                                       W_DropEvent(wr_pickup, player, it.m_id, item, weaponentity);
+                                       }
                                        W_GiveWeapon(player, it.m_id);
                                }
                        });
@@ -748,13 +768,25 @@ LABEL(skip)
        // crude hack to enforce switching weapons
        if(g_cts && item.itemdef.instanceOfWeaponPickup)
        {
-               W_SwitchWeapon_Force(player, Weapons_from(item.weapon));
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                               W_SwitchWeapon_Force(player, Weapons_from(item.weapon), weaponentity);
+               }
                return 1;
        }
 
-       if (_switchweapon)
-               if (PS(player).m_switchweapon != w_getbestweapon(player))
-                       W_SwitchWeapon_Force(player, w_getbestweapon(player));
+       if(_switchweapon)
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(_switchweapon & BIT(slot))
+                       if(player.(weaponentity).m_switchweapon != w_getbestweapon(player, weaponentity))
+                               W_SwitchWeapon_Force(player, w_getbestweapon(player, weaponentity), weaponentity);
+               }
+       }
 
        return 1;
 }
@@ -767,7 +799,7 @@ void Item_Touch(entity this, entity toucher)
        {
                if (ITEM_TOUCH_NEEDKILL())
                {
-                       remove(this);
+                       delete(this);
                        return;
                }
        }
@@ -816,20 +848,19 @@ LABEL(pickup)
        _sound (toucher, (this.itemdef.instanceOfPowerup ? CH_TRIGGER_SINGLE : CH_TRIGGER), (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
 
        if (this.classname == "droppedweapon")
-               remove (this);
+               delete (this);
        else if (this.spawnshieldtime)
        {
                entity e;
                if(this.team)
                {
                        RandomSelection_Init();
-                       FOREACH_ENTITY_FLAGS(flags, FL_ITEM,
+                       IL_EACH(g_items, it.team == this.team,
                        {
-                               if(it.team == this.team)
-                               if(it.classname != "item_flag_team" && it.classname != "item_key_team")
+                               if(it.classname != "item_flag_team" && it.classname != "item_kh_key")
                                {
                                        Item_Show(it, -1);
-                                       RandomSelection_Add(it, 0, string_null, it.cnt, 0);
+                                       RandomSelection_AddEnt(it, it.cnt, 0);
                                }
                        });
                        e = RandomSelection_chosen_ent;
@@ -866,23 +897,21 @@ void Item_FindTeam(entity this)
        if(this.effects & EF_NODRAW)
        {
                // marker for item team search
-               LOG_TRACE("Initializing item team ", ftos(this.team), "\n");
+               LOG_TRACE("Initializing item team ", ftos(this.team));
                RandomSelection_Init();
-               FOREACH_ENTITY_FLOAT(team, this.team,
+               IL_EACH(g_items, it.team == this.team,
                {
-                       if(it.flags & FL_ITEM)
-                       if(it.classname != "item_flag_team" && it.classname != "item_key_team")
-                               RandomSelection_Add(it, 0, string_null, it.cnt, 0);
+                       if(it.classname != "item_flag_team" && it.classname != "item_kh_key")
+                               RandomSelection_AddEnt(it, it.cnt, 0);
                });
 
                e = RandomSelection_chosen_ent;
                e.state = 0;
                Item_Show(e, 1);
 
-               FOREACH_ENTITY_FLOAT(team, this.team,
+               IL_EACH(g_items, it.team == this.team,
                {
-                       if(it.flags & FL_ITEM)
-                       if(it.classname != "item_flag_team" && it.classname != "item_key_team")
+                       if(it.classname != "item_flag_team" && it.classname != "item_kh_key")
                        {
                                if(it != e)
                                {
@@ -903,7 +932,7 @@ void RemoveItem(entity this)
 {
        if(wasfreed(this) || !this) { return; }
        Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
-       remove(this);
+       delete(this);
 }
 
 // pickup evaluation functions
@@ -1064,11 +1093,12 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                this.weapons = WepSet_FromWeapon(Weapons_from(weaponid));
 
        this.flags = FL_ITEM | itemflags;
+       IL_PUSH(g_items, this);
 
        if(MUTATOR_CALLHOOK(FilterItem, this)) // error means we do not want the item
        {
                startitem_failed = true;
-               remove(this);
+               delete(this);
                return;
        }
 
@@ -1077,7 +1107,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        {
                this.reset = SUB_Remove;
                // it's a dropped weapon
-               this.movetype = MOVETYPE_TOSS;
+               set_movetype(this, MOVETYPE_TOSS);
 
                // Savage: remove thrown items after a certain period of time ("garbage collection")
                setthink(this, RemoveItem);
@@ -1097,7 +1127,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                if (trace_dpstartcontents & DPCONTENTS_NODROP)
                {
                        startitem_failed = true;
-                       remove(this);
+                       delete(this);
                        return;
                }
        }
@@ -1106,7 +1136,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                if(!have_pickup_item(this))
                {
                        startitem_failed = true;
-                       remove (this);
+                       delete (this);
                        return;
                }
 
@@ -1118,9 +1148,9 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                if(this.spawnflags & 1)
                        this.noalign = 1;
                if (this.noalign > 0)
-                       this.movetype = MOVETYPE_NONE;
+                       set_movetype(this, MOVETYPE_NONE);
                else
-                       this.movetype = MOVETYPE_TOSS;
+                       set_movetype(this, MOVETYPE_TOSS);
                // do item filtering according to game mode and other things
                if (this.noalign <= 0)
                {
@@ -1154,7 +1184,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
             // why not flags & fl_item?
                    FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
                 LOG_TRACE("XXX Found duplicated item: ", itemname, vtos(this.origin));
-                LOG_TRACE(" vs ", it.netname, vtos(it.origin), "\n");
+                LOG_TRACE(" vs ", it.netname, vtos(it.origin));
                 error("Mapper sucks.");
             });
                        this.is_item = true;
@@ -1204,7 +1234,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
                        this.gravity = 1;
                if (!(this.spawnflags & 1024))
                        this.ItemStatus |= ITS_ANIMATE1;
-               this.ItemStatus |= ISF_COLORMAP;
+               this.SendFlags |= ISF_COLORMAP;
        }
 
        this.state = 0;
@@ -1225,7 +1255,7 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        if (MUTATOR_CALLHOOK(Item_Spawn, this))
        {
                startitem_failed = true;
-               remove(this);
+               delete(this);
                return;
        }
 }
@@ -1422,7 +1452,7 @@ void target_items_use(entity this, entity actor, entity trigger)
        if(actor.classname == "droppedweapon")
        {
                EXACTTRIGGER_TOUCH(this, trigger);
-               remove(actor);
+               delete(actor);
                return;
        }
 
@@ -1435,10 +1465,9 @@ void target_items_use(entity this, entity actor, entity trigger)
                EXACTTRIGGER_TOUCH(this, trigger);
        }
 
-       FOREACH_ENTITY_ENT(enemy, actor,
+       IL_EACH(g_items, it.enemy == actor && it.classname == "droppedweapon",
        {
-               if(it.classname == "droppedweapon")
-                       remove(it);
+               delete(it);
        });
 
        if(GiveItems(actor, 0, tokenize_console(this.netname)))
@@ -1636,7 +1665,6 @@ void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .floa
 float GiveItems(entity e, float beginarg, float endarg)
 {
        float got, i, val, op;
-       float _switchweapon;
        string cmd;
 
        val = 999;
@@ -1644,10 +1672,18 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        got = 0;
 
-       _switchweapon = false;
-       if (e.autoswitch)
-               if (PS(e).m_switchweapon == w_getbestweapon(e))
-                       _switchweapon = true;
+       int _switchweapon = 0;
+
+       if(e.autoswitch)
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                       if(e.(weaponentity).m_switchweapon == w_getbestweapon(e, weaponentity))
+                               _switchweapon |= BIT(slot);
+               }
+       }
 
        e.strength_finished = max(0, e.strength_finished - time);
        e.invincible_finished = max(0, e.invincible_finished - time);
@@ -1812,10 +1848,23 @@ float GiveItems(entity e, float beginarg, float endarg)
        else
                e.superweapons_finished += time;
 
-       if (!(e.weapons & WepSet_FromWeapon(PS(e).m_switchweapon)))
-               _switchweapon = true;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
+               if(!(e.weapons & WepSet_FromWeapon(e.(weaponentity).m_switchweapon)))
+                       _switchweapon |= BIT(slot);
+       }
+
        if(_switchweapon)
-               W_SwitchWeapon_Force(e, w_getbestweapon(e));
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(_switchweapon & BIT(slot))
+                               W_SwitchWeapon_Force(e, w_getbestweapon(e, weaponentity), weaponentity);
+               }
+       }
 
        return got;
 }