]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/t_items.qc
Merge branch 'master' into Mario/race_target_waypoint
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / t_items.qc
index 6d4fa7720f16da31197a59bcb30c239e12cdf7da..19e404a1a4ece51beca94a7ed33ba073145f887a 100644 (file)
@@ -22,6 +22,8 @@
 
     #include <common/weapons/_all.qh>
 
+    #include <common/mutators/mutator/buffs/buffs.qh>
+
     #include "../lib/warpzone/util_server.qh"
 #elif defined(CSQC)
        #include "physics/movetypes/movetypes.qh"
@@ -507,7 +509,7 @@ void Item_Respawn (entity this)
        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)
+    if (Item_ItemsTime_Allow(this.itemdef) || (this.weapons & WEPSET_SUPERWEAPONS))
        {
                float t = Item_ItemsTime_UpdateTime(this, 0);
                Item_ItemsTime_SetTime(this, t);
@@ -592,7 +594,7 @@ void Item_RespawnThink(entity this)
 void Item_ScheduleRespawnIn(entity e, float t)
 {
        // if the respawn time is longer than 10 seconds, show a waypoint, otherwise, just respawn normally
-       if ((Item_ItemsTime_Allow(e.itemdef) || e.weapons & WEPSET_SUPERWEAPONS) && (t - ITEM_RESPAWN_TICKS) > 0)
+       if ((Item_ItemsTime_Allow(e.itemdef) || (e.weapons & WEPSET_SUPERWEAPONS)) && (t - ITEM_RESPAWN_TICKS) > 0)
        {
                setthink(e, Item_RespawnCountdown);
                e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS);
@@ -608,6 +610,13 @@ void Item_ScheduleRespawnIn(entity e, float t)
                e.nextthink = time;
                e.scheduledrespawntime = time + t;
                e.wait = time + t;
+
+               if(Item_ItemsTime_Allow(e.itemdef) || (e.weapons & WEPSET_SUPERWEAPONS))
+               {
+                       t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime);
+                       Item_ItemsTime_SetTime(e, t);
+                       Item_ItemsTime_SetTimesForAllPlayers();
+               }
        }
 }
 
@@ -625,7 +634,7 @@ void Item_ScheduleRespawn(entity e)
 void Item_ScheduleInitialRespawn(entity e)
 {
        Item_Show(e, 0);
-       Item_ScheduleRespawnIn(e, game_starttime - time + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e)));
+       Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e)));
 }
 
 float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax, float mode)
@@ -871,7 +880,7 @@ LABEL(pickup)
                                }
                        });
                        e = RandomSelection_chosen_ent;
-
+                       Item_Show(e, 1); // reset its state so it is visible (extra sendflags doesn't matter, this happens anyway)
                }
                else
                        e = this;
@@ -1094,6 +1103,9 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default
        this.item_model_ent = itemmodel;
     this.item_pickupsound_ent = pickupsound;
 
+    if(def.m_iteminit)
+       def.m_iteminit(this);
+
        if(!this.respawntime) // both need to be set
        {
                this.respawntime = defaultrespawntime;
@@ -1327,7 +1339,7 @@ void setItemGroup(entity this)
                        {
                                int grY = it.item_group;
                                // move all items of item_group Y to item_group X
-                               FOREACH_ENTITY(IS_SMALL(it.itemdef),
+                               IL_EACH(g_items, IS_SMALL(it.itemdef),
                                {
                                        if(it.item_group == grY)
                                                it.item_group = this.item_group;
@@ -1342,16 +1354,14 @@ void setItemGroupCount()
        for (int k = 1; k <= group_count; k++)
        {
                int count = 0;
-               FOREACH_ENTITY(IS_SMALL(it.itemdef) && it.item_group == k, { count++; });
+               IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { count++; });
                if (count)
-                       FOREACH_ENTITY(IS_SMALL(it.itemdef) && it.item_group == k, { it.item_group_count = count; });
+                       IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { it.item_group_count = count; });
        }
 }
 
 spawnfunc(item_rockets)
 {
-       if(!this.ammo_rockets)
-               this.ammo_rockets = g_pickup_rockets;
     StartItem(this, ITEM_Rockets);
 }
 
@@ -1367,22 +1377,16 @@ spawnfunc(item_bullets)
                return;
        }
 
-       if(!this.ammo_nails)
-               this.ammo_nails = g_pickup_nails;
     StartItem(this, ITEM_Bullets);
 }
 
 spawnfunc(item_cells)
 {
-       if(!this.ammo_cells)
-               this.ammo_cells = g_pickup_cells;
        StartItem(this, ITEM_Cells);
 }
 
 spawnfunc(item_plasma)
 {
-       if(!this.ammo_plasma)
-               this.ammo_plasma = g_pickup_plasma;
        StartItem(this, ITEM_Plasma);
 }
 
