Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
quickmenu.qc
Go to the documentation of this file.
1#include "quickmenu.qh"
2
3#include <client/draw.qh>
4#include <client/hud/_mod.qh>
5#include <client/mapvoting.qh>
6#include <common/ent_cs.qh>
8#include <client/view.qh>
9
10// QuickMenu (#23)
11
13{
14 // allow saving cvars that aesthetically change the panel into hud skin files
15 HUD_Write_Cvar("hud_panel_quickmenu_align");
16}
17
18// QUICKMENU_MAXLINES must be <= 10
19const int QUICKMENU_MAXLINES = 10;
20// visible entries are loaded from QuickMenu_Buffer into QuickMenu_Page_* arrays
30// all the entries are loaded into QuickMenu_Buffer
31// each entry (submenu or command) is composed of 2 entries
32const int QUICKMENU_MAXENTRIES = 256;
39
40// QuickMenu_Buffer are labeled with these tags
41const string QM_TAG_TITLE = "T";
42const string QM_TAG_SUBMENU = "S";
43const string QM_TAG_COMMAND = "C";
44const string QM_TAG_KCOMMAND = "K";
45const string QM_TAG_PLCOMMAND = "P";
46
47// QuickMenu_Page_Command_Type
48const int QM_PCT_NONE = 0;
49const int QM_PCT_TOGGLE = 1;
50const int QM_PCT_KEEP = 2;
51
52#define QuickMenu_Buffer_Set(tag, string) bufstr_set(QuickMenu_Buffer, QuickMenu_Buffer_Size, strcat(tag, string))
53#define QuickMenu_Buffer_Get() bufstr_get(QuickMenu_Buffer, QuickMenu_Buffer_Index)
54
55void QuickMenu_Entry_WithTag(string title, string command, string tag)
56{
58 {
61 QuickMenu_Buffer_Set(tag, command);
62 }
64}
65
66#define QUICKMENU_ENTRY_TAG(title, command, tag) QuickMenu_Entry_WithTag(title, command, tag);
67
68#define QUICKMENU_ENTRY(title, command) QUICKMENU_ENTRY_TAG(title, command, QM_TAG_COMMAND)
69
70// special entries are shown with a different color
71#define QUICKMENU_ENTRY_SPECIAL(title, command) QUICKMENU_ENTRY(title, strcat("\n", command))
72
73
78
79// if s1 is not empty s will be displayed as command otherwise as submenu
80void QuickMenu_Page_LoadEntry(int i, string s, string s1)
81{
82 TC(int, i);
83 //LOG_INFOF("^xc80 entry %d: %s, %s\n", i, s, s1);
86}
87
95
97{
98 return (mv_active
99 || intermission_time == time // close upon game over, can still be opened during intermission
104}
105
106// returns true if succeded, false otherwise
107bool QuickMenu_Open(string mode, string submenu, string file)
108{
111 return false;
112
113 int fh = -1;
114
115 if (mode == "")
116 {
117 if (file == "" || file == "0")
118 mode = "default";
119 else
120 mode = "file";
121 }
122
123 if (mode == "default")
124 {
126 {
127 mode = "file";
129 }
130 }
131
132 if (mode == "file")
133 {
134 if (file == "" || file == "0")
135 LOG_INFO("No file name is set in hud_panel_quickmenu_file, loading default quickmenu");
136 else
137 {
138 fh = fopen(file, FILE_READ);
139 if (fh < 0)
140 LOG_INFOF("Couldn't open file \"%s\", loading default quickmenu", file);
141 }
142 if (fh < 0)
143 mode = "default";
144 }
145
146 if (mode == "default")
147 {
149 if (QuickMenu_Buffer < 0)
150 return false;
151
152 QuickMenu_Default(submenu);
153 }
154 else if (mode == "file")
155 {
157 if (QuickMenu_Buffer < 0)
158 {
159 fclose(fh);
160 return false;
161 }
162
164 string s;
166 {
167 // first skip invalid entries, so we don't check them anymore
168 int argc;
169 argc = tokenize_console(s);
170 if (argc == 0 || argv(0) == "")
171 continue;
172 if (argc == 1)
174 else if (argc == 2)
175 {
176 if (argv(1) == "")
177 continue;
181 }
182 else if (argc == 3 && argv(2) == "KEEP_OPEN")
183 {
184 if (argv(1) == "")
185 continue;
189 }
190 else if (argc == 3)
191 {
192 // check for special keywords
193 float teamplayers = 0, without_me = 0;
194 switch (argv(2))
195 {
196 case "ALLPLAYERS_BUT_ME": without_me = 1; // fall through
197 case "ALLPLAYERS": teamplayers = 0; break;
198 case "OWNTEAMPLAYERS_BUT_ME": without_me = 1; // fall through
199 case "OWNTEAMPLAYERS": teamplayers = 1; break;
200 case "ENEMYTEAMPLAYERS": teamplayers = 2; break;
201 default: continue;
202 }
203
205 {
208 QuickMenu_Buffer_Set(QM_TAG_TITLE, strcat(ftos(teamplayers), ftos(without_me))); // put PLCOMMAND arguments in the title string
213 }
214 }
216 }
217 fclose(fh);
218
219 // forcedly add this entry
221 {
222 string prev_value = cvar_string("hud_panel_quickmenu_server_is_default");
223 QUICKMENU_ENTRY_SPECIAL(_("Standard quick menu"), sprintf("hud_panel_quickmenu_server_is_default 0; quickmenu; wait; quickmenu; wait; hud_panel_quickmenu_server_is_default \"%s\"", prev_value))
224 }
225 }
226 else
227 {
228 LOG_WARNF("Unrecognized mode %s", mode);
229 return false;
230 }
231
232 if (QuickMenu_Buffer_Size <= 0)
233 {
234 buf_del(QuickMenu_Buffer);
235 QuickMenu_Buffer = -1;
236 return false;
237 }
238
239 if (mode == "file")
240 QuickMenu_Page_Load(submenu, 0);
241 else
242 QuickMenu_Page_Load("", 0);
243
244 mouseClicked = 0;
245 hudShiftState = 0;
246
248
250 return true;
251}
252
254{
255 if (QuickMenu_Buffer >= 0)
256 {
257 buf_del(QuickMenu_Buffer);
258 QuickMenu_Buffer = -1;
260 }
261}
262
273
274// It assumes submenu open tag is already detected
275void QuickMenu_skip_submenu(string submenu)
276{
277 string z_submenu = string_null;
278 strcpy(z_submenu, submenu);
280 {
281 string s = QuickMenu_Buffer_Get();
282 if (substring(s, 0, 1) != QM_TAG_SUBMENU)
283 continue;
284 if (substring(s, 1, -1) == z_submenu) // submenu end
285 break;
287 }
288 strfree(z_submenu);
289}
290
292{
293 return QuickMenu_Page_Entries > 0;
294}
295
296bool HUD_Quickmenu_PlayerListEntries_Create(string cmd, int teamplayers, bool without_me)
297{
298 TC(int, teamplayers); TC(bool, without_me);
299 for (int i = 0; i < QUICKMENU_MAXLINES; ++i)
302
304 if (QuickMenu_Buffer < 0)
305 return false;
306
307 HUD_Quickmenu_PlayerListEntries(cmd, teamplayers, without_me);
308
309 if (QuickMenu_Buffer_Size <= 0)
310 {
311 buf_del(QuickMenu_Buffer);
312 QuickMenu_Buffer = -1;
313 return false;
314 }
315 return true;
316}
317
318// new_page 0 means page 0, new_page != 0 means next page
320bool QuickMenu_Page_Load(string target_submenu, bool new_page)
321{
322 TC(bool, new_page);
323
325 if (new_page == 0)
326 QuickMenu_Page = 0;
327 else
329
330 string z_submenu = strzone(target_submenu);
332
335
337 string s = string_null;
338 if (z_submenu != "")
339 {
340 // skip everything until the submenu open tag is found
342 {
344 if (substring(s, 0, 1) == QM_TAG_SUBMENU && substring(s, 1, -1) == z_submenu)
345 {
346 //LOG_INFOF("^3 beginning of %s\n", z_submenu);
348 break; // target_submenu found!
349 }
350 //LOG_INFOF("^1 skipping %s\n", s);
351 }
353 LOG_WARNF("Couldn't find submenu \"%s\"", z_submenu);
354 }
355
356 // only the last page can contain up to QUICKMENU_MAXLINES entries
357 // the other ones contain only (QUICKMENU_MAXLINES - 2) entries
358 // so that the panel can show an empty row and "Continue..."
359 float first_entry = QuickMenu_Page * (QUICKMENU_MAXLINES - 2);
360 int entry_num = 0; // counts entries in target_submenu
362 {
364
365 if (z_submenu != "" && substring(s, 1, -1) == z_submenu)
366 {
367 //LOG_INFOF("^3 end of %s\n", z_submenu);
368 break;
369 }
370
371 if (entry_num >= first_entry)
372 {
377 {
380 QuickMenu_IsLastPage = false;
381 break;
382 }
383 }
384
385 // NOTE: entries are loaded starting from 1, not from 0
386 if (substring(s, 0, 1) == QM_TAG_SUBMENU)
387 {
388 if (entry_num >= first_entry)
391 }
392 else if (substring(s, 0, 1) == QM_TAG_TITLE)
393 {
395 if (entry_num >= first_entry)
396 {
397 string cmd = QuickMenu_Buffer_Get();
398 string command_code = substring(cmd, 0, 1);
399 if (command_code == QM_TAG_COMMAND)
400 {
401 cmd = substring(cmd, 1, -1);
403 }
404 else if (command_code == QM_TAG_KCOMMAND)
405 {
406 cmd = substring(cmd, 1, -1);
408 }
409 else if (command_code == QM_TAG_PLCOMMAND)
410 {
411 // throw away the current quickmenu buffer and load a new one
412 cmd = substring(cmd, 1, -1);
413 strunzone(z_submenu);
415 return QuickMenu_Page_Load("", 0);
417 return false;
418 }
419
421 if (argv(1) && argv(0) == "toggle")
423
425 }
426 }
427
428 ++entry_num;
429 }
430 strunzone(z_submenu);
431 if (QuickMenu_Page_Entries == 0)
432 {
434 return false;
435 }
437 return true;
438}
439
441{
442 TC(int, num);
444 {
445 if (num < 0 || num >= QUICKMENU_MAXLINES)
446 return false;
447 if (num == QUICKMENU_MAXLINES - 1)
448 return false;
449 if (num == 0)
450 {
452 return false;
453 }
454 }
455 else if (num <= 0 || num > QuickMenu_Page_Entries)
456 return false;
457
458 if (QuickMenu_Page_Command[num] != "")
459 {
461 localcmd(strcat("\n", QuickMenu_Page_Command[num], "\n"));
464 return false;
465 else
466 return true;
467 }
468 if (QuickMenu_Page_Description[num] != "")
470 return false;
471}
472
485
486bool QuickMenu_InputEvent(int bInputType, float nPrimary, float nSecondary)
487{
488 TC(int, bInputType);
489
491 return false;
492
493 if (bInputType == 3)
494 {
495 mousepos.x = nPrimary;
496 mousepos.y = nSecondary;
497 return true;
498 }
499
500 if (bInputType == 2)
501 return false;
502
503 // at this point bInputType can only be 0 or 1 (key pressed or released)
504 bool key_pressed = bInputType == 0;
505
506 int hudShiftState_prev = hudShiftState;
507 int mouseClicked_prev = mouseClicked;
508 if (key_pressed)
509 {
510 if (nPrimary == K_ALT) hudShiftState |= S_ALT;
511 if (nPrimary == K_CTRL) hudShiftState |= S_CTRL;
512 if (nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
513 if (nPrimary == K_MOUSE1) mouseClicked |= S_MOUSE1;
514 if (nPrimary == K_MOUSE2) mouseClicked |= S_MOUSE2;
515 }
516 else
517 {
518 if (nPrimary == K_ALT) hudShiftState &= ~S_ALT;
519 if (nPrimary == K_CTRL) hudShiftState &= ~S_CTRL;
520 if (nPrimary == K_SHIFT) hudShiftState &= ~S_SHIFT;
521 if (nPrimary == K_MOUSE1) mouseClicked &= ~S_MOUSE1;
522 if (nPrimary == K_MOUSE2) mouseClicked &= ~S_MOUSE2;
523 }
524
525 if (nPrimary == K_ESCAPE && key_pressed)
527 else if (nPrimary >= '0' && nPrimary <= '9' && key_pressed)
529 else if (hudShiftState_prev == hudShiftState && mouseClicked_prev == mouseClicked)
530 {
531 // allow console bind to work
532 string con_keys = findkeysforcommand("toggleconsole", 0);
533 int keys = tokenize(con_keys); // findkeysforcommand returns data for this
534 for (int i = 0; i < keys; ++i)
535 if (nPrimary == stof(argv(i)))
536 return false; // hit console bind
537 if (key_pressed)
539 return false;
540 }
541
542 return true;
543}
544
547{
548 if (mv_active)
549 return;
550
552 {
554 return;
555 }
556
557 panel = HUD_PANEL(QUICKMENU);
559
561 {
562 panel_pos += '1 1 0' * panel_bg_padding;
563 panel_size -= '2 2 0' * panel_bg_padding;
564 }
565
566 vector fontsize = '1 1 0' * (panel_size.y / QUICKMENU_MAXLINES);
567 float first_entry_pos = panel_pos.y + ((QUICKMENU_MAXLINES - QuickMenu_Page_Entries) * fontsize.y) * 0.5;
568 float entries_height = panel_size.y - ((QUICKMENU_MAXLINES - QuickMenu_Page_Entries) * fontsize.y);
569
570 if (mousepos.x >= panel_pos.x && mousepos.y >= first_entry_pos && mousepos.x <= panel_pos.x + panel_size.x && mousepos.y <= first_entry_pos + entries_height)
571 {
572 int entry_num = min(QuickMenu_Page_Entries - 1, floor((mousepos.y - first_entry_pos) / fontsize.y));
573 if (entry_num != entry_num_prev)
574 {
576 entry_num_prev = entry_num;
577 }
578 if (QuickMenu_IsLastPage || entry_num != QUICKMENU_MAXLINES - 2)
579 {
581 QuickMenu_Page_ActiveEntry((entry_num < QUICKMENU_MAXLINES - 1) ? entry_num + 1 : 0);
582
584 {
585 vector entry_pos = panel_pos;
586 entry_pos.y = first_entry_pos + entry_num * fontsize.y;
589 color = '0.5 1 0.5';
590 else if (hudShiftState & S_CTRL)
591 color = '1 1 0.3';
592 else
593 color = '1 1 1';
594 drawfill(entry_pos, vec2(panel_size.x, fontsize.y), color, 0.2, DRAWFLAG_NORMAL);
595 }
596 }
597 }
598}
599
600void HUD_Quickmenu_DrawEntry(vector pos, string desc, string option, vector fontsize)
601{
602 float desc_width = panel_size.x;
603 if (option)
604 {
605 string pic = strcat(hud_skin_path, "/", option);
606 if (precache_pic(pic) == "")
607 pic = strcat("gfx/hud/default/", option);
608 vector option_size = '1 1 0' * fontsize.y * 0.8;
609 desc_width -= option_size.x;
610 drawpic(pos + vec2(desc_width, (fontsize.y - option_size.y) / 2), pic, option_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE);
611 desc_width -= fontsize.x / 4;
612 }
613 string entry = textShortenToWidth(desc, desc_width, fontsize, stringwidth_colors);
615 {
616 float real_desc_width = stringwidth_colors(entry, fontsize);
617 float offset = (desc_width - real_desc_width) * min(autocvar_hud_panel_quickmenu_align, 1);
618
619 if (option)
620 {
621 // when there's enough room align description regardless the checkbox
622 float extra_offset = (panel_size.x - desc_width) * min(autocvar_hud_panel_quickmenu_align, 1);
623 if (offset + real_desc_width + extra_offset < desc_width)
624 offset += extra_offset;
625 else
626 offset = max(0, desc_width - real_desc_width);
627 }
628 drawcolorcodedstring(pos + eX * offset, entry, fontsize, panel_fg_alpha, DRAWFLAG_ADDITIVE);
629 }
630 else
632}
633
635{
637 {
639 return;
640
642 {
644 return;
645 }
646 }
647 else
648 {
649 if (!QuickMenu_IsOpened())
650 {
656 // although real command doesn't matter here, it must not be empty
657 // otherwise the entry is displayed like a submenu
662 QuickMenu_IsLastPage = false;
663 }
664 }
665
667
670
672 {
673 panel_pos += '1 1 0' * panel_bg_padding;
674 panel_size -= '2 2 0' * panel_bg_padding;
675 }
676
677 string color;
678 vector fontsize = '1 1 0' * (panel_size.y / QUICKMENU_MAXLINES);
679
681 {
682 color = "^5";
683 HUD_Quickmenu_DrawEntry(panel_pos + eY * (panel_size.y - fontsize.y), sprintf("%d: %s%s", 0, color, _("Continue...")), string_null, fontsize);
684 }
685 else
686 panel_pos.y += ((QUICKMENU_MAXLINES - QuickMenu_Page_Entries) * fontsize.y) / 2;
687
688 for (int i = 1; i <= QuickMenu_Page_Entries; ++i)
689 {
690 if (QuickMenu_Page_Description[i] == "")
691 break;
692 string option = string_null;
693 if (QuickMenu_Page_Command[i] == "")
694 color = "^4";
695 else
696 {
697 if (substring(QuickMenu_Page_Command[i], 0, 1) == "\n")
698 color = "^6"; // special command
699 else
700 color = "^3";
701 if (QuickMenu_Page_Command_Type[i] == QM_PCT_TOGGLE) // toggle command
702 {
703 int end = strstrofs(QuickMenu_Page_Command[i], ";", 0);
704 if (end < 0)
706 else
708
709 if (argv(1) && argv(0) == "toggle")
710 {
711 // "enable feature xxx" "toggle xxx" (or "toggle xxx 1 0")
712 // "disable feature xxx" "toggle xxx 0 1"
713 float ON_value = 1, OFF_value = 0;
714 if (argv(2))
715 ON_value = stof(argv(2));
716
717 if (argv(3))
718 OFF_value = stof(argv(3));
719 else
720 OFF_value = !ON_value;
721
722 float value = cvar(argv(1));
723 if (value == ON_value)
724 option = "checkbox_checked";
725 else if (value == OFF_value)
726 option = "checkbox_empty";
727 else
728 option = "checkbox_undefined";
729 }
730 }
731 }
732 HUD_Quickmenu_DrawEntry(panel_pos, sprintf("%d: %s%s", i, color, QuickMenu_Page_Description[i]), option, fontsize);
733
735 drawfill(panel_pos, vec2(panel_size.x, fontsize.y), '0.5 1 0.5', 0.2, DRAWFLAG_NORMAL);
736
737 panel_pos.y += fontsize.y;
738 }
739
741 {
743 {
747 }
752 }
753}
754
755
756#define QUICKMENU_SMENU(submenu, eng_submenu) { \
757 if (target_submenu == eng_submenu && target_submenu_found) \
758 return; /* target_submenu entries are now loaded, exit */ \
759 if (QuickMenu_Buffer_Size < QUICKMENU_BUFFER_MAXENTRIES) \
760 QuickMenu_Buffer_Set(QM_TAG_SUBMENU, submenu); \
761 ++QuickMenu_Buffer_Size; \
762 if (target_submenu == eng_submenu && !target_submenu_found) \
763 { \
764 QuickMenu_Buffer_Size = 0; /* enable load of next entries */ \
765 target_submenu_found = true; \
766 } \
767}
768
769#define QUICKMENU_SMENU_PL(submenu, eng_submenu, command, teamplayers, without_me) { \
770 if (QuickMenu_Buffer_Size + 3 < QUICKMENU_BUFFER_MAXENTRIES) \
771 { \
772 QUICKMENU_SMENU(submenu, eng_submenu) \
773 QuickMenu_Buffer_Set(QM_TAG_TITLE, strcat(ftos(teamplayers), ftos(without_me))); \
774 ++QuickMenu_Buffer_Size; \
775 QuickMenu_Buffer_Set(QM_TAG_PLCOMMAND, command); \
776 ++QuickMenu_Buffer_Size; \
777 QUICKMENU_SMENU(submenu, eng_submenu) \
778 } \
779}
780
781
782
783// useful to Translate a string inside the Command
784#define QUICKMENU_ENTRY_TC(title, command, text, translated_text) { \
785 if (prvm_language == "en") \
786 { \
787 tc_title = title; \
788 tc_cmd = sprintf(command, text); \
789 } \
790 else if (!autocvar_hud_panel_quickmenu_translatecommands || translated_text == text) \
791 { \
792 tc_title = strcat("(en)", title); \
793 tc_cmd = sprintf(command, text); \
794 } \
795 else \
796 { \
797 tc_title = strcat("(", prvm_language, ")", title); \
798 tc_cmd = sprintf(command, translated_text); \
799 } \
800 QUICKMENU_ENTRY(tc_title, tc_cmd) \
801}
802
803void HUD_Quickmenu_PlayerListEntries(string cmd, int teamplayers, bool without_me)
804{
805 TC(int, teamplayers); TC(bool, without_me);
806 if (teamplayers && !team_count)
807 return;
808
810 for (entity pl = players.sort_next; pl; pl = pl.sort_next)
811 {
812 if (teamplayers == 1 && (pl.team != myteam || pl.team == NUM_SPECTATOR)) // only own team players
813 continue;
814 if (teamplayers == 2 && (pl.team == myteam || pl.team == NUM_SPECTATOR)) // only enemy team players
815 continue;
816 if (without_me && pl.sv_entnum == player_localnum)
817 continue;
818 QUICKMENU_ENTRY(strcat("^7", entcs_GetName(pl.sv_entnum)), sprintf(cmd, entcs_GetName(pl.sv_entnum)))
819 }
820
821 return;
822}
823
824
825// Specifying target_submenu, this function only loads entries inside target_submenu
826// NOTE: alternatively we could have loaded the whole default quickmenu and
827// then called QuickMenu_Page_Load(target_submenu, 0);
828// but this sytem is more reliable since we can always refer to target_submenu
829// with the English title even if a translation is active
830void QuickMenu_Default(string target_submenu)
831{
832 bool target_submenu_found = false;
833 if (target_submenu != "")
834 QuickMenu_Buffer_Size = QUICKMENU_BUFFER_MAXENTRIES; // forbids load of next entries until target_submenu
835
836 string tc_title;
837 string tc_cmd;
838
839 QUICKMENU_SMENU(_("Chat"), "Chat")
840 QUICKMENU_SMENU_PL(CTX(_("QMCMD^Send public message to")), "Send public message to", "commandmode say %s:^7", 0, 1)
841 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^nice one")), "say %s", ":-) / nice one", CTX(_("QMCMD^:-) / nice one")))
842 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^good game")), "say %s", "good game", CTX(_("QMCMD^good game")))
843 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^hi / good luck")), "say %s", "hi / good luck and have fun", CTX(_("QMCMD^hi / good luck and have fun")))
844 if (prvm_language != "en")
845 QUICKMENU_ENTRY(CTX(_("QMCMD^Send in English")), "toggle hud_panel_quickmenu_translatecommands 0 1; quickmenu; wait; quickmenu default Chat")
846 QUICKMENU_SMENU(_("Chat"), "Chat")
847
848 if (teamplay)
849 {
850 QUICKMENU_SMENU(CTX(_("QMCMD^Team chat")), "Team chat")
851 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^strength soon")), "say_team %s", "strength soon", CTX(_("QMCMD^strength soon")))
852 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^free item, icon")), "say_team %s; g_waypointsprite_team_here_p", "free item %x^7 (l:%y^7)", CTX(_("QMCMD^free item %x^7 (l:%y^7)")))
853 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^took item, icon")), "say_team %s; g_waypointsprite_team_here", "took item (l:%l^7)", CTX(_("QMCMD^took item (l:%l^7)")))
854 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^negative")), "say_team %s", "negative", CTX(_("QMCMD^negative")))
855 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^positive")), "say_team %s", "positive", CTX(_("QMCMD^positive")))
856 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^need help, icon")), "say_team %s; g_waypointsprite_team_helpme; cmd voice needhelp", "need help (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)", CTX(_("QMCMD^need help (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)")))
857 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^enemy seen, icon")), "say_team %s; g_waypointsprite_team_danger_p; cmd voice incoming", "enemy seen (l:%y^7)", CTX(_("QMCMD^enemy seen (l:%y^7)")))
858 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^flag seen, icon")), "say_team %s; g_waypointsprite_team_here_p; cmd voice seenflag", "flag seen (l:%y^7)", CTX(_("QMCMD^flag seen (l:%y^7)")))
859 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^defending, icon")), "say_team %s; g_waypointsprite_team_here", "defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)", CTX(_("QMCMD^defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)")))
860 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^roaming, icon")), "say_team %s; g_waypointsprite_team_here", "roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)", CTX(_("QMCMD^roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)")))
861 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^attacking, icon")), "say_team %s; g_waypointsprite_team_here", "attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)", CTX(_("QMCMD^attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)")))
862 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^killed flagcarrier, icon")), "say_team %s; g_waypointsprite_team_here_p", "killed flagcarrier (l:%y^7)", CTX(_("QMCMD^killed flagcarrier (l:%y^7)")))
863 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^dropped flag, icon")), "say_team %s; g_waypointsprite_team_here_d", "dropped flag (l:%d^7)", CTX(_("QMCMD^dropped flag (l:%d^7)")))
864 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^drop weapon, icon")), "say_team %s; g_waypointsprite_team_here; wait; dropweapon", "dropped gun %w^7 (l:%l^7)", CTX(_("QMCMD^dropped weapon %w^7 (l:%l^7)")))
865 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^drop flag/key, icon")), "say_team %s; g_waypointsprite_team_here; wait; use", "dropped flag/key %w^7 (l:%l^7)", CTX(_("QMCMD^dropped flag/key %w^7 (l:%l^7)")))
866 QUICKMENU_SMENU(CTX(_("QMCMD^Team chat")), "Team chat")
867 }
868
869 QUICKMENU_SMENU_PL(CTX(_("QMCMD^Send private message to")), "Send private message to", "commandmode tell \"%s^7\"", 0, 1)
870
871 QUICKMENU_SMENU(CTX(_("QMCMD^Settings")), "Settings")
872 QUICKMENU_SMENU(CTX(_("QMCMD^View/HUD settings")), "View/HUD settings")
873 QUICKMENU_ENTRY(CTX(_("QMCMD^3rd person view")), "toggle chase_active")
874 QUICKMENU_ENTRY(CTX(_("QMCMD^Player models like mine")), "toggle cl_forceplayermodels")
875 QUICKMENU_ENTRY(CTX(_("QMCMD^Names above players")), "toggle hud_shownames")
876 QUICKMENU_ENTRY(CTX(_("QMCMD^Crosshair per weapon")), "toggle crosshair_per_weapon")
877 QUICKMENU_ENTRY(CTX(_("QMCMD^FPS")), "toggle hud_panel_engineinfo")
878 QUICKMENU_ENTRY(CTX(_("QMCMD^Net graph")), "toggle shownetgraph")
879 QUICKMENU_SMENU(CTX(_("QMCMD^View/HUD settings")), "View/HUD settings")
880
881 QUICKMENU_SMENU(CTX(_("QMCMD^Sound settings")), "Sound settings")
882 QUICKMENU_ENTRY(CTX(_("QMCMD^Hit sound")), "toggle cl_hitsound")
883 QUICKMENU_ENTRY(CTX(_("QMCMD^Chat sound")), "toggle con_chatsound")
884 QUICKMENU_SMENU(CTX(_("QMCMD^Sound settings")), "Sound settings")
885
886 if (spectatee_status > 0)
887 {
888 QUICKMENU_ENTRY_TAG(CTX(_("QMCMD^Change spectator camera")), "dropweapon", QM_TAG_KCOMMAND)
889 }
890 else if (spectatee_status == -1)
891 {
892 QUICKMENU_SMENU(CTX(_("QMCMD^Observer camera")), "Observer camera")
893 QUICKMENU_ENTRY_TAG(CTX(_("QMCMD^Increase speed")), "weapnext", QM_TAG_KCOMMAND)
894 QUICKMENU_ENTRY_TAG(CTX(_("QMCMD^Decrease speed")), "weapprev", QM_TAG_KCOMMAND)
895 QUICKMENU_ENTRY(CTX(_("QMCMD^Wall collision")), "toggle cl_clippedspectating")
896 QUICKMENU_SMENU(CTX(_("QMCMD^Observer camera")), "Observer camera")
897 }
898
899 QUICKMENU_ENTRY(CTX(_("QMCMD^Fullscreen")), "toggle vid_fullscreen; vid_restart")
900 QUICKMENU_SMENU(CTX(_("QMCMD^Settings")), "Settings")
901
902 QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote")
903 QUICKMENU_ENTRY(CTX(_("QMCMD^Restart the map")), "vcall restart")
904 QUICKMENU_ENTRY(CTX(_("QMCMD^End match")), "vcall endmatch")
905 if (STAT(TIMELIMIT) > 0)
906 {
907 QUICKMENU_ENTRY(CTX(_("QMCMD^Reduce match time")), "vcall reducematchtime")
908 QUICKMENU_ENTRY(CTX(_("QMCMD^Extend match time")), "vcall extendmatchtime")
909 }
910 if (teamplay)
911 QUICKMENU_ENTRY(CTX(_("QMCMD^Shuffle teams")), "vcall shuffleteams")
912 QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote")
913
915 {
916 string entry_name = _("Server quick menu");
918 entry_name = _("Waypoint editor menu");
919 QUICKMENU_ENTRY_SPECIAL(entry_name, "quickmenu; wait; quickmenu \"\" \"\" $_hud_panel_quickmenu_file_from_server")
921 entry_name = _("Waypoint editor menu as default");
922 else
923 entry_name = _("Server quick menu as default");
924 QUICKMENU_ENTRY(entry_name, "toggle hud_panel_quickmenu_server_is_default")
925 }
926
927 if (spectatee_status != 0)
928 {
929 QUICKMENU_SMENU_PL(CTX(_("QMCMD^Spectate a player")), "Spectate a player", "spectate \"%s^7\"", 0, 1)
930 }
931
932 if (target_submenu != "" && !target_submenu_found)
933 {
934 LOG_INFOF("Couldn't find submenu \"%s\"", target_submenu);
935 if (prvm_language != "en")
936 LOG_INFO("^3Warning: submenu title must be in English");
938 }
939}
940#undef QuickMenu_Buffer_Set
941#undef QuickMenu_Buffer_Get
942#undef QUICKMENU_ENTRY
943#undef QUICKMENU_ENTRY_SPECIAL
944#undef QUICKMENU_SMENU
945#undef QUICKMENU_ENTRY
946#undef QUICKMENU_ENTRY_TC
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
bool HUD_MinigameMenu_IsOpened()
#define drawcolorcodedstring(position, text, scale, alpha, flag)
Definition draw.qh:30
#define drawpic(position, pic, size, rgb, alpha, flag)
Definition draw.qh:21
#define drawfill(position, size, rgb, alpha, flag)
Definition draw.qh:36
void Release_Common_Keys()
Definition main.qc:477
entity players
Definition main.qh:57
int spectatee_status
the -1 disables HUD panels before CSQC receives necessary data
Definition main.qh:197
float team_count
Definition main.qh:59
bool mv_active
Definition mapvoting.qh:19
string textShortenToWidth(string theText, float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition util.qc:1071
const float DRAWFLAG_NORMAL
const float DRAWFLAG_ADDITIVE
float player_localnum
const float FILE_READ
float time
#define strstrofs
#define tokenize_console
#define buf_create
#define chr2str
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
bool hud_draw_maximized
Definition hud.qh:69
#define HUD_Panel_DrawBg()
Definition hud.qh:55
string hud_skin_path
Definition hud.qh:136
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
#define HUD_Write_Cvar(cvar)
Definition hud_config.qh:40
float hud_configure_prev
Definition hud_config.qh:18
const int S_MOUSE1
Definition hud_config.qh:10
bool autocvar__hud_configure
Definition hud_config.qh:3
int prevMouseClicked
Definition hud_config.qh:14
int mouseClicked
Definition hud_config.qh:13
const int S_MOUSE2
Definition hud_config.qh:11
ERASEABLE string CTX(string s)
Definition i18n.qh:45
string prvm_language
Definition i18n.qh:8
float K_SHIFT
Definition keycodes.qc:22
float K_MOUSE1
Definition keycodes.qc:129
float K_CTRL
Definition keycodes.qc:21
float K_ALT
Definition keycodes.qc:20
float K_MOUSE2
Definition keycodes.qc:130
float K_ESCAPE
Definition keycodes.qc:9
#define TC(T, sym)
Definition _all.inc:82
#define STAT(...)
Definition stats.qh:82
#define LOG_WARNF(...)
Definition log.qh:62
#define LOG_INFO(...)
Definition log.qh:65
#define LOG_INFOF(...)
Definition log.qh:66
void localcmd(string command,...)
string fgets(float fhandle)
void fclose(float fhandle)
float stof(string val,...)
string substring(string s, float start, float length)
float cvar(string name)
float fopen(string filename, float mode)
string precache_pic(string name,...)
const string cvar_string(string name)
void cmd(string command,...)
float min(float f,...)
void strunzone(string s)
string ftos(float f)
float floor(float f)
float tokenize(string s)
string strzone(string s)
string argv(float n)
float max(float f,...)
string string_null
Definition nil.qh:9
spree_inf s1 s2 s3loc s2 s1
Definition all.inc:281
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
const int QUICKMENU_MAXENTRIES
Definition quickmenu.qc:32
int QuickMenu_Page_Entries
Definition quickmenu.qc:24
void QuickMenu_Page_ActiveEntry(int entry_num)
Definition quickmenu.qc:473
#define QUICKMENU_ENTRY(title, command)
Definition quickmenu.qc:68
void QuickMenu_TimeOut_Set()
Definition quickmenu.qc:74
void HUD_Quickmenu_DrawEntry(vector pos, string desc, string option, vector fontsize)
Definition quickmenu.qc:600
bool HUD_Quickmenu_PlayerListEntries_Create(string cmd, int teamplayers, bool without_me)
Definition quickmenu.qc:296
#define QUICKMENU_ENTRY_TAG(title, command, tag)
Definition quickmenu.qc:66
void QuickMenu_Mouse()
Definition quickmenu.qc:546
float QuickMenu_TimeOut
Definition quickmenu.qc:38
int QuickMenu_Page
Definition quickmenu.qc:25
string QuickMenu_Page_Description[QUICKMENU_MAXLINES]
Definition quickmenu.qc:22
const string QM_TAG_KCOMMAND
Definition quickmenu.qc:44
#define QuickMenu_Buffer_Get()
Definition quickmenu.qc:53
const int QM_PCT_KEEP
Definition quickmenu.qc:50
void QuickMenu_Page_LoadEntry(int i, string s, string s1)
Definition quickmenu.qc:80
void QuickMenu_skip_submenu(string submenu)
Definition quickmenu.qc:275
#define QuickMenu_Buffer_Set(tag, string)
Definition quickmenu.qc:52
float QuickMenu_Page_ActivatedEntry_Time
Definition quickmenu.qc:28
const int QUICKMENU_MAXLINES
Definition quickmenu.qc:19
void QuickMenu_Page_ClearEntry(int i)
Definition quickmenu.qc:88
int QuickMenu_Buffer_Index_Prev
Definition quickmenu.qc:319
bool QuickMenu_Open(string mode, string submenu, string file)
Definition quickmenu.qc:107
int QuickMenu_Buffer
Definition quickmenu.qc:34
int entry_num_prev
Definition quickmenu.qc:545
int QuickMenu_Buffer_Size
Definition quickmenu.qc:35
void HUD_QuickMenu_Export(int fh)
Definition quickmenu.qc:12
const string QM_TAG_SUBMENU
Definition quickmenu.qc:42
bool QuickMenu_Page_Load(string target_submenu, bool new_page)
Definition quickmenu.qc:320
const int QUICKMENU_BUFFER_MAXENTRIES
Definition quickmenu.qc:33
void HUD_Quickmenu_PlayerListEntries(string cmd, int teamplayers, bool without_me)
Definition quickmenu.qc:803
#define QUICKMENU_ENTRY_TC(title, command, text, translated_text)
Definition quickmenu.qc:784
void QuickMenu_Buffer_Close()
Definition quickmenu.qc:253
const string QM_TAG_TITLE
Definition quickmenu.qc:41
const string QM_TAG_PLCOMMAND
Definition quickmenu.qc:45
void QuickMenu_Default(string target_submenu)
Definition quickmenu.qc:830
bool QuickMenu_InputEvent(int bInputType, float nPrimary, float nSecondary)
Definition quickmenu.qc:486
bool QuickMenu_IsOpened()
Definition quickmenu.qc:291
void QuickMenu_Close()
Definition quickmenu.qc:263
int QuickMenu_Page_Command_Type[QUICKMENU_MAXLINES]
Definition quickmenu.qc:23
void HUD_QuickMenu()
Definition quickmenu.qc:634
#define QUICKMENU_SMENU_PL(submenu, eng_submenu, command, teamplayers, without_me)
Definition quickmenu.qc:769
bool HUD_QuickMenu_Forbidden()
Definition quickmenu.qc:96
bool QuickMenu_Page_ActivatedEntry_Close
Definition quickmenu.qc:27
const int QM_PCT_NONE
Definition quickmenu.qc:48
void QuickMenu_Entry_WithTag(string title, string command, string tag)
Definition quickmenu.qc:55
int QuickMenu_Buffer_Index
Definition quickmenu.qc:36
string QuickMenu_Page_Command[QUICKMENU_MAXLINES]
Definition quickmenu.qc:21
const int QM_PCT_TOGGLE
Definition quickmenu.qc:49
int QuickMenu_Page_ActivatedEntry
Definition quickmenu.qc:26
string QuickMenu_CurrentSubMenu
Definition quickmenu.qc:37
bool QuickMenu_ActionForNumber(int num)
Definition quickmenu.qc:440
#define QUICKMENU_ENTRY_SPECIAL(title, command)
Definition quickmenu.qc:71
bool QuickMenu_IsLastPage
Definition quickmenu.qc:29
const string QM_TAG_COMMAND
Definition quickmenu.qc:43
#define QUICKMENU_SMENU(submenu, eng_submenu)
Definition quickmenu.qc:756
bool autocvar_hud_panel_quickmenu_server_is_default
Definition quickmenu.qh:9
float autocvar_hud_panel_quickmenu_time
Definition quickmenu.qh:8
float autocvar_hud_panel_quickmenu_align
Definition quickmenu.qh:5
string autocvar__hud_panel_quickmenu_file_from_server
Definition quickmenu.qh:10
void Scoreboard_UpdatePlayerTeams()
int scoreboard_ui_enabled
Definition scoreboard.qh:40
vector
Definition self.qh:92
#define strfree(this)
Definition string.qh:59
#define strcpy(this, s)
Definition string.qh:52
float stringwidth_colors(string s, vector theSize)
Definition string.qh:30
int myteam
Definition teams.qh:60
const int NUM_SPECTATOR
Definition teams.qh:23
bool teamplay
Definition teams.qh:59
const vector eY
Definition vector.qh:45
const vector eX
Definition vector.qh:44
#define vec2(...)
Definition vector.qh:90
float intermission_time
Definition view.qh:131