]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc
Use separate variable to store number of records to arrive from the server
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / damagetext / sv_damagetext.qc
1 #include "sv_damagetext.qh"
2
3 AUTOCVAR(sv_damagetext, int, 2, "<= 0: disabled, >= 1: visible to spectators, >= 2: visible to attacker, >= 3: all players see everyone's damage");
4
5 REGISTER_MUTATOR(damagetext, true);
6
7 #define SV_DAMAGETEXT_DISABLED()        (autocvar_sv_damagetext <= 0 || autocvar_g_instagib)
8 #define SV_DAMAGETEXT_SPECTATORS_ONLY() (autocvar_sv_damagetext >= 1)
9 #define SV_DAMAGETEXT_PLAYERS()         (autocvar_sv_damagetext >= 2)
10 #define SV_DAMAGETEXT_ALL()             (autocvar_sv_damagetext >= 3)
11 MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) {
12     if (SV_DAMAGETEXT_DISABLED()) return;
13     const entity attacker = M_ARGV(0, entity);
14     const entity hit = M_ARGV(1, entity); if (hit == attacker) return;
15     const float health = M_ARGV(2, float);
16     const float armor = M_ARGV(3, float);
17     const int deathtype = M_ARGV(5, int);
18     const float potential_damage = M_ARGV(6, float);
19     FOREACH_CLIENT(IS_REAL_CLIENT(it), {
20         if (
21             (SV_DAMAGETEXT_ALL()) ||
22             (SV_DAMAGETEXT_PLAYERS() && it == attacker) ||
23             (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_SPEC(it) && it.enemy == attacker) ||
24             (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_OBSERVER(it))
25         ) {
26             int flags = 0;
27             if (SAME_TEAM(hit, attacker)) flags |= DTFLAG_SAMETEAM;
28             if (health >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_HEALTH;
29             if (armor >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_ARMOR;
30             if (potential_damage >= DAMAGETEXT_SHORT_LIMIT) flags |= DTFLAG_BIG_POTENTIAL;
31             if (!armor) flags |= DTFLAG_NO_ARMOR;
32             if (almost_equals_eps(armor + health, potential_damage, 5)) flags |= DTFLAG_NO_POTENTIAL;
33
34             msg_entity = it;
35             WriteHeader(MSG_ONE, damagetext);
36             WriteByte(MSG_ONE, etof(hit));
37             WriteInt24_t(MSG_ONE, deathtype);
38             WriteByte(MSG_ONE, flags);
39
40             // we need to send a few decimal places to minimize errors when accumulating damage
41             // sending them multiplied saves bandwidth compared to using WriteCoord,
42             // however if the multiplied damage would be too much for (signed) short, we send an int24
43             if (flags & DTFLAG_BIG_HEALTH) WriteInt24_t(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER);
44             else WriteShort(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER);
45             if (!(flags & DTFLAG_NO_ARMOR))
46             {
47                 if (flags & DTFLAG_BIG_ARMOR) WriteInt24_t(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
48                 else WriteShort(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER);
49             }
50             if (!(flags & DTFLAG_NO_POTENTIAL))
51             {
52                 if (flags & DTFLAG_BIG_POTENTIAL) WriteInt24_t(MSG_ONE, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER);
53                 else WriteShort(MSG_ONE, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER);
54                         }
55         }
56     });
57 }