@@ -1398,80 +1402,46 @@ spawnfunc(item_shells)
                return;
        }
 
-       if(!this.ammo_shells)
-               this.ammo_shells = g_pickup_shells;
        StartItem(this, ITEM_Shells);
 }
 
 spawnfunc(item_armor_small)
 {
-       if(!this.armorvalue)
-               this.armorvalue = g_pickup_armorsmall;
-       if(!this.max_armorvalue)
-               this.max_armorvalue = g_pickup_armorsmall_max;
        StartItem(this, ITEM_ArmorSmall);
 }
 
 spawnfunc(item_armor_medium)
 {
-       if(!this.armorvalue)
-               this.armorvalue = g_pickup_armormedium;
-       if(!this.max_armorvalue)
-               this.max_armorvalue = g_pickup_armormedium_max;
        StartItem(this, ITEM_ArmorMedium);
 }
 
 spawnfunc(item_armor_big)
 {
-       if(!this.armorvalue)
-               this.armorvalue = g_pickup_armorbig;
-       if(!this.max_armorvalue)
-               this.max_armorvalue = g_pickup_armorbig_max;
        StartItem(this, ITEM_ArmorBig);
 }
 
 spawnfunc(item_armor_mega)
 {
-       if(!this.armorvalue)
-               this.armorvalue = g_pickup_armormega;
-       if(!this.max_armorvalue)
-               this.max_armorvalue = g_pickup_armormega_max;
        StartItem(this, ITEM_ArmorMega);
 }
 
 spawnfunc(item_health_small)
 {
-       if(!this.max_health)
-               this.max_health = g_pickup_healthsmall_max;
-       if(!this.health)
-               this.health = g_pickup_healthsmall;
        StartItem(this, ITEM_HealthSmall);
 }
 
 spawnfunc(item_health_medium)
 {
-       if(!this.max_health)
-               this.max_health = g_pickup_healthmedium_max;
-       if(!this.health)
-               this.health = g_pickup_healthmedium;
     StartItem(this, ITEM_HealthMedium);
 }
 
 spawnfunc(item_health_big)
 {
-       if(!this.max_health)
-               this.max_health = g_pickup_healthbig_max;
-       if(!this.health)
-               this.health = g_pickup_healthbig;
        StartItem(this, ITEM_HealthBig);
 }
 
 spawnfunc(item_health_mega)
 {
-    if(!this.max_health)
-        this.max_health = g_pickup_healthmega_max;
-    if(!this.health)
-        this.health = g_pickup_healthmega;
     StartItem(this, ITEM_HealthMega);
 }
 
@@ -1486,16 +1456,12 @@ spawnfunc(item_health100) { spawnfunc_item_health_mega(this); }
 
 spawnfunc(item_strength)
 {
-               if(!this.strength_finished)
-                       this.strength_finished = autocvar_g_balance_powerup_strength_time;
-               StartItem(this, ITEM_Strength);
+       StartItem(this, ITEM_Strength);
 }
 
 spawnfunc(item_invincible)
 {
-               if(!this.invincible_finished)
-                       this.invincible_finished = autocvar_g_balance_powerup_invincible_time;
-               StartItem(this, ITEM_Shield);
+       StartItem(this, ITEM_Shield);
 }
 
 // compatibility:
