From 1d4a86a094dd0c74b4259b6b7e39ec1b80cd13cd Mon Sep 17 00:00:00 2001 From: "Dr. Jaska" Date: Mon, 29 Mar 2021 13:28:16 +0000 Subject: [PATCH] Fixed electro secondary limit being global Now it tracks which electro entity has fired how many balls and destroys the oldest ones of that electro entity, not the oldest of any electro entity. I had to clone and edit the rubble functions to support entity storing and comparing the owner of the child entity to given entity, those are named electrorubble but can be renamed, they are just created for electro, they support other entities too and not only electro balls. --- qcsrc/common/effects/qc/casings.qc | 4 +-- qcsrc/common/effects/qc/gibs.qc | 4 +-- qcsrc/common/effects/qc/rubble.qc | 38 +++++++++++++++++--------- qcsrc/common/effects/qc/rubble.qh | 15 +++++++--- qcsrc/common/weapons/weapon/electro.qc | 9 +++--- qcsrc/lib/intrusivelist.qh | 4 +++ 6 files changed, 48 insertions(+), 26 deletions(-) diff --git a/qcsrc/common/effects/qc/casings.qc b/qcsrc/common/effects/qc/casings.qc index d5af50fb3..10dfa385d 100644 --- a/qcsrc/common/effects/qc/casings.qc +++ b/qcsrc/common/effects/qc/casings.qc @@ -149,7 +149,7 @@ NET_HANDLE(casings, bool isNew) ang_z = ReadByte() * 360 / 256; return = true; - Casing casing = RubbleNew(new(casing)); + Casing casing = ListNewChildRubble(CasingsNGibs, new(casing)); casing.silent = (_state & 0x80); casing.state = (_state & 0x7F); casing.origin = org; @@ -183,7 +183,7 @@ NET_HANDLE(casings, bool isNew) setsize(casing, '0 0 -1', '0 0 -1'); - RubbleLimit("casing", autocvar_cl_casings_maxcount, Casing_Delete); + LimitedChildrenRubble(CasingsNGibs, "casing", autocvar_cl_casings_maxcount, Casing_Delete, NULL); } #endif diff --git a/qcsrc/common/effects/qc/gibs.qc b/qcsrc/common/effects/qc/gibs.qc index ac69e9e01..64a847e27 100644 --- a/qcsrc/common/effects/qc/gibs.qc +++ b/qcsrc/common/effects/qc/gibs.qc @@ -170,7 +170,7 @@ void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector entity gib; // TODO remove some gibs according to cl_nogibs - gib = RubbleNew(new(gib)); + gib = ListNewChildRubble(CasingsNGibs, new(gib)); set_movetype(gib, MOVETYPE_BOUNCE); gib.gravity = 1; gib.solid = SOLID_CORPSE; @@ -205,7 +205,7 @@ void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15); gib.drawmask = MASK_NORMAL; - RubbleLimit("gib", autocvar_cl_gibs_maxcount, Gib_Delete); + LimitedChildrenRubble(CasingsNGibs, "gib", autocvar_cl_gibs_maxcount, Gib_Delete, NULL); } NET_HANDLE(net_gibsplash, bool isNew) diff --git a/qcsrc/common/effects/qc/rubble.qc b/qcsrc/common/effects/qc/rubble.qc index 27dd7d40e..f0a29bd5b 100644 --- a/qcsrc/common/effects/qc/rubble.qc +++ b/qcsrc/common/effects/qc/rubble.qc @@ -1,8 +1,8 @@ #include "rubble.qh" #ifdef GAMEQC -void RubbleLimit(string cname, int limit, void(entity) deleteproc) -{ + +void LimitedChildrenRubble(IntrusiveList list, string cname, int limit, void(entity) deleteproc, entity parent){ // remove rubble of the same type if it's at the limit // remove multiple rubble if the limit has been decreased while (1) @@ -13,13 +13,15 @@ void RubbleLimit(string cname, int limit, void(entity) deleteproc) entity oldest = NULL; float oldesttime = 0; // compare to all other matching entities - IL_EACH(g_rubble, it.classname == cname, + IL_EACH(list, it.classname == cname, { - ++c; - if(!oldest || oldesttime > it.creationtime) - { - oldest = it; - oldesttime = it.creationtime; + if(!parent ||parent == it.owner){ + ++c; + if(!oldest || oldesttime > it.creationtime) + { + oldest = it; + oldesttime = it.creationtime; + } } }); @@ -31,10 +33,20 @@ void RubbleLimit(string cname, int limit, void(entity) deleteproc) } } -entity RubbleNew(entity e) -{ - e.creationtime = time; - IL_PUSH(g_rubble, e); - return e; + +// This function doesn't preserve linked list order but it is not needed as creationtime is used instead of list position for comparing ages. +// IL_Replace or similiar order preserving function did not exist at the time of creating this. +entity ReplaceOldListedChildRubble(IntrusiveList list, entity child, entity oldChild){ + child.creationtime = oldChild.creationtime; + IL_REMOVE(list, oldChild); + IL_PUSH(list, child); + return child; } + +entity ListNewChildRubble(IntrusiveList list, entity child){ + child.creationtime = time; + IL_PUSH(list, child); + return child; +} + #endif diff --git a/qcsrc/common/effects/qc/rubble.qh b/qcsrc/common/effects/qc/rubble.qh index 406d602c1..bd75bae01 100644 --- a/qcsrc/common/effects/qc/rubble.qh +++ b/qcsrc/common/effects/qc/rubble.qh @@ -4,10 +4,17 @@ entityclass(Rubble); classfield(Rubble).float creationtime; -IntrusiveList g_rubble; -STATIC_INIT(g_rubble) { g_rubble = IL_NEW(); } +IntrusiveList CasingsNGibs; +STATIC_INIT(CasingsNGibs) { CasingsNGibs = IL_NEW(); } -void RubbleLimit(string cname, int limit, void(entity) deleteproc); +IntrusiveList LimitedElectroBallRubbleList; +STATIC_INIT(LimitedElectroBallRubbleList) { LimitedElectroBallRubbleList = IL_NEW(); } + + +void LimitedChildrenRubble(IntrusiveList list, string cname, int limit, void(entity) deleteproc, entity parent); + +entity ReplaceOldListedChildRubble(IntrusiveList list, entity child, entity oldChild); + +entity ListNewChildRubble(IntrusiveList list, entity child); -entity RubbleNew(entity e); #endif diff --git a/qcsrc/common/weapons/weapon/electro.qc b/qcsrc/common/weapons/weapon/electro.qc index 21a2f9b01..79cfa5ebf 100644 --- a/qcsrc/common/weapons/weapon/electro.qc +++ b/qcsrc/common/weapons/weapon/electro.qc @@ -297,10 +297,9 @@ void W_Electro_Orb_Stick(entity this, entity to) IL_PUSH(g_bot_dodge, newproj); // check if limits are enabled (we can tell by checking if the original orb is listed) and push it to the list if so - if(IL_CONTAINS(g_rubble, this)) + if(IL_CONTAINS(LimitedElectroBallRubbleList, this)) { - newproj.creationtime = this.creationtime; - IL_PUSH(g_rubble, newproj); + ReplaceOldListedChildRubble(LimitedElectroBallRubbleList, newproj, this); } delete(this); @@ -423,8 +422,8 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity) if(WEP_CVAR_SEC(electro, limit) > 0) { - RubbleNew(proj); - RubbleLimit("electro_orb", WEP_CVAR_SEC(electro, limit), adaptor_think2use_hittype_splash); + ListNewChildRubble(LimitedElectroBallRubbleList, proj); + LimitedChildrenRubble(LimitedElectroBallRubbleList, "electro_orb", WEP_CVAR_SEC(electro, limit), adaptor_think2use_hittype_splash, actor); } CSQCProjectile(proj, true, PROJECTILE_ELECTRO, false); // no culling, it has sound diff --git a/qcsrc/lib/intrusivelist.qh b/qcsrc/lib/intrusivelist.qh index be3fb00fa..dce561bb5 100644 --- a/qcsrc/lib/intrusivelist.qh +++ b/qcsrc/lib/intrusivelist.qh @@ -2,6 +2,10 @@ #include "iter.qh" +/** + * This limitation is only towards maximum amount of creatable lists. + * Lists can be given endless amount of entities, only restricted by engine limitations. + */ const int IL_MAX = 128; ERASEABLE -- 2.39.2