]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Refactor damage text code that keeps track of attackers to avoid using an intrusive...
authorterencehill <piuntn@gmail.com>
Sun, 7 Jul 2024 21:52:51 +0000 (23:52 +0200)
committerterencehill <piuntn@gmail.com>
Sun, 7 Jul 2024 21:52:51 +0000 (23:52 +0200)
qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc

index 9b596e922bc293c6e876b1b668bc84cbab731335..7c9043e00e4b7fdf838d86d12e06f7c7587b9be8 100644 (file)
@@ -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;
 }