]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/items/items.qc
Merge branch 'master' into 'Mario/status_effects'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / items / items.qc
index f0d8e3835e38d9310af0c6525049a0ec54d8392d..1a5cfdda5e74e236618996ba66cd988cdc7752e2 100644 (file)
@@ -9,6 +9,7 @@
 #include <common/monsters/_mod.qh>
 #include <common/mutators/mutator/buffs/buffs.qh>
 #include <common/mutators/mutator/buffs/sv_buffs.qh>
+#include <common/mutators/mutator/status_effects/_mod.qh>
 #include <common/notifications/all.qh>
 #include <common/util.qh>
 #include <common/weapons/_all.qh>
@@ -549,17 +550,17 @@ bool Item_GiveTo(entity item, entity player)
        if (item.strength_finished)
        {
                pickedup = true;
-               STAT(STRENGTH_FINISHED, player) = max(STAT(STRENGTH_FINISHED, player), time) + item.strength_finished;
+               StatusEffects_apply(STATUSEFFECT_Strength, player, max(StatusEffects_gettime(STATUSEFFECT_Strength, player), time) + item.strength_finished, 0);
        }
        if (item.invincible_finished)
        {
                pickedup = true;
-               STAT(INVINCIBLE_FINISHED, player) = max(STAT(INVINCIBLE_FINISHED, player), time) + item.invincible_finished;
+               StatusEffects_apply(STATUSEFFECT_Shield, player, max(StatusEffects_gettime(STATUSEFFECT_Shield, player), time) + item.invincible_finished, 0);
        }
        if (item.superweapons_finished)
        {
                pickedup = true;
-               STAT(SUPERWEAPONS_FINISHED, player) = max(STAT(SUPERWEAPONS_FINISHED, player), time) + item.superweapons_finished;
+               StatusEffects_apply(STATUSEFFECT_Superweapons, player, max(StatusEffects_gettime(STATUSEFFECT_Superweapons, player), time) + item.superweapons_finished, 0);
        }
 
        // always eat teamed entities
@@ -1223,14 +1224,14 @@ spawnfunc(target_items)
                        else if(argv(j) == "fuel_regen")             this.items |= ITEM_JetpackRegen.m_itemid;
                        else
                        {
-                               FOREACH(Buffs, it != BUFF_Null,
+                               FOREACH(StatusEffect, it.instanceOfBuff,
                                {
                                        string s = Buff_UndeprecateName(argv(j));
                                        if(s == it.netname)
                                        {
-                                               STAT(BUFFS, this) |= (it.m_itemid);
-                                               if(!STAT(BUFF_TIME, this))
-                                                       STAT(BUFF_TIME, this) = it.m_time(it);
+                                               this.buffdef = it;
+                                               if(!this.buffs_finished)
+                                                       this.buffs_finished = it.m_time(it);
                                                break;
                                        }
                                });
@@ -1291,9 +1292,7 @@ spawnfunc(target_items)
                res = GetResource(this, RES_FUEL);    if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "fuel");
                res = GetResource(this, RES_HEALTH);  if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "health");
                res = GetResource(this, RES_ARMOR);   if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "armor");
