Xonotic
scores.qh File Reference
#include <common/scores.qh>
+ Include dependency graph for scores.qh:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define PlayerScore_Get(player, scorefield)   PlayerScore_Add(player, scorefield, 0)
 Returns the player's score. More...
 
#define WINNINGCONDITIONHELPER_LOWERISBETTER_WORST   999999999
 

Functions

string GetPlayerScoreString (entity pl, float shortString)
 Returns score strings for eventlog etc. More...
 
string GetTeamScoreString (float tm, float shortString)
 
float PlayerScore_Add (entity player, PlayerScoreField scorefield, float score)
 Adds a score to the player's scores. More...
 
void PlayerScore_Attach (entity player)
 Attaches a PlayerScore entity to a player. More...
 
float PlayerScore_Clear (entity player)
 Initialize the score of this player if needed. More...
 
void PlayerScore_Detach (entity player)
 Detaches a PlayerScore entity from the player. More...
 
float PlayerScore_Set (entity player, PlayerScoreField scorefield, float score)
 Sets the player's score to the score parameter. More...
 
entity PlayerScore_Sort (.float field, int teams, bool strict, bool nospectators)
 Sorts the players and stores their place in the given field, starting with. More...
 
float PlayerTeamScore_Add (entity player, PlayerScoreField pscorefield, float tscorefield, float score)
 Adds a score to both the player and the team. More...
 
void Score_ClearAll ()
 Clear ALL scores (for ready-restart). More...
 
void Score_NicePrint (entity to)
 Prints the scores to the console of a player. More...
 
void ScoreInfo_Init (float teams)
 Initialize the scores info for the given number of teams. More...
 
void ScoreInfo_SetLabel_PlayerScore (PlayerScoreField i, string label, float scoreflags)
 Set the label of a player score item, as well as the scoring flags. More...
 
void ScoreInfo_SetLabel_TeamScore (float i, string label, float scoreflags)
 Set the label of a team score item, as well as the scoring flags. More...
 
float TeamScore_Add (entity player, float scorefield, float score)
 Adds a score to the player's team's scores. More...
 
float TeamScore_AddToTeam (int t, float scorefield, float score)
 Adds a score to the given team. More...
 
float TeamScore_GetCompareValue (float t)
 Returns a value indicating the team score (and higher is better). More...
 
void WinningConditionHelper (entity this)
 Sets the following results for the current scores entities. More...
 

Variables

bool autocvar_g_full_getstatus_responses
 
float scoreboard_pos
 
entity scores_initialized
 
float WinningConditionHelper_equality
 we have no winner More...
 
float WinningConditionHelper_lowerisbetter
 lower is better, duh More...
 
entity WinningConditionHelper_second
 the second player, or NULL if none More...
 
float WinningConditionHelper_secondscore
 second highest score More...
 
float WinningConditionHelper_secondteam
 the color of the second team, or -1 if none More...
 
float WinningConditionHelper_topscore
 highest score More...
 
entity WinningConditionHelper_winner
 the winning player, or NULL if none More...
 
float WinningConditionHelper_winnerteam
 the color of the winning team, or -1 if none More...
 
float WinningConditionHelper_zeroisworst
 zero is worst, duh More...
 

Macro Definition Documentation

◆ PlayerScore_Get

#define PlayerScore_Get (   player,
  scorefield 
)    PlayerScore_Add(player, scorefield, 0)

Returns the player's score.

Parameters
[in]playerPlayer to inspect.
[in]scorefieldField of the score.
Returns
Player's score.

Definition at line 43 of file scores.qh.

Referenced by DynamicHandicap_UpdateHandicap(), MUTATOR_HOOKFUNCTION(), and TeamBalance_GetPlayerForTeamSwitch().

◆ WINNINGCONDITIONHELPER_LOWERISBETTER_WORST

#define WINNINGCONDITIONHELPER_LOWERISBETTER_WORST   999999999

Definition at line 117 of file scores.qh.

Function Documentation

◆ GetPlayerScoreString()

string GetPlayerScoreString ( entity  pl,
float  shortString 
)

Returns score strings for eventlog etc.

When called with NULL, or 0, as argument, they return the labels in the same order. The strings are comma separated; labels that end with !! designate primary, labels that end with ! designate high priority. Labels get an appended < if the scores are better if smaller (e.g. deaths). High priorities always come first. Example label string: score!!,kills,deaths<,suicides< If shortString is set, only the sort keys are returned.

Definition at line 586 of file scores.qc.

References CS(), entity(), FOREACH, ftos(), GetScoreLogLabel(), scorekeeper, scores_flags, scores_label, SFL_SORT_PRIO_MASK, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_SECONDARY, strcat(), strlen(), and substring().

Referenced by DumpStats(), and WinningConditionHelper().

