1 /////////////////////////////////////////
2 //
3 // OpenLieroX
4 //
5 // code under LGPL, based on JasonBs work,
6 // enhanced by Dark Charlie and Albert Zeyer
7 //
8 //
9 /////////////////////////////////////////
10
11
12 // Local menu
13 // Created 30/6/02
14 // Jason Boettcher
15
16
17 #include <assert.h>
18 #include <string>
19
20 #include "LieroX.h"
21 #include "CGameScript.h"
22 #include "AuxLib.h"
23 #include "DeprecatedGUI/Graphics.h"
24 #include "CClient.h"
25 #include "CServer.h"
26 #include "DeprecatedGUI/Menu.h"
27 #include "DeprecatedGUI/CListview.h"
28 #include "GfxPrimitives.h"
29 #include "FindFile.h"
30 #include "StringUtils.h"
31 #include "DeprecatedGUI/CButton.h"
32 #include "DeprecatedGUI/CLabel.h"
33 #include "DeprecatedGUI/CImage.h"
34 #include "DeprecatedGUI/CTextbox.h"
35 #include "DeprecatedGUI/CSlider.h"
36 #include "DeprecatedGUI/CCheckbox.h"
37 #include "DeprecatedGUI/CTextButton.h"
38 #include "DeprecatedGUI/CListview.h"
39 #include "DeprecatedGUI/CGuiSkinnedLayout.h"
40 #include "DeprecatedGUI/CBrowser.h"
41 #include "Sounds.h"
42 #include "ProfileSystem.h"
43 #include "FeatureList.h"
44 #include "Options.h"
45 #include "CGameMode.h"
46
47
48 namespace DeprecatedGUI {
49
50 /*
51 =======================
52
53 Weapons Restrictions
54
55 For both local & host
56
57 =======================
58 */
59
60
61 CGuiLayout cWeaponsRest;
62 static CWpnRest cWpnRestList;
63 static CGameScript *cWpnGameScript = NULL;
64
65 // State strings
66 static const std::string szStates[] = {"Enabled", "Bonus", "Banned"};
67
68 // Weapons Restrictions
69 enum {
70 wr_Ok,
71 wr_Reset,
72 wr_ListBox,
73 wr_Cancel,
74 wr_Random,
75 wr_Load,
76 wr_Save,
77 wr_List,
78 };
79
80 static std::list<wpnrest_t *> tWeaponList;
81
82 /////////////////
83 // Updates the weapon list that is shown in the dialog
UpdateWeaponList()84 static void UpdateWeaponList()
85 {
86 tWeaponList.clear();
87 wpnrest_t *psWpn = cWpnRestList.getList();
88 if (!psWpn)
89 return;
90
91 for(int i=0; i < cWpnRestList.getNumWeapons(); i++) {
92 if(cWpnGameScript->weaponExists(psWpn[i].psLink->szName))
93 tWeaponList.push_back(&psWpn[i]);
94 }
95 }
96
UpdateWeaponListWidget()97 static void UpdateWeaponListWidget()
98 {
99 const Color cStateColours[] = { tLX->clNormalLabel, tLX->clSubHeading, tLX->clDisabled };
100
101 int idx = 0;
102 CListview *listWidget = dynamic_cast<CListview *>(cWeaponsRest.getWidget(wr_List));
103 if (!listWidget)
104 return;
105 listWidget->Clear();
106 for (auto weapon: tWeaponList) {
107 std::string buf = weapon->psLink->szName;
108 stripdot(buf,245);
109 listWidget->AddItem(buf, idx, tLX->clNormalLabel);
110 listWidget->AddSubitem(buf);
111 listWidget->AddSubitem(szStates[weapon->psLink->nState], VALIGN_MIDDLE, cStateColours[weapon->psLink->nState]);
112 idx++;
113 }
114 }
115
116 ///////////////////
117 // Initialize the weapons restrictions
Menu_WeaponsRestrictions(const std::string & szMod)118 void Menu_WeaponsRestrictions(const std::string& szMod)
119 {
120
121 // Setup the buffer
122 DrawImageAdv(tMenu->bmpBuffer.get(), tMenu->bmpMainBack_common, 120,150,120,150, 400,330);
123 Menu_DrawBox(tMenu->bmpBuffer.get(), 120,150, 520,470);
124 //DrawRectFillA(tMenu->bmpBuffer, 122,152, 518,438, 0, 100);
125
126
127 Menu_RedrawMouse(true);
128
129 cWeaponsRest.Initialize();
130 cWeaponsRest.Add( new CLabel("Weapon Options", tLX->clNormalLabel), -1, 275,155, 0, 0);
131 cWeaponsRest.Add( new CButton(BUT_RESET, tMenu->bmpButtons),wr_Reset, 180,420, 60,15);
132 cWeaponsRest.Add( new CButton(BUT_RANDOM, tMenu->bmpButtons),wr_Random,280,420, 80,15);
133 cWeaponsRest.Add( new CButton(BUT_OK, tMenu->bmpButtons), wr_Ok, 400,420, 30,15);
134 cWeaponsRest.Add( new CButton(BUT_LOAD, tMenu->bmpButtons), wr_Load, 250,445, 60,15);
135 cWeaponsRest.Add( new CButton(BUT_SAVE, tMenu->bmpButtons), wr_Save, 330,445, 60,15);
136 CListview * listWidget = new CListview();
137 cWeaponsRest.Add( listWidget, wr_List, 180,185, 320,230);
138 listWidget->AddColumn("", 240);
139 listWidget->AddColumn("", 55);
140
141 // Load the weapons
142 cWpnRestList.loadList("cfg/wpnrest.dat");
143
144
145 //
146 // Update the list with the currently selected mod
147 //
148
149 cWpnGameScript = new CGameScript;
150 if( cWpnGameScript ) {
151 if( cWpnGameScript->Load(szMod) )
152 cWpnRestList.updateList( cWpnGameScript );
153 }
154
155 // Get the weapons for the list
156 UpdateWeaponList();
157 UpdateWeaponListWidget();
158 }
159
160 //////////////////
161 // Shutdown the weapon restrictions
Menu_WeaponsRestrictionsShutdown()162 void Menu_WeaponsRestrictionsShutdown()
163 {
164 cWeaponsRest.Shutdown();
165
166 cWpnRestList.saveList("cfg/wpnrest.dat");
167 cWpnRestList.Shutdown();
168
169 if (cWpnGameScript) {
170 // HINT: the gamescript is shut down by the cache
171 delete cWpnGameScript;
172 cWpnGameScript = NULL;
173 }
174 }
175
176
177 ///////////////////
178 // Weapons Restrictions frame
179 // Returns whether or not we have finished with the weapons restrictions
Menu_WeaponsRestrictions_Frame()180 bool Menu_WeaponsRestrictions_Frame()
181 {
182 gui_event_t *ev = NULL;
183 //Uint32 blue = MakeColour(0,138,251);
184
185 assert(cWpnGameScript);
186
187
188 DrawImageAdv(VideoPostProcessor::videoSurface(), tMenu->bmpBuffer, 120,150, 120,150, 400,300);
189
190 /*
191 // Draw the list
192 int count = cWeaponsRest.SendMessage(wr_Scroll, SCM_GETVALUE,(DWORD)0,0);
193
194 int w, j;
195 w = j = 0;
196 for (std::list<wpnrest_t *>::iterator it = tWeaponList.begin(); it != tWeaponList.end(); it++) {
197 if( w++ < count )
198 continue;
199 if( j > 10 )
200 break;
201
202 int y = 190 + (j++)*20;
203 Color Colour = tLX->clNormalLabel;
204 Color StateColour = Colour;
205 if( (*it)->psLink->nState == wpr_bonus ) // Different color will make it more comfortable for eyes
206 StateColour = tLX->clSubHeading;
207 if( (*it)->psLink->nState == wpr_banned )
208 StateColour = tLX->clDisabled;
209
210 // If a mouse is over the line, highlight it
211 if( Mouse->X > 150 && Mouse->X < 450 ) {
212 if( Mouse->Y > y && Mouse->Y < y+20 ) {
213 Colour = tLX->clMouseOver;
214 StateColour = tLX->clMouseOver;
215
216 // If the mouse has been clicked, cycle through the states
217 if( Mouse->Up & SDL_BUTTON(1) ) {
218 (*it)->psLink->nState++;
219 (*it)->psLink->nState %= 3;
220 }
221 }
222 }
223
224 std::string buf = (*it)->psLink->szName;
225 stripdot(buf,245);
226 tLX->cFont.Draw( VideoPostProcessor::videoSurface(), 150, y, Colour, buf );
227 tLX->cFont.Draw( VideoPostProcessor::videoSurface(), 400, y, StateColour, szStates[(*it)->psLink->nState] );
228 }
229
230 // Adjust the scrollbar
231 cWeaponsRest.SendMessage(wr_Scroll, SCM_SETITEMSPERBOX, 12, 0);
232 cWeaponsRest.SendMessage(wr_Scroll, SCM_SETMIN, (DWORD)0, 0);
233 if(tWeaponList.size() > 10)
234 cWeaponsRest.SendMessage(wr_Scroll, SCM_SETMAX, tWeaponList.size() + 1, 0);
235 else
236 cWeaponsRest.SendMessage(wr_Scroll, SCM_SETMAX, (DWORD)0, 0);
237 */
238
239
240 ev = cWeaponsRest.Process();
241 cWeaponsRest.Draw(VideoPostProcessor::videoSurface());
242
243 if(ev) {
244
245 switch(ev->iControlID) {
246
247 // OK, done
248 case wr_Ok:
249 if(ev->iEventMsg == BTN_CLICKED) {
250
251 Menu_WeaponsRestrictionsShutdown();
252
253 return true;
254 }
255 break;
256
257 // Reset the list
258 case wr_Reset:
259 if( ev->iEventMsg == BTN_CLICKED ) {
260 cWpnRestList.cycleVisible(cWpnGameScript);
261 UpdateWeaponListWidget();
262 }
263 break;
264
265 // Randomize the list
266 case wr_Random:
267 if(ev->iEventMsg == BTN_CLICKED) {
268 cWpnRestList.randomizeVisible(cWpnGameScript);
269 UpdateWeaponListWidget();
270 }
271 break;
272
273 // Open the load dialog
274 case wr_Load:
275 if(ev->iEventMsg == BTN_CLICKED) {
276 Menu_WeaponPresets(false,&cWpnRestList);
277 UpdateWeaponListWidget();
278 }
279 break;
280
281 // Open the save dialog
282 case wr_Save:
283 if(ev->iEventMsg == BTN_CLICKED) {
284 Menu_WeaponPresets(true,&cWpnRestList);
285 UpdateWeaponListWidget();
286 }
287 break;
288
289 case wr_List:
290 if (ev->iEventMsg == LV_ENTER || ev->iEventMsg == LV_DOUBLECLK) {
291 const Color cStateColours[] = { tLX->clNormalLabel, tLX->clSubHeading, tLX->clDisabled };
292 CListview *listWidget = dynamic_cast<CListview *>(cWeaponsRest.getWidget(wr_List));
293 lv_subitem_t *sub = listWidget->getCurSubitem(1);
294 if (sub) {
295 int idx = 0;
296 for (auto weapon: tWeaponList) {
297 if (idx == listWidget->getCurIndex()) {
298 weapon->psLink->nState++;
299 weapon->psLink->nState %= 3;
300 sub->sText = szStates[weapon->psLink->nState];
301 sub->iColour = cStateColours[weapon->psLink->nState];
302 break;
303 }
304 idx++;
305 }
306 }
307 }
308 break;
309 }
310 }
311
312 // Draw the mouse
313 DrawCursor(VideoPostProcessor::videoSurface());
314
315 return false;
316 }
317
318
319 ///////////////////
320 // Weapon presets load/save
321 // For both local and host
322 enum {
323 wp_Cancel=0,
324 wp_Ok,
325 wp_PresetList,
326 wp_PresetName
327 };
328
329 CGuiLayout cWpnPresets;
330
331 struct WeaponPresetsAdder {
332 CListview* listview;
WeaponPresetsAdderDeprecatedGUI::WeaponPresetsAdder333 WeaponPresetsAdder(CListview* lv_) : listview(lv_) {}
operator ()DeprecatedGUI::WeaponPresetsAdder334 bool operator() (const std::string& f) {
335 if(stringcaseequal(GetFileExtension(f),"wps")) {
336 std::vector<std::string> fnparts = ListAsVector(SplitFilename(f, 3));
337 if(fnparts.size() < 3) return true; // strange
338 std::string fname = fnparts[1] + "/" + fnparts[2];
339 if(stringcaseequal(fnparts[0], "cfg") && stringcaseequal(fnparts[1], "presets"))
340 fname = fnparts[2];
341 std::string name = GetBaseFilenameWithoutExt(fname);
342 if(!listview->getItem(fname)) {
343 listview->AddItem(fname,0,tLX->clListView);
344 listview->AddSubitem(LVS_TEXT, name, (DynDrawIntf*)NULL, NULL);
345 }
346 }
347 return true;
348 }
349 };
350
Menu_WeaponPresets(bool save,CWpnRest * wpnrest)351 void Menu_WeaponPresets(bool save, CWpnRest *wpnrest)
352 {
353 if (!wpnrest)
354 return;
355
356 gui_event_t *ev = NULL;
357 int quitloop = false;
358 CTextbox *t;
359
360 // Save the background
361 DrawImageAdv(tMenu->bmpBuffer.get(), VideoPostProcessor::videoSurface(), 0,0, 0,0, 640,480);
362
363 Menu_RedrawMouse(true);
364
365 cWpnPresets.Initialize();
366
367 cWpnPresets.Add( new CButton(BUT_CANCEL, tMenu->bmpButtons), wp_Cancel, 180,310, 75,15);
368 cWpnPresets.Add( new CButton(BUT_OK, tMenu->bmpButtons), wp_Ok, 430,310, 40,15);
369 cWpnPresets.Add( new CListview(), wp_PresetList, 180,170, 280,110+(!save)*20);
370 cWpnPresets.Add( new CTextbox(), wp_PresetName, 270,285, 190,tLX->cFont.GetHeight());
371
372 cWpnPresets.SendMessage(wp_PresetList,LVM_SETOLDSTYLE,(DWORD)0,0);
373
374 t = (CTextbox *)cWpnPresets.getWidget(wp_PresetName);
375
376 // Hide the textbox for Load
377 t->setEnabled(save);
378
379 // Load the level list
380
381 CListview *lv = (CListview *)cWpnPresets.getWidget(wp_PresetList);
382 lv->AddColumn("Weapon presets",60);
383
384 WeaponPresetsAdder adder(lv);
385 FindFiles(adder, "cfg/presets/" + cWpnGameScript->directory(), false, FM_REG);
386 FindFiles(adder, "cfg/presets", false, FM_REG);
387
388 lv->SortBy( 0, true );
389
390 ProcessEvents();
391 while(!WasKeyboardEventHappening(SDLK_ESCAPE,false) && !quitloop && tMenu->bMenuRunning) {
392 Menu_RedrawMouse(true);
393
394 //DrawImageAdv(VideoPostProcessor::videoSurface(),tMenu->bmpBuffer, 170,150, 170,150, 300, 180);
395 Menu_DrawBox(VideoPostProcessor::videoSurface(), 170, 150, 470, 330);
396 DrawImageAdv(VideoPostProcessor::videoSurface(), tMenu->bmpMainBack_common, 172,152, 172,152, 297,177);
397 DrawImageAdv(tMenu->bmpBuffer.get(), tMenu->bmpMainBack_common, 172,152, 172,152, 297,177);
398
399 tLX->cFont.DrawCentre(VideoPostProcessor::videoSurface(), 320, 155, tLX->clNormalLabel, save ? "Save" : "Load");
400 if (save)
401 tLX->cFont.Draw(VideoPostProcessor::videoSurface(), 180,288,tLX->clNormalLabel,"Preset name");
402
403 ev = cWpnPresets.Process();
404 cWpnPresets.Draw(VideoPostProcessor::videoSurface());
405
406 // Process the widgets
407 if(ev) {
408
409 switch(ev->iControlID) {
410 // Cancel
411 case wp_Cancel:
412 if(ev->iEventMsg == BTN_CLICKED) {
413 PlaySoundSample(sfxGeneral.smpClick);
414 quitloop = true;
415 }
416 break;
417
418 // Presets list
419 case wp_PresetList:
420 if(ev->iEventMsg != LV_NONE) {
421 if(save) t->setText( GetBaseFilenameWithoutExt(lv->getCurSIndex()) );
422 else t->setText( lv->getCurSIndex() );
423 }
424 break;
425 }
426
427 // OK and double click on listview
428 if (ev->iControlID == wp_Ok || ev->iControlID == wp_PresetList) {
429 if((ev->iEventMsg == BTN_CLICKED && ev->iControlID == 1) || ev->iEventMsg == LV_DOUBLECLK || ev->iEventMsg == LV_ENTER) {
430
431 // Play the sound only for OK button
432 if (ev->iControlID == wp_Ok)
433 PlaySoundSample(sfxGeneral.smpClick);
434
435 // Don't process when nothing is selected
436 if(t->getText().length() > 0) {
437
438 quitloop = true;
439 if(save) {
440
441 // Save
442 std::string fn = "cfg/presets/" + cWpnGameScript->directory() + "/" + t->getText(); // + ".wps";
443 if(fn.find(".wps") == std::string::npos )
444 fn += ".wps";
445
446 // Check if it exists already. If so, ask user if they wanna overwrite
447 if(Menu_WeaponPresetsOkSave(fn))
448 wpnrest->saveList(fn);
449 else
450 quitloop = false;
451 } else {
452
453 // Load
454 std::string fn = "cfg/presets/" + t->getText();
455 wpnrest->loadList(fn);
456 wpnrest->updateList(cWpnGameScript);
457 UpdateWeaponList();
458 }
459 }
460 }
461 }
462 }
463
464 // Draw mouse
465 DrawCursor(VideoPostProcessor::videoSurface());
466
467 // Display the dialog
468 doVideoFrameInMainThread();
469
470 CapFPS();
471 WaitForNextEvent();
472 }
473
474 // Redraw back to normal
475 DrawImageAdv(tMenu->bmpBuffer.get(), tMenu->bmpMainBack_common, 120,150,122,152, 396,316);
476 DrawImage(VideoPostProcessor::videoSurface(),tMenu->bmpBuffer,0,0);
477
478 Menu_RedrawMouse(true);
479
480 Menu_WeaponPresetsShutdown();
481 }
482
483 /////////////
484 // Shutdown
Menu_WeaponPresetsShutdown()485 void Menu_WeaponPresetsShutdown()
486 {
487 cWpnPresets.Shutdown();
488 }
489
490
491 ///////////////////
492 // Check if there is a possible overwrite
Menu_WeaponPresetsOkSave(const std::string & szFilename)493 bool Menu_WeaponPresetsOkSave(const std::string& szFilename)
494 {
495 std::string filename = szFilename;
496
497 // Adjust the filename
498 if( stringcasecmp(GetFileExtension( szFilename ), "wps") != 0)
499 filename += ".wps";
500
501 FILE *fp = OpenGameFile(filename,"rb");
502 if( fp == NULL)
503 // File doesn't exist, ok to save
504 return true;
505
506 fclose(fp);
507
508
509 // The file already exists, show a message box to confirm the overwrite
510 int nResult = Menu_MessageBox("Confirmation","The preset already exists. Overwrite?", LMB_YESNO);
511 if( nResult == MBR_YES )
512 return true;
513
514
515 // No overwrite
516 return false;
517 }
518
519 }; // namespace DeprecatedGUI
520