Xonotic
scores.qc File Reference
+ Include dependency graph for scores.qc:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

string GetPlayerScoreString (entity pl, float shortString)
 Returns score strings for eventlog etc. More...
 
string GetScoreLogLabel (string label, float fl)
 
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...
 
float PlayerScore_Compare (entity t1, entity t2, bool strict)
 
void PlayerScore_Detach (entity player)
 Detaches a PlayerScore entity from the player. More...
 
void PlayerScore_PlayerStats (entity p)
 
bool PlayerScore_SendEntity (entity this, entity to, float sendflags)
 
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...
 
void PlayerScore_TeamStats ()
 
float PlayerTeamScore_Add (entity player, PlayerScoreField pscorefield, float tscorefield, float score)
 Adds a score to both the player and the team. More...
 
float PlayerTeamScore_Compare (entity p1, entity p2, float teams, bool strict)
 
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...
 
string Score_NicePrint_ItemColor (float vflags)
 
void Score_NicePrint_Player (entity to, entity p, float w)
 
void Score_NicePrint_Spectator (entity to, entity p)
 
void Score_NicePrint_Spectators (entity to)
 
void Score_NicePrint_Team (entity to, float t, float w)
 
vector ScoreField_Compare (entity t1, entity t2,.float field, float fieldflags, vector previous, bool strict)
 
void ScoreInfo_Init (int teams)
 
bool ScoreInfo_SendEntity (entity this, entity to, int sf)
 
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_Compare (entity t1, entity t2, bool strict)
 
float TeamScore_GetCompareValue (float t)
 Returns a value indicating the team score (and higher is better). More...
 
bool TeamScore_SendEntity (entity this, entity to, float sendflags)
 
void TeamScore_Spawn (float t, string name)
 
void WinningConditionHelper (entity this)
 Sets the following results for the current scores entities. More...
 

Variables

const float NAMEWIDTH = 22
 
float score_dummyfield
 
entity scorekeeper
 
float scores_flags_primary
 
var float scores_primary
 
const float SCORESWIDTH = 58
 
entity teamscorekeepers [16]
 
float teamscores_entities_count
 
float teamscores_flags_primary
 
var float teamscores_primary
 

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:

◆ GetScoreLogLabel()

string GetScoreLogLabel ( string  label,
float  fl 
)

Definition at line 575 of file scores.qc.

References SFL_LOWER_IS_BETTER, SFL_SORT_PRIO_MASK, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_SECONDARY, and strcat().

Referenced by GetPlayerScoreString(), and GetTeamScoreString().

