Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
cl_minigames_hud.qc
Go to the documentation of this file.
1#include "cl_minigames_hud.qh"
2
3#include <client/draw.qh>
4#include <client/hud/_mod.qh>
6#include <client/mapvoting.qh>
7#include <common/ent_cs.qh>
9
10.vector colormod;
11
13{
14 // allow saving cvars that aesthetically change the panel into hud skin files
15}
16
18{
19 // allow saving cvars that aesthetically change the panel into hud skin files
20}
21
23{
24 // allow saving cvars that aesthetically change the panel into hud skin files
25}
26
28{
29 // allow saving cvars that aesthetically change the panel into hud skin files
30}
31
32// whether the mouse is over the given panel
33bool HUD_mouse_over(entity somepanel)
34{
35 vector pos = stov(cvar_string(strcat("hud_panel_", somepanel.panel_name, "_pos")));
36 vector sz = stov(cvar_string(strcat("hud_panel_", somepanel.panel_name, "_size")));
37 return mousepos_x >= pos_x*vid_conwidth && mousepos_x <= (pos_x+sz_x)*vid_conwidth &&
38 mousepos_y >= pos_y*vid_conheight && mousepos_y <= (pos_y+sz_y)*vid_conheight ;
39}
40
41// ====================================================================
42// Minigame Board
43// ====================================================================
44
45// Draws the minigame game board
47{
49 return;
50
51 entity hud_minigame = NULL;
52
54 {
55 if (!active_minigame)
56 return;
57 hud_minigame = active_minigame.descriptor;
58 }
59 else
60 hud_minigame = minigame_get_descriptor("nmm");
61
62 if ( !hud_minigame )
63 return;
64
66
67
68 vector pos, mySize;
69 pos = panel_pos;
70 mySize = panel_size;
71
72 hud_minigame.minigame_hud_board(pos,mySize);
73}
74
75// ====================================================================
76// Minigame Status
77// ====================================================================
78// Draws the minigame status panel
80{
82 return;
83
84 entity hud_minigame = NULL;
85
87 {
88 if (!active_minigame)
89 return;
90 hud_minigame = active_minigame.descriptor;
91 }
92 else
93 hud_minigame = minigame_get_descriptor("nmm");
94
95 if ( !hud_minigame )
96 return;
97
99
100
101 vector pos, mySize;
102 pos = panel_pos;
103 mySize = panel_size;
104
106 {
107 pos += '1 1 0' * panel_bg_padding;
108 mySize -= '2 2 0' * panel_bg_padding;
109 }
110
112 hud_minigame.minigame_hud_status(pos,mySize);
113}
114
115// ====================================================================
116// Minigame Menu
117// ====================================================================
118
119// Minigame menu options: list head
121// Minigame menu options: list tail
123
124// Minigame menu options: insert entry after the given location
126{
128 {
129 HUD_MinigameMenu_entries = newentry;
131 return;
132 }
133
134 newentry.list_prev = prev;
135 newentry.list_next = prev.list_next;
136 if ( prev.list_next )
137 prev.list_next.list_prev = newentry;
138 else
140 prev.list_next = newentry;
141}
142
143
144// minigame menu item uder the mouse
146
147// Click the given item
149{
150 if ( menuitem )
151 {
152 menuitem.use(menuitem, NULL, NULL);
153 }
154}
155
156// Minigame menu options: Remove the given entry
157// Precondition: the given entry is actually in the list
159{
160 // remove child items (if any)
161 if ( e.flags & 2 )
162 {
164 }
165
166 if ( e.list_prev )
167 e.list_prev.list_next = e.list_next;
168 else
169 HUD_MinigameMenu_entries = e.list_next;
170
171 if ( e.list_next )
172 e.list_next.list_prev = e.list_prev;
173 else
174 HUD_MinigameMenu_last_entry = e.list_prev;
175
178
179 delete(e);
180}
181
182// Minigame menu options: create entry
183entity HUD_MinigameMenu_SpawnEntry(entity entry, string s, vector offset, vector fontsize, vector color,void(entity, entity, entity) click)
184{
185 entry.message = s;
186 entry.origin = offset;
187 entry.size = fontsize;
188 entry.colormod = color;
189 entry.flags = 0;
190 entry.use = click;
191 panel_pos_y += fontsize_y;
192 return entry;
193}
194
195// Spawn a child entry of a collapsable entry
197{
198 vector item_fontsize = hud_fontsize*1.25;
199 vector item_offset = '1 0 0' * item_fontsize_x;
200 entity item = HUD_MinigameMenu_SpawnEntry(new(hud_minigamemenu_subentry),
201 s,item_offset,item_fontsize,'0.8 0.8 0.8', click );
202 item.owner = parent;
203 return item;
204}
205
206// Click action for Create sub-entries
208{
209 minigame_cmd("create ", this.netname);
210}
211
212// Helper click action for collapsible entries
213// returns true when you have to create the sub-entries
215{
216 entity e;
217 if ( this.flags & 2 )
218 {
220 HUD_MinigameMenu_activeitem.owner == this )
222 this.flags &= ~2;
223 for ( e = this.list_next; e != NULL && e.owner == this; e = this.list_next )
224 {
225 if ( e.flags & 2 )
227 this.list_next = e.list_next;
228 delete(e);
229 }
230 if ( this.list_next )
231 this.list_next.list_prev = this;
232 else
234 }
235 else
236 {
237 for ( e = HUD_MinigameMenu_entries; e != NULL; e = e.list_next )
238 {
239 if ( (e.flags & 2) && e.origin_x == this.origin_x)
241 }
242
243 this.flags |= 2;
244
245 return true;
246 }
247 return false;
248}
249
250// Click action for the Create menu
252{
254 {
255 entity curr;
256 entity prev = this;
257 FOREACH(Minigames, true, {
259 curr.netname = it.netname;
260 curr.model = strzone(minigame_texture(strcat(it.netname,"/icon")));
262 prev = curr;
263 });
264 }
265}
266
267// Click action for Join sub-entries
269{
270 minigame_cmd("join ",this.netname);
272}
273
274// Click action for the Join menu
276{
278 {
279 entity e = NULL;
280 entity curr;
281 entity prev = this;
282 while( (e = find(e,classname,"minigame")) )
283 {
284 if ( e != active_minigame )
285 {
287 e.netname, HUD_MinigameMenu_ClickJoin_Entry, this );
288 curr.netname = e.netname;
289 curr.model = strzone(minigame_texture(strcat(e.descriptor.netname,"/icon")));
291 prev = curr;
292 }
293 }
294 }
295}
296
297/*// Temporary placeholder for un-implemented Click actions
298void HUD_MinigameMenu_ClickNoop()
299{
300 dprint("Placeholder for ",this.message,"\n");
301}*/
302
303// Click action for Quit
305{
307 minigame_cmd("end");
308}
309
310// Click action for Invite sub-entries
312{
313 minigame_cmd("invite #",this.netname);
314}
315
316// Click action for the Invite menu
318{
320 {
321 entity e;
322 entity prev = this;
323 for(int i = 0; i < maxclients; ++i)
324 {
325 if ( player_localnum != i && playerslots[i] && entcs_GetName(i) != "" &&
327 {
330 this );
331 e.flags |= 1;
332 e.netname = strzone(ftos(i+1));
333 e.origin_x *= 2;
335 prev = e;
336 }
337 }
338 }
339}
340
342{
343 if ( active_minigame )
344 active_minigame.minigame_event(active_minigame,"menu_click",this.netname);
345}
346
347// Adds a game-specific entry to the menu
348void HUD_MinigameMenu_CustomEntry(entity parent, string menumessage, string event_arg)
349{
352 e.netname = event_arg;
354 //dprint("CustomEntry ",ftos(num_for_edict(parent))," ",menumessage," ",event_arg,"\n");
355}
356
357// Click action for the Current Game menu
359{
361 {
363 _("Quit"), HUD_MinigameMenu_ClickQuit, this ), this);
364
365 active_minigame.minigame_event(active_minigame,"menu_show",this);
366
368 _("Invite"), HUD_MinigameMenu_ClickInvite, this), this);
369 }
370}
371// Whether the minigame menu panel is open
376
377// Close the minigame menu panel
378void HUD_MinigameMenu_Close(entity this, entity actor, entity trigger)
379{
381 {
382 entity e, p;
383 for ( e = HUD_MinigameMenu_entries; e != NULL; e = p )
384 {
385 p = e.list_next;
386 delete(e);
387 }
391 }
392}
393
394// toggle a button to manage the current game
396{
397 entity e;
398 if ( active_minigame )
399 {
400 for ( e = HUD_MinigameMenu_last_entry; e != NULL; e = e.list_prev )
401 if ( e.classname == "hud_minigamemenu_exit" )
402 {
404 break;
405 }
406 entity currb = HUD_MinigameMenu_SpawnEntry(new(hud_minigamemenu_current),
407 _("Current Game"), '0 0 0', hud_fontsize*1.5,'0.7 0.84 1', HUD_MinigameMenu_ClickCurrentGame );
408 currb.model = strzone(minigame_texture(strcat(active_minigame.descriptor.netname,"/icon")));
411 }
412 else
413 {
414 entity p;
415 for ( e = HUD_MinigameMenu_last_entry; e != NULL; e = p.list_prev )
416 {
417 p = e;
418 if ( e.classname == "hud_minigamemenu_current" )
419 {
420 p = e.list_next;
421 if ( !p )
424 break;
425 }
426 }
427 for ( e = HUD_MinigameMenu_last_entry; e != NULL; e = e.list_prev )
428 if ( e.classname == "hud_minigamemenu_exit" )
429 return;
430 entity exit = HUD_MinigameMenu_SpawnEntry(new(hud_minigamemenu_exit),
431 _("Exit Menu"),'0 0 0',hud_fontsize*1.5,'0.7 0.84 1', HUD_MinigameMenu_Close);
433 }
434}
435
436// Open the minigame menu panel
438{
440 {
442 _("Create"), '0 0 0', hud_fontsize*1.5,'0.7 0.84 1', HUD_MinigameMenu_ClickCreate),
444 HUD_MinigameMenu_InsertEntry ( HUD_MinigameMenu_SpawnEntry(new(hud_minigamemenu_entry),
445 _("Join"),'0 0 0',hud_fontsize*1.5,'0.7 0.84 1', HUD_MinigameMenu_ClickJoin),
449 }
450}
451
452// Handles mouse input on to minigame menu panel
454{
455 panel = HUD_PANEL(MINIGAMEMENU);
456
458
460 {
461 panel_pos += '1 1 0' * panel_bg_padding;
462 panel_size -= '2 2 0' * panel_bg_padding;
463 }
464
465 entity e;
466
467 panel_pos_y += hud_fontsize_y*2;
468
470 vector sz;
471 for ( e = HUD_MinigameMenu_entries; e != NULL; e = e.list_next )
472 {
473 sz = eX*panel_size_x + eY*e.size_y;
474 if ( e.model )
475 sz_y = 22;
476 if ( !HUD_MinigameMenu_activeitem && mousepos_y >= panel_pos_y && mousepos_y <= panel_pos_y + sz_y )
477 {
479 }
480 panel_pos_y += sz_y;
481 }
482}
483
484// Draw a menu entry
486{
487 minigame_drawstring_trunc(panel_size_x-pos_x+panel_pos_x, pos, s,
489}
490// Draw a color-coded menu
492{
493 minigame_drawcolorcodedstring_trunc(panel_size_x-pos_x+panel_pos_x, pos, s,
495}
496
497// Minigame menu panel UI
499{
500 if (mv_active)
501 {
504 return;
505 }
506
508 return;
509
511
514
516 {
517 panel_pos += '1 1 0' * panel_bg_padding;
518 panel_size -= '2 2 0' * panel_bg_padding;
519 }
520
521 HUD_MinigameMenu_DrawEntry(panel_pos,_("Minigames"),hud_fontsize*2,'0.25 0.47 0.72');
522 panel_pos_y += hud_fontsize_y*2;
523
525 vector offset;
526 float itemh;
527 vector imgsz = '22 22 0'; // NOTE: if changed, edit where HUD_MinigameMenu_activeitem is selected
528 for ( entity e = HUD_MinigameMenu_entries; e != NULL; e = e.list_next )
529 {
530 color = e.colormod;
531
532 offset = e.origin;
533 itemh = e.size_y;
534
535 if ( e.model )
536 itemh = imgsz_y;
537
538 if ( e.flags & 2 )
539 {
540 drawfill(panel_pos, eX*panel_size_x + eY*itemh, e.colormod, panel_fg_alpha, DRAWFLAG_NORMAL);
541 color = '0 0 0';
542 }
543
544 if ( e.model )
545 {
546 drawpic( panel_pos+offset, e.model, imgsz, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
547 offset_x += imgsz_x;
548 offset_y = (imgsz_y-e.size_y) / 2;
549 }
550
551 if ( e.flags & 1 )
552 HUD_MinigameMenu_DrawColoredEntry(panel_pos+offset,e.message,e.size);
553 else
554 HUD_MinigameMenu_DrawEntry(panel_pos+offset,e.message,e.size,color);
555
557 drawfill(panel_pos, eX*panel_size_x + eY*itemh,'1 1 1', 0.25 * panel_fg_alpha, DRAWFLAG_ADDITIVE);
558
559 panel_pos_y += itemh;
560 }
561}
562
563// ====================================================================
564// Minigame Help Panel
565// ====================================================================
566
568{
570 return;
571
572 string help_message;
573
575 {
576 if (!active_minigame)
577 return;
578 help_message = active_minigame.message;
579 }
580 else
581 help_message = _("Minigame message");
582
583 if ( !help_message )
584 return;
585
587
588
589 vector pos, mySize;
590 pos = panel_pos;
591 mySize = panel_size;
592
594 {
595 pos += '1 1 0' * panel_bg_padding;
596 mySize -= '2 2 0' * panel_bg_padding;
597 }
598
599 minigame_drawcolorcodedstring_wrapped( mySize_x, pos, help_message,
601}
602
603// ====================================================================
604// Minigame Panel Input
605// ====================================================================
606float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary)
607{
608
610 return false;
611
612 if(bInputType == 3)
613 {
614 mousepos_x = nPrimary;
615 mousepos_y = nSecondary;
616 if ( active_minigame && HUD_mouse_over(HUD_PANEL(MINIGAMEBOARD)) )
617 active_minigame.minigame_event(active_minigame,"mouse_moved",mousepos);
618 return true;
619 }
620
621 if(bInputType == 2)
622 {
623 if ( active_minigame && HUD_mouse_over(HUD_PANEL(MINIGAMEBOARD)) )
624 active_minigame.minigame_event(active_minigame,"mouse_moved",mousepos);
625 return false;
626 }
627
628 // at this point bInputType can only be 0 or 1 (key pressed or released)
629 bool key_pressed = (bInputType == 0);
630
631 if(key_pressed) {
632 if(nPrimary == K_ALT) hudShiftState |= S_ALT;
633 if(nPrimary == K_CTRL) hudShiftState |= S_CTRL;
634 if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
635 if(nPrimary == K_MOUSE1) mouseClicked |= S_MOUSE1;
636 if(nPrimary == K_MOUSE2) mouseClicked |= S_MOUSE2;
637 }
638 else {
639 if(nPrimary == K_ALT) hudShiftState &= ~S_ALT;
640 if(nPrimary == K_CTRL) hudShiftState &= ~S_CTRL;
641 if(nPrimary == K_SHIFT) hudShiftState &= ~S_SHIFT;
642 if(nPrimary == K_MOUSE1) mouseClicked &= ~S_MOUSE1;
643 if(nPrimary == K_MOUSE2) mouseClicked &= ~S_MOUSE2;
644 }
645
646 // allow some binds
647 string con_keys = findkeysforcommand("toggleconsole", 0);
648 int keys = tokenize(con_keys); // findkeysforcommand returns data for this
649 int i;
650 for (i = 0; i < keys; ++i)
651 {
652 if(nPrimary == stof(argv(i)))
653 return false;
654 }
655
656 if ( active_minigame )
657 {
658 string device = "";
659 string action = key_pressed ? "pressed" : "released";
660 if ( nPrimary >= K_MOUSE1 && nPrimary <= K_MOUSE16 )
661 {
662 if ( HUD_mouse_over(HUD_PANEL(MINIGAMEBOARD)) )
663 device = "mouse";
664 }
665 else
666 device = "key";
667
668 if ( device && active_minigame.minigame_event(
669 active_minigame,strcat(device,"_",action),nPrimary) )
670 return true;
671 }
672
673 if ( nPrimary == K_MOUSE2 )
674 {
675 return true;
676 }
677 if ( nPrimary == K_MOUSE1 )
678 {
679 if (!key_pressed)
680 return true;
683 return true;
684 }
685 if ( nPrimary == K_UPARROW || nPrimary == K_KP_UPARROW )
686 {
687 if (!key_pressed)
688 return true;
691 else
693 return true;
694 }
695 else if ( nPrimary == K_DOWNARROW || nPrimary == K_KP_DOWNARROW )
696 {
697 if (!key_pressed)
698 return true;
701 else
703 return true;
704 }
705 else if ( nPrimary == K_HOME || nPrimary == K_KP_HOME )
706 {
707 if (!key_pressed)
708 return true;
710 return true;
711 }
712 else if ( nPrimary == K_END || nPrimary == K_KP_END )
713 {
714 if (!key_pressed)
715 return true;
717 return true;
718 }
719 else if ( nPrimary == K_KP_ENTER || nPrimary == K_ENTER || nPrimary == K_SPACE )
720 {
721 if (!key_pressed)
722 return true;
724 return true;
725 }
726 else if ( nPrimary == K_ESCAPE )
727 {
728 if (!key_pressed)
729 return true;
731 return true;
732 }
733
734 return false;
735}
736
entity parent
Definition animhost.qc:7
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text, vector fontsize, float theAlpha, int drawflags)
void deactivate_minigame()
string minigame_texture(string name)
vector minigame_drawcolorcodedstring_wrapped(float maxwidth, vector pos, string text, vector fontsize, float theAlpha, int drawflags, float align)
void minigame_drawstring_trunc(float maxwidth, vector pos, string text, vector fontsize, vector color, float theAlpha, int drawflags)
entity active_minigame
#define minigame_cmd(...)
float minigame_playerslot
entity HUD_MinigameMenu_entries
void HUD_MinigameMenu_ClickCreate_Entry(entity this, entity actor, entity trigger)
void HUD_MinigameMenu_MouseInput()
void HUD_MinigameMenu_ClickInvite(entity this, entity actor, entity trigger)
bool HUD_MinigameMenu_Click_ExpandCollapse(entity this)
void HUD_MinigameMenu_EraseEntry(entity e)
void HUD_MinigameStatus_Export(int fh)
void HUD_MinigameMenu_DrawColoredEntry(vector pos, string s, vector fontsize)
entity HUD_MinigameMenu_last_entry
void HUD_MinigameMenu_Click(entity menuitem)
void HUD_Minigame_Mouse()
void HUD_MinigameBoard_Export(int fh)
entity HUD_MinigameMenu_activeitem
void HUD_MinigameMenu_CustomEntry(entity parent, string menumessage, string event_arg)
void HUD_MinigameMenu_ClickJoin(entity this, entity actor, entity trigger)
void HUD_MinigameMenu_ClickInvite_Entry(entity this, entity actor, entity trigger)
entity HUD_MinigameMenu_SpawnEntry(entity entry, string s, vector offset, vector fontsize, vector color, void(entity, entity, entity) click)
void HUD_MinigameMenu_ClickCustomEntry(entity this, entity actor, entity trigger)
bool HUD_mouse_over(entity somepanel)
void HUD_MinigameStatus()
void HUD_MinigameMenu_Close(entity this, entity actor, entity trigger)
void HUD_MinigameMenu_ClickCurrentGame(entity this, entity actor, entity trigger)
void HUD_MinigameHelp()
void HUD_MinigameMenu_CurrentButton()
void HUD_MinigameMenu_ClickQuit(entity this, entity actor, entity trigger)
void HUD_MinigameMenu_InsertEntry(entity newentry, entity prev)
entity HUD_MinigameMenu_SpawnSubEntry(string s, void(entity, entity, entity) click, entity parent)
bool HUD_MinigameMenu_IsOpened()
void HUD_MinigameMenu_Open()
void HUD_MinigameMenu_DrawEntry(vector pos, string s, vector fontsize, vector color)
float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary)
void HUD_MinigameHelp_Export(int fh)
void HUD_MinigameMenu_ClickCreate(entity this, entity actor, entity trigger)
void HUD_MinigameBoard()
void HUD_MinigameMenu()
void HUD_MinigameMenu_ClickJoin_Entry(entity this, entity actor, entity trigger)
void HUD_MinigameMenu_Export(int fh)
#define drawpic(position, pic, size, rgb, alpha, flag)
Definition draw.qh:21
#define drawfill(position, size, rgb, alpha, flag)
Definition draw.qh:36
string netname
Definition powerups.qc:20
vector colormod
Definition powerups.qc:21
entity playerslots[255]
Definition main.qh:84
float ping
Definition main.qh:169
vector hud_fontsize
Definition main.qh:77
bool mv_active
Definition mapvoting.qh:19
string classname
float flags
const float DRAWFLAG_NORMAL
float maxclients
const float DRAWFLAG_ADDITIVE
float player_localnum
vector color
Definition dynlight.qc:15
string entcs_GetName(int i)
Definition ent_cs.qh:151
void HUD_Panel_LoadCvars()
Definition hud.qc:215
void HUD_Scale_Disable()
Definition hud.qc:84
vector panel_size
Definition hud.qh:163
float panel_fg_alpha
Definition hud.qh:169
#define HUD_PANEL(NAME)
Definition hud.qh:52
const int S_SHIFT
Definition hud.qh:129
int hudShiftState
Definition hud.qh:128
const int S_ALT
Definition hud.qh:131
float panel_bg_padding
Definition hud.qh:174
#define HUD_Panel_DrawBg()
Definition hud.qh:55
vector panel_pos
Definition hud.qh:162
vector mousepos
Definition hud.qh:103
entity panel
Definition hud.qh:147
const int S_CTRL
Definition hud.qh:130
const int S_MOUSE1
Definition hud_config.qh:10
bool autocvar__hud_configure
Definition hud_config.qh:3
int mouseClicked
Definition hud_config.qh:13
const int S_MOUSE2
Definition hud_config.qh:11
prev
Definition all.qh:71
#define FOREACH(list, cond, body)
Definition iter.qh:19
float K_SHIFT
Definition keycodes.qc:22
float K_MOUSE16
Definition keycodes.qc:146
float K_UPARROW
Definition keycodes.qc:15
float K_DOWNARROW
Definition keycodes.qc:16
float K_MOUSE1
Definition keycodes.qc:129
float K_CTRL
Definition keycodes.qc:21
float K_KP_UPARROW
Definition keycodes.qc:64
float K_SPACE
Definition keycodes.qc:10
float K_ALT
Definition keycodes.qc:20
float K_ENTER
Definition keycodes.qc:8
float K_KP_HOME
Definition keycodes.qc:62
float K_KP_DOWNARROW
Definition keycodes.qc:53
float K_MOUSE2
Definition keycodes.qc:130
float K_HOME
Definition keycodes.qc:41
float K_KP_ENTER
Definition keycodes.qc:74
float K_END
Definition keycodes.qc:42
float K_KP_END
Definition keycodes.qc:51
float K_ESCAPE
Definition keycodes.qc:9
noref float vid_conwidth
Definition draw.qh:8
noref float vid_conheight
Definition draw.qh:9
float stof(string val,...)
entity find(entity start,.string field, string match)
vector stov(string s)
const string cvar_string(string name)
string ftos(float f)
float tokenize(string s)
string strzone(string s)
string argv(float n)
entity findfloat(entity start,.float field, float match)
entity minigame_get_descriptor(string id)
Definition minigames.qc:5
entity list_next
Definition minigames.qh:6
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define NULL
Definition post.qh:14
vector
Definition self.qh:92
const vector eY
Definition vector.qh:45
const vector eX
Definition vector.qh:44