Avoid an additional map list reload on menu start
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / xonotic / dialog_multiplayer_create.qc
1 #include "dialog_multiplayer_create.qh"
2
3 #include "dialog_multiplayer_create_mapinfo.qh"
4 #include "dialog_multiplayer_create_mutators.qh"
5
6 #include "gametypelist.qh"
7 #include "maplist.qh"
8 #include <common/mapinfo.qh>
9
10 #include "image.qh"
11 #include "textslider.qh"
12 #include "textlabel.qh"
13 #include "slider.qh"
14 #include "mainwindow.qh"
15 #include "button.qh"
16 #include "inputbox.qh"
17
18 void GameType_ConfigureSliders(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip)
19 {
20         int i;
21         entity e = me.sliderFraglimit;
22         entity l = me.labelFraglimit;
23         e.configureXonoticTextSlider(e, pCvar, pTooltip);
24         e.disabled = l.disabled = !pCvar;
25         l.setText(l, pLabel);
26
27         // clear old values
28         for(i = 0; i < e.nValues; ++i);
29         {
30                 if(e.(valueStrings[i]))
31                 {
32                         strunzone(e.(valueStrings[i]));
33                         e.(valueStrings[i]) = string_null;
34                 }
35                 if(e.(valueIdentifiers[i]))
36                 {
37                         strunzone(e.(valueIdentifiers[i]));
38                         e.(valueIdentifiers[i]) = string_null;
39                 }
40         }
41         e.clearValues(e);
42
43         if(pCvar != "")
44         {
45                 // set new values
46                 e.addValue(e, strzone(_("Default")), strzone("-1"));
47                 for(i = pMin; i <= pMax; i += pStep) { e.addValue(e, strzone(ftos(i)), strzone(ftos(i))); }
48                 e.addValue(e, strzone(_("Unlimited")), strzone("0"));
49         }
50         e.configureXonoticTextSliderValues(e);
51
52
53         entity t = me.sliderTeams;
54         entity tl = me.labelTeams;
55         t.configureXonoticTextSlider(t, tCvar, string_null);
56         tl.disabled = t.disabled = !tCvar;
57         t.nValues = (tCvar == "") ? 0 : 4; // instead of clearing / readding the very same values
58         t.configureXonoticTextSliderValues(t);
59 }
60
61 void GameType_ConfigureSliders_for_CurrentGametype(entity me)
62 {
63         switch(MapInfo_CurrentGametype())
64         {
65                 case MAPINFO_TYPE_CA:              GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_ca_teams_override",          _("The amount of frags needed before the match will end")); break;
66                 case MAPINFO_TYPE_FREEZETAG:       GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        "g_freezetag_teams_override",   _("The amount of frags needed before the match will end")); break;
67                 case MAPINFO_TYPE_CTF:             GameType_ConfigureSliders(me, _("Capture limit:"),   1,   20,  1, "capturelimit_override",     string_null,                    _("The amount of captures needed before the match will end")); break;
68                 case MAPINFO_TYPE_DOMINATION:      GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, "g_domination_point_limit",  "g_domination_teams_override",  _("The amount of points needed before the match will end")); break;
69                 case MAPINFO_TYPE_KEYHUNT:         GameType_ConfigureSliders(me, _("Point limit:"),   200, 1500, 50, "g_keyhunt_point_limit",     "g_keyhunt_teams_override",     _("The amount of points needed before the match will end")); break;
70                 case MAPINFO_TYPE_LMS:             GameType_ConfigureSliders(me, _("Lives:"),           3,   50,  1, "g_lms_lives_override",      string_null,                    string_null); break;
71                 case MAPINFO_TYPE_RACE:            GameType_ConfigureSliders(me, _("Laps:"),            1,   25,  1, "g_race_laps_limit",         string_null,                    string_null); break;
72                 case MAPINFO_TYPE_NEXBALL:         GameType_ConfigureSliders(me, _("Goals:"),           1,   50,  1, "g_nexball_goallimit",       string_null,                    _("The amount of goals needed before the match will end")); break;
73                 case MAPINFO_TYPE_ASSAULT:         GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
74                 case MAPINFO_TYPE_ONSLAUGHT:       GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
75                 case MAPINFO_TYPE_CTS:             GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
76                 case MAPINFO_TYPE_INVASION:        GameType_ConfigureSliders(me, _("Point limit:"),    50,  500, 10, string_null,                 string_null,                    string_null); break;
77                 case MAPINFO_TYPE_TEAM_DEATHMATCH: GameType_ConfigureSliders(me, _("Point limit:"),     5,  100,  5, "g_tdm_point_limit",         "g_tdm_teams_override",         _("The amount of points needed before the match will end")); break;
78                 default:                           GameType_ConfigureSliders(me, _("Frag limit:"),      5,  100,  5, "fraglimit_override",        string_null,                    _("The amount of frags needed before the match will end")); break;
79         }
80 }
81
82 entity makeXonoticServerCreateTab()
83 {
84         entity me;
85         me = NEW(XonoticServerCreateTab);
86         me.configureDialog(me);
87         return me;
88 }
89
90 void XonoticServerCreateTab_fill(entity me)
91 {
92         entity e, e0;
93
94         // the left half begins here
95
96         me.gotoRC(me, 0.5, 0);
97                 me.TD(me, 1, 3, makeXonoticHeaderLabel(_("Gametype")));
98         me.TR(me);
99                 me.TD(me, 10.5, 3, e = makeXonoticGametypeList());
100
101         me.gotoRC(me, 12.5, 0);
102                 me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Time limit:")));
103                 me.TD(me, 1, 2, e = makeXonoticTextSlider_T("timelimit_override",
104                         _("Timelimit in minutes that when hit, will end the match")));
105                         #define ADDVALUE_MINUTES(i) e.addValue(e, strzone(sprintf(_("%d minutes"), i)), #i)
106                         e.addValue(e, ZCTX(_("TIMLIM^Default")), "-1");
107                         e.addValue(e, _("1 minute"), "1");
108                         ADDVALUE_MINUTES(2);
109                         ADDVALUE_MINUTES(3);
110                         ADDVALUE_MINUTES(4);
111                         ADDVALUE_MINUTES(5);
112                         ADDVALUE_MINUTES(6);
113                         ADDVALUE_MINUTES(7);
114                         ADDVALUE_MINUTES(8);
115                         ADDVALUE_MINUTES(9);
116                         ADDVALUE_MINUTES(10);
117                         ADDVALUE_MINUTES(15);
118                         ADDVALUE_MINUTES(20);
119                         ADDVALUE_MINUTES(25);
120                         ADDVALUE_MINUTES(30);
121                         ADDVALUE_MINUTES(40);
122                         ADDVALUE_MINUTES(50);
123                         ADDVALUE_MINUTES(60);
124                         e.addValue(e, ZCTX(_("TIMLIM^Infinite")), "0");
125                         e.configureXonoticTextSliderValues(e);
126                         #undef ADDVALUE_MINUTES
127         me.TR(me);
128                 me.TD(me, 1, 1, me.labelFraglimit = makeXonoticTextLabel(0, _("Frag limit:")));
129                 me.TD(me, 1, 2, e = me.sliderFraglimit = makeXonoticTextSlider("fraglimit_override"));
130
131         me.gotoRC(me, 15, 0);
132                 me.TD(me, 1, 1, me.labelTeams = makeXonoticTextLabel(0, _("Teams:")));
133                 me.TD(me, 1, 2, e = me.sliderTeams = makeXonoticTextSlider(string_null));
134                         e.addValue(e, _("Default"), "0");
135                         e.addValue(e, _("2 teams"), "2");
136                         e.addValue(e, _("3 teams"), "3");
137                         e.addValue(e, _("4 teams"), "4");
138                         e.configureXonoticTextSliderValues(e);
139         me.TR(me);
140                 me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Player slots:")));
141                 me.TD(me, 1, 2, e = makeXonoticSlider_T(1, 32, 1, "menu_maxplayers",
142                         _("The maximum amount of players or bots that can be connected to your server at once")));
143         me.TR(me);
144                 me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Number of bots:")));
145                 me.TD(me, 1, 2, e = makeXonoticSlider_T(0, 9, 1, "bot_number",
146                         _("Amount of bots on your server")));
147         me.TR(me);
148                 me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Bot skill:")));
149                         setDependent(e, "bot_number", 0, -1);
150                 me.TD(me, 1, 2, e = makeXonoticTextSlider_T("skill",
151                         _("Specify how experienced the bots will be")));
152                         e.addValue(e, _("Botlike"), "0");
153                         e.addValue(e, _("Beginner"), "1");
154                         e.addValue(e, _("You will win"), "2");
155                         e.addValue(e, _("You can win"), "3");
156                         e.addValue(e, _("You might win"), "4");
157                         e.addValue(e, _("Advanced"), "5");
158                         e.addValue(e, _("Expert"), "6");
159                         e.addValue(e, _("Pro"), "7");
160                         e.addValue(e, _("Assassin"), "8");
161                         e.addValue(e, _("Unhuman"), "9");
162                         e.addValue(e, _("Godlike"), "10");
163                         e.configureXonoticTextSliderValues(e);
164                         setDependent(e, "bot_number", 0, -1);
165
166         me.gotoRC(me, me.rows - 3.8, 0);
167                 me.TD(me, 1, 3, e0 = makeXonoticTextLabel(0.5, string_null));
168                         e0.textEntity = main.mutatorsDialog;
169                         e0.allowCut = 1;
170                         //e0.allowWrap = 1;
171
172         // mapListBox is in the right column but the ref is needed for mutators dialog here
173         me.mapListBox = makeXonoticMapList();
174         // here we use the following line instead of me.TR(me) for better visual spacing;
175         // this decision was made in this poll: http://forums.xonotic.org/showthread.php?tid=5445
176         me.gotoRC(me, me.rows - 2.5, 0);
177                 me.TDempty(me, 0.5);
178                 me.TD(me, 1, 2, e = makeXonoticButton_T(_("Mutators..."), '0 0 0',
179                         _("Mutators and weapon arenas")));
180                         e.onClick = DialogOpenButton_Click;
181                         e.onClickEntity = main.mutatorsDialog;
182                         main.mutatorsDialog.refilterEntity = me.mapListBox;
183
184         // The right half begins here
185
186         me.gotoRC(me, 0.5, 3.2); me.setFirstColumn(me, me.currentColumn);
187                 // the maplistbox
188                 me.TD(me, 1, 3, e = makeXonoticHeaderLabel(_("Maplist")));
189                         makeCallback(e, me.mapListBox, me.mapListBox.refilterCallback);
190         me.TR(me);
191                 // we use 5.8 here to visually match the bottom line of the component on the left (Bot Skill)
192                 me.TD(me, me.rows - 6.8, 3, me.mapListBox);
193
194         me.gotoRC(me, me.rows - 4.5, me.firstColumn);
195                 // string filter label and box
196                 me.TD(me, 1, 0.35, e = makeXonoticTextLabel(1, _("Filter:")));
197                 me.mapListBox.stringFilterBox = makeXonoticInputBox_T(0, string_null,
198                         _("Click here or Ctrl-F to provide a keyword to narrow down the map list. Ctrl-Delete to clear; Enter when done."));
199                 me.TD(me, 1, me.columns - me.firstColumn - 0.35, e = me.mapListBox.stringFilterBox);
200                         e.onChange = MapList_StringFilterBox_Change;
201                         e.keyDown = MapList_StringFilterBox_keyDown;
202                         e.onChangeEntity = me.mapListBox;
203
204         me.gotoRC(me, me.rows - 3.5, me.firstColumn);
205                 // the selection buttons
206                 me.TDempty(me, 0.2);
207                 me.TD(me, 1, 1.3, e = makeXonoticButton_T(_("Add shown"), '0 0 0',
208                         _("Add the maps shown in the list to your selection")));
209                         e.onClick = MapList_Add_Shown;
210                         e.onClickEntity = me.mapListBox;
211                 me.TD(me, 1, 1.3, e = makeXonoticButton_T(_("Remove shown"), '0 0 0',
212                         _("Remove the maps shown in the list from your selection")));
213                         e.onClick = MapList_Remove_Shown;
214                         e.onClickEntity = me.mapListBox;
215         me.gotoRC(me, me.rows - 2.5, me.firstColumn);
216                 me.TDempty(me, 0.2);
217                 me.TD(me, 1, 1.3, e = makeXonoticButton_T(_("Add all"), '0 0 0',
218                         _("Add every available map to your selection")));
219                         e.onClick = MapList_Add_All;
220                         e.onClickEntity = me.mapListBox;
221                 me.TD(me, 1, 1.3, e = makeXonoticButton_T(_("Remove all"), '0 0 0',
222                         _("Remove all the maps from your selection")));
223                         e.onClick = MapList_Remove_All;
224                         e.onClickEntity = me.mapListBox;
225
226         // The big button at the bottom
227
228         me.gotoRC(me, me.rows - 1, 0);
229                 me.TD(me, 1, me.columns, e = makeXonoticButton(_("Start Multiplayer!"), '0 0 0'));
230                         e.onClick = MapList_LoadMap;
231                         e.onClickEntity = me.mapListBox;
232                         me.mapListBox.startButton = e;
233
234         GameType_ConfigureSliders_for_CurrentGametype(me);
235 }
236
237 void XonoticServerCreateTab_gameTypeChangeNotify(entity me)
238 {
239         GameType_ConfigureSliders_for_CurrentGametype(me);
240
241         me.mapListBox.refilter(me.mapListBox);
242 }
243
244 void XonoticServerCreateTab_gameTypeSelectNotify(entity me)
245 {
246         me.setFocus(me, me.mapListBox);
247 }