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