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.
{
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);
}
{ 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); },
#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;
}
/**
- * @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);
}
/**
- * @param i zero indexed player
- */
+ * @param i zero indexed player
+ */
int entcs_GetClientColors(int i)
{
entity e = entcs_receiver(i);
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);
/// \copyright GNU GPLv2 or any later version.
#include <common/state.qh>
+#include <common/ent_cs.qh> // for .handicap_total
+#include <lib/replicate.qh> // for REPLICATE_APPLYCHANGE
#include <server/client.qh>
.float m_handicap_give; ///< Holds the forced handicap value.
// 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)
return bound(1.0, handicap_value, 10.0);
#endif
-
}
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)
CS(player).m_handicap_take = value;
else
CS(player).m_handicap_give = value;
+
+ Handicap_UpdateHandicapLevel(player);
}
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); });
+
/// \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