587 {
588  string out;
589  entity sk;
590  float f;
591  string l;
592 
593  out = "";
594  if(!pl)
595  {
596  // label
597  FOREACH(Scores, true, {
599  {
600  f = scores_flags(it);
601  l = scores_label(it);
602  out = strcat(out, GetScoreLogLabel(l, f), ",");
603  }
604  });
605  if(shortString < 2)
606  FOREACH(Scores, true, {
607  if((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
608  {
609  f = scores_flags(it);
610  l = scores_label(it);
611  out = strcat(out, GetScoreLogLabel(l, f), ",");
612  }
613  });
614  if(shortString < 1)
615  FOREACH(Scores, true, {
616  if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
617  if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
618  {
619  f = scores_flags(it);
620  l = scores_label(it);
621  out = strcat(out, GetScoreLogLabel(l, f), ",");
622  }
623  });
624  out = substring(out, 0, strlen(out) - 1);
625  }
626  else if((sk = CS(pl).scorekeeper))
627  {
628  FOREACH(Scores, true, {
629  if ((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
630  out = strcat(out, ftos(sk.(scores(it))), ",");
631  });
632  if(shortString < 2)
633  FOREACH(Scores, true, {
634  if ((scores_flags(it) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
635  out = strcat(out, ftos(sk.(scores(it))), ",");
636  });
637  if(shortString < 1)
638  FOREACH(Scores, true, {
639  if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
640  if((scores_flags(it) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
641  out = strcat(out, ftos(sk.(scores(it))), ",");
642  });
643  out = substring(out, 0, strlen(out) - 1);
644  }
645  return out;
646 }
const int SFL_SORT_PRIO_MASK
Definition: scores.qh:128
const int SFL_SORT_PRIO_SECONDARY
Scoring priority (NOTE: PRIMARY is used for fraglimit)
Definition: scores.qh:126
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
const int SFL_SORT_PRIO_PRIMARY
Definition: scores.qh:127
string GetScoreLogLabel(string label, float fl)
Definition: scores.qc:575
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
entity scorekeeper
Definition: scores.qc:19
#define scores_flags(this)
Definition: scores.qh:140
#define scores_label(this)
Definition: scores.qh:139
#define FOREACH(list, cond, body)
Definition: iter.qh:19
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetTeamScoreString()

string GetTeamScoreString ( float  tm,
float  shortString 
)

Definition at line 648 of file scores.qc.

References entity(), ftos(), GetScoreLogLabel(), MAX_TEAMSCORE, SFL_SORT_PRIO_MASK, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_SECONDARY, strcat(), strlen(), substring(), teamscorekeepers, teamscores_flags, and teamscores_label.

Referenced by DumpStats(), and WinningConditionHelper().

649 {
650  string out;
651  entity sk;
652  float i, f;
653  string l;
654 
655  out = "";
656  if(tm == 0)
657  {
658  // label
659  for(i = 0; i < MAX_TEAMSCORE; ++i)
661  {
662  f = teamscores_flags(i);
663  l = teamscores_label(i);
664  out = strcat(out, GetScoreLogLabel(l, f), ",");
665  }
666  if(shortString < 2)
667  for(i = 0; i < MAX_TEAMSCORE; ++i)
668  if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
669  {
670  f = teamscores_flags(i);
671  l = teamscores_label(i);
672  out = strcat(out, GetScoreLogLabel(l, f), ",");
673  }
674  if(shortString < 1)
675  for(i = 0; i < MAX_TEAMSCORE; ++i)
676  if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_PRIMARY)
677  if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) != SFL_SORT_PRIO_SECONDARY)
678  {
679  f = teamscores_flags(i);
680  l = teamscores_label(i);
681  out = strcat(out, GetScoreLogLabel(l, f), ",");
682  }
683  out = substring(out, 0, strlen(out) - 1);
684  }
685  else if((sk = teamscorekeepers[tm - 1]))
686  {
687  for(i = 0; i < MAX_TEAMSCORE; ++i)
688  if((teamscores_flags(i) & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
689  out = strcat(out, ftos(sk.(teamscores(i))), ",");
690  if(shortString < 2)
691  for(i = 0; i < MAX_TEAMSCORE; ++i)
693  out = strcat(out, ftos(sk.(teamscores(i))), ",");
694  if(shortString < 1)
695  for(i = 0; i < MAX_TEAMSCORE; ++i)
698  out = strcat(out, ftos(sk.(teamscores(i))), ",");
699  out = substring(out, 0, strlen(out) - 1);
700  }
701  return out;
702 }
const int SFL_SORT_PRIO_MASK
Definition: scores.qh:128
const int SFL_SORT_PRIO_SECONDARY
Scoring priority (NOTE: PRIMARY is used for fraglimit)
Definition: scores.qh:126
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
const int SFL_SORT_PRIO_PRIMARY
Definition: scores.qh:127
#define teamscores_label(i)
Definition: scores.qh:147
string GetScoreLogLabel(string label, float fl)
Definition: scores.qc:575
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define MAX_TEAMSCORE
Definition: scores.qh:142
#define teamscores_flags(i)
Definition: scores.qh:149
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PlayerScore_Add()

float PlayerScore_Add ( entity  player,
PlayerScoreField  scorefield,
float  score 
)

Adds a score to the player's scores.

NEVER call this if PlayerScore_Attach has not been called yet! Means: FIXME make players unable to join the game when not called ClientConnect yet. Returns the new score.

Definition at line 336 of file scores.qc.

References BIT, CS(), entity(), LOG_WARN, M_ARGV, MUTATOR_CALLHOOK, scores_initialized, scores_label, strcat(), and warmup_stage.

Referenced by _GameRules_scoring_add(), _GameRules_scoring_add_float2int(), and PlayerTeamScore_Add().

337 {
338  bool mutator_returnvalue = MUTATOR_CALLHOOK(AddPlayerScore, scorefield, score, player);
339  score = M_ARGV(1, float);
340 
341  if(!mutator_returnvalue && game_stopped)
342  {
343  score = 0;
344  }
345 
346  if(!scores_initialized) return 0; // FIXME remove this when everything uses this system
347  entity s = CS(player).scorekeeper;
348  if(!s)
349  {
350  if(game_stopped)
351  return 0;
352  LOG_WARN("Adding score to unknown player!");
353  return 0;
354  }
355  if(!score)
356  {
357  return s.(scores(scorefield));
358  }
359  if(scores_label(scorefield) != "")
360  s.SendFlags |= BIT(scorefield.m_id % 16);
361  if(!warmup_stage)
362  PlayerStats_GameReport_Event_Player(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label(scorefield)), score);
363  s.(scores(scorefield)) += score;
364  MUTATOR_CALLHOOK(AddedPlayerScore, scorefield, score, player);
365  return s.(scores(scorefield));
366 }
#define LOG_WARN(...)
Definition: log.qh:66
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
bool warmup_stage
Definition: main.qh:103
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
entity scores_initialized
Definition: scores.qh:7
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define M_ARGV(x, type)
Definition: events.qh:17
#define scores_label(this)
Definition: scores.qh:139
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PlayerScore_Attach()

void PlayerScore_Attach ( entity  player)

Attaches a PlayerScore entity to a player.

Use that in ClientConnect. Remember to detach it in ClientDisconnect!

Definition at line 318 of file scores.qc.

References CS(), entity(), error(), new_pure, PlayerScore_SendEntity(), and scorekeeper.

319 {
320  if(CS(player).scorekeeper)
321  error("player already has a scorekeeper");
322  entity sk = new_pure(scorekeeper);
323  sk.owner = player;
324  Net_LinkEntity(sk, false, 0, PlayerScore_SendEntity);
325  CS(player).scorekeeper = sk;
326 }
bool PlayerScore_SendEntity(entity this, entity to, float sendflags)
Definition: scores.qc:239
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
entity scorekeeper
Definition: scores.qc:19
#define new_pure(class)
purely logical entities (.origin doesn&#39;t work)
Definition: oo.qh:62
+ Here is the call graph for this function:

◆ PlayerScore_Clear()

float PlayerScore_Clear ( entity  player)

Initialize the score of this player if needed.

Does nothing in teamplay. Use that when a spectator becomes a player. Returns whether clearing has been performed

Definition at line 267 of file scores.qc.

References BIT, CS(), entity(), FOREACH, MUTATOR_CALLHOOK, scores_label, and teamscores_entities_count.

Referenced by PutPlayerInServer(), and SetPlayerTeam().

268 {
269  entity sk;
270 
272  return 0;
273 
274  if(MUTATOR_CALLHOOK(ForbidPlayerScore_Clear)) return 0;
275 
276  sk = CS(player).scorekeeper;
277  FOREACH(Scores, true, {
278  if(sk.(scores(it)) != 0)
279  if(scores_label(it) != "")
280  sk.SendFlags |= BIT(i % 16);
281  if(i != SP_ELO.m_id)
282  sk.(scores(it)) = 0;
283  });
284 
285  return 1;
286 }
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
#define scores_label(this)
Definition: scores.qh:139
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
float teamscores_entities_count
Definition: scores.qc:21
#define FOREACH(list, cond, body)
Definition: iter.qh:19
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PlayerScore_Detach()

void PlayerScore_Detach ( entity  player)

Detaches a PlayerScore entity from the player.

Use that in ClientDisconnect.

Definition at line 328 of file scores.qc.

References CS(), error(), NULL, and scorekeeper.

329 {
330  if(!CS(player).scorekeeper)
331  error("player has no scorekeeper");
332  delete(CS(player).scorekeeper);
333  CS(player).scorekeeper = NULL;
334 }
ClientState CS(Client this)
Definition: state.qh:47
entity scorekeeper
Definition: scores.qc:19
#define NULL
Definition: post.qh:17
+ Here is the call graph for this function:

◆ PlayerScore_Set()

float PlayerScore_Set ( entity  player,
PlayerScoreField  scorefield,
float  score 
)

Sets the player's score to the score parameter.

NEVER call this if PlayerScore_Attach has not been called yet! Means: FIXME make players unable to join the game when not called ClientConnect yet. Returns the new (or old if unchanged) score.

Definition at line 368 of file scores.qc.

References BIT, CS(), entity(), LOG_WARN, scores_initialized, and scores_label.

Referenced by NET_HANDLE().

369 {
370  if(!scores_initialized) return 0; // FIXME remove this when everything uses this system
371  entity s = CS(player).scorekeeper;
372  if(!s)
373  {
374  if(game_stopped)
375  return 0;
376  LOG_WARN("Setting score of unknown player!");
377  return 0;
378  }
379 
380  float oldscore = s.(scores(scorefield));
381  if(oldscore == score)
382  return oldscore;
383 
384  if(scores_label(scorefield) != "")
385  s.SendFlags |= BIT(scorefield.m_id % 16);
386  s.(scores(scorefield)) = score;
387  return s.(scores(scorefield));
388 }
#define LOG_WARN(...)
Definition: log.qh:66
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
entity scores_initialized
Definition: scores.qh:7
#define scores_label(this)
Definition: scores.qh:139
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PlayerScore_Sort()

entity PlayerScore_Sort ( .float  field,
int  teams,
bool  strict,
bool  nospectators 
)

Sorts the players and stores their place in the given field, starting with.

  1. Non-players get 0 written into that field. Returns the beginning of a sorted chain of the non-spectators. teams: >0: sort by teams first (always strict ordering); <0: sort by teams only (respects strict flag) strict: return a strict ordering nospectators: exclude spectators

Definition at line 724 of file scores.qc.

References CS(), entity(), FOREACH_CLIENT, FRAGS_SPECTATOR, NULL, PlayerTeamScore_Compare(), and scorekeeper.

Referenced by MUTATOR_HOOKFUNCTION(), and Score_NicePrint().

725 {
726  entity p, plist, pprev, pbest, pbestprev, pfirst, plast;
727  float i, j;
728 
729  plist = NULL;
730 
731  FOREACH_CLIENT(true, { it.(field) = 0; });
732 
734  {
735  if(nospectators)
736  if(it.frags == FRAGS_SPECTATOR)
737  continue;
738 
739  it.chain = plist;
740  plist = it;
741  });
742  // Now plist points to the whole list.
743 
744  pfirst = plast = NULL;
745 
746  i = j = 0;
747  while(plist)
748  {
749  pprev = pbestprev = NULL;
750  pbest = plist;
751  for(p = plist; (pprev = p), (p = p.chain); )
752  {
753  if(PlayerTeamScore_Compare(p, pbest, teams, strict) > 0)
754  {
755  pbest = p;
756  pbestprev = pprev;
757  }
758  }
759 
760  // remove pbest out of the chain
761  if(pbestprev == NULL)
762  plist = pbest.chain;
763  else
764  pbestprev.chain = pbest.chain;
765  pbest.chain = NULL;
766 
767  ++i;
768  if(!plast || PlayerTeamScore_Compare(plast, pbest, teams, strict))
769  j = i;
770 
771  pbest.(field) = j;
772 
773  if (!pfirst)
774  pfirst = pbest;
775  if(plast)
776  plast.chain = pbest;
777  plast = pbest;
778  }
779 
780  return pfirst;
781 }
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
entity teams
Definition: main.qh:44
entity scorekeeper
Definition: scores.qc:19
#define NULL
Definition: post.qh:17
float PlayerTeamScore_Compare(entity p1, entity p2, float teams, bool strict)
Definition: scores.qc:704
const int FRAGS_SPECTATOR
Definition: constants.qh:4
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PlayerTeamScore_Add()

float PlayerTeamScore_Add ( entity  player,
PlayerScoreField  pscorefield,
float  tscorefield,
float  score 
)

Adds a score to both the player and the team.

Returns the team score if possible, otherwise the player score.

Definition at line 390 of file scores.qc.

References PlayerScore_Add(), TeamScore_Add(), and teamscores_entities_count.

Referenced by _GameRules_scoring_add_team().

391 {
392  float r;
393  r = PlayerScore_Add(player, pscorefield, score);
394  if(teamscores_entities_count) // only for teamplay
395  r = TeamScore_Add(player, tscorefield, score);
396  return r;
397 }
float teamscores_entities_count
Definition: scores.qc:21
float TeamScore_Add(entity player, float scorefield, float score)
Adds a score to the player&#39;s team&#39;s scores.
Definition: scores.qc:137
float PlayerScore_Add(entity player, PlayerScoreField scorefield, float score)
Adds a score to the player&#39;s scores.
Definition: scores.qc:336
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Score_ClearAll()

void Score_ClearAll ( )

Clear ALL scores (for ready-restart).

Definition at line 288 of file scores.qc.

References BIT, CS(), entity(), FOREACH, FOREACH_CLIENTSLOT, MAX_TEAMSCORE, scores_label, teamscorekeepers, and teamscores_label.

Referenced by reset_map().

289 {
290  entity sk;
291  float t;
292  FOREACH_CLIENTSLOT(true, {
293  sk = CS(it).scorekeeper;
294  if (!sk) continue;
295  FOREACH(Scores, true, {
296  if(sk.(scores(it)) != 0)
297  if(scores_label(it) != "")
298  sk.SendFlags |= BIT(i % 16);
299  if(i != SP_ELO.m_id)
300  sk.(scores(it)) = 0;
301  });
302  });
303  for(t = 0; t < 16; ++t)
304  {
305  sk = teamscorekeepers[t];
306  if(!sk)
307  continue;
308  for(int j = 0; j < MAX_TEAMSCORE; ++j)
309  {
310  if(sk.(teamscores(j)) != 0)
311  if(teamscores_label(j) != "")
312  sk.SendFlags |= BIT(j);
313  sk.(teamscores(j)) = 0;
314  }
315  }
316 }
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
ClientState CS(Client this)
Definition: state.qh:47
#define teamscores_label(i)
Definition: scores.qh:147
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
#define FOREACH_CLIENTSLOT(cond, body)
Definition: utils.qh:39
#define MAX_TEAMSCORE
Definition: scores.qh:142
#define scores_label(this)
Definition: scores.qh:139
#define FOREACH(list, cond, body)
Definition: iter.qh:19
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Score_NicePrint()

void Score_NicePrint ( entity  to)

Prints the scores to the console of a player.

Definition at line 903 of file scores.qc.

References bound(), entity(), floor(), FOREACH, FOREACH_CLIENT, IS_PLAYER, PlayerScore_Sort(), score_dummyfield, Score_NicePrint_Player(), Score_NicePrint_Spectator(), Score_NicePrint_Spectators(), Score_NicePrint_Team(), scores_label, SCORESWIDTH, and teamscores_entities_count.

Referenced by CommonCommand_teamstatus(), and MUTATOR_HOOKFUNCTION().

904 {
905  entity p;
906  float w;
907 
908  int t = 0;
909  FOREACH(Scores, true, {
910  if(scores_label(it) != "")
911  ++t;
912  });
913  w = bound(6, floor(SCORESWIDTH / t - 1), 9);
914 
915  p = PlayerScore_Sort(score_dummyfield, 1, true, false);
916  t = -1;
917 
919  Score_NicePrint_Team(to, t, w);
920  while(p)
921  {
923  if(t != p.team)
924  Score_NicePrint_Team(to, p.team, w);
925  Score_NicePrint_Player(to, p, w);
926  t = p.team;
927  p = p.chain;
928  }
929 
930  t = 0;
931  FOREACH_CLIENT(!IS_PLAYER(it), {
932  if (!t)
935  t = 1;
936  });
937 }
void Score_NicePrint_Player(entity to, entity p, float w)
Definition: scores.qc:857
float score_dummyfield
Definition: scores.qc:902
entity() spawn
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
entity to
Definition: self.qh:96
const float SCORESWIDTH
Definition: scores.qc:808
void Score_NicePrint_Team(entity to, float t, float w)
Definition: scores.qc:820
void Score_NicePrint_Spectators(entity to)
Definition: scores.qc:892
void Score_NicePrint_Spectator(entity to, entity p)
Definition: scores.qc:897
entity PlayerScore_Sort(.float field, int teams, bool strict, bool nospectators)
Sorts the players and stores their place in the given field, starting with.
Definition: scores.qc:724
#define scores_label(this)
Definition: scores.qh:139
float teamscores_entities_count
Definition: scores.qc:21
#define FOREACH(list, cond, body)
Definition: iter.qh:19
#define IS_PLAYER(v)
Definition: utils.qh:9
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ScoreInfo_Init()

void ScoreInfo_Init ( float  teams)

Initialize the scores info for the given number of teams.

Set all labels right before this call.

◆ ScoreInfo_SetLabel_PlayerScore()

void ScoreInfo_SetLabel_PlayerScore ( PlayerScoreField  i,
string  label,
float  scoreflags 
)

Set the label of a player score item, as well as the scoring flags.

Definition at line 165 of file scores.qc.

References scores, scores_flags, scores_flags_primary, scores_label, scores_primary, SFL_SORT_PRIO_MASK, SFL_SORT_PRIO_PRIMARY, and strcat().

Referenced by _GameRules_scoring_field(), and ScoreRules_basics().

166 {
167  scores_label(i) = label;
168  scores_flags(i) = scoreflags;
169  if((scoreflags & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
170  {
171  scores_primary = scores(i);
172  scores_flags_primary = scoreflags;
173  }
174  if(label != "")
175  {
176  PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_TOTAL, label));
177  PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_SCOREBOARD, label));
178  }
179 }
const int SFL_SORT_PRIO_MASK
Definition: scores.qh:128
float scores_flags_primary
Definition: scores.qc:24
const int SFL_SORT_PRIO_PRIMARY
Definition: scores.qh:127
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
#define scores_flags(this)
Definition: scores.qh:140
#define scores_label(this)
Definition: scores.qh:139
var float scores_primary
Definition: scores.qc:22
#define scores(this)
Definition: scores.qh:138
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ScoreInfo_SetLabel_TeamScore()

void ScoreInfo_SetLabel_TeamScore ( float  i,
string  label,
float  scoreflags 
)

Set the label of a team score item, as well as the scoring flags.

Definition at line 181 of file scores.qc.

References SFL_SORT_PRIO_MASK, SFL_SORT_PRIO_PRIMARY, strcat(), teamscores, teamscores_flags, teamscores_flags_primary, teamscores_label, and teamscores_primary.

Referenced by _GameRules_scoring_field_team(), and ScoreRules_basics().

182 {
183  teamscores_label(i) = label;
184  teamscores_flags(i) = scoreflags;
185  if((scoreflags & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_PRIMARY)
186  {
188  teamscores_flags_primary = scoreflags;
189  }
190  if(label != "")
191  {
192  PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_TOTAL, label));
193  PlayerStats_GameReport_AddEvent(strcat(PLAYERSTATS_SCOREBOARD, label));
194  }
195 }
const int SFL_SORT_PRIO_MASK
Definition: scores.qh:128
const int SFL_SORT_PRIO_PRIMARY
Definition: scores.qh:127
#define teamscores_label(i)
Definition: scores.qh:147
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
var float teamscores_primary
Definition: scores.qc:23
float teamscores_flags_primary
Definition: scores.qc:25
#define teamscores_flags(i)
Definition: scores.qh:149
#define teamscores(i)
Definition: scores.qh:145
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamScore_Add()

float TeamScore_Add ( entity  player,
float  scorefield,
float  score 
)

Adds a score to the player's team's scores.

NEVER call this if team has not been set yet! Returns the new score.

Definition at line 137 of file scores.qc.

References TeamScore_AddToTeam().

Referenced by PlayerTeamScore_Add().

138 {
139  return TeamScore_AddToTeam(player.team, scorefield, score);
140 }
float TeamScore_AddToTeam(int t, float scorefield, float score)
Adds a score to the given team.
Definition: scores.qc:108
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamScore_AddToTeam()

float TeamScore_AddToTeam ( int  t,
float  scorefield,
float  score 
)

Adds a score to the given team.

NEVER call this if team has not been set yet! Returns the new score.

Definition at line 108 of file scores.qc.

References BIT, entity(), error(), scores_initialized, teamscorekeepers, and teamscores_label.

Referenced by CA_CheckWinner(), ctf_Handle_Return(), Domination_CheckWinner(), dompointthink(), freezetag_CheckWinner(), GoalTouch(), MUTATOR_HOOKFUNCTION(), Onslaught_CheckWinner(), TeamScore_Add(), WinningCondition_Assault(), and WinningCondition_RanOutOfSpawns().

109 {
110  entity s;
111 
112  if(game_stopped)
113  {
114  score = 0;
115  }
116 
117  if(!scores_initialized) return 0; // FIXME remove this when everything uses this system
118  if(t <= 0 || t >= 16)
119  {
120  if(game_stopped)
121  return 0;
122  error("Adding score to invalid team!");
123  }
124  s = teamscorekeepers[t - 1];
125  if(!s)
126  {
127  if(game_stopped)
128  return 0;
129  error("Adding score to unknown team!");
130  }
131  if(score)
132  if(teamscores_label(scorefield) != "")
133  s.SendFlags |= BIT(scorefield);
134  return (s.(teamscores(scorefield)) += score);
135 }
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
#define teamscores_label(i)
Definition: scores.qh:147
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
entity scores_initialized
Definition: scores.qh:7
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamScore_GetCompareValue()

float TeamScore_GetCompareValue ( float  t)

Returns a value indicating the team score (and higher is better).

Definition at line 783 of file scores.qc.

References entity(), error(), SFL_LOWER_IS_BETTER, SFL_ZERO_IS_WORST, teamscorekeepers, and teamscores_flags_primary.

Referenced by WinningCondition_Scores().

784 {
785  float s;
786  entity sk;
787 
788  if(t <= 0 || t >= 16)
789  {
790  if(game_stopped)
791  return 0;
792  error("Reading score of invalid team!");
793  }
794 
795  sk = teamscorekeepers[t - 1];
796  if (!sk)
797  return -999999999;
798  s = sk.teamscores_primary;
800  if(!s)
801  return -999999999;
803  s = -s;
804  return s;
805 }
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
#define SFL_ZERO_IS_WORST
Definition: scores.qh:121
const int SFL_LOWER_IS_BETTER
Lower scores are better (e.g.
Definition: scores.qh:98
float teamscores_flags_primary
Definition: scores.qc:25
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ WinningConditionHelper()

void WinningConditionHelper ( entity  this)

Sets the following results for the current scores entities.

Definition at line 415 of file scores.qc.

References autocvar_g_full_getstatus_responses, autocvar_g_xonoticversion, CS(), cvar_purechanges_count, entity(), FOREACH_CLIENT, ftos(), GetGametype(), GetPlayerScoreString(), GetTeamScoreString(), INGAME_JOINED, IS_PLAYER, IS_REAL_CLIENT, modname, nJoinAllowed(), NULL, player_count, PlayerScore_Compare(), scores_flags_primary, serverflags, SFL_LOWER_IS_BETTER, SFL_ZERO_IS_WORST, strcat(), strcpy, sv_termsofservice_url_escaped, TeamScore_Compare(), teamscorekeepers, teamscores_entities_count, teamscores_flags_primary, WinningConditionHelper_equality, WinningConditionHelper_lowerisbetter, WinningConditionHelper_second, WinningConditionHelper_secondscore, WinningConditionHelper_secondteam, WinningConditionHelper_topscore, WinningConditionHelper_winner, WinningConditionHelper_winnerteam, WinningConditionHelper_zeroisworst, and worldstatus.

Referenced by spawnfunc(), WinningCondition_Assault(), WinningCondition_Invasion(), WinningCondition_LMS(), and WinningCondition_Scores().

416 {
417  float c;
418  string s;
419  float fullstatus;
420  entity winnerscorekeeper;
421  entity secondscorekeeper;
422  entity sk;
423 
424  // format:
425  // gametype:P<pure>:S<slots>::plabel,plabel:tlabel,tlabel:teamid:tscore,tscore:teamid:tscore,tscore
426  // score labels always start with a symbol or with lower case
427  // so to match pure, match for :P0:
428  // to match full, match for :S0:
429 
431 
432  s = GetGametype();
433  s = strcat(s, ":", autocvar_g_xonoticversion);
434  s = strcat(s, ":P", ftos(cvar_purechanges_count));
435  s = strcat(s, ":S", ftos(nJoinAllowed(this, NULL)));
436  s = strcat(s, ":F", ftos(serverflags));
438  s = strcat(s, ":M", modname);
439  s = strcat(s, "::", GetPlayerScoreString(NULL, (fullstatus ? 1 : 2)));
440 
442  {
443  float t;
444 
445  s = strcat(s, ":", GetTeamScoreString(0, 1));
446  for(t = 0; t < 16; ++t)
447  if(teamscorekeepers[t])
448  s = strcat(s, ":", ftos(t+1), ":", GetTeamScoreString(t+1, 1));
449 
452  winnerscorekeeper = NULL;
453  secondscorekeeper = NULL;
454  for(t = 0; t < 16; ++t)
455  {
456  sk = teamscorekeepers[t];
457  c = TeamScore_Compare(winnerscorekeeper, sk, 1);
458  if(c < 0)
459  {
462  secondscorekeeper = winnerscorekeeper;
463  winnerscorekeeper = sk;
464  }
465  else
466  {
467  c = TeamScore_Compare(secondscorekeeper, sk, 1);
468  if(c < 0)
469  {
471  secondscorekeeper = sk;
472  }
473  }
474  }
475 
476  WinningConditionHelper_equality = (TeamScore_Compare(winnerscorekeeper, secondscorekeeper, 0) == 0);
479 
480  WinningConditionHelper_topscore = winnerscorekeeper.teamscores_primary;
481  WinningConditionHelper_secondscore = secondscorekeeper.teamscores_primary;
484 
485  WinningConditionHelper_winner = NULL; // not supported in teamplay
486  WinningConditionHelper_second = NULL; // not supported in teamplay
487  }
488  else
489  {
492  winnerscorekeeper = NULL;
493  secondscorekeeper = NULL;
495  sk = CS(it).scorekeeper;
496  c = PlayerScore_Compare(winnerscorekeeper, sk, true);
497  if(c < 0)
498  {
501  secondscorekeeper = winnerscorekeeper;
502  winnerscorekeeper = sk;
503  }
504  else
505  {
506  c = PlayerScore_Compare(secondscorekeeper, sk, true);
507  if(c < 0)
508  {
510  secondscorekeeper = sk;
511  }
512  }
513  });
514 
515  WinningConditionHelper_equality = (PlayerScore_Compare(winnerscorekeeper, secondscorekeeper, false) == 0);
516  if(WinningConditionHelper_equality)
518 
519  WinningConditionHelper_topscore = winnerscorekeeper.scores_primary;
520  WinningConditionHelper_secondscore = secondscorekeeper.scores_primary;
523 
524  WinningConditionHelper_winnerteam = -1; // no teamplay
525  WinningConditionHelper_secondteam = -1; // no teamplay
526  }
527 
529  {
531  {
534  else
535  WinningConditionHelper_topscore = -999999999;
536  }
537  if(player_count == 0) // special case: empty servers DO end the match at a 0:0 tie
538  WinningConditionHelper_equality = 0;
539  }
540 
542  {
543  if(scores_flags_primary & SFL_ZERO_IS_WORST)
544  {
547  else
549  }
550  }
551 
552  strcpy(worldstatus, s);
553 
554  FOREACH_CLIENT(true, {
555  string s = "";
556  if(fullstatus)
557  {
558  s = GetPlayerScoreString(it, 1);
559  s = strcat(s, IS_REAL_CLIENT(it) ? ":human" : ":bot");
560  if(!(IS_PLAYER(it) || INGAME_JOINED(it)))
561  s = strcat(s, ":spectator");
562  }
563  else
564  {
565  if (IS_PLAYER(it) || INGAME_JOINED(it))
566  s = GetPlayerScoreString(it, 2);
567  else
568  s = "-666";
569  }
570 
571  strcpy(it.clientstatus, s);
572  });
573 }
int serverflags
Definition: main.qh:184
bool autocvar_g_full_getstatus_responses
Definition: scores.qh:5
float PlayerScore_Compare(entity t1, entity t2, bool strict)
Definition: scores.qc:399
string GetTeamScoreString(float tm, float shortString)
Definition: scores.qc:648
float WinningConditionHelper_secondteam
the color of the second team, or -1 if none
Definition: scores.qh:111
float TeamScore_Compare(entity t1, entity t2, bool strict)
Definition: scores.qc:142
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
int player_count
Definition: api.qh:103
float scores_flags_primary
Definition: scores.qc:24
ClientState CS(Client this)
Definition: state.qh:47
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
float WinningConditionHelper_lowerisbetter
lower is better, duh
Definition: scores.qh:115
#define SFL_ZERO_IS_WORST
Definition: scores.qh:121
const int SFL_LOWER_IS_BETTER
Lower scores are better (e.g.
Definition: scores.qh:98
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
#define strcpy(this, s)
Definition: string.qh:49
string modname
Definition: world.qh:45
entity WinningConditionHelper_winner
the winning player, or NULL if none
Definition: scores.qh:113
float WinningConditionHelper_zeroisworst
zero is worst, duh
Definition: scores.qh:116
float cvar_purechanges_count
Definition: world.qh:43
float WinningConditionHelper_secondscore
second highest score
Definition: scores.qh:109
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
entity WinningConditionHelper_second
the second player, or NULL if none
Definition: scores.qh:114
#define NULL
Definition: post.qh:17
float WinningConditionHelper_winnerteam
the color of the winning team, or -1 if none
Definition: scores.qh:110
string GetGametype()
Definition: intermission.qc:13
#define INGAME_JOINED(it)
Definition: sv_rules.qh:21
float teamscores_flags_primary
Definition: scores.qc:25
string sv_termsofservice_url_escaped
Definition: world.qh:53
float teamscores_entities_count
Definition: scores.qc:21
int nJoinAllowed(entity this, entity ignore)
Determines whether the player is allowed to join.
Definition: client.qc:2006
float WinningConditionHelper_topscore
highest score
Definition: scores.qh:108
string GetPlayerScoreString(entity pl, float shortString)
Returns score strings for eventlog etc.
Definition: scores.qc:586
float WinningConditionHelper_equality
we have no winner
Definition: scores.qh:112
#define IS_PLAYER(v)
Definition: utils.qh:9
string worldstatus
string autocvar_g_xonoticversion
Definition: client.qh:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ autocvar_g_full_getstatus_responses

bool autocvar_g_full_getstatus_responses

Definition at line 5 of file scores.qh.

Referenced by WinningConditionHelper().

◆ scoreboard_pos

float scoreboard_pos

Definition at line 8 of file scores.qh.

◆ scores_initialized

entity scores_initialized

◆ WinningConditionHelper_equality

float WinningConditionHelper_equality

we have no winner

Definition at line 112 of file scores.qh.

Referenced by WinningCondition_Scores(), and WinningConditionHelper().

◆ WinningConditionHelper_lowerisbetter

float WinningConditionHelper_lowerisbetter

lower is better, duh

Definition at line 115 of file scores.qh.

Referenced by WinningCondition_Scores(), and WinningConditionHelper().

◆ WinningConditionHelper_second

entity WinningConditionHelper_second

the second player, or NULL if none

Definition at line 114 of file scores.qh.

Referenced by WinningConditionHelper().

◆ WinningConditionHelper_secondscore

float WinningConditionHelper_secondscore

second highest score

Definition at line 109 of file scores.qh.

Referenced by WinningCondition_LMS(), WinningCondition_Scores(), and WinningConditionHelper().

◆ WinningConditionHelper_secondteam

float WinningConditionHelper_secondteam

the color of the second team, or -1 if none

Definition at line 111 of file scores.qh.

Referenced by WinningConditionHelper().

◆ WinningConditionHelper_topscore

float WinningConditionHelper_topscore

highest score

Definition at line 108 of file scores.qh.

Referenced by WinningCondition_LMS(), WinningCondition_Scores(), and WinningConditionHelper().

◆ WinningConditionHelper_winner

entity WinningConditionHelper_winner

the winning player, or NULL if none

Definition at line 113 of file scores.qh.

Referenced by WinningCondition_LMS(), WinningCondition_Scores(), and WinningConditionHelper().

◆ WinningConditionHelper_winnerteam

float WinningConditionHelper_winnerteam

the color of the winning team, or -1 if none

Definition at line 110 of file scores.qh.

Referenced by WinningCondition_Scores(), and WinningConditionHelper().

◆ WinningConditionHelper_zeroisworst

float WinningConditionHelper_zeroisworst

zero is worst, duh

Definition at line 116 of file scores.qh.

Referenced by WinningCondition_Scores(), and WinningConditionHelper().