Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
infomessages.qc
Go to the documentation of this file.
1#include "infomessages.qh"
2
3#include <client/draw.qh>
4#include <common/ent_cs.qh>
5
6// Info messages (#14)
7
9{
10 // allow saving cvars that aesthetically change the panel into hud skin files
11 HUD_Write_Cvar("hud_panel_infomessages_flip");
12}
13
17const int IMG_COUNT = 1; // number of InfoMessage Groups
21
22int img_select(int group_id)
23{
25 if (time > img_time[group_id])
26 {
27 img_fade[group_id] = max(0, img_fade[group_id] - frametime / fadetime);
28 if (!img_fade[group_id])
29 {
30 ++img_cur_msg[group_id];
32 }
33 }
34 else
35 img_fade[group_id] = min(1, img_fade[group_id] + frametime / fadetime);
36 return img_cur_msg[group_id];
37}
38
39vector InfoMessages_drawstring(string s, vector pos, vector sz, float a, vector fontsize)
40{
42 float offset = 0;
44 {
45 s = getWrappedLine(sz.x - offset, fontsize, stringwidth_colors);
47 offset = sz.x - stringwidth_colors(s, fontsize) - offset;
48 drawcolorcodedstring(pos + eX * offset, s, fontsize, a, DRAWFLAG_NORMAL);
49 pos.y += fontsize.y;
50 offset = fontsize.x;
51 }
52 pos.y += fontsize.y * 0.25;
53 return pos;
54}
55
56#define InfoMessage(s) MACRO_BEGIN \
57 pos = InfoMessages_drawstring(s, pos, mySize, ((img_curr_group >= 0) ? panel_fg_alpha * img_fade[img_curr_group] : panel_fg_alpha), fontsize); \
58 img_curr_group = -1; \
59MACRO_END
60
61string get_team_list(int team_mask, string suf_col)
62{
63 return strcat(
64 ((team_mask & BIT(0)) ? strcat(Team_ColoredFullName_WithSuffixColor(NUM_TEAM_1, suf_col), (team_mask >> 1) ? ", " : "") : ""),
65 ((team_mask & BIT(1)) ? strcat(Team_ColoredFullName_WithSuffixColor(NUM_TEAM_2, suf_col), (team_mask >> 2) ? ", " : "") : ""),
66 ((team_mask & BIT(2)) ? strcat(Team_ColoredFullName_WithSuffixColor(NUM_TEAM_3, suf_col), (team_mask >> 3) ? ", " : "") : ""),
67 ((team_mask & BIT(3)) ? Team_ColoredFullName_WithSuffixColor(NUM_TEAM_4, suf_col) : "")
68 );
69}
70
71void HUD_InfoMessages(bool should_draw)
72{
73 if (!should_draw)
74 return;
76 return;
77
79 vector pos = panel_pos;
80 vector mySize = panel_size;
81
84 else
88 {
89 pos += '1 1 0' * panel_bg_padding;
90 mySize -= '2 2 0' * panel_bg_padding;
91 }
92
93 vector fontsize = '0.2 0.2 0' * mySize.y;
94 int img_curr_group = -1;
95
97 {
98 string s;
100
102 {
103 if (spectatee_status == -1)
104 s = _("^1Observing");
105 else
106 s = sprintf(_("^1Spectating: ^7%s"), entcs_GetName(current_player));
107 InfoMessage(s);
108
110 {
111 img_curr_group = 0;
112 switch (img_select(img_curr_group) % 3)
113 {
114 default:
115 case 0:
116 if (spectatee_status == -1)
117 s = sprintf(_("^1Press ^3%s^1 to spectate"), getcommandkey(_("primary fire"), "+fire"));
118 else
119 s = sprintf(_("^1Press ^3%s^1 or ^3%s^1 for next or previous player"), getcommandkey(_("next weapon"), "weapnext"), getcommandkey(_("previous weapon"), "weapprev"));
120 break;
121 case 1:
122 if (spectatee_status == -1)
123 s = sprintf(_("^1Use ^3%s^1 or ^3%s^1 to change the speed"), getcommandkey(_("next weapon"), "weapnext"), getcommandkey(_("previous weapon"), "weapprev"));
124 else if (!observe_blocked)
125 s = sprintf(_("^1Press ^3%s^1 to observe, ^3%s^1 to change camera mode"), getcommandkey(_("secondary fire"), "+fire2"), getcommandkey(_("drop weapon"), "dropweapon"));
126 else
127 s = sprintf(_("^1Press ^3%s^1 to change camera mode"), getcommandkey(_("drop weapon"), "dropweapon"));
128 break;
129 case 2:
130 s = sprintf(_("^1Press ^3%s^1 for gametype info"), getcommandkey(_("server info"), "+show_info"));
131 break;
132 }
133 InfoMessage(s);
134 }
135
136 bool mutator_returnvalue = MUTATOR_CALLHOOK(DrawInfoMessages, pos, mySize, img_curr_group);
137 pos = M_ARGV(0, vector);
138 img_curr_group = M_ARGV(2, int);
139
140 if (!mutator_returnvalue && !wants_join)
141 InfoMessage(sprintf(_("^1Press ^3%s^1 to join"), getcommandkey(_("jump"), "+jump")));
142 }
143
144 if (wants_join > 0)
145 {
147 InfoMessage(sprintf(_("^2You're queued to join the %s%s^2 team"), Team_ColorCode(wants_join), Team_ColorName(wants_join)));
148 }
149 else if (wants_join < 0)
150 InfoMessage(sprintf(_("^2You're queued to join any available team")));
151
152 if (time < STAT(GAMESTARTTIME))
153 {
154 //we need to ceil, otherwise the countdown would be off by .5 when using round()
155 float countdown = ceil(STAT(GAMESTARTTIME) - time);
156 s = sprintf(_("^1Game starts in ^3%d^1 seconds"), countdown);
157 InfoMessage(s);
158 }
159
160 string blinkcolor = (time % 1 >= 0.5) ? "^1" : "^3";
161
162 if (warmup_stage)
163 {
164 InfoMessage(_("^2Currently in ^1warmup^2 stage!"));
165
166 int players_needed = 0;
167 Scoreboard_UpdatePlayerTeams(); // ensure numplayers, ts_min, ts_max are current
168 if (STAT(WARMUP_TIMELIMIT) <= 0 && srv_minplayers)
169 players_needed = srv_minplayers - numplayers;
170
171 if (players_needed > 0)
172 {
173 if (players_needed == 1)
174 s = _("^31^2 more player is needed for the match to start.");
175 else
176 s = sprintf(_("^3%d^2 more players are needed for the match to start."), players_needed);
177 InfoMessage(s);
178 }
179 else if (teamnagger && (ts_max - ts_min) >= teamnagger)
180 {
181 // ready won't end warmup so don't display that message
182 // see below for unbalanced teams warning
183 }
184 else if (!spectatee_status)
185 {
186 string ready_key = getcommandkey(_("ready"), "ready");
187 if (ready_waiting)
188 {
190 s = sprintf(_("%sPress ^3%s%s to end warmup"), blinkcolor, ready_key, blinkcolor);
191 else
192 s = _("^2Waiting for others to ready up to end warmup...");
193 }
194 else
195 s = sprintf(_("^2Press ^3%s^2 to end warmup"), ready_key);
196 InfoMessage(s);
197 }
198 }
199
200 // NOTE: this stat is used for missing players in ffa games
201 int missing_teams_mask = STAT(MISSING_TEAMS_MASK);
203 {
204 if (teamplay)
205 s = sprintf(_("%sNeed active players for: %s"), blinkcolor, get_team_list(missing_teams_mask, blinkcolor));
206 else
207 {
208 if (missing_teams_mask == 1)
209 s = sprintf(_("%sWaiting for 1 player to join..."), blinkcolor);
210 else
211 s = sprintf(_("%sWaiting for %d players to join..."), blinkcolor, missing_teams_mask);
212 }
213 InfoMessage(s);
214 }
215
216 if (teamplay && numplayers > 1 && teamnagger)
217 {
218 if (!warmup_stage) // in warmup this was done above
220
221 if ((ts_max - ts_min) >= teamnagger)
222 {
223 s = strcat(blinkcolor, _("Teams are unbalanced!"));
224 entity tm = GetTeam(myteam, false);
225 if (tm && tm.team != NUM_SPECTATOR && tm.team_size == ts_max)
226 s = strcat(s, sprintf(_(" Press ^3%s%s to adjust"), getcommandkey(_("team selection"), "team_selection_show"), blinkcolor));
227 fontsize *= 1.125; // perfect float
229 InfoMessage(s);
231 fontsize /= 1.125;
232 }
233 }
234
236 if (num_spectators)
237 //if (spectatee_status != -1)
238 {
239 s = ((spectatee_status) ? _("^1Spectating this player:") : _("^1Spectating you:"));
240 // InfoMessage(s)
241 string spec_name;
242 int limit = min(num_spectators, MAX_SPECTATORS);
243 for (int i = 0; i < limit; ++i)
244 {
245 spec_name = entcs_GetName(spectatorlist[i]);
246 if (i == 0)
247 s = strcat(s, " ^7", spec_name);
248 else
249 s = strcat("^7", spec_name);
250 InfoMessage(s);
251 }
252 }
253 }
254 else
255 {
256 InfoMessage(_("^7Press ^3ESC ^7to show HUD options."));
257 InfoMessage(_("^3Double-click ^7a panel for panel-specific options."));
258 InfoMessage(_("^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"));
259 InfoMessage(_("^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."));
260 }
261}
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition bits.qh:8
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
#define drawcolorcodedstring(position, text, scale, alpha, flag)
Definition draw.qh:30
#define draw_beginBoldFont()
Definition draw.qh:4
#define draw_endBoldFont()
Definition draw.qh:5
entity GetTeam(int Team, bool add)
Definition main.qc:330
bool ready_waiting
Definition main.qh:143
int spectatorlist[MAX_SPECTATORS]
Definition main.qh:178
#define getcommandkey(cmd_name, command)
Definition main.qh:137
bool observe_blocked
Definition main.qh:115
int spectatee_status
the -1 disables HUD panels before CSQC receives necessary data
Definition main.qh:197
bool warmup_stage
Definition main.qh:120
int num_spectators
Definition main.qh:176
int srv_minplayers
Definition main.qh:125
bool ready_waiting_for_me
Definition main.qh:144
const int MAX_SPECTATORS
Definition main.qh:177
#define M_ARGV(x, type)
Definition events.qh:17
int missing_teams_mask
Definition stats.qh:85
string getWrappedLine(float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition util.qc:1131
string getWrappedLine_remaining
Definition util.qh:147
const float DRAWFLAG_NORMAL
float frametime
float time
string entcs_GetName(int i)
Definition ent_cs.qh:151
int wants_join
Definition ent_cs.qh:73
int entcs_GetWantsJoin(int i)
Definition ent_cs.qh:106
void HUD_Panel_LoadCvars()
Definition hud.qc:215
void HUD_Scale_Enable()
Definition hud.qc:91
void HUD_Scale_Disable()
Definition hud.qc:84
vector panel_size
Definition hud.qh:163
int teamnagger
Definition hud.qh:126
float panel_bg_padding
Definition hud.qh:174
#define HUD_Panel_DrawBg()
Definition hud.qh:55
float current_player
Definition hud.qh:185
vector panel_pos
Definition hud.qh:162
#define HUD_Write_Cvar(cvar)
Definition hud_config.qh:40
bool autocvar__hud_configure
Definition hud_config.qh:3
void HUD_InfoMessages_Export(int fh)
float autocvar_hud_panel_infomessages_group_fadetime
string get_team_list(int team_mask, string suf_col)
void HUD_InfoMessages(bool should_draw)
vector InfoMessages_drawstring(string s, vector pos, vector sz, float a, vector fontsize)
float autocvar_hud_panel_infomessages_group0
int img_cur_msg[IMG_COUNT]
float img_time[IMG_COUNT]
const int IMG_COUNT
float autocvar_hud_panel_infomessages_group_time
int img_select(int group_id)
#define InfoMessage(s)
float img_fade[IMG_COUNT]
bool autocvar_hud_panel_infomessages
bool autocvar_hud_panel_infomessages_dynamichud
bool autocvar_hud_panel_infomessages_flip
bool autocvar_cl_showspectators
#define STAT(...)
Definition stats.qh:82
float ceil(float f)
float min(float f,...)
float floor(float f)
float max(float f,...)
fadetime
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Scoreboard_UpdatePlayerTeams()
int ts_min
Definition scoreboard.qh:27
int numplayers
Definition scoreboard.qh:26
int ts_max
team size
Definition scoreboard.qh:27
vector
Definition self.qh:92
float stringwidth_colors(string s, vector theSize)
Definition string.qh:30
int myteam
Definition teams.qh:60
const int NUM_TEAM_2
Definition teams.qh:14
const int NUM_SPECTATOR
Definition teams.qh:23
string Team_ColorName(int teamid)
Definition teams.qh:89
#define Team_ColoredFullName_WithSuffixColor(teamid, suf_col)
Definition teams.qh:231
const int NUM_TEAM_4
Definition teams.qh:16
const int NUM_TEAM_3
Definition teams.qh:15
int Team_IndexToTeam(int index)
Converts team index into team value.
Definition teams.qh:169
bool teamplay
Definition teams.qh:59
string Team_ColorCode(int teamid)
Definition teams.qh:63
const int NUM_TEAM_1
Definition teams.qh:13
const vector eX
Definition vector.qh:44