]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Don't allow StatusEffects_gettime to return a time in the past
authorterencehill <piuntn@gmail.com>
Sun, 1 Sep 2024 12:12:09 +0000 (14:12 +0200)
committerterencehill <piuntn@gmail.com>
Sun, 1 Sep 2024 12:21:00 +0000 (14:21 +0200)
By not doing so the effect would be still active in the last frame even if end time has passed.
It prevents wrong usage of the returned value, for example in Fire_AddDamage where mintime can be set to a negative value and used to apply a negative damage to the player
Removed now redundant max operations at StatusEffects_gettime call sites

.gitlab-ci.yml
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/status_effects/status_effects.qc
qcsrc/server/client.qc
qcsrc/server/items/items.qc

index 55eb8a1bb81b593d300a6c4de7567366fba083b5..d96b58c55e4f71de6d2335ba10d1c94fb4f13af6 100644 (file)
@@ -36,7 +36,7 @@ test_compilation_units:
 test_sv_game:
   stage: test
   script:
-    - export EXPECT=e67187c8446f97a8b062a431dccb89e0
+    - export EXPECT=28a49dd762a7a794f210eeadbbc37a8e
     - qcsrc/tools/sv_game-hashtest.sh
     - exit $?
 
index e51c7cc9d6d97696511c6df3323ddbc8365aa62a..4c6db060a5651e704d2a832a080a328ddae07f9d 100644 (file)
@@ -247,7 +247,7 @@ void buff_Touch(entity this, entity toucher)
 
        buff_RemoveAll(toucher, STATUSEFFECT_REMOVE_NORMAL); // remove previous buffs so that a new one may be added
        if(bufftime)
-               StatusEffects_apply(thebuff, toucher, min(time + bufftime, max(oldtime, time) + bufftime), 0);
+               StatusEffects_apply(thebuff, toucher, min(time + bufftime, oldtime + bufftime), 0);
        else
                StatusEffects_apply(thebuff, toucher, time + 999, 0); // HACK: zero timer means "infinite"!
 
index 5775032440a83c7144b73dccdb80d9ba9daa9966..e4301d3c59a05965a864ee1dc6f46b980a212f96 100644 (file)
@@ -21,7 +21,10 @@ float StatusEffects_gettime(StatusEffects this, entity actor)
        store = actor.statuseffects;
 #endif
        if(!store) return 0;
-       return store.statuseffect_time[this.m_id];
+       float eff_time = store.statuseffect_time[this.m_id];
+       // if effect end time has passed and m_tick hasn't removed the effect yet
+       // return current time since the effect is actually still active in this frame
+       return (eff_time < time ? time : eff_time);
 }
 #endif
 #ifdef SVQC
index c5dd182685cdb8faf359371949415bacd69f737f..355c134d82d7dde70fc9846e0e3fce8062679bd2 100644 (file)
@@ -1557,7 +1557,7 @@ void player_powerups(entity this)
                        else
                        {
                                play_countdown(this, StatusEffects_gettime(STATUSEFFECT_Superweapons, this), SND_POWEROFF);
-                               if (time > StatusEffects_gettime(STATUSEFFECT_Superweapons, this))
+                               if (time >= StatusEffects_gettime(STATUSEFFECT_Superweapons, this))
                                {
                                        this.items = this.items - (this.items & IT_SUPERWEAPON);
                                        STAT(WEAPONS, this) &= ~WEPSET_SUPERWEAPONS;
index 6fc66efbdf4264bcfc446a4d6cf33028e48bc707..7ceb2b62ff381461f6d73c4832a6f1066455de14 100644 (file)
@@ -604,7 +604,7 @@ bool Item_GiveTo(entity item, entity player)
        if (item.strength_finished)
        {
                pickedup = true;
-               float t = max(StatusEffects_gettime(STATUSEFFECT_Strength, player), time);
+               float t = StatusEffects_gettime(STATUSEFFECT_Strength, player);
                if (autocvar_g_powerups_stack)
                        t += item.strength_finished;
                else
@@ -614,7 +614,7 @@ bool Item_GiveTo(entity item, entity player)
        if (item.invincible_finished)
        {
                pickedup = true;
-               float t = max(StatusEffects_gettime(STATUSEFFECT_Shield, player), time);
+               float t = StatusEffects_gettime(STATUSEFFECT_Shield, player);
                if (autocvar_g_powerups_stack)
                        t += item.invincible_finished;
                else
@@ -624,7 +624,7 @@ bool Item_GiveTo(entity item, entity player)
        if (item.speed_finished)
        {
                pickedup = true;
-               float t = max(StatusEffects_gettime(STATUSEFFECT_Speed, player), time);
+               float t = StatusEffects_gettime(STATUSEFFECT_Speed, player);
                if (autocvar_g_powerups_stack)
                        t += item.speed_finished;
                else
@@ -634,7 +634,7 @@ bool Item_GiveTo(entity item, entity player)
        if (item.invisibility_finished)
        {
                pickedup = true;
-               float t = max(StatusEffects_gettime(STATUSEFFECT_Invisibility, player), time);
+               float t = StatusEffects_gettime(STATUSEFFECT_Invisibility, player);
                if (autocvar_g_powerups_stack)
                        t += item.invisibility_finished;
                else
@@ -644,7 +644,8 @@ bool Item_GiveTo(entity item, entity player)
        if (item.superweapons_finished)
        {
                pickedup = true;
-               StatusEffects_apply(STATUSEFFECT_Superweapons, player, max(StatusEffects_gettime(STATUSEFFECT_Superweapons, player), time) + item.superweapons_finished, 0);
+               float t = StatusEffects_gettime(STATUSEFFECT_Superweapons, player);
+               StatusEffects_apply(STATUSEFFECT_Superweapons, player, t + item.superweapons_finished, 0);
        }
 
        // always eat teamed entities