-               // HACK: buffs share a single timer, so we need to include enabled buffs AFTER disabled ones to avoid loss
-               FOREACH(Buffs, it != BUFF_Null && !(STAT(BUFFS, this) & it.m_itemid), str = sprintf("%s %s%d %s", str, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
-               FOREACH(Buffs, it != BUFF_Null && (STAT(BUFFS, this) & it.m_itemid), str = sprintf("%s %s%d %s", str, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
+               FOREACH(StatusEffect, it.instanceOfBuff, str = sprintf("%s %s%d %s", str, valueprefix, this.buffs_finished * boolean(this.buffdef == it), it.netname));
                FOREACH(Weapons, it != WEP_Null, str = sprintf("%s %s%d %s", str, itemprefix, !!(STAT(WEAPONS, this) & (it.m_wepset)), it.netname));
        }
        this.netname = strzone(str);
@@ -1341,8 +1340,8 @@ float GiveWeapon(entity e, float wpn, float op, float val)
 
 bool GiveBuff(entity e, Buff thebuff, int op, int val)
 {
-       bool had_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
-       float new_buff_time = ((had_buff) ? STAT(BUFF_TIME, e) : 0);
+       bool had_buff = StatusEffects_active(thebuff, e);
+       float new_buff_time = ((had_buff) ? StatusEffects_gettime(thebuff, e) : 0);
        switch (op)
        {
                case OP_SET:
@@ -1363,16 +1362,14 @@ bool GiveBuff(entity e, Buff thebuff, int op, int val)
        }
        if(new_buff_time <= 0)
        {
-               if(had_buff)
-                       STAT(BUFF_TIME, e) = new_buff_time;
-               STAT(BUFFS, e) &= ~thebuff.m_itemid;
+               StatusEffects_remove(thebuff, e, STATUSEFFECT_REMOVE_TIMEOUT);
        }
        else
        {
-               STAT(BUFF_TIME, e) = new_buff_time;
-               STAT(BUFFS, e) = thebuff.m_itemid; // NOTE: replaces any existing buffs on the player!
+               buff_RemoveAll(e, STATUSEFFECT_REMOVE_CLEAR); // clear old buffs on the player first!
+               StatusEffects_apply(thebuff, e, new_buff_time, 0);
        }
-       bool have_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
+       bool have_buff = StatusEffects_active(thebuff, e);
        return (had_buff != have_buff);
 }
 
@@ -1416,6 +1413,35 @@ bool GiveResourceValue(entity e, int res_type, int op, int val)
 
        return SetResourceExplicit(e, res_type, new_val);
 }
+bool GiveStatusEffect(entity e, StatusEffects this, int op, float val)
+{
+       bool had_eff = StatusEffects_active(this, e);
+       float new_eff_time = ((had_eff) ? StatusEffects_gettime(this, e) : 0);
+       switch (op)
+       {
+               case OP_SET:
+                       new_eff_time = val;
+                       break;
+               case OP_MIN:
+                       new_eff_time = max(new_eff_time, val);
+                       break;
+               case OP_MAX:
+                       new_eff_time = min(new_eff_time, val);
+                       break;
+               case OP_PLUS:
+                       new_eff_time += val;
+                       break;
+               case OP_MINUS:
+                       new_eff_time -= val;
+                       break;
+       }
+       if(new_eff_time <= 0)
+               StatusEffects_remove(this, e, STATUSEFFECT_REMOVE_TIMEOUT);
+       else
+               StatusEffects_apply(this, e, new_eff_time, 0);
+       bool have_eff = StatusEffects_active(this, e);
+       return (had_eff != have_eff);
+}
 
 float GiveItems(entity e, float beginarg, float endarg)
 {
@@ -1440,16 +1466,19 @@ float GiveItems(entity e, float beginarg, float endarg)
                }
        }
 
-       STAT(STRENGTH_FINISHED, e) = max(0, STAT(STRENGTH_FINISHED, e) - time);
-       STAT(INVINCIBLE_FINISHED, e) = max(0, STAT(INVINCIBLE_FINISHED, e) - time);
-       STAT(SUPERWEAPONS_FINISHED, e) = max(0, STAT(SUPERWEAPONS_FINISHED, e) - time);
-       STAT(BUFF_TIME, e) = max(0, STAT(BUFF_TIME, e) - time);
+       if(e.statuseffects)
+       {
+               FOREACH(StatusEffect, true,
+               {
+                       e.statuseffects.statuseffect_time[it.m_id] = max(0, e.statuseffects.statuseffect_time[it.m_id] - time);
+               });
+       }
 
        PREGIVE(e, items);
        PREGIVE_WEAPONS(e);
-       PREGIVE(e, stat_STRENGTH_FINISHED);
-       PREGIVE(e, stat_INVINCIBLE_FINISHED);
-       PREGIVE(e, stat_SUPERWEAPONS_FINISHED);
+       PREGIVE_STATUSEFFECT(e, STATUSEFFECT_Strength);
+       PREGIVE_STATUSEFFECT(e, STATUSEFFECT_Shield);
+       //PREGIVE_STATUSEFFECT(e, STATUSEFFECT_Superweapons);
        PREGIVE_RESOURCE(e, RES_BULLETS);
        PREGIVE_RESOURCE(e, RES_CELLS);
        PREGIVE_RESOURCE(e, RES_PLASMA);
@@ -1488,9 +1517,9 @@ float GiveItems(entity e, float beginarg, float endarg)
                                continue;
                        case "ALL":
                                got += GiveBit(e, items, ITEM_JetpackRegen.m_itemid, op, val);
-                               got += GiveValue(e, stat_STRENGTH_FINISHED, op, val);
-                               got += GiveValue(e, stat_INVINCIBLE_FINISHED, op, val);
-                               got += GiveValue(e, stat_SUPERWEAPONS_FINISHED, op, val);
+                               got += GiveStatusEffect(e, STATUSEFFECT_Strength, op, val);
+                               got += GiveStatusEffect(e, STATUSEFFECT_Shield, op, val);
+                               got += GiveStatusEffect(e, STATUSEFFECT_Superweapons, 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);
@@ -1499,7 +1528,7 @@ float GiveItems(entity e, float beginarg, float endarg)
                        case "allweapons":
                                FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)), 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));
+                               //FOREACH(StatusEffect, it.instanceOfBuff, got += GiveBuff(e, it, op, val));
                        case "allammo":
                                got += GiveResourceValue(e, RES_CELLS, op, val);
                                got += GiveResourceValue(e, RES_PLASMA, op, val);
