]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/damagetext/sv_damagetext.qc
take3: format 903 files
[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 {
13         if (SV_DAMAGETEXT_DISABLED()) { return; }
14         const entity attacker = M_ARGV(0, entity);
15         const entity hit = M_ARGV(1, entity);
16         if (hit == attacker) { return; }
17         const float health = M_ARGV(2, float);
18         const float armor = M_ARGV(3, float);
19         const int deathtype = M_ARGV(5, int);
20         const float potential_damage = M_ARGV(6, float);
21         FOREACH_CLIENT(IS_REAL_CLIENT(it), {
22                 if (
23                         (SV_DAMAGETEXT_ALL())
24                         || (SV_DAMAGETEXT_PLAYERS() && it == attacker)
25                         || (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_SPEC(it) && it.enemy == attacker)
26                         || (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_OBSERVER(it))
27                 ) {
28                         int flags = 0;
29                         if (SAME_TEAM(hit, attacker)) { flags |= DTFLAG_SAMETEAM; }
30                         if (health >= DAMAGETEXT_SHORT_LIMIT) { flags |= DTFLAG_BIG_HEALTH; }
31                         if (armor >= DAMAGETEXT_SHORT_LIMIT) { flags |= DTFLAG_BIG_ARMOR; }
32                         if (potential_damage >= DAMAGETEXT_SHORT_LIMIT) { flags |= DTFLAG_BIG_POTENTIAL; }
33                         if (!armor) { flags |= DTFLAG_NO_ARMOR; }
34                         if (almost_equals_eps(armor + health, potential_damage, 5)) { flags |= DTFLAG_NO_POTENTIAL; }
35
36                         msg_entity = it;
37                         WriteHeader(MSG_ONE, damagetext);
38                         WriteByte(MSG_ONE, etof(hit));
39                         WriteInt24_t(MSG_ONE, deathtype);
40                         WriteByte(MSG_ONE, flags);
41
42                     // we need to send a few decimal places to minimize errors when accumulating damage
43                     // sending them multiplied saves bandwidth compared to using WriteCoord,
44                     // however if the multiplied damage would be too much for (signed) short, we send an int24
45                         if (flags & DTFLAG_BIG_HEALTH) { WriteInt24_t(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER); } else { WriteShort(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER); }
46                         if (!(flags & DTFLAG_NO_ARMOR)) {
47                                 if (flags & DTFLAG_BIG_ARMOR) { WriteInt24_t(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER); } else { WriteShort(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER); }
48                         }
49                         if (!(flags & DTFLAG_NO_POTENTIAL)) {
50                                 if (flags & DTFLAG_BIG_POTENTIAL) { WriteInt24_t(MSG_ONE, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER); } else { WriteShort(MSG_ONE, potential_damage * DAMAGETEXT_PRECISION_MULTIPLIER); }
51                         }
52                 }
53         });
54 }