@@ -1560,6 +1526,15 @@ spawnfunc(target_items)
                        else if(argv(j) == "fuel_regen")             this.items |= ITEM_JetpackRegen.m_itemid;
                        else
                        {
+                               FOREACH(Buffs, it != BUFF_Null,
+                               {
+                                       s = Buff_UndeprecateName(argv(j));
+                                       if(s == it.m_name)
+                                       {
+                                               this.buffs |= (it.m_itemid);
+                                               break;
+                                       }
+                               });
                                FOREACH(Weapons, it != WEP_Null, {
                                        s = W_UndeprecateName(argv(j));
                                        if(s == it.netname)
@@ -1616,6 +1591,7 @@ spawnfunc(target_items)
                if(this.ammo_fuel != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, this.ammo_fuel), "fuel");
                if(this.health != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, this.health), "health");
                if(this.armorvalue != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, this.armorvalue), "armor");
+               FOREACH(Buffs, it != BUFF_Null, this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, !!(this.buffs & (it.m_itemid)), it.m_name));
                FOREACH(Weapons, it != WEP_Null, this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, !!(this.weapons & (it.m_wepset)), it.netname));
        }
        this.netname = strzone(this.netname);
@@ -1633,8 +1609,6 @@ spawnfunc(target_items)
 
 spawnfunc(item_fuel)
 {
-       if(!this.ammo_fuel)
-               this.ammo_fuel = g_pickup_fuel;
        StartItem(this, ITEM_JetpackFuel);
 }
 
@@ -1650,8 +1624,6 @@ spawnfunc(item_fuel_regen)
 
 spawnfunc(item_jetpack)
 {
-       if(!this.ammo_fuel)
-               this.ammo_fuel = g_pickup_fuel_jetpack;
        if(start_items & ITEM_Jetpack.m_itemid)
        {
                spawnfunc_item_fuel(this);
@@ -1691,6 +1663,35 @@ float GiveWeapon(entity e, float wpn, float op, float val)
        return (v0 != v1);
 }
 
+bool GiveBuff(entity e, Buff thebuff, int op, int val)
+{
+       bool had_buff = (e.buffs & thebuff.m_itemid);
+       switch(op)
+       {
+               case OP_SET:
+                       if(val > 0)
+                               e.buffs |= thebuff.m_itemid;
+                       else
+                               e.buffs &= ~thebuff.m_itemid;
+                       break;
+               case OP_MIN:
+               case OP_PLUS:
+                       if(val > 0)
+                               e.buffs |= thebuff.m_itemid;
+                       break;
+               case OP_MAX:
+                       if(val <= 0)
+                               e.buffs &= ~thebuff.m_itemid;
+                       break;
+               case OP_MINUS:
+                       if(val > 0)
+                               e.buffs &= ~thebuff.m_itemid;
+                       break;
+       }
+       bool have_buff = (e.buffs & thebuff.m_itemid);
+       return (had_buff != have_buff);
+}
+
 void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr)
 {
        if(v1 == v0)
@@ -1794,6 +1795,8 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveValue(e, armorvalue, op, val);
                        case "allweapons":
                                FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED), got += GiveWeapon(e, it.m_id, op, val));
+                       //case "allbuffs": // all buffs makes a player god, do not want!
+                               //FOREACH(Buffs, it != BUFF_Null, got += GiveBuff(e, it.m_itemid, op, val));
                        case "allammo":
                                got += GiveValue(e, ammo_cells, op, val);
                                got += GiveValue(e, ammo_plasma, op, val);
@@ -1852,6 +1855,11 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveValue(e, ammo_fuel, op, val);
                                break;
                        default:
+                               FOREACH(Buffs, it != BUFF_Null && Buff_UndeprecateName(cmd) == it.m_name,
+                               {
+                                       got += GiveBuff(e, it, op, val);
+                                       break;
+                               });
                                FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(cmd) == it.netname, {
                     got += GiveWeapon(e, it.m_id, op, val);
                     break;
@@ -1915,7 +1923,11 @@ float GiveItems(entity e, float beginarg, float endarg)
                {
                        .entity weaponentity = weaponentities[slot];
                        if(_switchweapon & BIT(slot))
-                               W_SwitchWeapon_Force(e, w_getbestweapon(e, weaponentity), weaponentity);
+                       {
+                               Weapon wep = w_getbestweapon(e, weaponentity);
+                               if(wep != e.(weaponentity).m_switchweapon)
+                                       W_SwitchWeapon_Force(e, wep, weaponentity);
+                       }
                }
        }