@@ -1525,13 +1554,13 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveBit(e, items, ITEM_JetpackRegen.m_itemid, op, val);
                                break;
                        case "strength":
-                               got += GiveValue(e, stat_STRENGTH_FINISHED, op, val);
+                               got += GiveStatusEffect(e, STATUSEFFECT_Strength, op, val);
                                break;
                        case "invincible":
-                               got += GiveValue(e, stat_INVINCIBLE_FINISHED, op, val);
+                               got += GiveStatusEffect(e, STATUSEFFECT_Shield, op, val);
                                break;
                        case "superweapons":
-                               got += GiveValue(e, stat_SUPERWEAPONS_FINISHED, op, val);
+                               got += GiveStatusEffect(e, STATUSEFFECT_Superweapons, op, val);
                                break;
                        case "cells":
                                got += GiveResourceValue(e, RES_CELLS, op, val);
@@ -1559,7 +1588,7 @@ float GiveItems(entity e, float beginarg, float endarg)
                                got += GiveResourceValue(e, RES_FUEL, op, val);
                                break;
                        default:
-                               FOREACH(Buffs, it != BUFF_Null && buff_Available(it) && Buff_UndeprecateName(cmd) == it.netname,
+                               FOREACH(StatusEffect, it.instanceOfBuff && buff_Available(it) && Buff_UndeprecateName(cmd) == it.netname,
                                {
                                        got += GiveBuff(e, it, op, val);
                                        break;
@@ -1584,9 +1613,8 @@ float GiveItems(entity e, float beginarg, float endarg)
                        if(STAT(WEAPONS, e) & (it.m_wepset))
                                it.wr_init(it);
        });
-       POSTGIVE_VALUE(e, stat_STRENGTH_FINISHED, 1, SND_POWERUP, SND_POWEROFF);
-       POSTGIVE_VALUE(e, stat_INVINCIBLE_FINISHED, 1, SND_Shield, SND_POWEROFF);
-       //POSTGIVE_VALUE(e, stat_SUPERWEAPONS_FINISHED, 1, SND_Null, SND_Null);
+       POSTGIVE_STATUSEFFECT(e, STATUSEFFECT_Strength, 1, SND_POWERUP, SND_POWEROFF);
+       POSTGIVE_STATUSEFFECT(e, STATUSEFFECT_Shield, 1, SND_POWERUP, SND_POWEROFF);
        POSTGIVE_RESOURCE(e, RES_BULLETS, 0, SND_ITEMPICKUP, SND_Null);
        POSTGIVE_RESOURCE(e, RES_CELLS, 0, SND_ITEMPICKUP, SND_Null);
        POSTGIVE_RESOURCE(e, RES_PLASMA, 0, SND_ITEMPICKUP, SND_Null);
@@ -1596,26 +1624,24 @@ float GiveItems(entity e, float beginarg, float endarg)
        POSTGIVE_RES_ROT(e, RES_ARMOR, 1, pauserotarmor_finished, autocvar_g_balance_pause_armor_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_ARMOR25, SND_Null);
        POSTGIVE_RES_ROT(e, RES_HEALTH, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_MEGAHEALTH, SND_Null);
 
-       if(STAT(SUPERWEAPONS_FINISHED, e) <= 0)
+       if(!StatusEffects_active(STATUSEFFECT_Superweapons, e))
+       {
                if(!g_weaponarena && (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
-                       STAT(SUPERWEAPONS_FINISHED, e) = autocvar_g_balance_superweapons_time;
+                       StatusEffects_apply(STATUSEFFECT_Superweapons, e, autocvar_g_balance_superweapons_time, 0);
+       }
 
-       if(STAT(STRENGTH_FINISHED, e) <= 0)
-               STAT(STRENGTH_FINISHED, e) = 0;
-       else
-               STAT(STRENGTH_FINISHED, e) += time;
-       if(STAT(INVINCIBLE_FINISHED, e) <= 0)
-               STAT(INVINCIBLE_FINISHED, e) = 0;
-       else
-               STAT(INVINCIBLE_FINISHED, e) += time;
-       if(STAT(SUPERWEAPONS_FINISHED, e) <= 0)
-               STAT(SUPERWEAPONS_FINISHED, e) = 0;
-       else
-               STAT(SUPERWEAPONS_FINISHED, e) += time;
-       if(STAT(BUFF_TIME, e) <= 0)
-               STAT(BUFF_TIME, e) = 0;
-       else
-               STAT(BUFF_TIME, e) += time;
+       if(e.statuseffects)
+       {
+               FOREACH(StatusEffect, true,
+               {
+                       if(e.statuseffects.statuseffect_time[it.m_id] <= 0)
+                               e.statuseffects.statuseffect_time[it.m_id] = 0;
+                       else
+                               e.statuseffects.statuseffect_time[it.m_id] += time;
+               });
+                       
+               StatusEffects_update(e);
+       }
 
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {