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 = tokenize_console(s);
169 if (argc == 0 || argv(0) == "")
170 continue;
171 if (argc == 1)
173 else if (argc == 2)
174 {
175 if (argv(1) == "")
176 continue;
180 }
181 else if (argc == 3 && argv(2) == "KEEP_OPEN")
182 {
183 if (argv(1) == "")
184 continue;
188 }
189 else if (argc == 3)
190 {
191 // check for special keywords
192 float teamplayers = 0, without_me = 0;
193 switch (argv(2))
194 {
195 case "ALLPLAYERS_BUT_ME": without_me = 1; // fall through
196 case "ALLPLAYERS": teamplayers = 0; break;
197 case "OWNTEAMPLAYERS_BUT_ME": without_me = 1; // fall through
198 case "OWNTEAMPLAYERS": teamplayers = 1; break;
199 case "ENEMYTEAMPLAYERS": teamplayers = 2; break;
200 default: continue;
201 }
202
204 {
207 QuickMenu_Buffer_Set(QM_TAG_TITLE, strcat(ftos(teamplayers), ftos(without_me))); // put PLCOMMAND arguments in the title string
212 }
213 }
215 }
216 fclose(fh);
217
218 // forcedly add this entry
220 {
221 string prev_value = cvar_string("hud_panel_quickmenu_server_is_default");
222 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))
223 }
224 }
225 else
226 {
227 LOG_WARNF("Unrecognized mode %s", mode);
228 return false;
229 }
230
231 if (QuickMenu_Buffer_Size <= 0)
232 {
233 buf_del(QuickMenu_Buffer);
234 QuickMenu_Buffer = -1;
235 return false;
236 }
237
238 if (mode == "file")
239 QuickMenu_Page_Load(submenu, 0);
240 else
241 QuickMenu_Page_Load("", 0);
242
243 mouseClicked = 0;
244 hudShiftState = 0;
245
247
249 return true;
250}
251
253{
254 if (QuickMenu_Buffer >= 0)
255 {
256 buf_del(QuickMenu_Buffer);
257 QuickMenu_Buffer = -1;
259 }
260}
261
272
273// It assumes submenu open tag is already detected
274void QuickMenu_skip_submenu(string submenu)
275{
276 string z_submenu = string_null;
277 strcpy(z_submenu, submenu);
279 {
280 string s = QuickMenu_Buffer_Get();
281 if (substring(s, 0, 1) != QM_TAG_SUBMENU)
282 continue;
283 if (substring(s, 1, -1) == z_submenu) // submenu end
284 break;
286 }
287 strfree(z_submenu);
288}
289
291{
292 return QuickMenu_Page_Entries > 0;
293}
294
295bool HUD_Quickmenu_PlayerListEntries_Create(string cmd, int teamplayers, bool without_me)
296{
297 TC(int, teamplayers); TC(bool, without_me);
298 for (int i = 0; i < QUICKMENU_MAXLINES; ++i)
301
303 if (QuickMenu_Buffer < 0)
304 return false;
305
306 HUD_Quickmenu_PlayerListEntries(cmd, teamplayers, without_me);
307
308 if (QuickMenu_Buffer_Size <= 0)
309 {
310 buf_del(QuickMenu_Buffer);
311 QuickMenu_Buffer = -1;
312 return false;
313 }
314 return true;
315}
316
317// new_page 0 means page 0, new_page != 0 means next page
319bool QuickMenu_Page_Load(string target_submenu, bool new_page)
320{
321 TC(bool, new_page);
322
324 if (new_page == 0)
325 QuickMenu_Page = 0;
326 else
328
329 string z_submenu = strzone(target_submenu);
331
334
336 string s = string_null;
337 if (z_submenu != "")
338 {
339 // skip everything until the submenu open tag is found
341 {
343 if (substring(s, 0, 1) == QM_TAG_SUBMENU && substring(s, 1, -1) == z_submenu)
344 {
345 //LOG_INFOF("^3 beginning of %s\n", z_submenu);
347 break; // target_submenu found!
348 }
349 //LOG_INFOF("^1 skipping %s\n", s);
350 }
352 LOG_WARNF("Couldn't find submenu \"%s\"", z_submenu);
353 }
354
355 // only the last page can contain up to QUICKMENU_MAXLINES entries
356 // the other ones contain only (QUICKMENU_MAXLINES - 2) entries
357 // so that the panel can show an empty row and "Continue..."
358 float first_entry = QuickMenu_Page * (QUICKMENU_MAXLINES - 2);
359 int entry_num = 0; // counts entries in target_submenu
361 {
363
364 if (z_submenu != "" && substring(s, 1, -1) == z_submenu)
365 {
366 //LOG_INFOF("^3 end of %s\n", z_submenu);
367 break;
368 }
369
370 if (entry_num >= first_entry)
371 {
376 {
379 QuickMenu_IsLastPage = false;
380 break;
381 }
382 }
383
384 // NOTE: entries are loaded starting from 1, not from 0
385 if (substring(s, 0, 1) == QM_TAG_SUBMENU)
386 {
387 if (entry_num >= first_entry)
390 }
391 else if (substring(s, 0, 1) == QM_TAG_TITLE)
392 {
394 if (entry_num >= first_entry)
395 {
396 string cmd = QuickMenu_Buffer_Get();
397 string command_code = substring(cmd, 0, 1);
398 if (command_code == QM_TAG_COMMAND)
399 {
400 cmd = substring(cmd, 1, -1);
402 }
403 else if (command_code == QM_TAG_KCOMMAND)
404 {
405 cmd = substring(cmd, 1, -1);
407 }
408 else if (command_code == QM_TAG_PLCOMMAND)
409 {
410 // throw away the current quickmenu buffer and load a new one
411 cmd = substring(cmd, 1, -1);
412 strunzone(z_submenu);
414 return QuickMenu_Page_Load("", 0);
416 return false;
417 }
418
420 if (argv(1) && argv(0) == "toggle")
422
424 }
425 }
426
427 ++entry_num;
428 }
429 strunzone(z_submenu);
430 if (QuickMenu_Page_Entries == 0)
431 {
433 return false;
434 }
436 return true;
437}
438
440{
441 TC(int, num);
443 {
444 if (num < 0 || num >= QUICKMENU_MAXLINES)
445 return false;
446 if (num == QUICKMENU_MAXLINES - 1)
447 return false;
448 if (num == 0)
449 {
451 return false;
452 }
453 }
454 else if (num <= 0 || num > QuickMenu_Page_Entries)
455 return false;
456
457 if (QuickMenu_Page_Command[num] != "")
458 {
460 localcmd(strcat("\n", QuickMenu_Page_Command[num], "\n"));
463 return false;
464 else
465 return true;
466 }
467 if (QuickMenu_Page_Description[num] != "")
469 return false;
470}
471
484
485bool QuickMenu_InputEvent(int bInputType, float nPrimary, float nSecondary)
486{
487 TC(int, bInputType);
488
490 return false;
491
492 if (bInputType == 3)
493 {
494 mousepos.x = nPrimary;
495 mousepos.y = nSecondary;
496 return true;
497 }
498
499 if (bInputType == 2)
500 return false;
501
502 // at this point bInputType can only be 0 or 1 (key pressed or released)
503 bool key_pressed = bInputType == 0;
504
505 int hudShiftState_prev = hudShiftState;
506 int mouseClicked_prev = mouseClicked;
507 if (key_pressed)
508 {
509 if (nPrimary == K_ALT) hudShiftState |= S_ALT;
510 if (nPrimary == K_CTRL) hudShiftState |= S_CTRL;
511 if (nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
512 if (nPrimary == K_MOUSE1) mouseClicked |= S_MOUSE1;
513 if (nPrimary == K_MOUSE2) mouseClicked |= S_MOUSE2;
514 }
515 else
516 {
517 if (nPrimary == K_ALT) hudShiftState &= ~S_ALT;
518 if (nPrimary == K_CTRL) hudShiftState &= ~S_CTRL;
519 if (nPrimary == K_SHIFT) hudShiftState &= ~S_SHIFT;
520 if (nPrimary == K_MOUSE1) mouseClicked &= ~S_MOUSE1;
521 if (nPrimary == K_MOUSE2) mouseClicked &= ~S_MOUSE2;
522 }
523
524 if (nPrimary == K_ESCAPE && key_pressed)
526 else if (nPrimary >= '0' && nPrimary <= '9' && key_pressed)
528 else if (hudShiftState_prev == hudShiftState && mouseClicked_prev == mouseClicked)
529 {
530 // allow console bind to work
531 string con_keys = findkeysforcommand("toggleconsole", 0);
532 int keys = tokenize(con_keys); // findkeysforcommand returns data for this
533 for (int i = 0; i < keys; ++i)
534 if (nPrimary == stof(argv(i)))
535 return false; // hit console bind
536 if (key_pressed)
538 return false;
539 }
540
541 return true;
542}
543
546{
547 if (mv_active)
548 return;
549
551 {
553 return;
554 }
555
556 panel = HUD_PANEL(QUICKMENU);
558
560 {
561 panel_pos += '1 1 0' * panel_bg_padding;
562 panel_size -= '2 2 0' * panel_bg_padding;
563 }
564
565 vector fontsize = '1 1 0' * (panel_size.y / QUICKMENU_MAXLINES);
566 float first_entry_pos = panel_pos.y + ((QUICKMENU_MAXLINES - QuickMenu_Page_Entries) * fontsize.y) * 0.5;
567 float entries_height = panel_size.y - ((QUICKMENU_MAXLINES - QuickMenu_Page_Entries) * fontsize.y);
568
569 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)
570 {
571 int entry_num = min(QuickMenu_Page_Entries - 1, floor((mousepos.y - first_entry_pos) / fontsize.y));
572 if (entry_num != entry_num_prev)
573 {
575 entry_num_prev = entry_num;
576 }
577 if (QuickMenu_IsLastPage || entry_num != QUICKMENU_MAXLINES - 2)
578 {
580 QuickMenu_Page_ActiveEntry((entry_num < QUICKMENU_MAXLINES - 1) ? entry_num + 1 : 0);
581
583 {
584 vector entry_pos = panel_pos;
585 entry_pos.y = first_entry_pos + entry_num * fontsize.y;
588 color = '0.5 1 0.5';
589 else if (hudShiftState & S_CTRL)
590 color = '1 1 0.3';
591 else
592 color = '1 1 1';
593 drawfill(entry_pos, vec2(panel_size.x, fontsize.y), color, 0.2, DRAWFLAG_NORMAL);
594 }
595 }
596 }
597}
598
599void HUD_Quickmenu_DrawEntry(vector pos, string desc, string option, vector fontsize)
600{
601 float desc_width = panel_size.x;
602 if (option)
603 {
604 string pic = strcat(hud_skin_path, "/", option);
605 if (precache_pic(pic) == "")
606 pic = strcat("gfx/hud/default/", option);
607 vector option_size = '1 1 0' * fontsize.y * 0.8;
608 desc_width -= option_size.x;
609 drawpic(pos + vec2(desc_width, (fontsize.y - option_size.y) / 2), pic, option_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE);
610 desc_width -= fontsize.x / 4;
611 }
612 string entry = textShortenToWidth(desc, desc_width, fontsize, stringwidth_colors);
614 {
615 float real_desc_width = stringwidth_colors(entry, fontsize);
616 float offset = (desc_width - real_desc_width) * min(autocvar_hud_panel_quickmenu_align, 1);
617
618 if (option)
619 {
620 // when there's enough room align description regardless the checkbox
621 float extra_offset = (panel_size.x - desc_width) * min(autocvar_hud_panel_quickmenu_align, 1);
622 if (offset + real_desc_width + extra_offset < desc_width)
623 offset += extra_offset;
624 else
625 offset = max(0, desc_width - real_desc_width);
626 }
627 drawcolorcodedstring(pos + eX * offset, entry, fontsize, panel_fg_alpha, DRAWFLAG_ADDITIVE);
628 }
629 else
631}
632
633void HUD_QuickMenu(bool should_draw)
634{
635 if (!should_draw)
636 return;
638 {
640 return;
641
643 {
645 return;
646 }
647 }
648 else
649 {
650 if (!QuickMenu_IsOpened())
651 {
657 // although real command doesn't matter here, it must not be empty
658 // otherwise the entry is displayed like a submenu
663 QuickMenu_IsLastPage = false;
664 }
665 }
666
668
671
673 {
674 panel_pos += '1 1 0' * panel_bg_padding;
675 panel_size -= '2 2 0' * panel_bg_padding;
676 }
677
678 string color;
679 vector fontsize = '1 1 0' * (panel_size.y / QUICKMENU_MAXLINES);
680
682 {
683 color = "^5";
684 HUD_Quickmenu_DrawEntry(panel_pos + eY * (panel_size.y - fontsize.y), sprintf("%d: %s%s", 0, color, _("Continue...")), string_null, fontsize);
685 }
686 else
687 panel_pos.y += ((QUICKMENU_MAXLINES - QuickMenu_Page_Entries) * fontsize.y) / 2;
688
689 for (int i = 1; i <= QuickMenu_Page_Entries; ++i)
690 {
691 if (QuickMenu_Page_Description[i] == "")
692 break;
693 string option = string_null;
694 if (QuickMenu_Page_Command[i] == "")
695 color = "^4";
696 else
697 {
698 if (substring(QuickMenu_Page_Command[i], 0, 1) == "\n")
699 color = "^6"; // special command
700 else
701 color = "^3";
702 if (QuickMenu_Page_Command_Type[i] == QM_PCT_TOGGLE) // toggle command
703 {
704 int end = strstrofs(QuickMenu_Page_Command[i], ";", 0);
705 if (end < 0)
707 else
709
710 if (argv(1) && argv(0) == "toggle")
711 {
712 // "enable feature xxx" "toggle xxx" (or "toggle xxx 1 0")
713 // "disable feature xxx" "toggle xxx 0 1"
714 float ON_value = 1, OFF_value = 0;
715 if (argv(2))
716 ON_value = stof(argv(2));
717
718 if (argv(3))
719 OFF_value = stof(argv(3));
720 else
721 OFF_value = !ON_value;
722
723 float value = cvar(argv(1));
724 if (value == ON_value)
725 option = "checkbox_checked";
726 else if (value == OFF_value)
727 option = "checkbox_empty";
728 else
729 option = "checkbox_undefined";
730 }
731 }
732 }
733 HUD_Quickmenu_DrawEntry(panel_pos, sprintf("%d: %s%s", i, color, QuickMenu_Page_Description[i]), option, fontsize);
734
736 drawfill(panel_pos, vec2(panel_size.x, fontsize.y), '0.5 1 0.5', 0.2, DRAWFLAG_NORMAL);
737
738 panel_pos.y += fontsize.y;
739 }
740
742 {
744 {
748 }
753 }
754}
755
756
757#define QUICKMENU_SMENU(submenu, eng_submenu) { \
758 if (target_submenu == eng_submenu && target_submenu_found) \
759 return; /* target_submenu entries are now loaded, exit */ \
760 if (QuickMenu_Buffer_Size < QUICKMENU_BUFFER_MAXENTRIES) \
761 QuickMenu_Buffer_Set(QM_TAG_SUBMENU, submenu); \
762 ++QuickMenu_Buffer_Size; \
763 if (target_submenu == eng_submenu && !target_submenu_found) \
764 { \
765 QuickMenu_Buffer_Size = 0; /* enable load of next entries */ \
766 target_submenu_found = true; \
767 } \
768}
769
770#define QUICKMENU_SMENU_PL(submenu, eng_submenu, command, teamplayers, without_me) { \
771 if (QuickMenu_Buffer_Size + 3 < QUICKMENU_BUFFER_MAXENTRIES) \
772 { \
773 QUICKMENU_SMENU(submenu, eng_submenu) \
774 QuickMenu_Buffer_Set(QM_TAG_TITLE, strcat(ftos(teamplayers), ftos(without_me))); \
775 ++QuickMenu_Buffer_Size; \
776 QuickMenu_Buffer_Set(QM_TAG_PLCOMMAND, command); \
777 ++QuickMenu_Buffer_Size; \
778 QUICKMENU_SMENU(submenu, eng_submenu) \
779 } \
780}
781
782
783
784// useful to Translate a string inside the Command
785#define QUICKMENU_ENTRY_TC(title, command, text, translated_text) { \
786 if (prvm_language == "en") \
787 { \
788 tc_title = title; \
789 tc_cmd = sprintf(command, text); \
790 } \
791 else if (!autocvar_hud_panel_quickmenu_translatecommands || translated_text == text) \
792 { \
793 tc_title = strcat("(en)", title); \
794 tc_cmd = sprintf(command, text); \
795 } \
796 else \
797 { \
798 tc_title = strcat("(", prvm_language, ")", title); \
799 tc_cmd = sprintf(command, translated_text); \
800 } \
801 QUICKMENU_ENTRY(tc_title, tc_cmd) \
802}
803
804void HUD_Quickmenu_PlayerListEntries(string cmd, int teamplayers, bool without_me)
805{
806 TC(int, teamplayers); TC(bool, without_me);
807 if (teamplayers && !team_count)
808 return;
809
811 for (entity pl = players.sort_next; pl; pl = pl.sort_next)
812 {
813 if (teamplayers == 1 && (pl.team != myteam || pl.team == NUM_SPECTATOR)) // only own team players
814 continue;
815 if (teamplayers == 2 && (pl.team == myteam || pl.team == NUM_SPECTATOR)) // only enemy team players
816 continue;
817 if (without_me && pl.sv_entnum == player_localnum)
818 continue;
819 QUICKMENU_ENTRY(strcat("^7", entcs_GetName(pl.sv_entnum)), sprintf(cmd, entcs_GetName(pl.sv_entnum)))
820 }
821
822 return;
823}
824
825
826// Specifying target_submenu, this function only loads entries inside target_submenu
827// NOTE: alternatively we could have loaded the whole default quickmenu and
828// then called QuickMenu_Page_Load(target_submenu, 0);
829// but this sytem is more reliable since we can always refer to target_submenu
830// with the English title even if a translation is active
831void QuickMenu_Default(string target_submenu)
832{
833 bool target_submenu_found = false;
834 if (target_submenu != "")
835 QuickMenu_Buffer_Size = QUICKMENU_BUFFER_MAXENTRIES; // forbids load of next entries until target_submenu
836
837 string tc_title;
838 string tc_cmd;
839
840 QUICKMENU_SMENU(_("Chat"), "Chat")
841 QUICKMENU_SMENU_PL(CTX(_("QMCMD^Send public message to")), "Send public message to", "commandmode say %s:^7", 0, 1)
842 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^nice one")), "say %s", ":-) / nice one", CTX(_("QMCMD^:-) / nice one")))
843 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^good game")), "say %s", "good game", CTX(_("QMCMD^good game")))
844 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^hi / good luck")), "say %s", "hi / good luck and have fun", CTX(_("QMCMD^hi / good luck and have fun")))
845 if (prvm_language != "en")
846 QUICKMENU_ENTRY(CTX(_("QMCMD^Send in English")), "toggle hud_panel_quickmenu_translatecommands 0 1; quickmenu; wait; quickmenu default Chat")
847 QUICKMENU_SMENU(_("Chat"), "Chat")
848
849 if (teamplay)
850 {
851 QUICKMENU_SMENU(CTX(_("QMCMD^Team chat")), "Team chat")
852 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^strength soon")), "say_team %s", "strength soon", CTX(_("QMCMD^strength soon")))
853 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)")))
854 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)")))
855 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^negative")), "say_team %s", "negative", CTX(_("QMCMD^negative")))
856 QUICKMENU_ENTRY_TC(CTX(_("QMCMD^positive")), "say_team %s", "positive", CTX(_("QMCMD^positive")))
857 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)")))
858 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)")))
859 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)")))
860 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)")))
861 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)")))
862 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)")))
863 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)")))
864 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)")))
865 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)")))
866 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)")))
867 QUICKMENU_SMENU(CTX(_("QMCMD^Team chat")), "Team chat")
868 }
869
870 QUICKMENU_SMENU_PL(CTX(_("QMCMD^Send private message to")), "Send private message to", "commandmode tell \"%s^7\"", 0, 1)
871
872 QUICKMENU_SMENU(CTX(_("QMCMD^Settings")), "Settings")
873 QUICKMENU_SMENU(CTX(_("QMCMD^View/HUD settings")), "View/HUD settings")
874 QUICKMENU_ENTRY(CTX(_("QMCMD^3rd person view")), "toggle chase_active")
875 QUICKMENU_ENTRY(CTX(_("QMCMD^Player models like mine")), "toggle cl_forceplayermodels")
876 QUICKMENU_ENTRY(CTX(_("QMCMD^Names above players")), "toggle hud_shownames")
877 QUICKMENU_ENTRY(CTX(_("QMCMD^Crosshair per weapon")), "toggle crosshair_per_weapon")
878 QUICKMENU_ENTRY(CTX(_("QMCMD^FPS")), "toggle hud_panel_engineinfo")
879 QUICKMENU_ENTRY(CTX(_("QMCMD^Net graph")), "toggle shownetgraph")
880 QUICKMENU_SMENU(CTX(_("QMCMD^View/HUD settings")), "View/HUD settings")
881
882 QUICKMENU_SMENU(CTX(_("QMCMD^Sound settings")), "Sound settings")
883 QUICKMENU_ENTRY(CTX(_("QMCMD^Hit sound")), "toggle cl_hitsound")
884 QUICKMENU_ENTRY(CTX(_("QMCMD^Chat sound")), "toggle con_chatsound")
885 QUICKMENU_SMENU(CTX(_("QMCMD^Sound settings")), "Sound settings")
886
887 if (spectatee_status > 0)
888 {
889 QUICKMENU_ENTRY_TAG(CTX(_("QMCMD^Change spectator camera")), "dropweapon", QM_TAG_KCOMMAND)
890 }
891 else if (spectatee_status == -1)
892 {
893 QUICKMENU_SMENU(CTX(_("QMCMD^Observer camera")), "Observer camera")
894 QUICKMENU_ENTRY_TAG(CTX(_("QMCMD^Increase speed")), "weapnext", QM_TAG_KCOMMAND)
895 QUICKMENU_ENTRY_TAG(CTX(_("QMCMD^Decrease speed")), "weapprev", QM_TAG_KCOMMAND)
896 QUICKMENU_ENTRY(CTX(_("QMCMD^Wall collision")), "toggle cl_clippedspectating")
897 QUICKMENU_SMENU(CTX(_("QMCMD^Observer camera")), "Observer camera")
898 }
899
900 QUICKMENU_ENTRY(CTX(_("QMCMD^Fullscreen")), "toggle vid_fullscreen; vid_restart")
901 QUICKMENU_SMENU(CTX(_("QMCMD^Settings")), "Settings")
902
903 QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote")
904 QUICKMENU_ENTRY(CTX(_("QMCMD^Restart the map")), "vcall restart")
905 QUICKMENU_ENTRY(CTX(_("QMCMD^End match")), "vcall endmatch")
906 if (STAT(TIMELIMIT) > 0)
907 {
908 QUICKMENU_ENTRY(CTX(_("QMCMD^Reduce match time")), "vcall reducematchtime")
909 QUICKMENU_ENTRY(CTX(_("QMCMD^Extend match time")), "vcall extendmatchtime")
910 }
911 if (teamplay)
912 QUICKMENU_ENTRY(CTX(_("QMCMD^Shuffle teams")), "vcall shuffleteams")
913 QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote")
914
916 {
917 string entry_name = _("Server quick menu");
919 entry_name = _("Waypoint editor menu");
920 QUICKMENU_ENTRY_SPECIAL(entry_name, "quickmenu; wait; quickmenu \"\" \"\" $_hud_panel_quickmenu_file_from_server")
922 entry_name = _("Waypoint editor menu as default");
923 else
924 entry_name = _("Server quick menu as default");
925 QUICKMENU_ENTRY(entry_name, "toggle hud_panel_quickmenu_server_is_default")
926 }
927
928 if (spectatee_status != 0)
929 {
930 QUICKMENU_SMENU_PL(CTX(_("QMCMD^Spectate a player")), "Spectate a player", "spectate \"%s^7\"", 0, 1)
931 }
932
933 if (target_submenu != "" && !target_submenu_found)
934 {
935 LOG_INFOF("Couldn't find submenu \"%s\"", target_submenu);
936 if (prvm_language != "en")
937 LOG_INFO("^3Warning: submenu title must be in English");
939 }
940}
941#undef QuickMenu_Buffer_Set
942#undef QuickMenu_Buffer_Get
943#undef QUICKMENU_ENTRY
944#undef QUICKMENU_ENTRY_SPECIAL
945#undef QUICKMENU_SMENU
946#undef QUICKMENU_ENTRY
947#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:475
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:17
string textShortenToWidth(string theText, float maxWidth, vector theFontSize, textLengthUpToWidth_widthFunction_t tw)
Definition util.qc:1171
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:472
#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:599
bool HUD_Quickmenu_PlayerListEntries_Create(string cmd, int teamplayers, bool without_me)
Definition quickmenu.qc:295
#define QUICKMENU_ENTRY_TAG(title, command, tag)
Definition quickmenu.qc:66
void QuickMenu_Mouse()
Definition quickmenu.qc:545
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:274
#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:318
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:544
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:319
const int QUICKMENU_BUFFER_MAXENTRIES
Definition quickmenu.qc:33
void HUD_Quickmenu_PlayerListEntries(string cmd, int teamplayers, bool without_me)
Definition quickmenu.qc:804
#define QUICKMENU_ENTRY_TC(title, command, text, translated_text)
Definition quickmenu.qc:785
void QuickMenu_Buffer_Close()
Definition quickmenu.qc:252
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:831
bool QuickMenu_InputEvent(int bInputType, float nPrimary, float nSecondary)
Definition quickmenu.qc:485
bool QuickMenu_IsOpened()
Definition quickmenu.qc:290
void QuickMenu_Close()
Definition quickmenu.qc:262
int QuickMenu_Page_Command_Type[QUICKMENU_MAXLINES]
Definition quickmenu.qc:23
void HUD_QuickMenu(bool should_draw)
Definition quickmenu.qc:633
#define QUICKMENU_SMENU_PL(submenu, eng_submenu, command, teamplayers, without_me)
Definition quickmenu.qc:770
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:439
#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:757
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:39
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