From 336807ce9c608cef86d699f3a6fd7e707d8cdd98 Mon Sep 17 00:00:00 2001 From: terencehill Date: Sun, 7 Jul 2024 23:52:51 +0200 Subject: [PATCH] Refactor damage text code that keeps track of attackers to avoid using an intrusive list for every player --- .../mutator/damagetext/sv_damagetext.qc | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc b/qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc index 9b596e922..7c9043e00 100644 --- a/qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc +++ b/qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc @@ -14,7 +14,11 @@ REGISTER_MUTATOR(damagetext, true); .float dent_net_health; .float dent_net_armor; .float dent_net_potential; -.entity dent_attackers; + +const int BITS_PER_INT = 24; +const int DENT_ATTACKERS_SIZE = 11; // ceil(255 / BITS_PER_INT) +// where 255 is the max number of clients that the engine can support +.int dent_attackers[DENT_ATTACKERS_SIZE]; bool write_damagetext(entity this, entity client, int sf) { @@ -97,11 +101,17 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) { net_text_prev.dent_net_potential = potential_damage; return; } - else if (attacker && !IL_CONTAINS(hit.dent_attackers, attacker)) + else if (attacker) { - // player is hit for the first time after respawn by this attacker - IL_PUSH(hit.dent_attackers, attacker); - flags |= DTFLAG_STOP_ACCUMULATION; // forcedly stop client-side damage accumulation + int attacker_id = etof(attacker) - 1; + int idx = floor(attacker_id / BITS_PER_INT); + int bit = attacker_id % BITS_PER_INT; + if (!(hit.dent_attackers[idx] & BIT(bit))) + { + // player is hit for the first time after respawn by this attacker + hit.dent_attackers[idx] |= BIT(bit); + flags |= DTFLAG_STOP_ACCUMULATION; // forcedly stop client-side damage accumulation + } } entity net_text = new_pure(net_damagetext); @@ -125,21 +135,18 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) { MUTATOR_HOOKFUNCTION(damagetext, ClientDisconnect) { entity player = M_ARGV(0, entity); - if (player.dent_attackers) - IL_DELETE(player.dent_attackers); - - // NOTE this player is automatically removed from dent_attackers lists of other players - // by intrusive list's ONREMOVE + int player_id = etof(player) - 1; + int idx = floor(player_id / BITS_PER_INT); + int bit = player_id % BITS_PER_INT; + // remove from attacker list of all players + FOREACH_CLIENT(IS_PLAYER(it), { + it.dent_attackers[idx] &= ~BIT(bit); + }); } MUTATOR_HOOKFUNCTION(damagetext, PlayerSpawn) { entity player = M_ARGV(0, entity); - if (player.dent_attackers == NULL) - { - player.dent_attackers = IL_NEW(); - return true; - } - - IL_CLEAR(player.dent_attackers); + for (int i = 0; i < DENT_ATTACKERS_SIZE; ++i) + player.dent_attackers[i] = 0; } -- 2.39.2