]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Network damage text with reliable messages by using linked entities (same technique...
authorMario <zacjardine@y7mail.com>
Thu, 3 Dec 2020 14:11:29 +0000 (00:11 +1000)
committerMario <zacjardine@y7mail.com>
Thu, 3 Dec 2020 14:11:29 +0000 (00:11 +1000)
qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc
qcsrc/common/mutators/mutator/damagetext/damagetext.qc
qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc

index 899c6d63c1284fce107e2a348ab482d731d620ab..d398ecf3aae553245dd3f7727120d46cf4ff0871 100644 (file)
@@ -206,6 +206,7 @@ float current_alpha(entity damage_text) {
 
 NET_HANDLE(damagetext, bool isNew)
 {
+    make_pure(this);
     int server_entity_index = ReadByte();
     int deathtype = ReadInt24_t();
     int flags = ReadByte();
@@ -222,6 +223,7 @@ NET_HANDLE(damagetext, bool isNew)
     else potential_damage = ReadShort();
 
     return = true;
+    if (!isNew) return;
     if (autocvar_cl_damagetext == 0) return;
     if (friendlyfire) {
         if (autocvar_cl_damagetext_friendlyfire == 0) return;
index 78118d4b5698e9ab763cf38a8579381ac2ce6e79..7cdd567f1a59d7057c1c36348cf38b54fa1d72d8 100644 (file)
@@ -1,3 +1,3 @@
 #include "damagetext.qh"
 
-REGISTER_NET_TEMP(damagetext)
+REGISTER_NET_LINKED(damagetext)
index 38d28a4494e2217e480249f6ecc8fc35ac100d5c..c9ded88f00adc6dc05c627199baef0f3f4b80ab7 100644 (file)
@@ -8,6 +8,52 @@ REGISTER_MUTATOR(damagetext, true);
 #define SV_DAMAGETEXT_SPECTATORS_ONLY() (autocvar_sv_damagetext >= 1)
 #define SV_DAMAGETEXT_PLAYERS()         (autocvar_sv_damagetext >= 2)
 #define SV_DAMAGETEXT_ALL()             (autocvar_sv_damagetext >= 3)
+
+.int dent_net_flags;
+.float dent_net_deathtype;
+.float dent_net_health;
+.float dent_net_armor;
+.float dent_net_potential;
+
+bool write_damagetext(entity this, entity client, int sf)
+{
+    entity attacker = this.realowner;
+    entity hit = this.enemy;
+    int flags = this.dent_net_flags;
+    int deathtype = this.dent_net_deathtype;
+    float health = this.dent_net_health;
+    float armor = this.dent_net_armor;
+    float potential_damage = this.dent_net_potential;
+    if (!(
+        (SV_DAMAGETEXT_ALL()) ||
+        (SV_DAMAGETEXT_PLAYERS() && client == attacker) ||
+        (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_SPEC(client) && client.enemy == attacker) ||
+        (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_OBSERVER(client))
+    )) return false;
+
+    WriteHeader(MSG_ENTITY, damagetext);
+    WriteByte(MSG_ENTITY, etof(hit));
+    WriteInt24_t(MSG_ENTITY, deathtype);
+    WriteByte(MSG_ENTITY, flags);
+
+    // we need to send a few decimal places to minimize errors when accumulating damage
+    // sending them multiplied saves bandwidth compared to using WriteCoord,
+    // however if the multiplied damage would be too much for (signed) short, we send an int24
+    if (flags & DTFLAG_BIG_HEALTH) WriteInt24_t(MSG_ENTITY, health * DAMAGETEXT_PRECISION_MULTIPLIER);
+    else WriteShort(MSG_ENTITY, health * DAMAGETEXT_PRECISION_MULTIPLIER);
+    if (!(flags & DTFLAG_NO_ARMOR))
+    {
+        if (flags & DTFLAG_BIG_ARMOR) WriteInt24_t(MSG_ENTITY, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
+        else WriteShort(MSG_ENTITY, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
+    }
+    if (!(flags & DTFLAG_NO_POTENTIAL))
+    {
+        if (flags & DTFLAG_BIG_POTENTIAL) WriteInt24_t(MSG_ENTITY, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER);
+        else WriteShort(MSG_ENTITY, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER);
+    }
+    return true;
+}
+
 MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
     if (SV_DAMAGETEXT_DISABLED()) return;
     entity attacker = M_ARGV(0, entity);
@@ -18,42 +64,26 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
     float potential_damage = M_ARGV(6, float);
     if(DEATH_WEAPONOF(deathtype) == WEP_VAPORIZER) return;
     if(deathtype == DEATH_FIRE.m_id || deathtype == DEATH_BUFF.m_id) return; // TODO: exclude damage over time and thorn effects
-    FOREACH_CLIENT(IS_REAL_CLIENT(it), {
-        if (
-            (SV_DAMAGETEXT_ALL()) ||
-            (SV_DAMAGETEXT_PLAYERS() && it == attacker) ||
-            (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_SPEC(it) && it.enemy == attacker) ||
-            (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_OBSERVER(it))
-        ) {
-            int flags = 0;
-            if (SAME_TEAM(hit, attacker)) flags |= DTFLAG_SAMETEAM;
-            if (health >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_HEALTH;
-            if (armor >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_ARMOR;
-            if (potential_damage >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_POTENTIAL;
-            if (!armor) flags |= DTFLAG_NO_ARMOR;
-            if (almost_equals_eps(armor + health, potential_damage, 5)) flags |= DTFLAG_NO_POTENTIAL;
-
-            msg_entity = it;
-            WriteHeader(MSG_ONE, damagetext);
-            WriteByte(MSG_ONE, etof(hit));
-            WriteInt24_t(MSG_ONE, deathtype);
-            WriteByte(MSG_ONE, flags);
-
-            // we need to send a few decimal places to minimize errors when accumulating damage
-            // sending them multiplied saves bandwidth compared to using WriteCoord,
-            // however if the multiplied damage would be too much for (signed) short, we send an int24
-            if (flags & DTFLAG_BIG_HEALTH) WriteInt24_t(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER);
-            else WriteShort(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER);
-            if (!(flags & DTFLAG_NO_ARMOR))
-            {
-                if (flags & DTFLAG_BIG_ARMOR) WriteInt24_t(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
-                else WriteShort(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
-            }
-            if (!(flags & DTFLAG_NO_POTENTIAL))
-            {
-                if (flags & DTFLAG_BIG_POTENTIAL) WriteInt24_t(MSG_ONE, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER);
-                else WriteShort(MSG_ONE, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER);
-                       }
-        }
-    });
+
+    int flags = 0;
+    if (SAME_TEAM(hit, attacker)) flags |= DTFLAG_SAMETEAM;
+    if (health >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_HEALTH;
+    if (armor >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_ARMOR;
+    if (potential_damage >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_POTENTIAL;
+    if (!armor) flags |= DTFLAG_NO_ARMOR;
+    if (almost_equals_eps(armor + health, potential_damage, 5)) flags |= DTFLAG_NO_POTENTIAL;
+
+    entity net_text = new_pure(net_damagetext);
+    net_text.realowner = attacker;
+    net_text.enemy = hit;
+    net_text.dent_net_flags = flags;
+    net_text.dent_net_deathtype = deathtype;
+    net_text.dent_net_health = health;
+    net_text.dent_net_armor = armor;
+    net_text.dent_net_potential = potential_damage;
+
+    setthink(net_text, SUB_Remove);
+    net_text.nextthink = (time > 10) ? (time + 0.5) : 10; // allow a buffer from start time for clients to load in
+
+    Net_LinkEntity(net_text, false, 0, write_damagetext);
 }