576 {
577  if(fl & SFL_LOWER_IS_BETTER)
578  label = strcat(label, "<");
580  label = strcat(label, "!!");
581  else if((fl & SFL_SORT_PRIO_MASK) == SFL_SORT_PRIO_SECONDARY)
582  label = strcat(label, "!");
583  return label;
584 }
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
const int SFL_SORT_PRIO_PRIMARY
Definition: scores.qh:127
const int SFL_LOWER_IS_BETTER
Lower scores are better (e.g.
Definition: scores.qh:98
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"))
+ 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.

Referenced by ClientState_attach(), and PlayerState_detach().

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:
+ Here is the caller 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_Compare()

float PlayerScore_Compare ( entity  t1,
entity  t2,
bool  strict 
)

Definition at line 399 of file scores.qc.

References FOREACH, result, ScoreField_Compare(), scores, scores_flags, and vector().

Referenced by PlayerTeamScore_Compare(), and WinningConditionHelper().

400 {
401  if(!t1 || !t2) return (!t2) - !t1;
402 
403  vector result = '0 0 0';
404  FOREACH(Scores, true, {
405  var .float f = scores(it);
406  result = ScoreField_Compare(t1, t2, f, scores_flags(it), result, strict);
407  });
408 
409  if (result.x == 0 && strict)
410  result.x = t1.owner.playerid - t2.owner.playerid;
411 
412  return result.x;
413 }
vector ScoreField_Compare(entity t1, entity t2,.float field, float fieldflags, vector previous, bool strict)
Definition: scores.qc:27
entity result
Definition: promise.qc:43
#define scores_flags(this)
Definition: scores.qh:140
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#define FOREACH(list, cond, body)
Definition: iter.qh:19
#define scores(this)
Definition: scores.qh:138
+ 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.

Referenced by ClientState_attach(), and ClientState_detach().

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:
+ Here is the caller graph for this function:

◆ PlayerScore_PlayerStats()

void PlayerScore_PlayerStats ( entity  p)

Definition at line 939 of file scores.qc.

References CS(), entity(), FOREACH, scores_label, and strcat().

940 {
941  entity s = CS(p).scorekeeper;
942  FOREACH(Scores, true, {
943  if(s.(scores(it)) != 0 && scores_label(it) != "")
944  PlayerStats_GameReport_Event_Player(s.owner,
945  strcat(PLAYERSTATS_SCOREBOARD, scores_label(it)), s.(scores(it)));
946  });
947 }
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
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_label(this)
Definition: scores.qh:139
#define FOREACH(list, cond, body)
Definition: iter.qh:19
+ Here is the call graph for this function:

◆ PlayerScore_SendEntity()

bool PlayerScore_SendEntity ( entity  this,
entity  to,
float  sendflags 
)

Definition at line 239 of file scores.qc.

References etof(), FOREACH, owner, scores, WriteByte(), WriteChar(), and WriteShort().

Referenced by PlayerScore_Attach().

240 {
241  WriteHeader(MSG_ENTITY, ENT_CLIENT_SCORES);
242  WriteByte(MSG_ENTITY, etof(this.owner));
243 
244  int longflags = 0;
245  FOREACH(Scores, true, {
246  int p = 1 << (i % 16);
247  if (this.(scores(it)) > 127 || this.(scores(it)) <= -128)
248  longflags |= p;
249  });
250 
251  WriteShort(MSG_ENTITY, sendflags);
252  WriteShort(MSG_ENTITY, longflags);
253  FOREACH(Scores, true, {
254  int p = 1 << (i % 16);
255  if (sendflags & p)
256  {
257  if(longflags & p)
258  WriteInt24_t(MSG_ENTITY, this.(scores(it)));
259  else
260  WriteChar(MSG_ENTITY, this.(scores(it)));
261  }
262  });
263 
264  return true;
265 }
entity owner
Definition: main.qh:73
entity int sendflags
Definition: self.qh:96
#define FOREACH(list, cond, body)
Definition: iter.qh:19
#define scores(this)
Definition: scores.qh:138
+ Here is the call graph for this function:
+ Here is the caller 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:

◆ PlayerScore_TeamStats()

void PlayerScore_TeamStats ( )

Definition at line 949 of file scores.qc.

References entity(), MAX_TEAMSCORE, strcat(), teamscorekeepers, and teamscores_label.

950 {
951  entity sk;
952  float t, i;
953  for(t = 0; t < 16; ++t)
954  {
955  sk = teamscorekeepers[t];
956  if(!sk)
957  continue;
958  for(i = 0; i < MAX_TEAMSCORE; ++i)
959  if(sk.(teamscores(i)) != 0 && teamscores_label(i) != "")
960  // the +1 is important here!
961  PlayerStats_GameReport_Event_Team(t+1,
962  strcat(PLAYERSTATS_SCOREBOARD, teamscores_label(i)), sk.(teamscores(i)));
963  }
964 }
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
#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"))
#define MAX_TEAMSCORE
Definition: scores.qh:142
+ Here is the call 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:

◆ PlayerTeamScore_Compare()

float PlayerTeamScore_Compare ( entity  p1,
entity  p2,
float  teams,
bool  strict 
)

Definition at line 704 of file scores.qc.

References CS(), entity(), PlayerScore_Compare(), scorekeeper, TeamScore_Compare(), teamscorekeepers, and teamscores_entities_count.

Referenced by PlayerScore_Sort().

705 {
707  {
708  if(p1.team != p2.team)
709  {
710  entity t1, t2;
711  float r;
712  t1 = teamscorekeepers[p1.team - 1];
713  t2 = teamscorekeepers[p2.team - 1];
714  r = TeamScore_Compare(t1, t2, ((teams >= 0) ? 1 : strict));
715  return r;
716  }
717  if(teams < 0)
718  return 0;
719  }
720 
721  return PlayerScore_Compare(CS(p1).scorekeeper, CS(p2).scorekeeper, strict);
722 }
float PlayerScore_Compare(entity t1, entity t2, bool strict)
Definition: scores.qc:399
float TeamScore_Compare(entity t1, entity t2, bool strict)
Definition: scores.qc:142
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
ClientState CS(Client this)
Definition: state.qh:47
entity teams
Definition: main.qh:44
entity scorekeeper
Definition: scores.qc:19
float teamscores_entities_count
Definition: scores.qc:21
+ 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:

◆ Score_NicePrint_ItemColor()

string Score_NicePrint_ItemColor ( float  vflags)

Definition at line 810 of file scores.qc.

References SFL_SORT_PRIO_PRIMARY, and SFL_SORT_PRIO_SECONDARY.

Referenced by Score_NicePrint_Player(), and Score_NicePrint_Team().

811 {
812  if(vflags & SFL_SORT_PRIO_PRIMARY)
813  return "^3";
814  else if(vflags & SFL_SORT_PRIO_SECONDARY)
815  return "^5";
816  else
817  return "^7";
818 }
const int SFL_SORT_PRIO_SECONDARY
Scoring priority (NOTE: PRIMARY is used for fraglimit)
Definition: scores.qh:126
const int SFL_SORT_PRIO_PRIMARY
Definition: scores.qh:127
+ Here is the caller graph for this function:

◆ Score_NicePrint_Player()

void Score_NicePrint_Player ( entity  to,
entity  p,
float  w 
)

Definition at line 857 of file scores.qc.

References CS(), entity(), FOREACH, NAMEWIDTH, print_to(), Score_NicePrint_ItemColor(), scores_flags, scores_label, strcat(), strlen(), and substring().

Referenced by Score_NicePrint().

858 {
859  string s;
860  float i;
861  entity sk;
862  float fl, sc;
863  s = " ";
864 
865  sk = CS(p).scorekeeper;
866 
867  s = strcat(s, playername(p.netname, p.team, false));
868  for (;;)
869  {
870  i = strlennocol(s) - NAMEWIDTH;
871  if(i > 0)
872  s = substring(s, 0, strlen(s) - i);
873  else
874  {
875  s = strcat(s, strpad(i, ""));
876  break;
877  }
878  }
879 
880  FOREACH(Scores, true, {
881  if(scores_label(it) != "")
882  {
883  fl = scores_flags(it);
884  sc = sk.(scores(it));
885  s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, ScoreString(fl, sc)));
886  }
887  });
888 
889  print_to(to, s);
890 }
const float NAMEWIDTH
Definition: scores.qc:807
entity() spawn
ClientState CS(Client this)
Definition: state.qh:47
entity to
Definition: self.qh:96
void print_to(entity to, string input)
Definition: common.qc:172
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
string Score_NicePrint_ItemColor(float vflags)
Definition: scores.qc:810
#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_Spectator()

