Xonotic
cl_race.qc
Go to the documentation of this file.
1 #include "cl_race.qh"
2 
3 #include <client/draw.qh>
5 
6 // Race/CTS HUD mod icons
7 float crecordtime_prev; // last remembered crecordtime
8 float crecordtime_change_time; // time when crecordtime last changed
9 float srecordtime_prev; // last remembered srecordtime
10 float srecordtime_change_time; // time when srecordtime last changed
11 
15 
16 // Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
17 int race_CheckName(string net_name)
18 {
19  int rank = 0;
20  string zoned_name = strzone(strdecolorize(entcs_GetName(player_localnum)));
21  for (int i = RANKINGS_CNT - 1; i >= 0; --i)
22  if (strdecolorize(grecordholder[i]) == zoned_name)
23  {
24  rank = i + 1;
25  break;
26  }
27  strfree(zoned_name);
28  return rank;
29 }
30 
31 void race_showTime(string text, vector pos, vector timeText_ofs, float theTime, vector textSize, float f)
32 {
33  drawstring_aspect(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
34  drawstring_aspect(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
35  if (f < 1) {
36  drawstring_aspect_expanding(pos, text, textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
37  drawstring_aspect_expanding(pos + timeText_ofs, TIME_ENCODED_TOSTRING(theTime), textSize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, f);
38  }
39 }
40 
41 void HUD_Mod_Race(vector pos, vector mySize)
42 {
44  float score = me.(scores(ps_primary));
45 
46  if(!(scores_flags(ps_primary) & SFL_TIME) || teamplay) // race/cts record display on HUD
47  {
48  mod_active = 0; // hide it in this case!
49  return; // no records in the actual race
50  }
51 
52  mod_active = 1;
53 
54  // clientside personal record
55  string rr;
56  if(ISGAMETYPE(CTS))
57  rr = CTS_RECORD;
58  else
59  rr = RACE_RECORD;
60  float t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
61 
62  if(score && (score < t || !t)) {
63  db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
65  {
67  f &= ~1;
68  cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record!
69  }
70  }
71 
72  if(t != crecordtime_prev) {
73  crecordtime_prev = t;
75  }
76 
77  vector textPos, medalPos;
78  float squareSize;
79  if(mySize.x > mySize.y) {
80  // text on left side
81  squareSize = min(mySize.y, mySize.x/2);
82  vector ofs = vec2(0.5 * max(0, mySize.x/2 - squareSize), 0.5 * (mySize.y - squareSize));
83  textPos = pos + ofs;
84  ofs.x += 0.5 * mySize.x;
85  medalPos = pos + ofs;
86  } else {
87  // text on top
88  squareSize = min(mySize.x, mySize.y/2);
89  vector ofs = vec2(0.5 * (mySize.x - squareSize), 0.5 * max(0, mySize.y/2 - squareSize));
90  textPos = pos + ofs;
91  ofs.y += 0.5 * mySize.y;
92  medalPos = pos + ofs;
93  }
94  vector textSize = vec2(squareSize, 0.25 * squareSize);
95 
96  race_showTime(_("Personal best"), textPos, eY * 0.25 * squareSize, t, textSize, time - crecordtime_change_time);
97 
98  // server record
100  if(t != srecordtime_prev) {
101  srecordtime_prev = t;
103  }
104 
105  textPos += eY * 0.5 * squareSize;
106  race_showTime(_("Server best"), textPos, eY * 0.25 * squareSize, t, textSize, time - srecordtime_change_time);
107 
109  race_status_time = time + 5;
112  }
113 
114  // race "awards"
115  float a = bound(0, race_status_time - time, 1);
116  string s = textShortenToWidth(ColorTranslateRGB(race_status_name), squareSize, '1 1 0' * 0.1 * squareSize, stringwidth_colors);
117 
118  float rank = 0;
119  if(race_status > 0)
121  string rankname = count_ordinal(rank);
122  vector namepos = medalPos + '0 0.8 0' * squareSize;
123  vector rankpos = medalPos + '0 0.15 0' * squareSize;
124 
125  if(race_status == 0)
126  drawpic_aspect_skin(medalPos, "race_newfail", '1 1 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
127  else if(race_status == 1) {
128  drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newtime", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
129  drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
130  drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
131  } else if(race_status == 2) {
132  if(strdecolorize(race_status_name) == strdecolorize(entcs_GetName(player_localnum)) || !race_myrank || race_myrank < rank)
133  drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankgreen", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
134  else
135  drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrankyellow", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
136  drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
137  drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
138  } else if(race_status == 3) {
139  drawpic_aspect_skin(medalPos + '0.1 0 0' * squareSize, "race_newrecordserver", '1 1 0' * 0.8 * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
140  drawcolorcodedstring_aspect(namepos, s, '1 0.2 0' * squareSize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
141  drawstring_aspect(rankpos, rankname, '1 0.15 0' * squareSize, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
142  }
143 
144  if (race_status_time - time <= 0) {
145  race_status_prev = -1;
146  race_status = -1;
149  }
150 }
151 
152 REGISTER_MUTATOR(cl_race, true);
153 
154 MUTATOR_HOOKFUNCTION(cl_race, HUD_Physics_showoptional)
155 {
156  return ISGAMETYPE(RACE); // show the optional physics panel
157 }
158 
159 MUTATOR_HOOKFUNCTION(cl_race, HUD_StrafeHUD_showoptional)
160 {
161  return ISGAMETYPE(RACE); // show the optional strafehud
162 }
163 
164 MUTATOR_HOOKFUNCTION(cl_race, HUD_Score_show)
165 {
166  return spectatee_status == -1 && ISGAMETYPE(RACE); // hide the score panel while observing
167 }
168 
169 MUTATOR_HOOKFUNCTION(cl_race, DrawScoreboardItemStats)
170 {
171  return ISGAMETYPE(RACE); // hide the item stats panel
172 }
173 
174 MUTATOR_HOOKFUNCTION(cl_race, ShowRankings)
175 {
176  if(ISGAMETYPE(RACE))
177  {
178  M_ARGV(0, string) = _("Rankings");
179  return true;
180  }
181 }
182 
183 MUTATOR_HOOKFUNCTION(cl_race, DrawScoreboardAccuracy)
184 {
185  return ISGAMETYPE(RACE); // accuracy is not a factor in this gamemode
186 }
187 
188 MUTATOR_HOOKFUNCTION(cl_race, ShowRaceTimer)
189 {
190  return ISGAMETYPE(RACE); // show the race timer panel
191 }
192 
193 MUTATOR_HOOKFUNCTION(cl_race, TeamRadar_Draw)
194 {
195  return ISGAMETYPE(RACE); // show all competitors in a race
196 }
ERASEABLE void db_put(int db, string key, string value)
Definition: map.qh:101
string shortmapname
Definition: main.qh:172
float panel_fg_alpha
Definition: hud.qh:166
float race_myrank
Definition: racetimer.qh:43
void drawstring_aspect(vector pos, string text, vector sz, vector color, float theAlpha, float drawflag)
Definition: draw.qc:102
const vector eY
Definition: vector.qh:45
float crecordtime_prev
Definition: cl_race.qc:7
bool mod_active
Definition: modicons.qh:7
entity() spawn
int race_status_prev
Definition: cl_race.qc:13
float race_status
Definition: racetimer.qh:41
#define RACE_RECORD
Definition: util.qh:58
string textShortenToWidth(string theText, float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition: util.qc:956
float race_server_record
Definition: racetimer.qh:23
int ClientProgsDB
Definition: main.qh:176
bool autocvar_cl_autodemo_delete
Definition: cl_race.qh:3
entity playerslots[255]
Definition: main.qh:70
REGISTER_MUTATOR(cl_race, true)
#define TIME_ENCODED_TOSTRING(n)
Definition: util.qh:57
float crecordtime_change_time
Definition: cl_race.qc:8
float race_status_time
Definition: cl_race.qc:12
#define CTS_RECORD
Definition: util.qh:59
#define strcpy(this, s)
Definition: string.qh:49
ERASEABLE string count_ordinal(int interval)
Definition: counting.qh:66
string race_status_name_prev
Definition: cl_race.qc:14
string grecordholder[RANKINGS_CNT]
Definition: main.qh:67
#define drawpic_aspect_skin(pos, pic, sz, color, theAlpha, drawflag)
Definition: draw.qh:78
MUTATOR_HOOKFUNCTION(cl_race, HUD_Physics_showoptional)
Definition: cl_race.qc:154
void drawstring_aspect_expanding(vector pos, string text, vector sz, vector color, float theAlpha, float drawflag, float fadelerp)
Definition: draw.qc:131
float srecordtime_change_time
Definition: cl_race.qc:10
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"))
void drawcolorcodedstring_aspect(vector pos, string text, vector sz, float theAlpha, float drawflag)
Definition: draw.qc:108
ERASEABLE string ColorTranslateRGB(string s)
Definition: string.qh:177
bool autocvar_cl_autodemo_delete_keeprecords
Definition: cl_race.qh:4
const float DRAWFLAG_NORMAL
Definition: csprogsdefs.qc:317
ERASEABLE string db_get(int db, string key)
Definition: map.qh:91
float teamplay
Definition: progsdefs.qc:31
#define M_ARGV(x, type)
Definition: events.qh:17
#define scores_flags(this)
Definition: scores.qh:140
void HUD_Mod_Race(vector pos, vector mySize)
Definition: cl_race.qc:41
string race_status_name
Definition: racetimer.qh:42
vector(float skel, float bonenum) _skel_get_boneabs_hidden
float spectatee_status
Definition: main.qh:166
#define ISGAMETYPE(NAME)
Definition: main.qh:32
#define vec2(...)
Definition: vector.qh:90
PlayerScoreField ps_primary
Definition: hud.qh:116
int race_CheckName(string net_name)
Definition: cl_race.qc:17
#define strfree(this)
Definition: string.qh:56
float time
Definition: csprogsdefs.qc:16
void race_showTime(string text, vector pos, vector timeText_ofs, float theTime, vector textSize, float f)
Definition: cl_race.qc:31
float player_localnum
Definition: csprogsdefs.qc:20
const int SFL_TIME
Display as mm:ss.s, value is stored as 10ths of a second (AND 0 is the worst possible value!) ...
Definition: scores.qh:118
float srecordtime_prev
Definition: cl_race.qc:9