]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
items: only draw the removal effect when appropriate
authorbones_was_here <bones_was_here@xonotic.au>
Fri, 21 Jul 2023 08:57:27 +0000 (18:57 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Fri, 21 Jul 2023 08:57:27 +0000 (18:57 +1000)
Sends an extra update that triggers the effect prior to removal.
Currently only used for loot items when picked up or touching void.

Fixes #2849
without reverting to the old way of sending the effect in SVQC which
caused every player to receive it even if they couldn't see the item,
and without the expense of additional culling.

Changes the pipeline hash because g_powerups_drop_ondeath is enabled by
default and bots remove an item from their goals immediately if it's
deleted, but if it still exists (for 1-2 frames in this case) they only
remove it if it's in their PVS.

.gitlab-ci.yml
qcsrc/client/items/items.qc
qcsrc/common/items/item.qh
qcsrc/server/items/items.qc

index 48fa0d93faeb79c99967a078cdca69fe092c34c4..c6adaed4d6e4d551ddb2b472077169bc42aa4373 100644 (file)
@@ -75,7 +75,7 @@ test_sv_game:
     - wget -nv -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
     - wget -nv -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
 
-    - EXPECT=9fb6b4ba8c0f8b04995c123e3801b32d
+    - EXPECT=f68507df6290e8a8bd8b2a383913184f
     - HASH=$(${ENGINE} +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index 755f0f9cd40d0a52aff03018e70a485ef9574d17..1b03ba8fc22443dbd100ebb101b3e7be3d906abe 100644 (file)
@@ -215,9 +215,6 @@ void ItemDraw(entity this)
 
 void ItemRemove(entity this)
 {
-       if(this.alpha)
-       if(!this.wait || time < this.wait - ticrate) // despawning loot items have their own effects
-               pointparticles(EFFECT_ITEM_PICKUP, (this.absmin + this.absmax) * 0.5, '0 0 0', 1);
        strfree(this.mdl);
 }
 
@@ -290,6 +287,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
                        IL_PUSH(g_drawables, this);
                        this.draw = ItemDraw;
                        this.flags |= FL_ITEM;
+                       this.entremove = ItemRemove;
                }
 
                this.fade_end = ReadShort();
@@ -325,7 +323,16 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
                SET_ONGROUND(this); // extra overkill
        }
 
-       this.entremove = ItemRemove;
+       if(sf & ISF_REMOVEFX && !(sf & ISF_SIZE) && !(sf & ISF_MODEL)) // TODO !isnew isn't reliable for this... are we double sending initialisations?
+       {
+               // no longer available to pick up, about to be removed
+               if (this.drawmask) // this.alpha > 0
+                       pointparticles(EFFECT_ITEM_PICKUP, (this.absmin + this.absmax) * 0.5, '0 0 0', 1);
+               // removing now causes CSQC_Ent_Remove() to spam
+               this.drawmask = 0;
+               IL_REMOVE(g_drawables, this);
+               this.solid = SOLID_NOT;
+       }
 
        return true;
 }
index 038566784725b962e5403755f2e3cae674a13323..4beeda8498a52a4056f5ba101d8797b25c021acc 100644 (file)
@@ -38,6 +38,7 @@ const int IT_SPEED                                            = BIT(13);
 const int IT_PICKUPMASK                        = IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS | IT_JETPACK | IT_FUEL_REGEN; // strength and invincible are handled separately
 
 // item networking
+const int ISF_REMOVEFX          = BIT(0); // technically unnecessary (after the kludge in Item_Think() is reverted), but cheaper and cleaner than using ITS_AVAILABLE
 const int ISF_LOCATION          = BIT(1);
 const int ISF_MODEL             = BIT(2);
 const int ISF_STATUS            = BIT(3);
index e0013b5ce0d37ff4eff0cd2a5bedd0c52407e189..829418497dff6483dd53816dd2451714b6624f60 100644 (file)
@@ -679,6 +679,7 @@ void Item_Touch(entity this, entity toucher)
        {
                if (ITEM_TOUCH_NEEDKILL())
                {
+                       this.SendFlags |= ISF_REMOVEFX;
                        RemoveItem(this);
                        return;
                }
@@ -742,7 +743,8 @@ LABEL(pickup)
 
        if (ITEM_IS_LOOT(this))
        {
-               delete(this);
+               this.SendFlags |= ISF_REMOVEFX;
+               RemoveItem(this);
                return;
        }
        if (!this.spawnshieldtime)
@@ -847,7 +849,16 @@ void RemoveItem(entity this)
        if(wasfreed(this) || !this) { return; }
        if(this.waypointsprite_attached)
                WaypointSprite_Kill(this.waypointsprite_attached);
-       delete(this);
+
+       if (this.SendFlags & ISF_REMOVEFX)
+       {
+               // delay removal until ISF_REMOVEFX has been sent
+               setthink(this, RemoveItem);
+               this.nextthink = time + 2 * autocvar_sys_ticrate; // micro optimisation: next frame will be too soon
+               this.solid = SOLID_NOT; // untouchable
+       }
+       else
+               delete(this);
 }
 
 // pickup evaluation functions