From 6d11e75ad6893a32c1227c7a502495c790989bf0 Mon Sep 17 00:00:00 2001 From: otta8634 Date: Sat, 14 Dec 2024 17:43:12 +0800 Subject: [PATCH] Network handicap "level" to the client and display on scoreboard Total bidirectional handicap (client-set & server-enforced, and given & taken) is now networked to the client with .handicap_level. - Values from 1 to 5 are mapped to be between 1 and 255 resulting in the "level". The "5" value is arbitrary and can be replaced in future. The handicap logo now displays on the scoreboard next to players with .handicap_level > 0. - Starts as white at 1, becomes full-red as the handicap level increases up to 255. Also changed spaces to tabs in qcsrc/common/ent_cs.qh as a cleanup. None of the newly added code should become redundant after 0.9 releases. --- qcsrc/client/hud/panel/scoreboard.qc | 6 ++- qcsrc/common/ent_cs.qc | 4 ++ qcsrc/common/ent_cs.qh | 56 ++++++++++++++++------------ qcsrc/server/handicap.qc | 20 ++++++++-- qcsrc/server/handicap.qh | 10 +++-- 5 files changed, 64 insertions(+), 32 deletions(-) diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index 6bf269152..7fb6c512c 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -1006,10 +1006,12 @@ string Scoreboard_GetName(entity pl) { sbt_field_icon_extra0 = "gfx/scoreboard/player_ready"; } - if (false) // TODO + int handicap_lvl = entcs_GetHandicapLevel(pl.sv_entnum); + if (handicap_lvl != 0) { sbt_field_icon_extra1 = "gfx/scoreboard/player_handicap"; - sbt_field_icon_extra1_rgb = '1 1 1'; + sbt_field_icon_extra1_rgb = '1 0 0' + '0 1 1' * ((255 - handicap_lvl) / 254); + // goes from white to red over level 1 to 255 } return entcs_GetName(pl.sv_entnum); } diff --git a/qcsrc/common/ent_cs.qc b/qcsrc/common/ent_cs.qc index cca9b7015..f68000f48 100644 --- a/qcsrc/common/ent_cs.qc +++ b/qcsrc/common/ent_cs.qc @@ -152,6 +152,10 @@ ENTCS_PROP(FRAGS, true, frags, frags, ENTCS_SET_NORMAL, { WriteShort(chan, ent.frags); }, { ent.frags = ReadShort(); }) +ENTCS_PROP(HANDICAP_LEVEL, true, handicap_level, handicap_level, ENTCS_SET_NORMAL, + { WriteByte(chan, ent.handicap_level); }, + { ent.handicap_level = ReadByte(); }) + // index of join queue team selection, max 127 because -1 means any available team ENTCS_PROP(WANTSJOIN, true, wants_join, wants_join, ENTCS_SET_NORMAL, { WriteChar(chan, ent.wants_join); }, diff --git a/qcsrc/common/ent_cs.qh b/qcsrc/common/ent_cs.qh index 3c96661e6..6f144b645 100644 --- a/qcsrc/common/ent_cs.qh +++ b/qcsrc/common/ent_cs.qh @@ -67,15 +67,16 @@ REGISTER_NET_TEMP(CLIENT_ENTCS) #define entcs_receiver_2(i, v) AL_sete(_entcs, i, v) #define entcs_is_self(e) ((e).sv_entnum == player_localentnum - 1) - /** - * @param i zero indexed player - */ - .int frags; - .int wants_join; + .int frags; + .int handicap_level; + .int wants_join; const int ENTCS_SPEC_PURE = 1; // real spectator const int ENTCS_SPEC_IN_SCOREBOARD = 2; // spectator but still in game (can be in a team) #define entcs_IsSpectating(i) boolean(entcs_GetSpecState(i)) + /** + * @param i zero indexed player + */ int entcs_GetSpecState(int i) { bool unconnected = !playerslots[i].gotscores; @@ -90,8 +91,17 @@ REGISTER_NET_TEMP(CLIENT_ENTCS) } /** - * @param i zero indexed player - */ + * @param i zero indexed player + */ + int entcs_GetHandicapLevel(int i) + { + entity e = entcs_receiver(i); + return e.handicap_level; + } + + /** + * @param i zero indexed player + */ int entcs_GetWantsJoin(int i) { entity e = entcs_receiver(i); @@ -99,8 +109,8 @@ REGISTER_NET_TEMP(CLIENT_ENTCS) } /** - * @param i zero indexed player - */ + * @param i zero indexed player + */ int entcs_GetClientColors(int i) { entity e = entcs_receiver(i); @@ -143,39 +153,39 @@ REGISTER_NET_TEMP(CLIENT_ENTCS) return e ? ColorTranslateRGB(e.netname) : ""; } - /** - * @param i zero indexed player - */ + /** + * @param i zero indexed player + */ entity CSQCModel_server2csqc(int i); - .float alpha; + .float alpha; - /** - * @param i zero indexed player - */ + /** + * @param i zero indexed player + */ float entcs_GetAlpha(int i) { entity e = CSQCModel_server2csqc(i); return e ? e.alpha : 1; } - /** - * @param i zero indexed player - */ + /** + * @param i zero indexed player + */ vector entcs_GetColor(int i) { entity e = CSQCModel_server2csqc(i); return (!e || e.colormap <= 0) - ? '1 1 1' + ? '1 1 1' : colormapPaletteColor(((e.colormap >= 1024) ? e.colormap : entcs_GetClientColors(e.colormap - 1)) & 15, true) ; } - /** - * @param i zero indexed player - */ + /** + * @param i zero indexed player + */ bool entcs_IsDead(int i) { entity e = CSQCModel_server2csqc(i); diff --git a/qcsrc/server/handicap.qc b/qcsrc/server/handicap.qc index 8669897dc..12cfbed84 100644 --- a/qcsrc/server/handicap.qc +++ b/qcsrc/server/handicap.qc @@ -6,6 +6,8 @@ /// \copyright GNU GPLv2 or any later version. #include +#include // for .handicap_total +#include // for REPLICATE_APPLYCHANGE #include .float m_handicap_give; ///< Holds the forced handicap value. @@ -16,6 +18,8 @@ void Handicap_Initialize(entity player) // forced handicap defaults CS(player).m_handicap_give = 1; CS(player).m_handicap_take = 1; + + Handicap_UpdateHandicapLevel(player); } float Handicap_GetVoluntaryHandicap(entity player, bool receiving) @@ -60,7 +64,6 @@ float Handicap_GetVoluntaryHandicap(entity player, bool receiving) return bound(1.0, handicap_value, 10.0); #endif - } float Handicap_GetForcedHandicap(entity player, bool receiving) @@ -69,7 +72,6 @@ float Handicap_GetForcedHandicap(entity player, bool receiving) return (CS(player)) ? CS(player).m_handicap_take : 1; else return (CS(player)) ? CS(player).m_handicap_give : 1; - } void Handicap_SetForcedHandicap(entity player, float value, bool receiving) @@ -81,6 +83,8 @@ void Handicap_SetForcedHandicap(entity player, float value, bool receiving) CS(player).m_handicap_take = value; else CS(player).m_handicap_give = value; + + Handicap_UpdateHandicapLevel(player); } float Handicap_GetTotalHandicap(entity player, bool receiving) @@ -89,8 +93,16 @@ float Handicap_GetTotalHandicap(entity player, bool receiving) Handicap_GetVoluntaryHandicap(player, receiving); } -float Handicap_GetTotalBidirectionalHandicap(entity player) +void Handicap_UpdateHandicapLevel(entity player) { - return Handicap_GetTotalHandicap(player, true) * + float handicap_total = Handicap_GetTotalHandicap(player, true) * Handicap_GetTotalHandicap(player, false); + if (handicap_total <= 1) + player.handicap_level = 0; + else + player.handicap_level = map_bound_ranges(handicap_total, 1, 5, 1, 255); } + +REPLICATE_APPLYCHANGE("cl_handicap_damage_given", { Handicap_UpdateHandicapLevel(this); }); +REPLICATE_APPLYCHANGE("cl_handicap_damage_taken", { Handicap_UpdateHandicapLevel(this); }); + diff --git a/qcsrc/server/handicap.qh b/qcsrc/server/handicap.qh index 987245f80..b31f3273c 100644 --- a/qcsrc/server/handicap.qh +++ b/qcsrc/server/handicap.qh @@ -46,7 +46,11 @@ void Handicap_SetForcedHandicap(entity player, float value, bool receiving); /// \return Total handicap of the player. float Handicap_GetTotalHandicap(entity player, bool receiving); -/// \brief Returns the total both-ways handicap of the player. +/// \brief Updates .handicap_level for the player. /// \param[in] player Player to check. -/// \return Total handicap of the player accounting for damage given and taken. -float Handicap_GetTotalBidirectionalHandicap(entity player); +void Handicap_UpdateHandicapLevel(entity player); + +.int handicap_level; +// This int ranges 0 to 255, 0 meaning no handicap, 1-255 representing handicap "levels" +// ... mapped from 1.0 to 5.0, using given * taken (i.e. both-ways handicap) +// It is networked to the client -- 2.39.2