void Score_NicePrint_Spectator ( entity  to,
entity  p 
)

Definition at line 897 of file scores.qc.

References print_to(), and strcat().

Referenced by Score_NicePrint().

898 {
899  print_to(to, strcat(" ", playername(p.netname, p.team, false)));
900 }
entity to
Definition: self.qh:96
void print_to(entity to, string input)
Definition: common.qc:172
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"))
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Score_NicePrint_Spectators()

void Score_NicePrint_Spectators ( entity  to)

Definition at line 892 of file scores.qc.

References print_to().

Referenced by Score_NicePrint().

893 {
894  print_to(to, "Spectators:");
895 }
entity to
Definition: self.qh:96
void print_to(entity to, string input)
Definition: common.qc:172
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Score_NicePrint_Team()

void Score_NicePrint_Team ( entity  to,
float  t,
float  w 
)

Definition at line 820 of file scores.qc.

References entity(), FOREACH, max(), MAX_TEAMSCORE, NAMEWIDTH, print_to(), s2, Score_NicePrint_ItemColor(), scores_flags, scores_label, strcat(), substring(), Team_ColoredFullName, teamscorekeepers, teamscores_flags, and teamscores_label.

Referenced by Score_NicePrint().

821 {
822  string s, s2;
823  float i;
824  entity sk;
825  float fl, sc;
826  s = "";
827 
828  sk = teamscorekeepers[t - 1];
829  if(sk)
830  {
831  s = strcat(s, Team_ColoredFullName(t));
832  for(i = 0; i < MAX_TEAMSCORE; ++i)
833  if(teamscores_label(i) != "")
834  {
835  fl = teamscores_flags(i);
836  sc = sk.(teamscores(i));
837  s = strcat(s, " ", Score_NicePrint_ItemColor(fl), ScoreString(fl, sc));
838  }
839  }
840  else
841  s = "Scores:";
842 
843  s = strcat(s, strpad(max(0, NAMEWIDTH - strlennocol(s)), ""));
844 
845  FOREACH(Scores, true, {
846  if(scores_label(it) != "")
847  {
848  fl = scores_flags(it);
849  s2 = scores_label(it);
850  s = strcat(s, " ", Score_NicePrint_ItemColor(fl), strpad(-w, substring(s2, 0, w)));
851  }
852  });
853 
854  print_to(to, s);
855 }
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1 f1points s1 s2
Definition: all.inc:438
const float NAMEWIDTH
Definition: scores.qc:807
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
entity to
Definition: self.qh:96
void print_to(entity to, string input)
Definition: common.qc:172
#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"))
#define MAX_TEAMSCORE
Definition: scores.qh:142
#define scores_flags(this)
Definition: scores.qh:140
#define scores_label(this)
Definition: scores.qh:139
string Score_NicePrint_ItemColor(float vflags)
Definition: scores.qc:810
#define teamscores_flags(i)
Definition: scores.qh:149
#define Team_ColoredFullName(teamid)
Definition: teams.qh:230
#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:

