Linux makefiles
[canaan.git] / prj / cam / src / shock / shkmenu.cpp
blob32f93ef6d9262e5b4fdc9997908b7724ae179881
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 // $Header: r:/t2repos/thief2/src/shock/shkmenu.cpp,v 1.27 2000/02/19 13:25:39 toml Exp $
7 #include <shkmenu.h>
8 #include <appagg.h>
9 #include <drkpanl.h>
10 #include <shkoptmn.h>
11 #include <shksavui.h>
12 #include <shknetui.h>
14 #include <resapi.h>
15 #include <imgrstyp.h>
16 #include <schema.h>
18 #include <drawelem.h>
19 #include <gcompose.h>
20 #include <questapi.h>
21 #include <drkdiff.h>
22 #include <config.h>
23 #include <uigame.h>
25 #include <panltool.h>
26 #include <appapi.h>
27 #include <mprintf.h>
28 #include <campaign.h>
29 #include <metasnd.h>
31 #include <command.h>
32 #include <uiamov.h>
33 #include <uianim.h>
35 #include <netman.h>
37 #include <shkmulti.h>
38 #include <shkgame.h>
39 #include <shkutils.h>
40 #include <playrobj.h>
41 #include <shklding.h>
42 #include <shkpgapi.h>
45 #include <netsynch.h>
46 #include <memall.h>
47 #include <dbmem.h> // must be last header!
49 ////////////////////////////////////////////////////////////
50 // DARK METAGAME MENUS
54 // Base Menu class
56 // Some day, I expect this will
57 // deal with levers and other festoonery
60 class cMenuBase: public cDarkPanel, public cUiAnim
62 public:
63 cMenuBase(const sDarkPanelDesc* desc)
64 : cDarkPanel(desc), cUiAnim(desc->panel_name,INTERFACE_PATH)
68 ~cMenuBase() {};
70 protected:
71 void InitUI()
73 cDarkPanel::InitUI();
74 cUiAnim::InitUI();
77 void TermUI()
79 cUiAnim::TermUI();
80 cDarkPanel::TermUI();
83 void OnLoopMsg(eLoopMessage msg, tLoopMessageData data)
85 cUiAnim::OnLoopMsg(msg,data);
86 cDarkPanel::OnLoopMsg(msg,data);
90 //------------------------------------------------------------
91 // MAIN MENU
94 // Avoid name conflicts
95 class cShockMainMenu;
96 typedef cShockMainMenu cMainMenu;
98 EXTERN void SwitchToShockNewGameMode(BOOL push);
101 class cShockMainMenu: public cMenuBase
103 static sDarkPanelDesc gDesc;
105 public:
106 cMainMenu() : cMenuBase(&gDesc)
110 cMainMenu(const sDarkPanelDesc* pdesc) : cMenuBase(pdesc)
115 enum eRects
117 kNewGame,
118 kLoadGame,
119 kOptions,
120 kCredits,
121 kIntro,
122 kQuit,
124 kNumRects
128 protected:
130 void OnButtonList(ushort action, int button)
132 if (!(action & BUTTONGADG_LCLICK))
133 return ;
135 //SchemaPlay((Label *)"menubutt",NULL);
137 switch (button)
139 case kNewGame:
140 SwitchToShockNewGameMode(TRUE);
141 break;
143 case kLoadGame:
144 SwitchToShockLoadGameMode(TRUE);
145 break;
147 case kOptions:
148 SwitchToShockOptionsMode(TRUE);
149 break;
151 case kCredits:
152 MoviePanel("credits.avi");
153 break;
155 case kIntro:
156 MoviePanel("cs1.avi");
157 break;
159 case kQuit:
161 AutoAppIPtr_(Application,pApp);
162 pApp->Quit();
163 return;
165 break;
173 void OnEscapeKey() // trap escape
179 // Main Menu descriptor
182 static const char* main_button_names[] =
184 "new_game",
185 "load_game",
186 "options",
187 "credits",
188 "intro",
189 "quit",
192 sDarkPanelDesc cMainMenu::gDesc =
194 "main",
195 cMainMenu::kNumRects,
196 cMainMenu::kNumRects,
197 cMainMenu::kNumRects,
198 main_button_names,
199 NULL, // font
201 kMetaSndPanelMain,
204 //------------------------------------------------------------
205 // NET MAIN MENU
208 class cShockNetMainMenu: public cShockMainMenu
210 static sDarkPanelDesc gDesc;
211 typedef cShockMainMenu cParent;
213 public:
214 cShockNetMainMenu() : cParent(&gDesc)
218 enum eRects
220 kNewGame,
221 kLoadGame,
222 kOptions,
223 kCredits,
224 kIntro,
225 kQuit,
226 kMultiPlayer,
228 kNumRects
232 protected:
234 void OnButtonList(ushort action, int button)
236 if (!(action & BUTTONGADG_LCLICK))
237 return ;
239 switch (button)
241 case kMultiPlayer:
242 SwitchToShockMultiplayUIMode(TRUE);
243 break;
245 default:
246 cParent::OnButtonList(action,button);
247 break;
252 void OnLoopMsg(eLoopMessage msg, tLoopMessageData data)
254 cParent::OnLoopMsg(msg,data);
255 switch (msg)
257 case kMsgEnterMode:
258 case kMsgResumeMode:
260 // Disconnect any net session we may be in
261 AutoAppIPtr(NetManager);
262 pNetManager->Leave();
263 // If we had network synch disabled, make sure it's normal
264 // again:
265 NetSynchEnable();
267 break;
276 // Main Menu descriptor
279 static const char* netmain_button_names[] =
281 "new_game",
282 "load_game",
283 "options",
284 "credits",
285 "intro",
286 "quit",
287 "multiplayer",
290 sDarkPanelDesc cShockNetMainMenu::gDesc =
292 "netmain",
293 cShockNetMainMenu::kNumRects,
294 cShockNetMainMenu::kNumRects,
295 cShockNetMainMenu::kNumRects,
296 netmain_button_names,
297 NULL, // font
299 kMetaSndPanelMain,
305 static cMainMenu* gpMainMenu = NULL;
307 void SwitchToShockMainMenuMode(BOOL push)
309 if (gpMainMenu)
311 cAutoIPtr<IPanelMode> panel = gpMainMenu->GetPanelMode();
312 panel->Switch((push) ? kLoopModePush : kLoopModeSwitch);
317 const sLoopInstantiator* DescribeShockMainMenuMode(void)
319 if (gpMainMenu)
321 cAutoIPtr<IPanelMode> panel = gpMainMenu->GetPanelMode();
322 return panel->Instantiator();
324 return NULL;
327 //------------------------------------------------------------
328 // SIM MENU
331 // Avoid name conflicts
332 class cShockSimMenu;
333 typedef cShockSimMenu cSimMenu;
335 class cShockSimMenu: public cMenuBase
337 static sDarkPanelDesc gDesc;
339 public:
340 cSimMenu() : cMenuBase(&gDesc)
344 enum eRects
346 kContinue,
347 kOptions,
348 kSaveGame,
349 kLoadGame,
350 kQuit,
352 kNumRects
355 protected:
357 void OnButtonList(ushort action, int button)
359 if (!(action & BUTTONGADG_LCLICK))
360 return ;
362 //SchemaPlay((Label *)"menubutt",NULL);
364 AutoAppIPtr(NetManager);
366 switch (button)
368 case kContinue:
370 cAutoIPtr<IPanelMode> mode = GetPanelMode();
371 mode->Exit();
373 break;
376 case kOptions:
377 SwitchToShockOptionsMode(TRUE);
378 break;
380 case kSaveGame:
381 if (pNetManager->IsNetworkGame())
383 char levelname[64];
384 ShockGetLevelName(levelname,sizeof(levelname));
385 // okay this is hack-a-riffic
386 if ((stricmp(levelname,"station") == 0) || (stricmp(levelname,"earth") == 0))
387 break;
389 SwitchToShockSaveGameMode(TRUE);
390 break;
392 case kLoadGame:
393 SwitchToShockLoadGameMode(TRUE);
394 break;
396 case kQuit:
398 if (gpMainMenu)
400 // Unwind to the main menu
401 cAutoIPtr<IPanelMode> panel = gpMainMenu->GetPanelMode();
402 panel->Switch(kLoopModeUnwindTo);
407 break;
409 default:
410 Warning(("%s button is unimplemented\n",gDesc.string_names[button]));
411 break;
418 // Sim Menu descriptor
421 static const char* sim_button_names[] =
423 "continue",
424 "options",
425 "save_game",
426 "load_game",
427 "quit",
430 sDarkPanelDesc cSimMenu::gDesc =
432 "sim",
433 cSimMenu::kNumRects,
434 cSimMenu::kNumRects,
435 cSimMenu::kNumRects,
436 sim_button_names,
440 static cSimMenu* gpSimMenu = NULL;
442 void SwitchToShockSimMenuMode(BOOL push)
444 if (gpSimMenu)
446 cAutoIPtr<IPanelMode> panel = gpSimMenu->GetPanelMode();
447 panel->Switch((push) ? kLoopModePush : kLoopModeSwitch);
452 const sLoopInstantiator* DescribeShockSimMenuMode(void)
454 if (gpSimMenu)
456 cAutoIPtr<IPanelMode> panel = gpSimMenu->GetPanelMode();
457 return panel->Instantiator();
459 return NULL;
463 //------------------------------------------------------------
464 // NewGame MENU
467 #define MIN_DIFF 1
468 extern int g_diff;
469 #define DIFF2BUTT(x) (((x) < MIN_DIFF) ? MIN_DIFF - 1 : (x) - 1)
470 #define BUTT2DIFF(x) ((x) + 1)
472 class cShockNewGame: public cDarkPanel
474 static sDarkPanelDesc gDesc;
476 public:
477 cShockNewGame()
478 : cDarkPanel(&gDesc)
480 memset(&mDiffButtons,0,sizeof(mDiffButtons));
483 enum eRects
485 kStart,
486 kOptions,
487 kCancel,
488 kNumButts,
490 kDifficulty = kNumButts,
491 kDiff0,
492 kDiff1,
493 kDiff2,
494 kDiff3,
496 kNumRects,
498 kNumDiffs = kNumRects - kDiff0,
502 protected:
503 guiStyle mDiffStyle;
504 LGadButtonList mDiffButtons;
505 DrawElement mDiffElems[kNumDiffs];
506 cStr mDiffStrs[kNumDiffs];
508 static bool DiffCB (ushort action, int button, void *data, LGadBox *)
510 g_diff = BUTT2DIFF(button);
511 return FALSE;
514 void InitUI()
516 cDarkPanel::InitUI();
518 // default to current style colors
519 AssertMsg(GetCurrentStyle(),"No current style for diff defaults");
520 memset(&mDiffStyle,0,sizeof(mDiffStyle));
521 memcpy(mDiffStyle.colors,GetCurrentStyle()->colors,sizeof(mDiffStyle.colors));
522 uiGameLoadStyle("diff_",&mDiffStyle,mResPath);
524 // set up drawlelems for diff
525 for (int i = 0; i < kNumDiffs; i++)
527 DrawElement& elem = mDiffElems[i];
528 memset(&elem,0,sizeof(elem));
530 char buf[16];
531 sprintf(buf,"diff_%d",i);
532 mDiffStrs[i] = FetchUIString(panel_name,buf,mResPath);
533 elem.draw_type = DRAWTYPE_TEXT;
534 elem.draw_data = (void*)(const char*)mDiffStrs[i];
535 elem.draw_flags = INTERNAL(DRAWFLAG_INT_TRANSP);
538 LGadButtonListDesc desc =
540 kNumDiffs,
541 &mRects[(int)kDiff0],
542 mDiffElems,
543 DiffCB,
545 BUTTONLIST_RADIO_FLAG,
548 LGadCreateButtonListDesc(&mDiffButtons,LGadCurrentRoot(),&desc);
550 //set the current difficulty setting
551 if (g_diff < MIN_DIFF) g_diff = MIN_DIFF;
552 LGadRadioButtonSelect (&mDiffButtons, DIFF2BUTT(g_diff));
553 int flags = LGadBoxFlags(&mDiffButtons);
554 LGadBoxSetFlags(&mDiffButtons, flags | BOXFLAG_CLEAR);
555 LGadBoxSetStyle(&mDiffButtons,&mDiffStyle);
558 void TermUI()
560 g_diff = BUTT2DIFF(LGadRadioButtonSelection(&mDiffButtons));
561 LGadDestroyButtonList(&mDiffButtons);
562 memset(&mDiffElems,0,sizeof(mDiffElems));
563 for (int i = 0; i < kNumDiffs; i++)
564 mDiffStrs[i] = "";
566 uiGameUnloadStyle(&mDiffStyle);
567 cDarkPanel::TermUI();
570 void RedrawDisplay()
573 // Draw the difficulty string. This is a lot of code to draw a lousy string.
575 cStr str = FetchUIString(panel_name,"difficulty",mResPath); // copy the string
576 char* s = (char*)(const char*)str; // get a mutable pointer
578 Rect& r = mRects[(int)kDifficulty];
580 GUIcompose c;
581 GUIsetup(&c,&r,GUIcomposeFlags(ComposeFlagClear|ComposeFlagRead),GUI_CANV_ANY);
583 guiStyleSetupFont(&mDiffStyle,StyleFontTitle);
584 gr_set_fcolor(guiStyleGetColor(&mDiffStyle,StyleColorText));
586 gr_font_string_wrap(gr_get_font(),s,RectWidth(&r));
588 short w,h;
589 gr_string_size(s,&w,&h);
591 gr_string(s,(RectWidth(&r) - w)/2,(RectHeight(&r) - h)/2);
592 // gr_string(s,gr_char_width('X'),(RectHeight(&r) - h)/2);
594 guiStyleCleanupFont(&mDiffStyle,StyleFontTitle) ;
596 GUIdone(&c);
599 // Make sure the buttonlist gets drawn
601 region_expose(LGadBoxRegion(&mDiffButtons),LGadBoxRect(&mDiffButtons));
605 // Actually do the work of starting a game
607 void StartGame()
610 // Push the init game mode, and the initial cutscene
611 // mode to the mode stack. That way the cutscene happens first.
612 SwitchToShockInitGame(FALSE);
613 MoviePanel("cs1.avi");
617 BOOL mGo;
619 void OnButtonList(ushort action, int button)
621 if (!(action & BUTTONGADG_LCLICK))
622 return ;
624 //SchemaPlay((Label *)"menubutt",NULL);
626 switch (button)
628 case kStart:
630 mGo = TRUE;
632 break;
634 case kOptions:
635 SwitchToShockOptionsMode(TRUE);
636 break;
638 case kCancel:
640 cAutoIPtr<IPanelMode> mode = GetPanelMode();
641 mode->Exit();
643 break;
649 void OnLoopMsg(eLoopMessage msg, tLoopMessageData data)
651 switch(msg)
653 case kMsgEnterMode:
654 mGo = FALSE;
655 break;
656 case kMsgNormalFrame:
657 if (mGo) StartGame();
658 break;
661 cDarkPanel::OnLoopMsg(msg,data);
668 // NewGame Menu descriptor
671 static const char* newgame_button_names[] =
673 "start",
674 "options",
675 "cancel"
678 sDarkPanelDesc cShockNewGame::gDesc =
680 "newgame",
681 cShockNewGame::kNumButts,
682 cShockNewGame::kNumRects,
683 cShockNewGame::kNumButts,
684 newgame_button_names,
685 NULL,
687 kMetaSndPanelMain,
691 static cShockNewGame* gpNewGame = NULL;
693 void SwitchToShockNewGameMode(BOOL push)
695 if (gpNewGame)
697 cAutoIPtr<IPanelMode> panel = gpNewGame->GetPanelMode();
698 panel->Switch((push) ? kLoopModePush : kLoopModeSwitch);
703 const sLoopInstantiator* DescribeShockNewGameMode(void)
705 if (gpNewGame)
707 cAutoIPtr<IPanelMode> panel = gpNewGame->GetPanelMode();
708 return panel->Instantiator();
710 return NULL;
713 //------------------------------------------------------------------
714 // INIT/TERM
718 void init_commands();
721 void ShockMenusInit()
723 if (config_is_defined("netplay_ui"))
724 gpMainMenu = new cShockNetMainMenu;
725 else
726 gpMainMenu = new cMainMenu;
727 gpSimMenu = new cSimMenu;
728 gpNewGame = new cShockNewGame;
730 init_commands();
732 // default difficulty
733 g_diff = MIN_DIFF + 1;
735 // What the hell. Initialize the loading screens too
736 ShockLoadingInit();
737 ShockMultiplayUIInit();
740 void ShockMenusTerm()
742 delete gpMainMenu;
743 delete gpSimMenu;
744 delete gpNewGame;
746 ShockLoadingTerm();
747 ShockMultiplayUITerm();
751 //----------------------------------------
752 // COMMANDS
755 static void do_mainmenu()
757 SwitchToShockMainMenuMode(TRUE);
760 static void do_simmenu()
762 // don't do anything if the trigger is pulled
763 AutoAppIPtr(PlayerGun);
764 ObjID gun = pPlayerGun->Get();
765 if ((gun != OBJ_NULL) && pPlayerGun->IsTriggerPulled())
766 return;
768 // throw any objects on the cursor into the world
769 if (drag_obj != OBJ_NULL)
771 ThrowObj(drag_obj,PlayerObject());
772 ClearCursor();
774 SwitchToShockSimMenuMode(TRUE);
779 static Command commands[] =
781 { "main_menu", FUNC_VOID, do_mainmenu, "Go to main menu.", HK_ALL },
782 { "sim_menu", FUNC_VOID, do_simmenu, "Go to sim menu.", HK_ALL },
787 static void init_commands()
789 COMMANDS(commands,HK_ALL);