From: Mario Date: Thu, 3 Dec 2020 14:11:29 +0000 (+1000) Subject: Network damage text with reliable messages by using linked entities (same technique... X-Git-Tag: xonotic-v0.8.5~632^2~2 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=2300b0c288d9a50adf370c2d7dcded0325b5eecb;p=xonotic%2Fxonotic-data.pk3dir.git Network damage text with reliable messages by using linked entities (same technique used by notifications) --- diff --git a/qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc b/qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc index 899c6d63c..d398ecf3a 100644 --- a/qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc +++ b/qcsrc/common/mutators/mutator/damagetext/cl_damagetext.qc @@ -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; diff --git a/qcsrc/common/mutators/mutator/damagetext/damagetext.qc b/qcsrc/common/mutators/mutator/damagetext/damagetext.qc index 78118d4b5..7cdd567f1 100644 --- a/qcsrc/common/mutators/mutator/damagetext/damagetext.qc +++ b/qcsrc/common/mutators/mutator/damagetext/damagetext.qc @@ -1,3 +1,3 @@ #include "damagetext.qh" -REGISTER_NET_TEMP(damagetext) +REGISTER_NET_LINKED(damagetext) diff --git a/qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc b/qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc index 38d28a449..c9ded88f0 100644 --- a/qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc +++ b/qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc @@ -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); }