◆ ScoreField_Compare()

vector ScoreField_Compare ( entity  t1,
entity  t2,
.float  field,
float  fieldflags,
vector  previous,
bool  strict 
)

Definition at line 27 of file scores.qc.

References SFL_LOWER_IS_BETTER, SFL_SORT_PRIO_MASK, and SFL_ZERO_IS_WORST.

Referenced by PlayerScore_Compare(), and TeamScore_Compare().

28 {
29  if(!strict && !(fieldflags & SFL_SORT_PRIO_MASK)) // column does not sort
30  return previous;
31  if((fieldflags & SFL_SORT_PRIO_MASK) < previous.y)
32  return previous;
33  if (t1.(field) == t2.(field))
34  return previous;
35 
36  previous.y = fieldflags & SFL_SORT_PRIO_MASK;
37 
38  if(fieldflags & SFL_ZERO_IS_WORST)
39  {
40  if (t1.(field) == 0)
41  {
42  previous.x = -1;
43  return previous;
44  }
45  else if (t2.(field) == 0)
46  {
47  previous.x = +1;
48  return previous;
49  }
50  }
51 
52  if (fieldflags & SFL_LOWER_IS_BETTER)
53  previous.x = (t2.(field) - t1.(field));
54  else
55  previous.x = (t1.(field) - t2.(field));
56 
57  return previous;
58 }
const int SFL_SORT_PRIO_MASK
Definition: scores.qh:128
#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
+ Here is the caller graph for this function:

◆ ScoreInfo_Init()

void ScoreInfo_Init ( int  teams)

Definition at line 214 of file scores.qc.

References BIT, new_pure, NUM_TEAM_1, NUM_TEAM_2, NUM_TEAM_3, NUM_TEAM_4, ScoreInfo_SendEntity(), scores_initialized, and TeamScore_Spawn().

