Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
cl_minigames.qc
Go to the documentation of this file.
1#include "cl_minigames.qh"
2
3// Draw a square in the center of the avaliable area
4void minigame_hud_simpleboard(vector pos, vector mySize, string board_texture)
5{
6 if(panel.current_panel_bg != "0" && panel.current_panel_bg != "")
8 panel.current_panel_bg,
9 mySize + '1 1 0' * 2 * panel_bg_border,
12 drawpic(pos, board_texture, mySize, '1 1 1', panel_bg_alpha, DRAWFLAG_NORMAL);
13}
14
15// De-normalize (2D vector) v from relative coordinate inside pos mySize
17{
18 v_x = pos_x + v_x * mySize_x;
19 v_y = pos_y + v_y * mySize_y;
20 return v;
21}
22// De-normalize (2D vector) v from relative size inside pos mySize
24{
25 v_x *= mySize_x;
26 v_y *= mySize_y;
27 return v;
28}
29
30// Normalize (2D vector) v to relative coordinate inside pos mySize
32{
33 v_x = ( v_x - pos_x ) / mySize_x;
34 v_y = ( v_y - pos_y ) / mySize_y;
35 return v;
36}
37
38// Check if the mouse is inside the given area
40{
41 return mousepos_x >= pos_x && mousepos_x < pos_x + sz_x &&
42 mousepos_y >= pos_y && mousepos_y < pos_y + sz_y ;
43}
44
45string minigame_texture_skin(string skinname, string name)
46{
47 return sprintf("gfx/hud/%s/minigames/%s", skinname, name);
48}
49string minigame_texture(string name)
50{
52 if ( precache_pic(path) == "" )
53 path = minigame_texture_skin("default", name);
54 return path;
55}
56
57#define FIELD(Flags, Type, Name) \
58 MSLE_CLEAN_##Type(this.Name)
59
60#define MSLE_CLEAN_String(x) strfree(x);
61#define MSLE_CLEAN_Byte(x)
62#define MSLE_CLEAN_Char(x)
63#define MSLE_CLEAN_Short(x)
64#define MSLE_CLEAN_Long(x)
65#define MSLE_CLEAN_Coord(x)
66#define MSLE_CLEAN_Angle(x)
67#define MSLE_CLEAN_Float(x)
68#define MSLE_CLEAN_Vector(x)
69#define MSLE_CLEAN_Vector2D(x)
70
71#define MSLE(Name, Fields) \
72 void msle_entremove_##Name(entity this) \
73 { \
74 strfree(this.netname); \
75 Fields \
76 }
78#undef MSLE
79#undef FIELD
80
82{
83 LOG_DEBUG("CL Auto-cleaned: ",ftos(etof(e)), " (",e.classname,")");
84 strfree(e.netname);
85 delete(e);
86}
87
91{
92 if ( !active_minigame )
93 return;
94
95 active_minigame.minigame_event(active_minigame,"deactivate");
96 entity e = NULL;
97 while( (e = findfloat(e, minigame_id, active_minigame.minigame_id)) )
98 if ( e.minigame_autoclean )
99 {
101 }
102
105
107 {
110 }
111 else
113}
114
116{
117 if ( this == active_minigame )
119}
120
122{
123 if ( !minigame )
124 {
126 return;
127 }
128
129 if ( !minigame.descriptor || minigame.classname != "minigame" )
130 {
131 LOG_TRACE("Trying to activate unregistered minigame ",minigame.netname," in client");
132 return;
133 }
134
135 if ( minigame == active_minigame )
136 return;
137
138 if ( active_minigame )
139 {
141 }
142
143 active_minigame = minigame;
144 active_minigame.minigame_event(active_minigame,"activate");
145
148 else
149 {
152 }
153}
154
160
161string() ReadString_Raw = #366;
163{
164 return strzone(ReadString_Raw());
165}
166#define ReadString ReadString_Zoned
167#define FIELD(Flags, Type, Name) \
168 if (sf & (Flags)) \
169 this.Name = Read##Type();
170
171#define MSLE(Name, Fields) \
172 else if (this.classname == #Name) \
173 { \
174 if (sf & MINIG_SF_CREATE) \
175 { \
176 this.entremove = msle_entremove_##Name; \
177 } \
178 minigame_ent = minigame_get_owner(this.minigame_id); \
179 Fields \
180 }
181
182NET_HANDLE(ENT_CLIENT_MINIGAME, bool isnew)
183{
184 float sf = ReadByte();
185 if ( sf & MINIG_SF_CREATE )
186 {
187 this.classname = msle_classname(ReadShort());
188 this.minigame_id = ReadShort();
189 this.descriptor = ReadRegistered(Minigames);
190 this.netname = ReadString_Zoned();
191 }
192
193 entity minigame_ent = NULL;
194
195 if ( this.classname == "minigame" )
196 {
197 minigame_ent = this;
198 bool is_local = ReadByte();
199 bool activate = (is_local && active_minigame != this);
200
201 if ( sf & MINIG_SF_CREATE )
202 {
203 this.entremove = minigame_entremove;
204 if ( !this.descriptor )
205 LOG_TRACE("Got a minigame without a client-side descriptor!");
206 else
207 {
208 // copy of start_minigame logic to save networking the string
209 strcpy(this.netname, strcat(this.descriptor.netname, "_", ftos(this.minigame_id)));
210 this.minigame_event = this.descriptor.minigame_event;
211 }
212 }
213 if ( sf & MINIG_SF_UPDATE )
214 this.minigame_flags = ReadLong();
215
216 if (activate)
217 activate_minigame(this);
218 }
219 else if ( this.classname == "minigame_player" )
220 {
221 if ( sf & MINIG_SF_CREATE )
222 {
223 this.entremove = minigame_player_entremove;
224 float ent = ReadShort();
225 this.minigame_playerslot = ent;
226 //LOG_DEBUG("Player: ",entcs_GetName(ent-1));
227 if (ent == player_localnum+1)
228 minigame_self = this;
229 }
230 minigame_ent = minigame_get_owner(this.minigame_id);
231
232 if ( sf & MINIG_SF_UPDATE )
233 this.team = ReadByte();
234 }
236
237 this.descriptor.minigame_event(minigame_ent,"network_receive",this,sf);
238
239 if ( sf & MINIG_SF_CREATE )
240 {
241 LOG_DEBUG("CL Reading entity: ",ftos(etof(this)),
242 " classname:",this.classname," enttype:",ftos(this.enttype) );
243 LOG_DEBUG(" sf:",ftos(sf)," netname:",this.netname);
244 }
245 return true;
246}
247#undef ReadString
248#undef FIELD
249#undef MSLE
250
251void minigame_show_allspecs(vector boardpos, vector boardsize)
252{
253 string allspecs = "";
254 float allspecs_width = 0;
255 float max_allspecs_width = boardsize.x;
256 float max_current_spec_width = hud_fontsize.x * 5;
257 int allspecs_lines = 2;
258
259 entity e;
261 {
262 if (allspecs_width >= 0 && e.classname == "minigame_player" && e.team == C4_SPECTATOR_TEAM)
263 {
264 string current_spec = ColorTranslateRGB(entcs_GetName(e.minigame_playerslot - 1));
265 current_spec = textShortenToWidth(current_spec, max_current_spec_width, hud_fontsize, stringwidth_colors);
266 if (allspecs != "")
267 current_spec = strcat(", ", current_spec);
268
269 allspecs_width = stringwidth(allspecs, true, hud_fontsize);
270
271 float max_width = max_allspecs_width * allspecs_lines - max_current_spec_width;
272 if (allspecs_width + stringwidth(current_spec, true, hud_fontsize) < max_width)
273 allspecs = strcat(allspecs, current_spec);
274 else
275 {
276 // current_spec doesn't fit in the list
277 allspecs = strcat(allspecs, ", ...");
278 allspecs_width = -1; // skip remaining spectators
279 }
280 }
281 }
282
283 if (allspecs != "")
284 {
285 vector pos = boardpos;
286 pos.y -= panel_bg_border + hud_fontsize.y * (1.25 + allspecs_lines + 0.5);
287 minigame_drawstring_wrapped(max_allspecs_width, pos, _("Spectators:"), hud_fontsize * 1.25, '0.85 0.47 0.42', panel_fg_alpha, DRAWFLAG_NORMAL, 0);
288
289 pos.y += hud_fontsize.y * 1.25;
291 }
292}
293
295{
296 string s = getWrappedLine_remaining;
297
298 if(w <= 0)
299 {
301 return s; // the line has no size ANYWAY, nothing would be displayed.
302 }
303
304 int take_until = textLengthUpToWidth(s, w, theFontSize, tw);
305
306 if ( take_until > strlen(s) )
307 take_until = strlen(s);
308
309 int skip = 0;
310 for ( int i = 0; i < take_until; ++i )
311 if ( substring(s,i,1) == "\n" )
312 {
313 take_until = i;
314 skip = 1;
315 break;
316 }
317
318 if ( take_until > 0 || skip > 0 )
319 {
320 if ( skip == 0 && take_until < strlen(s) )
321 {
322 int last_word = take_until;
323 while(last_word > 0 && substring(s, last_word, 1) != " ")
324 --last_word;
325
326 if ( last_word != 0 )
327 {
328 take_until = last_word;
329 skip = 1;
330 }
331 }
332
333 getWrappedLine_remaining = substring(s, take_until+skip, strlen(s) - (take_until+skip));
336 else if (tw("^7", theFontSize) == 0)
338 return substring(s, 0, take_until);
339 }
340 else
341 {
343 return s;
344 }
345}
346
347vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text,
348 vector fontsize, vector color, float theAlpha, int drawflags, float align )
349{
351 vector mypos = pos;
353 {
354 string line = minigame_getWrappedLine(maxwidth,fontsize,stringwidth_nocolors);
355 if ( line == "" )
356 break;
357 mypos_x = pos_x + (maxwidth - stringwidth_nocolors(line, fontsize)) * align;
358 drawstring(mypos, line, fontsize, color, theAlpha, drawflags);
359 mypos_y += fontsize_y;
360 }
361 mypos_x = maxwidth;
362 mypos_y -= pos_y;
363 return mypos;
364}
365
367 string text, vector fontsize, float theAlpha, int drawflags, float align )
368{
370 vector mypos = pos;
372 {
373 string line = minigame_getWrappedLine(maxwidth,fontsize,stringwidth_colors);
374 if ( line == "" )
375 break;
376 mypos_x = pos_x + (maxwidth - stringwidth_colors(line, fontsize)) * align;
377 drawcolorcodedstring(mypos, line, fontsize, theAlpha, drawflags);
378 mypos_y += fontsize_y;
379 }
380 mypos_x = maxwidth;
381 mypos_y -= pos_y;
382 return mypos;
383}
384
385void minigame_drawstring_trunc(float maxwidth, vector pos, string text,
386 vector fontsize, vector color, float theAlpha, int drawflags )
387{
388 string line = textShortenToWidth(text,maxwidth,fontsize,stringwidth_nocolors);
389 drawstring(pos, line, fontsize, color, theAlpha, drawflags);
390}
391
392void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text,
393 vector fontsize, float theAlpha, int drawflags )
394{
395 string line = textShortenToWidth(text,maxwidth,fontsize,stringwidth_colors);
396 drawcolorcodedstring(pos, line, fontsize, theAlpha, drawflags);
397}
398
399void minigame_drawpic_centered( vector pos, string texture, vector sz,
400 vector color, float thealpha, int drawflags )
401{
402 drawpic( pos-sz/2, texture, sz, color, thealpha, drawflags );
403}
404
405// Workaround because otherwise variadic arguments won't work properly
406// It could be a bug in the compiler or in darkplaces
407void minigame_cmd_workaround(float dummy, string...cmdargc)
408{
409 string cmd = "cmd minigame ";
410 float i;
411 for ( i = 0; i < cmdargc; ++i )
412 cmd = strcat(cmd,...(i,string));
413 localcmd(strcat(cmd,"\n"));
414}
415
416// Prompt the player to play in the current minigame
417// (ie: it's their turn and they should get back to the minigame)
419{
421 {
422 HUD_Notify_Push(sprintf("minigames/%s/icon_notif",active_minigame.descriptor.netname),
423 _("It's your turn"), "");
424 }
425}
426
427// handle commands etc.
428REGISTER_MUTATOR(minigames, true);
429
430MUTATOR_HOOKFUNCTION(minigames, HUD_Command)
431{
432 if(MUTATOR_RETURNVALUE) { return false; } // command was already handled
433
434 if(argv(1) == "minigame")
435 {
436 if (isdemo())
437 return true; // minigames can't function properly in demo mode
440 else
442 return true;
443 }
444
445 return false;
446}
#define REGISTER_MUTATOR(...)
Definition base.qh:349
#define MUTATOR_HOOKFUNCTION(...)
Definition base.qh:394
#define MUTATOR_RETURNVALUE
Definition base.qh:384
const int C4_SPECTATOR_TEAM
Definition c4.qc:21
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
string autocvar_menu_skin
void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text, vector fontsize, float theAlpha, int drawflags)
void minigame_show_allspecs(vector boardpos, vector boardsize)
void minigame_prompt()
vector minigame_drawstring_wrapped(float maxwidth, vector pos, string text, vector fontsize, vector color, float theAlpha, int drawflags, float align)
void minigame_cmd_workaround(float dummy, string...cmdargc)
bool minigame_hud_mouse_in(vector pos, vector sz)
void minigame_hud_simpleboard(vector pos, vector mySize, string board_texture)
void deactivate_minigame()
string minigame_getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
string minigame_texture_skin(string skinname, string name)
string minigame_texture(string name)
bool auto_close_minigamemenu
vector minigame_hud_denormalize_size(vector v, vector pos, vector mySize)
vector minigame_drawcolorcodedstring_wrapped(float maxwidth, vector pos, string text, vector fontsize, float theAlpha, int drawflags, float align)
MINIGAME_SIMPLELINKED_ENTITIES void minigame_autoclean_entity(entity e)
void minigame_drawstring_trunc(float maxwidth, vector pos, string text, vector fontsize, vector color, float theAlpha, int drawflags)
void HUD_MinigameMenu_CurrentButton()
void minigame_player_entremove(entity this)
vector minigame_hud_denormalize(vector v, vector pos, vector mySize)
string() ReadString_Raw
void minigame_entremove(entity this)
vector minigame_hud_normalize(vector v, vector pos, vector mySize)
string ReadString_Zoned()
void activate_minigame(entity minigame)
void minigame_drawpic_centered(vector pos, string texture, vector sz, vector color, float thealpha, int drawflags)
entity minigame_self
entity active_minigame
#define FOREACH_MINIGAME_ENTITY(entityvar)
float minigame_playerslot
void HUD_MinigameMenu_Close(entity this, entity actor, entity trigger)
bool HUD_MinigameMenu_IsOpened()
void HUD_MinigameMenu_Open()
#define drawcolorcodedstring(position, text, scale, alpha, flag)
Definition draw.qh:30
#define drawstring(position, text, scale, rgb, alpha, flag)
Definition draw.qh:27
#define drawpic(position, pic, size, rgb, alpha, flag)
Definition draw.qh:21
string netname
Definition powerups.qc:20
int enttype
Definition main.qh:185
vector hud_fontsize
Definition main.qh:77
int team
Definition main.qh:188
string find_last_color_code(string s)
Definition util.qc:956
string textShortenToWidth(string theText, float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition util.qc:1173
float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)
Definition util.qc:884
string getWrappedLine_remaining
Definition util.qh:154
float(string s, vector size) textLengthUpToWidth_widthFunction_t
Definition util.qh:147
string classname
const float DRAWFLAG_NORMAL
float player_localnum
float player_localentnum
#define stringwidth
#define strlen
vector color
Definition dynlight.qc:15
string entcs_GetName(int i)
Definition ent_cs.qh:148
float panel_fg_alpha
Definition hud.qh:169
void HUD_Notify_Push(string icon, string attacker, string victim)
Definition notify.qc:19
float panel_bg_border
Definition hud.qh:172
const float BORDER_MULTIPLIER
Definition hud.qh:110
float panel_bg_alpha
Definition hud.qh:170
vector panel_bg_color
Definition hud.qh:165
entity panel
Definition hud.qh:147
void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
Definition draw.qh:43
#define NET_HANDLE(id, param)
Definition net.qh:15
#define ReadRegistered(r)
Definition net.qh:290
int ReadByte()
#define LOG_TRACE(...)
Definition log.qh:74
#define LOG_DEBUG(...)
Definition log.qh:78
string name
Definition menu.qh:30
void localcmd(string command,...)
float isdemo()
string substring(string s, float start, float length)
string precache_pic(string name,...)
void cmd(string command,...)
string ftos(float f)
string strzone(string s)
string argv(float n)
entity findfloat(entity start,.float field, float match)
#define MINIGAME_SIMPLELINKED_ENTITIES
Set up automatic entity read/write functionality To ensure that everything is handled automatically,...
Definition all.qh:100
entity minigame_get_owner(int id)
Definition minigames.qc:11
string msle_classname(int id)
Definition minigames.qc:121
int minigame_id
Unique ID for the minigame session, associated with all objects currently the result of etof(minigame...
Definition minigames.qh:49
int minigame_flags
Definition minigames.qh:107
const int MINIG_SF_UPDATE
Definition minigames.qh:113
const int MINIG_SF_CREATE
Definition minigames.qh:112
entity descriptor
For minigame sessions: minigame descriptor object.
Definition minigames.qh:45
#define etof(e)
Definition misc.qh:25
string string_null
Definition nil.qh:9
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define NULL
Definition post.qh:14
vector
Definition self.qh:96
ERASEABLE string ColorTranslateRGB(string s)
Definition string.qh:194
#define strfree(this)
Definition string.qh:57
#define strcpy(this, s)
Definition string.qh:51
float stringwidth_nocolors(string s, vector theSize)
Definition string.qh:35
float stringwidth_colors(string s, vector theSize)
Definition string.qh:30