1 #include "minigames.qh"
2 #include "../../client/mapvoting.qh"
4 // whether the mouse is over the given panel
5 bool HUD_mouse_over(entity somepanel)
7 vector pos = stov(cvar_string(strcat("hud_panel_", somepanel.panel_name, "_pos")));
8 vector sz = stov(cvar_string(strcat("hud_panel_", somepanel.panel_name, "_size")));
9 return mousepos_x >= pos_x*vid_conwidth && mousepos_x <= (pos_x+sz_x)*vid_conwidth &&
10 mousepos_y >= pos_y*vid_conheight && mousepos_y <= (pos_y+sz_y)*vid_conheight ;
13 // ====================================================================
15 // ====================================================================
17 // Draws the minigame game board
18 void HUD_MinigameBoard ()
20 entity hud_minigame = world;
22 if(!autocvar__hud_configure)
23 hud_minigame = active_minigame.descriptor;
25 hud_minigame = minigame_get_descriptor("nmm");
30 HUD_Panel_UpdateCvars();
37 hud_minigame.minigame_hud_board(pos,mySize);
40 // ====================================================================
42 // ====================================================================
43 // Draws the minigame status panel
44 void HUD_MinigameStatus ()
46 entity hud_minigame = world;
48 if(!autocvar__hud_configure)
49 hud_minigame = active_minigame.descriptor;
51 hud_minigame = minigame_get_descriptor("nmm");
56 HUD_Panel_UpdateCvars();
65 pos += '1 1 0' * panel_bg_padding;
66 mySize -= '2 2 0' * panel_bg_padding;
69 hud_minigame.minigame_hud_status(pos,mySize);
72 // ====================================================================
74 // ====================================================================
76 // Minigame menu options: list head
77 entity HUD_MinigameMenu_entries;
78 // Minigame menu options: list tail
79 entity HUD_MinigameMenu_last_entry;
81 // Minigame menu options: insert entry after the given location
82 void HUD_MinigameMenu_InsertEntry(entity newentry, entity prev)
84 if ( !HUD_MinigameMenu_entries )
86 HUD_MinigameMenu_entries = newentry;
87 HUD_MinigameMenu_last_entry = newentry;
91 newentry.list_prev = prev;
92 newentry.list_next = prev.list_next;
94 prev.list_next.list_prev = newentry;
96 HUD_MinigameMenu_last_entry = newentry;
97 prev.list_next = newentry;
102 // minigame menu item uder the mouse
103 entity HUD_MinigameMenu_activeitem;
105 // Click the given item
106 void HUD_MinigameMenu_Click(entity menuitem)
110 WITH(entity, self, menuitem, menuitem.use());
114 // Minigame menu options: Remove the given entry
115 // Precondition: the given entry is actually in the list
116 void HUD_MinigameMenu_EraseEntry ( entity e )
118 // remove child items (if any)
121 HUD_MinigameMenu_Click(e);
125 e.list_prev.list_next = e.list_next;
127 HUD_MinigameMenu_entries = e.list_next;
130 e.list_next.list_prev = e.list_prev;
132 HUD_MinigameMenu_last_entry = e.list_prev;
134 if ( HUD_MinigameMenu_activeitem == e )
135 HUD_MinigameMenu_activeitem = world;
140 // Minigame menu options: create entry
141 entity HUD_MinigameMenu_SpawnEntry(string s, vector offset, vector fontsize, vector color,void() click)
143 entity entry = spawn();
145 entry.origin = offset;
146 entry.size = fontsize;
147 entry.colormod = color;
150 panel_pos_y += fontsize_y;
154 // Spawn a child entry of a collapsable entry
155 entity HUD_MinigameMenu_SpawnSubEntry(string s, void() click, entity parent)
157 vector item_fontsize = hud_fontsize*1.25;
158 vector item_offset = '1 0 0' * item_fontsize_x;
159 entity item = HUD_MinigameMenu_SpawnEntry(
160 s,item_offset,item_fontsize,'0.8 0.8 0.8', click );
165 // Click action for Create sub-entries
166 void HUD_MinigameMenu_ClickCreate_Entry()
168 minigame_cmd("create ",self.netname);
171 // Helper click action for collapsible entries
172 // returns true when you have to create the sub-entries
173 bool HUD_MinigameMenu_Click_ExpandCollapse()
176 if ( self.flags & 2 )
178 if ( HUD_MinigameMenu_activeitem &&
179 HUD_MinigameMenu_activeitem.owner == self )
180 HUD_MinigameMenu_activeitem = world;
182 for ( e = self.list_next; e != world && e.owner == self; e = self.list_next )
185 HUD_MinigameMenu_Click(e);
186 self.list_next = e.list_next;
189 if ( self.list_next )
190 self.list_next.list_prev = self;
192 HUD_MinigameMenu_last_entry = self;
196 for ( e = HUD_MinigameMenu_entries; e != world; e = e.list_next )
198 if ( e.flags & 2 && e.origin_x == self.origin_x)
199 HUD_MinigameMenu_Click(e);
209 // Click action for the Create menu
210 void HUD_MinigameMenu_ClickCreate()
212 if ( HUD_MinigameMenu_Click_ExpandCollapse() )
217 for ( e = minigame_descriptors; e != world; e = e.list_next )
219 curr = HUD_MinigameMenu_SpawnSubEntry(
220 e.message, HUD_MinigameMenu_ClickCreate_Entry, self );
221 curr.netname = e.netname;
222 curr.model = strzone(minigame_texture(strcat(e.netname,"/icon")));
223 HUD_MinigameMenu_InsertEntry( curr, prev );
229 // Click action for Join sub-entries
230 void HUD_MinigameMenu_ClickJoin_Entry()
232 minigame_cmd("join ",self.netname);
233 HUD_MinigameMenu_EraseEntry(self);
236 // Click action for the Join menu
237 void HUD_MinigameMenu_ClickJoin()
239 if ( HUD_MinigameMenu_Click_ExpandCollapse() )
244 while( (e = find(e,classname,"minigame")) )
246 if ( e != active_minigame )
248 curr = HUD_MinigameMenu_SpawnSubEntry(
249 e.netname, HUD_MinigameMenu_ClickJoin_Entry, self );
250 curr.netname = e.netname;
251 curr.model = strzone(minigame_texture(strcat(e.descriptor.netname,"/icon")));
252 HUD_MinigameMenu_InsertEntry( curr, prev );
259 /*// Temporary placeholder for un-implemented Click actions
260 void HUD_MinigameMenu_ClickNoop()
262 dprint("Placeholder for ",self.message,"\n");
265 // Click action for Quit
266 void HUD_MinigameMenu_ClickQuit()
268 deactivate_minigame();
272 // Click action for Invite sub-entries
273 void HUD_MinigameMenu_ClickInvite_Entry()
275 minigame_cmd("invite #",self.netname);
278 // Click action for the Invite menu
279 void HUD_MinigameMenu_ClickInvite()
281 if ( HUD_MinigameMenu_Click_ExpandCollapse() )
285 for(int i = 0; i < maxclients; ++i)
287 if ( player_localnum != i && playerslots[i] && GetPlayerName(i) != "" &&
288 !findfloat(world,minigame_playerslot,i+1) && playerslots[i].ping )
290 e = HUD_MinigameMenu_SpawnSubEntry(
291 strzone(GetPlayerName(i)), HUD_MinigameMenu_ClickInvite_Entry,
294 e.netname = strzone(ftos(i+1));
296 HUD_MinigameMenu_InsertEntry(e,prev);
303 void HUD_MinigameMenu_ClickCustomEntry()
305 if ( active_minigame )
306 active_minigame.minigame_event(active_minigame,"menu_click",self.netname);
309 // Adds a game-specific entry to the menu
310 void HUD_MinigameMenu_CustomEntry(entity parent, string menumessage, string event_arg)
312 entity e = HUD_MinigameMenu_SpawnSubEntry(
313 menumessage, HUD_MinigameMenu_ClickCustomEntry, parent );
314 e.netname = event_arg;
315 HUD_MinigameMenu_InsertEntry(e, parent);
316 //dprint("CustomEntry ",ftos(num_for_edict(parent))," ",menumessage," ",event_arg,"\n");
319 // Click action for the Current Game menu
320 void HUD_MinigameMenu_ClickCurrentGame()
322 if ( HUD_MinigameMenu_Click_ExpandCollapse() )
324 HUD_MinigameMenu_InsertEntry( HUD_MinigameMenu_SpawnSubEntry(
325 _("Quit"), HUD_MinigameMenu_ClickQuit, self ), self);
327 active_minigame.minigame_event(active_minigame,"menu_show",self);
329 HUD_MinigameMenu_InsertEntry( HUD_MinigameMenu_SpawnSubEntry(
330 _("Invite"), HUD_MinigameMenu_ClickInvite, self), self);
333 // Whether the minigame menu panel is open
334 bool HUD_MinigameMenu_IsOpened()
336 return !!HUD_MinigameMenu_entries;
339 // Close the minigame menu panel
340 void HUD_MinigameMenu_Close()
342 if ( HUD_MinigameMenu_IsOpened() )
345 for ( e = HUD_MinigameMenu_entries; e != world; e = p )
350 HUD_MinigameMenu_entries = world;
351 HUD_MinigameMenu_last_entry = world;
352 HUD_MinigameMenu_activeitem = world;
353 if(autocvar_hud_cursormode)
354 if ( !autocvar__hud_configure )
359 // toggle a button to manage the current game
360 void HUD_MinigameMenu_CurrentButton()
363 if ( active_minigame )
365 for ( e = HUD_MinigameMenu_last_entry; e != world; e = e.list_prev )
366 if ( e.classname == "hud_minigamemenu_exit" )
368 HUD_MinigameMenu_EraseEntry(e);
371 entity currb = HUD_MinigameMenu_SpawnEntry(
372 _("Current Game"), '0 0 0', hud_fontsize*1.5,'0.7 0.84 1', HUD_MinigameMenu_ClickCurrentGame );
373 currb.classname = "hud_minigamemenu_current";
374 currb.model = strzone(minigame_texture(strcat(active_minigame.descriptor.netname,"/icon")));
375 HUD_MinigameMenu_InsertEntry(currb,HUD_MinigameMenu_last_entry);
376 HUD_MinigameMenu_Click(currb);
381 for ( e = HUD_MinigameMenu_last_entry; e != world; e = p.list_prev )
384 if ( e.classname == "hud_minigamemenu_current" )
388 p = HUD_MinigameMenu_last_entry;
389 HUD_MinigameMenu_EraseEntry(e);
393 for ( e = HUD_MinigameMenu_last_entry; e != world; e = e.list_prev )
394 if ( e.classname == "hud_minigamemenu_exit" )
396 entity exit = HUD_MinigameMenu_SpawnEntry(
397 _("Exit Menu"),'0 0 0',hud_fontsize*1.5,'0.7 0.84 1', HUD_MinigameMenu_Close);
398 exit.classname = "hud_minigamemenu_exit";
399 HUD_MinigameMenu_InsertEntry ( exit, HUD_MinigameMenu_last_entry );
403 // Open the minigame menu panel
404 void HUD_MinigameMenu_Open()
406 if ( !HUD_MinigameMenu_IsOpened() )
408 HUD_MinigameMenu_InsertEntry( HUD_MinigameMenu_SpawnEntry(
409 _("Create"), '0 0 0', hud_fontsize*1.5,'0.7 0.84 1', HUD_MinigameMenu_ClickCreate),
410 HUD_MinigameMenu_last_entry );
411 HUD_MinigameMenu_InsertEntry ( HUD_MinigameMenu_SpawnEntry(
412 _("Join"),'0 0 0',hud_fontsize*1.5,'0.7 0.84 1', HUD_MinigameMenu_ClickJoin),
413 HUD_MinigameMenu_last_entry );
414 HUD_MinigameMenu_CurrentButton();
415 HUD_MinigameMenu_activeitem = world;
416 if(autocvar_hud_cursormode)
421 // Handles mouse input on to minigame menu panel
422 void HUD_MinigameMenu_MouseInput()
424 panel = HUD_PANEL(MINIGAME_MENU);
426 HUD_Panel_UpdateCvars();
430 panel_pos += '1 1 0' * panel_bg_padding;
431 panel_size -= '2 2 0' * panel_bg_padding;
436 panel_pos_y += hud_fontsize_y*2;
438 HUD_MinigameMenu_activeitem = world;
440 for ( e = HUD_MinigameMenu_entries; e != world; e = e.list_next )
442 sz = eX*panel_size_x + eY*e.size_y;
445 if ( !HUD_MinigameMenu_activeitem && mousepos_y >= panel_pos_y && mousepos_y <= panel_pos_y + sz_y )
447 HUD_MinigameMenu_activeitem = e;
454 void HUD_MinigameMenu_DrawEntry(vector pos, string s, vector fontsize, vector color)
456 minigame_drawstring_trunc(panel_size_x-pos_x+panel_pos_x, pos, s,
457 fontsize, color, panel_fg_alpha, DRAWFLAG_NORMAL);
459 // Draw a color-coded menu
460 void HUD_MinigameMenu_DrawColoredEntry(vector pos, string s, vector fontsize)
462 minigame_drawcolorcodedstring_trunc(panel_size_x-pos_x+panel_pos_x, pos, s,
463 fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
466 // Minigame menu panel UI
467 void HUD_MinigameMenu ()
469 if ( !HUD_MinigameMenu_IsOpened() )
472 HUD_Panel_UpdateCvars();
478 panel_pos += '1 1 0' * panel_bg_padding;
479 panel_size -= '2 2 0' * panel_bg_padding;
482 HUD_MinigameMenu_DrawEntry(panel_pos,_("Minigames"),hud_fontsize*2,'0.25 0.47 0.72');
483 panel_pos_y += hud_fontsize_y*2;
488 vector imgsz = '22 22 0'; // NOTE: if changed, edit where HUD_MinigameMenu_activeitem is selected
489 for ( entity e = HUD_MinigameMenu_entries; e != world; e = e.list_next )
501 drawfill(panel_pos, eX*panel_size_x + eY*itemh, e.colormod,
502 panel_fg_alpha, DRAWFLAG_NORMAL);
508 drawpic( panel_pos+offset, e.model, imgsz, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
510 offset_y = (imgsz_y-e.size_y) / 2;
514 HUD_MinigameMenu_DrawColoredEntry(panel_pos+offset,e.message,e.size);
516 HUD_MinigameMenu_DrawEntry(panel_pos+offset,e.message,e.size,color);
518 if ( e == HUD_MinigameMenu_activeitem )
519 drawfill(panel_pos, eX*panel_size_x + eY*itemh,'1 1 1', 0.25, DRAWFLAG_ADDITIVE);
521 panel_pos_y += itemh;
525 // ====================================================================
526 // Minigame Help Panel
527 // ====================================================================
529 void HUD_MinigameHelp()
533 if(!autocvar__hud_configure)
534 help_message = active_minigame.message;
536 help_message = "Minigame message";
541 HUD_Panel_UpdateCvars();
550 pos += '1 1 0' * panel_bg_padding;
551 mySize -= '2 2 0' * panel_bg_padding;
554 minigame_drawcolorcodedstring_wrapped( mySize_x, pos, help_message,
555 hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5 );
558 // ====================================================================
559 // Minigame Panel Input
560 // ====================================================================
561 float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary)
564 if( !HUD_MinigameMenu_IsOpened() || autocvar__hud_configure )
569 mousepos_x = nPrimary;
570 mousepos_y = nSecondary;
571 if ( minigame_isactive() && HUD_mouse_over(HUD_PANEL(MINIGAME_BOARD)) )
572 active_minigame.minigame_event(active_minigame,"mouse_moved",mousepos);
578 if(bInputType == 0) {
579 if(nPrimary == K_ALT) hudShiftState |= S_ALT;
580 if(nPrimary == K_CTRL) hudShiftState |= S_CTRL;
581 if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
582 if(nPrimary == K_MOUSE1) mouseClicked |= S_MOUSE1;
583 if(nPrimary == K_MOUSE2) mouseClicked |= S_MOUSE2;
585 else if(bInputType == 1) {
586 if(nPrimary == K_ALT) hudShiftState -= (hudShiftState & S_ALT);
587 if(nPrimary == K_CTRL) hudShiftState -= (hudShiftState & S_CTRL);
588 if(nPrimary == K_SHIFT) hudShiftState -= (hudShiftState & S_SHIFT);
589 if(nPrimary == K_MOUSE1) mouseClicked -= (mouseClicked & S_MOUSE1);
590 if(nPrimary == K_MOUSE2) mouseClicked -= (mouseClicked & S_MOUSE2);
595 con_keys = findkeysforcommand("toggleconsole", 0);
596 int keys = tokenize(con_keys); // findkeysforcommand returns data for this
597 for (int i = 0; i < keys; ++i)
599 if(nPrimary == stof(argv(i)))
603 if ( minigame_isactive() && ( bInputType == 0 || bInputType == 1 ) )
606 string action = bInputType == 0 ? "pressed" : "released";
607 if ( nPrimary >= K_MOUSE1 && nPrimary <= K_MOUSE16 )
609 if ( HUD_mouse_over(HUD_PANEL(MINIGAME_BOARD)) )
615 if ( device && active_minigame.minigame_event(
616 active_minigame,strcat(device,"_",action),nPrimary) )
619 /// TODO: bInputType == 2?
622 if ( bInputType == 0 )
624 if ( nPrimary == K_MOUSE1 && HUD_MinigameMenu_activeitem &&
625 HUD_mouse_over(HUD_PANEL(MINIGAME_MENU)) )
627 HUD_MinigameMenu_Click(HUD_MinigameMenu_activeitem);
630 if ( nPrimary == K_UPARROW || nPrimary == K_KP_UPARROW )
632 if ( HUD_MinigameMenu_activeitem && HUD_MinigameMenu_activeitem.list_prev )
633 HUD_MinigameMenu_activeitem = HUD_MinigameMenu_activeitem.list_prev;
635 HUD_MinigameMenu_activeitem = HUD_MinigameMenu_last_entry;
638 else if ( nPrimary == K_DOWNARROW || nPrimary == K_KP_DOWNARROW )
640 if ( HUD_MinigameMenu_activeitem && HUD_MinigameMenu_activeitem.list_next )
641 HUD_MinigameMenu_activeitem = HUD_MinigameMenu_activeitem.list_next;
643 HUD_MinigameMenu_activeitem = HUD_MinigameMenu_entries;
646 else if ( nPrimary == K_HOME || nPrimary == K_KP_HOME )
648 HUD_MinigameMenu_activeitem = HUD_MinigameMenu_entries;
651 else if ( nPrimary == K_END || nPrimary == K_KP_END )
653 HUD_MinigameMenu_activeitem = HUD_MinigameMenu_entries;
656 else if ( nPrimary == K_KP_ENTER || nPrimary == K_ENTER || nPrimary == K_SPACE )
658 HUD_MinigameMenu_Click(HUD_MinigameMenu_activeitem);
661 else if ( nPrimary == K_ESCAPE )
663 HUD_MinigameMenu_Close();
673 void HUD_Minigame_Mouse()
675 if( !HUD_MinigameMenu_IsOpened() || autocvar__hud_configure || mv_active )
678 if(!autocvar_hud_cursormode)
680 mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
682 mousepos_x = bound(0, mousepos_x, vid_conwidth);
683 mousepos_y = bound(0, mousepos_y, vid_conheight);
686 if ( HUD_MinigameMenu_IsOpened() && HUD_mouse_over(HUD_PANEL(MINIGAME_MENU)) )
687 HUD_MinigameMenu_MouseInput();
689 vector cursorsize = '32 32 0';
690 drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"),
691 cursorsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
694 bool HUD_Minigame_Showpanels()
696 return HUD_MinigameMenu_IsOpened() && ( autocvar__hud_configure || minigame_isactive() );