X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fmutators%2Fmutator%2Fdamagetext%2Fdamagetext.qc;h=c8435027fa36224d90372df696b4c50f8e7ed64d;hb=31319dc70c4b2d237f4b32104a99ee4e1e30069e;hp=371bf2bbe08a581396a4e4a65d2f6286e51f0ac4;hpb=284c92dabbbdfcbb511e2688204622c5dcf01ac1;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/mutators/mutator/damagetext/damagetext.qc b/qcsrc/common/mutators/mutator/damagetext/damagetext.qc index 371bf2bbe..c8435027f 100644 --- a/qcsrc/common/mutators/mutator/damagetext/damagetext.qc +++ b/qcsrc/common/mutators/mutator/damagetext/damagetext.qc @@ -1,18 +1,13 @@ -#ifndef MUTATOR_DAMAGETEXT_H -#define MUTATOR_DAMAGETEXT_H +#include "damagetext.qh" -#ifdef MENUQC -#include -#endif - -#endif +#define DAMAGETEXT_PRECISION_MULTIPLIER 128 +#define DAMAGETEXT_MAX_SHORT 255 // 2^15 (signed short) / DAMAGETEXT_PRECISION_MULTIPLIER - 1 -#ifdef IMPLEMENTATION REGISTER_MUTATOR(damagetext, true); #if defined(CSQC) || defined(MENUQC) // no translatable cvar description please -AUTOCVAR_SAVE(cl_damagetext, bool, false, "Draw damage dealt where you hit the enemy"); +AUTOCVAR_SAVE(cl_damagetext, bool, true, "Draw damage dealt where you hit the enemy"); AUTOCVAR_SAVE(cl_damagetext_format, string, "-{total}", "How to format the damage text. {health}, {armor}, {total}"); STATIC_INIT(DamageText_LegacyFormat) { if (strstrofs(autocvar_cl_damagetext_format, "{", 0) < 0) autocvar_cl_damagetext_format = "-{total}"; @@ -31,25 +26,25 @@ AUTOCVAR_SAVE(cl_damagetext_friendlyfire_color, vector, '1 0 0', "Damage text #ifdef CSQC CLASS(DamageText, Object) - ATTRIB(DamageText, m_color, vector, autocvar_cl_damagetext_color) - ATTRIB(DamageText, m_color_friendlyfire, vector, autocvar_cl_damagetext_friendlyfire_color) - ATTRIB(DamageText, m_size, float, autocvar_cl_damagetext_size) - ATTRIB(DamageText, alpha, float, autocvar_cl_damagetext_alpha_start) - ATTRIB(DamageText, fade_rate, float, 1 / autocvar_cl_damagetext_alpha_lifetime) - ATTRIB(DamageText, velocity, vector, autocvar_cl_damagetext_velocity) - ATTRIB(DamageText, m_group, int, 0) - ATTRIB(DamageText, m_friendlyfire, bool, false) - ATTRIB(DamageText, m_damage, int, 0) - ATTRIB(DamageText, m_armordamage, int, 0) - ATTRIB(DamageText, m_deathtype, int, 0) - ATTRIB(DamageText, time_prev, float, time) + ATTRIB(DamageText, m_color, vector, autocvar_cl_damagetext_color); + ATTRIB(DamageText, m_color_friendlyfire, vector, autocvar_cl_damagetext_friendlyfire_color); + ATTRIB(DamageText, m_size, float, autocvar_cl_damagetext_size); + ATTRIB(DamageText, alpha, float, autocvar_cl_damagetext_alpha_start); + ATTRIB(DamageText, fade_rate, float, 1 / autocvar_cl_damagetext_alpha_lifetime); + ATTRIB(DamageText, velocity, vector, autocvar_cl_damagetext_velocity); + ATTRIB(DamageText, m_group, int, 0); + ATTRIB(DamageText, m_friendlyfire, bool, false); + ATTRIB(DamageText, m_damage, int, 0); + ATTRIB(DamageText, m_armordamage, int, 0); + ATTRIB(DamageText, m_deathtype, int, 0); + ATTRIB(DamageText, time_prev, float, time); void DamageText_draw2d(DamageText this) { float dt = time - this.time_prev; this.time_prev = time; setorigin(this, this.origin + dt * this.velocity); this.alpha -= dt * this.fade_rate; - if (this.alpha < 0) remove(this); + if (this.alpha < 0) delete(this); vector pos = project_3d_to_2d(this.origin) + autocvar_cl_damagetext_offset; if (pos.z >= 0 && this.m_size > 0) { pos.z = 0; @@ -65,13 +60,13 @@ CLASS(DamageText, Object) if (w != WEP_Null) rgb = w.wpcolor; } string s = autocvar_cl_damagetext_format; - s = strreplace("{health}", sprintf("%d", this.m_damage), s); - s = strreplace("{armor}", sprintf("%d", this.m_armordamage), s); - s = strreplace("{total}", sprintf("%d", this.m_damage + this.m_armordamage), s); + s = strreplace("{health}", sprintf("%d", rint(this.m_damage / DAMAGETEXT_PRECISION_MULTIPLIER)), s); + s = strreplace("{armor}", sprintf("%d", rint(this.m_armordamage / DAMAGETEXT_PRECISION_MULTIPLIER)), s); + s = strreplace("{total}", sprintf("%d", rint((this.m_damage + this.m_armordamage) / DAMAGETEXT_PRECISION_MULTIPLIER)), s); drawcolorcodedstring2_builtin(pos, s, this.m_size * '1 1 0', rgb, this.alpha, DRAWFLAG_NORMAL); } } - ATTRIB(DamageText, draw2d, void(DamageText), DamageText_draw2d) + ATTRIB(DamageText, draw2d, void(DamageText), DamageText_draw2d); void DamageText_update(DamageText this, vector _origin, int _health, int _armor, int _deathtype) { this.m_damage = _health; @@ -86,6 +81,7 @@ CLASS(DamageText, Object) this.m_group = _group; this.m_friendlyfire = _friendlyfire; DamageText_update(this, _origin, _health, _armor, _deathtype); + IL_PUSH(g_drawables_2d, this); } ENDCLASS(DamageText) #endif @@ -102,8 +98,8 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) { if (SV_DAMAGETEXT_DISABLED()) return; const entity attacker = M_ARGV(0, entity); const entity hit = M_ARGV(1, entity); if (hit == attacker) return; - const int health = M_ARGV(2, int); - const int armor = M_ARGV(3, int); + const float health = M_ARGV(2, float); + const float armor = M_ARGV(3, float); const int deathtype = M_ARGV(5, int); const vector location = hit.origin; FOREACH_CLIENT(IS_REAL_CLIENT(it), LAMBDA( @@ -113,16 +109,26 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) { (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_SPEC(it) && it.enemy == attacker) || (SV_DAMAGETEXT_SPECTATORS_ONLY() && IS_OBSERVER(it)) ) { + int flags = SAME_TEAM(hit, attacker); // BIT(0) + if (health > DAMAGETEXT_MAX_SHORT) flags |= BIT(1); + if (armor > DAMAGETEXT_MAX_SHORT) flags |= BIT(2); + msg_entity = it; WriteHeader(MSG_ONE, damagetext); - WriteShort(MSG_ONE, rint(health)); - WriteShort(MSG_ONE, rint(armor)); WriteEntity(MSG_ONE, hit); WriteCoord(MSG_ONE, location.x); WriteCoord(MSG_ONE, location.y); WriteCoord(MSG_ONE, location.z); WriteInt24_t(MSG_ONE, deathtype); - WriteByte(MSG_ONE, SAME_TEAM(hit, attacker)); + 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 (health > DAMAGETEXT_MAX_SHORT) WriteInt24_t(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER); + else WriteShort(MSG_ONE, health * DAMAGETEXT_PRECISION_MULTIPLIER); + if (armor > DAMAGETEXT_MAX_SHORT) WriteInt24_t(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER); + else WriteShort(MSG_ONE, armor * DAMAGETEXT_PRECISION_MULTIPLIER); } )); } @@ -131,12 +137,18 @@ MUTATOR_HOOKFUNCTION(damagetext, PlayerDamaged) { #ifdef CSQC NET_HANDLE(damagetext, bool isNew) { - int health = ReadShort(); - int armor = ReadShort(); int group = ReadShort(); vector location = vec3(ReadCoord(), ReadCoord(), ReadCoord()); int deathtype = ReadInt24_t(); - bool friendlyfire = ReadByte(); + int flags = ReadByte(); + bool friendlyfire = flags & 1; + + int health, armor; + if (flags & BIT(1)) health = ReadInt24_t(); + else health = ReadShort(); + if (flags & BIT(2)) armor = ReadInt24_t(); + else armor = ReadShort(); + return = true; if (autocvar_cl_damagetext) { if (friendlyfire && !autocvar_cl_damagetext_friendlyfire) { @@ -150,19 +162,21 @@ NET_HANDLE(damagetext, bool isNew) } } } - NEW(DamageText, group, location, health, armor, deathtype, friendlyfire); + make_impure(NEW(DamageText, group, location, health, armor, deathtype, friendlyfire)); } } #endif #ifdef MENUQC + +#include + CLASS(XonoticDamageTextSettings, XonoticTab) - #include REGISTER_SETTINGS(damagetext, NEW(XonoticDamageTextSettings)); - ATTRIB(XonoticDamageTextSettings, title, string, _("Damage text")) - ATTRIB(XonoticDamageTextSettings, intendedWidth, float, 0.9) - ATTRIB(XonoticDamageTextSettings, rows, float, 15.5) - ATTRIB(XonoticDamageTextSettings, columns, float, 5) + ATTRIB(XonoticDamageTextSettings, title, string, _("Damage text")); + ATTRIB(XonoticDamageTextSettings, intendedWidth, float, 0.9); + ATTRIB(XonoticDamageTextSettings, rows, float, 15.5); + ATTRIB(XonoticDamageTextSettings, columns, float, 5); INIT(XonoticDamageTextSettings) { this.configureDialog(this); } METHOD(XonoticDamageTextSettings, showNotify, void(entity this)) { loadAllCvars(this); } METHOD(XonoticDamageTextSettings, fill, void(entity this)) @@ -192,11 +206,10 @@ CLASS(XonoticDamageTextSettings, XonoticTab) setDependent(e, "cl_damagetext", 1, 1); this.TR(this); this.TR(this); - // friendly fire this.TD(this, 1, 3, e = makeXonoticCheckBox(0, "cl_damagetext_friendlyfire", _("Draw damage numbers for friendly fire"))); setDependent(e, "cl_damagetext", 1, 1); this.TR(this); - this.TD(this, 1, 1, e = makeXonoticTextLabel(0, _("Color (Friendly Fire):"))); + this.TD(this, 1, 1, e = makeXonoticTextLabel(0, _("Color:"))); setDependentAND(e, "cl_damagetext", 1, 1, "cl_damagetext_friendlyfire", 1, 1); this.TD(this, 2, 2, e = makeXonoticColorpickerString("cl_damagetext_friendlyfire_color", "cl_damagetext_friendlyfire_color")); setDependentAND(e, "cl_damagetext", 1, 1, "cl_damagetext_friendlyfire", 1, 1); @@ -204,4 +217,3 @@ CLASS(XonoticDamageTextSettings, XonoticTab) } ENDCLASS(XonoticDamageTextSettings) #endif -#endif