]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/gamemodes/gamemode/race/cl_race.qc
Merge branch 'master' into terencehill/glowmod_color_fix
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / gamemodes / gamemode / race / cl_race.qc
1 #include "cl_race.qh"
2
3 #include <client/draw.qh>
4 #include <common/mutators/base.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
12 float race_status_time;
13 int race_status_prev;
14 string race_status_name_prev;
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 {
43         entity me = playerslots[player_localnum];
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));
64                 if(autocvar_cl_autodemo_delete_keeprecords)
65                 {
66                         float f = autocvar_cl_autodemo_delete;
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;
74                 crecordtime_change_time = time;
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
99         t = race_server_record;
100         if(t != srecordtime_prev) {
101                 srecordtime_prev = t;
102                 srecordtime_change_time = time;
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
108         if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
109                 race_status_time = time + 5;
110                 race_status_prev = race_status;
111                 strcpy(race_status_name_prev, race_status_name);
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)
120                 rank = race_CheckName(race_status_name);
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;
147                 strfree(race_status_name);
148                 strfree(race_status_name_prev);
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, ShowRankings)
170 {
171         if(ISGAMETYPE(RACE))
172         {
173                 M_ARGV(0, string) = _("Rankings");
174                 return true;
175         }
176 }
177
178 MUTATOR_HOOKFUNCTION(cl_race, DrawScoreboardAccuracy)
179 {
180         return ISGAMETYPE(RACE); // accuracy is not a factor in this gamemode
181 }
182
183 MUTATOR_HOOKFUNCTION(cl_race, ShowRaceTimer)
184 {
185         return ISGAMETYPE(RACE); // show the race timer panel
186 }
187
188 MUTATOR_HOOKFUNCTION(cl_race, TeamRadar_Draw)
189 {
190         return ISGAMETYPE(RACE); // show all competitors in a race
191 }