Referenced by ScoreRules_basics_end().

215 {
217  {
218  scores_initialized.SendFlags |= 1; // force a resend
219  }
220  else
221  {
222  scores_initialized = new_pure(ent_client_scoreinfo);
223  Net_LinkEntity(scores_initialized, false, 0, ScoreInfo_SendEntity);
224  }
225  if(teams & BIT(0))
226  TeamScore_Spawn(NUM_TEAM_1, "Red");
227  if(teams & BIT(1))
228  TeamScore_Spawn(NUM_TEAM_2, "Blue");
229  if(teams & BIT(2))
230  TeamScore_Spawn(NUM_TEAM_3, "Yellow");
231  if(teams & BIT(3))
232  TeamScore_Spawn(NUM_TEAM_4, "Pink");
233 }
const int NUM_TEAM_2
Definition: teams.qh:19
void TeamScore_Spawn(float t, string name)
Definition: scores.qc:97
entity teams
Definition: main.qh:44
bool ScoreInfo_SendEntity(entity this, entity to, int sf)
Definition: scores.qc:197
#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
const int NUM_TEAM_4
Definition: teams.qh:21
#define new_pure(class)
purely logical entities (.origin doesn&#39;t work)
Definition: oo.qh:62
const int NUM_TEAM_1
Definition: teams.qh:18
const int NUM_TEAM_3
Definition: teams.qh:20
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ScoreInfo_SendEntity()

bool ScoreInfo_SendEntity ( entity  this,
entity  to,
int  sf 
)

Definition at line 197 of file scores.qc.

References FOREACH, MapInfo_LoadedGametype, MAX_TEAMSCORE, scores_flags, scores_label, teamscores_flags, teamscores_label, WriteByte(), WriteRegistered, and WriteString().

Referenced by ScoreInfo_Init().

198 {
199  float i;
200  WriteHeader(MSG_ENTITY, ENT_CLIENT_SCORES_INFO);
201  WriteRegistered(Gametypes, MSG_ENTITY, MapInfo_LoadedGametype);
202  FOREACH(Scores, true, {
203  WriteString(MSG_ENTITY, scores_label(it));
204  WriteByte(MSG_ENTITY, scores_flags(it));
205  });
206  for(i = 0; i < MAX_TEAMSCORE; ++i)
207  {
208  WriteString(MSG_ENTITY, teamscores_label(i));
209  WriteByte(MSG_ENTITY, teamscores_flags(i));
210  }
211  return true;
212 }
Gametype MapInfo_LoadedGametype
Definition: mapinfo.qh:193
#define WriteRegistered(r, to, it)
Definition: net.qh:294
#define teamscores_label(i)
Definition: scores.qh:147
#define MAX_TEAMSCORE
Definition: scores.qh:142
#define scores_flags(this)
Definition: scores.qh:140
#define scores_label(this)
Definition: scores.qh:139
#define teamscores_flags(i)
Definition: scores.qh:149
#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:

◆ 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_Compare()

float TeamScore_Compare ( entity  t1,
entity  t2,
bool  strict 
)

Definition at line 142 of file scores.qc.

References MAX_TEAMSCORE, result, ScoreField_Compare(), teamscores, teamscores_flags, and vector().

Referenced by PlayerTeamScore_Compare(), and WinningConditionHelper().

143 {
144  if(!t1 || !t2) return (!t2) - !t1;
145 
146  vector result = '0 0 0';
147  float i;
148  for(i = 0; i < MAX_TEAMSCORE; ++i)
149  {
150  var .float f;
151  f = teamscores(i);
152  result = ScoreField_Compare(t1, t2, f, teamscores_flags(i), result, strict);
153  }
154 
155  if (result.x == 0 && strict)
156  result.x = t1.team - t2.team;
157 
158  return result.x;
159 }
vector ScoreField_Compare(entity t1, entity t2,.float field, float fieldflags, vector previous, bool strict)
Definition: scores.qc:27
entity result
Definition: promise.qc:43
#define MAX_TEAMSCORE
Definition: scores.qh:142
vector(float skel, float bonenum) _skel_get_boneabs_hidden
#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_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:

◆ TeamScore_SendEntity()

bool TeamScore_SendEntity ( entity  this,
entity  to,
float  sendflags 
)

Definition at line 64 of file scores.qc.

References assert, BIT, eprint(), MAX_TEAMSCORE, team, teamscores, WriteByte(), WriteChar(), and WriteShort().

Referenced by TeamScore_Spawn().

65 {
66  float i, longflags;
67 
68  WriteHeader(MSG_ENTITY, ENT_CLIENT_TEAMSCORES);
69  int t = this.team - 1;
70  assert(t, eprint(this));
71  WriteByte(MSG_ENTITY, t);
72 
73  longflags = 0;
74  for(i = 0; i < MAX_TEAMSCORE; ++i)
75  if(this.(teamscores(i)) > 127 || this.(teamscores(i)) <= -128)
76  longflags |= BIT(i);
77 
78 #if MAX_TEAMSCORE <= 8
79  WriteByte(MSG_ENTITY, sendflags);
80  WriteByte(MSG_ENTITY, longflags);
81 #else
82  WriteShort(MSG_ENTITY, sendflags);
83  WriteShort(MSG_ENTITY, longflags);
84 #endif
85  for(i = 0; i < MAX_TEAMSCORE; ++i)
86  if(sendflags & BIT(i))
87  {
88  if(longflags & BIT(i))
89  WriteInt24_t(MSG_ENTITY, this.(teamscores(i)));
90  else
91  WriteChar(MSG_ENTITY, this.(teamscores(i)));
92  }
93 
94  return true;
95 }
#define assert(expr,...)
Definition: log.qh:8
int team
Definition: main.qh:157
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
#define MAX_TEAMSCORE
Definition: scores.qh:142
entity int sendflags
Definition: self.qh:96
#define teamscores(i)
Definition: scores.qh:145
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TeamScore_Spawn()

void TeamScore_Spawn ( float  t,
string  name 
)

Definition at line 97 of file scores.qc.

References entity(), name, new_pure, TeamScore_SendEntity(), teamscorekeepers, and teamscores_entities_count.

Referenced by ScoreInfo_Init().

98 {
99  entity ts = new_pure(csqc_score_team);
100  ts.netname = name; // not used yet, FIXME
101  ts.team = t;
102  Net_LinkEntity(ts, false, 0, TeamScore_SendEntity);
103  teamscorekeepers[t - 1] = ts;
105  PlayerStats_GameReport_AddTeam(t);
106 }
entity() spawn
entity teamscorekeepers[16]
Definition: scores.qc:20
bool TeamScore_SendEntity(entity this, entity to, float sendflags)
Definition: scores.qc:64
float teamscores_entities_count
Definition: scores.qc:21
#define new_pure(class)
purely logical entities (.origin doesn&#39;t work)
Definition: oo.qh:62
+ 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

◆ NAMEWIDTH

const float NAMEWIDTH = 22

Definition at line 807 of file scores.qc.

Referenced by Score_NicePrint_Player(), and Score_NicePrint_Team().

◆ score_dummyfield

float score_dummyfield

Definition at line 902 of file scores.qc.

Referenced by Score_NicePrint().

◆ scorekeeper

◆ scores_flags_primary

float scores_flags_primary

Definition at line 24 of file scores.qc.

Referenced by ScoreInfo_SetLabel_PlayerScore(), and WinningConditionHelper().

◆ scores_primary

var float scores_primary

Definition at line 22 of file scores.qc.

Referenced by ScoreInfo_SetLabel_PlayerScore().

◆ SCORESWIDTH

const float SCORESWIDTH = 58

Definition at line 808 of file scores.qc.

Referenced by Score_NicePrint().

◆ teamscorekeepers

◆ teamscores_entities_count

◆ teamscores_flags_primary

float teamscores_flags_primary

◆ teamscores_primary

var float teamscores_primary

Definition at line 23 of file scores.qc.

Referenced by ScoreInfo_SetLabel_TeamScore().