From eabf9f8338e6689e92404411e4c8e6462ac50dc4 Mon Sep 17 00:00:00 2001 From: Mario Date: Sat, 7 Jan 2023 04:40:27 +1000 Subject: [PATCH] Add a new function to copy fields from items to replacements, fixes #2792 --- qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc | 5 ++--- .../common/mutators/mutator/instagib/sv_instagib.qc | 10 ++-------- .../common/mutators/mutator/overkill/sv_overkill.qc | 12 ++---------- .../mutator/random_items/sv_random_items.qc | 5 ++--- qcsrc/server/items/items.qc | 13 +++++++++++++ qcsrc/server/items/items.qh | 2 ++ qcsrc/server/weapons/spawning.qc | 5 ++++- 7 files changed, 27 insertions(+), 25 deletions(-) diff --git a/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc b/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc index 947111a08..7b41f9824 100644 --- a/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc +++ b/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc @@ -674,10 +674,9 @@ MUTATOR_HOOKFUNCTION(lms, OnEntityPreSpawn) entity e = spawn(); setthink(e, lms_extralife); + Item_CopyFields(ent, e); + e.nextthink = time + 0.1; - e.spawnflags = ent.spawnflags; - e.noalign = ent.noalign; - setorigin(e, ent.origin); return true; } diff --git a/qcsrc/common/mutators/mutator/instagib/sv_instagib.qc b/qcsrc/common/mutators/mutator/instagib/sv_instagib.qc index 2131228eb..7b270f32f 100644 --- a/qcsrc/common/mutators/mutator/instagib/sv_instagib.qc +++ b/qcsrc/common/mutators/mutator/instagib/sv_instagib.qc @@ -297,11 +297,7 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, SetWeaponArena) void replace_with_insta_cells(entity item) { entity e = new(item_vaporizer_cells); - setorigin(e, item.origin); - e.noalign = Item_ShouldKeepPosition(item); - e.cnt = item.cnt; - e.team = item.team; - e.spawnfunc_checked = true; + Item_CopyFields(item, e); spawnfunc_item_vaporizer_cells(e); } @@ -438,10 +434,8 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, OnEntityPreSpawn) setthink(e, instagib_speed); } + Item_CopyFields(ent, e); e.nextthink = time + 0.1; - e.spawnflags = ent.spawnflags; - e.noalign = ent.noalign; - setorigin(e, ent.origin); return true; } diff --git a/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc b/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc index 7b2459869..009acc355 100644 --- a/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc +++ b/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc @@ -227,28 +227,20 @@ MUTATOR_HOOKFUNCTION(ok, FilterItem) if (item.classname == "item_strength") { entity wep = new(weapon_okhmg); - setorigin(wep, item.origin); + Item_CopyFields(item, wep); wep.ok_item = true; - wep.noalign = Item_ShouldKeepPosition(item); - wep.cnt = item.cnt; - wep.team = item.team; wep.respawntime = g_pickup_respawntime_superweapon; wep.pickup_anyway = true; - wep.spawnfunc_checked = true; Item_Initialize(wep, "weapon_okhmg"); // doesn't actually use spawnfunc return true; } else if (item.classname == "item_shield") { entity wep = new(weapon_okrpc); - setorigin(wep, item.origin); + Item_CopyFields(item, wep); wep.ok_item = true; - wep.noalign = Item_ShouldKeepPosition(item); - wep.cnt = item.cnt; - wep.team = item.team; wep.respawntime = g_pickup_respawntime_superweapon; wep.pickup_anyway = true; - wep.spawnfunc_checked = true; Item_Initialize(wep, "weapon_okrpc"); // doesn't actually use spawnfunc return true; } diff --git a/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc b/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc index 183808021..c0fa7ff96 100644 --- a/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc +++ b/qcsrc/common/mutators/mutator/random_items/sv_random_items.qc @@ -269,6 +269,7 @@ entity RandomItems_ReplaceMapItem(entity item) entity new_item; if (!MUTATOR_IS_ENABLED(ok)) { + // TODO: doesn't copy many fields from items new_item = Item_Create(strzone(new_classname), item.origin, Item_ShouldKeepPosition(item)); random_items_is_spawning = false; @@ -280,9 +281,8 @@ entity RandomItems_ReplaceMapItem(entity item) else { new_item = spawn(); + Item_CopyFields(item, new_item); new_item.classname = strzone(new_classname); - new_item.spawnfunc_checked = true; - new_item.noalign = Item_ShouldKeepPosition(item); new_item.ok_item = true; Item_Initialize(new_item, new_classname); random_items_is_spawning = false; @@ -290,7 +290,6 @@ entity RandomItems_ReplaceMapItem(entity item) { return NULL; } - setorigin(new_item, item.origin); } if (item.team) { diff --git a/qcsrc/server/items/items.qc b/qcsrc/server/items/items.qc index e68d858a8..6b653d9c3 100644 --- a/qcsrc/server/items/items.qc +++ b/qcsrc/server/items/items.qc @@ -795,6 +795,19 @@ void Item_FindTeam(entity this) }); } +void Item_CopyFields(entity this, entity to) +{ + setorigin(to, this.origin); + to.spawnflags = this.spawnflags; + to.noalign = Item_ShouldKeepPosition(this); + to.cnt = this.cnt; + to.team = this.team; + to.spawnfunc_checked = true; + // TODO: copy respawn times? this may not be desirable in some cases + //to.respawntime = this.respawntime; + //to.respawntimejitter = this.respawntimejitter; +} + // Savage: used for item garbage-collection void RemoveItem(entity this) { diff --git a/qcsrc/server/items/items.qh b/qcsrc/server/items/items.qh index f00b7bdc3..95e27f836 100644 --- a/qcsrc/server/items/items.qh +++ b/qcsrc/server/items/items.qh @@ -75,6 +75,8 @@ void Item_Reset(entity this); void Item_FindTeam(entity this); +void Item_CopyFields(entity this, entity to); + bool ItemSend(entity this, entity to, int sf); void ItemUpdate(entity this); diff --git a/qcsrc/server/weapons/spawning.qc b/qcsrc/server/weapons/spawning.qc index e38a508a9..b14579e24 100644 --- a/qcsrc/server/weapons/spawning.qc +++ b/qcsrc/server/weapons/spawning.qc @@ -60,7 +60,10 @@ void weapon_defaultspawnfunc(entity this, Weapon wpn) if(wep != WEP_Null) { entity replacement = spawn(); - copyentity(this, replacement); + Item_CopyFields(this, replacement); + // copyentity is an engine function which unintentionally copies intrusive list data + // DO NOTE USE, causes #2792 + //copyentity(this, replacement); replacement.m_isreplaced = true; weapon_defaultspawnfunc(replacement, wep); } -- 2.39.2