From e854e6badb58cecb0c8f07e312e79f79a9c3a89e Mon Sep 17 00:00:00 2001 From: bones_was_here Date: Fri, 16 Jun 2023 06:36:11 +1000 Subject: [PATCH] items: replace broken loot think implementation Implements a slow update rate for loot items, just enough to correct occasional prediction errors. Includes SVQC prerequisites for loot item despawn effects --- qcsrc/common/items/item.qh | 7 ++++++ qcsrc/server/items/items.qc | 41 ++++++++++++++++++++++++++++---- qcsrc/server/weapons/throwing.qc | 22 +---------------- qcsrc/server/weapons/throwing.qh | 3 --- 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/qcsrc/common/items/item.qh b/qcsrc/common/items/item.qh index 350421465..2de498aaf 100644 --- a/qcsrc/common/items/item.qh +++ b/qcsrc/common/items/item.qh @@ -57,6 +57,13 @@ const int ITS_AVAILABLE = BIT(3); const int ITS_ALLOWFB = BIT(4); const int ITS_ALLOWSI = BIT(5); const int ITS_GLOW = BIT(6); +const int ITS_EXPIRING = BIT(7); + +// enough to notice it's about to despawn and circle jump to grab it +const float IT_DESPAWNFX_TIME = 1.5; + +// 2hz probably enough to correct a desync caused by serious lag +const float IT_UPDATE_INTERVAL = 0.5; .float fade_start; .float fade_end; diff --git a/qcsrc/server/items/items.qc b/qcsrc/server/items/items.qc index 57720ef9a..5214d12ef 100644 --- a/qcsrc/server/items/items.qc +++ b/qcsrc/server/items/items.qc @@ -188,9 +188,40 @@ void Item_Show(entity e, int mode) void Item_Think(entity this) { - this.nextthink = time; - if(this.origin != this.oldorigin) + if (Item_IsLoot(this)) + { + if (time < this.wait - IT_DESPAWNFX_TIME) + this.nextthink = min(time + IT_UPDATE_INTERVAL, this.wait - IT_DESPAWNFX_TIME); // ensuring full time for effects + else + { + // despawning soon, start effects + this.ItemStatus |= ITS_EXPIRING; + this.SendFlags |= ISF_STATUS; + if (time < this.wait - IT_UPDATE_INTERVAL) + this.nextthink = time + IT_UPDATE_INTERVAL; + else + { + setthink(this, RemoveItem); + this.nextthink = this.wait; + } + } + + // enable pickup by the player who threw it + this.owner = NULL; + + // send slow updates even if the item didn't move + // recovers prediction desyncs where server thinks item stopped, client thinks it didn't ItemUpdate(this); + } + else + { + // bones_was_here: TODO: predict movers, enable client prediction of items with a groundentity, + // and then send those less often too (and not all on the same frame) + this.nextthink = time; + + if(this.origin != this.oldorigin) + ItemUpdate(this); + } } bool Item_ItemsTime_SpectatorOnly(GameItem it); @@ -986,9 +1017,9 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default this.reset = RemoveItem; set_movetype(this, MOVETYPE_TOSS); - // Savage: remove thrown items after a certain period of time ("garbage collection") - setthink(this, RemoveItem); - this.nextthink = time + autocvar_g_items_dropped_lifetime; + setthink(this, Item_Think); + this.nextthink = time + IT_UPDATE_INTERVAL; + this.wait = time + autocvar_g_items_dropped_lifetime; this.takedamage = DAMAGE_YES; this.event_damage = Item_Damage; diff --git a/qcsrc/server/weapons/throwing.qc b/qcsrc/server/weapons/throwing.qc index 01c6ac0d2..a979b7b0c 100644 --- a/qcsrc/server/weapons/throwing.qc +++ b/qcsrc/server/weapons/throwing.qc @@ -18,24 +18,6 @@ #include #include -void thrown_wep_think(entity this) -{ - this.nextthink = time; - if(this.oldorigin != this.origin) - { - this.SendFlags |= ISF_LOCATION; - this.oldorigin = this.origin; - } - this.owner = NULL; - float timeleft = this.savenextthink - time; - if(timeleft > 1) - SUB_SetFade(this, this.savenextthink - 1, 1); - else if(timeleft > 0) - SUB_SetFade(this, time, timeleft); - else - SUB_VanishOrRemove(this); -} - // returns amount of ammo used, or -1 for failure, or 0 for no ammo count float W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity) { @@ -91,9 +73,7 @@ float W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector weapon_defaultspawnfunc(wep, info); if(startitem_failed) return -1; - setthink(wep, thrown_wep_think); - wep.savenextthink = wep.nextthink; - wep.nextthink = min(wep.nextthink, time + 0.5); + wep.pickup_anyway = true; // these are ALWAYS pickable //wa = W_AmmoItemCode(wpn); diff --git a/qcsrc/server/weapons/throwing.qh b/qcsrc/server/weapons/throwing.qh index b3c7df645..afbc51851 100644 --- a/qcsrc/server/weapons/throwing.qh +++ b/qcsrc/server/weapons/throwing.qh @@ -5,9 +5,6 @@ bool autocvar_g_weapon_throwable; -.float savenextthink; -void thrown_wep_think(entity this); - // returns amount of ammo used, or -1 for failure, or 0 for no ammo count float W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity); -- 2.39.2