Assume map compatibility by default if client's map version is 1
[neverball] / ball / st_title.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14
15 #include <string.h>
16
17 #include "gui.h"
18 #include "vec3.h"
19 #include "demo.h"
20 #include "audio.h"
21 #include "config.h"
22 #include "st_shared.h"
23 #include "cmd.h"
24
25 #include "game_common.h"
26 #include "game_server.h"
27 #include "game_client.h"
28 #include "game_proxy.h"
29
30 #include "st_title.h"
31 #include "st_help.h"
32 #include "st_demo.h"
33 #include "st_conf.h"
34 #include "st_set.h"
35 #include "st_name.h"
36
37 /*---------------------------------------------------------------------------*/
38
39 static int init_title_level(void)
40 {
41     if (game_client_init("map-medium/title.sol"))
42     {
43         union cmd cmd;
44
45         cmd.type = CMD_GOAL_OPEN;
46         game_proxy_enq(&cmd);
47
48         game_client_step(NULL);
49
50         return 1;
51     }
52     return 0;
53 }
54
55 /*---------------------------------------------------------------------------*/
56
57 static float real_time = 0.0f;
58 static int   mode      = 0;
59
60 static int play_id = 0;
61
62 #define TITLE_PLAY 1
63 #define TITLE_HELP 2
64 #define TITLE_DEMO 3
65 #define TITLE_CONF 4
66 #define TITLE_EXIT 5
67
68 static int title_action(int i)
69 {
70     static const char keyphrase[] = "CHEAT";
71     static char queue[sizeof (keyphrase)] = "";
72
73     size_t queue_len = strlen(queue);
74
75     char player[MAXNAM];
76
77     audio_play(AUD_MENU, 1.0f);
78
79     switch (i)
80     {
81     case TITLE_PLAY:
82         config_get_s(CONFIG_PLAYER, player, MAXNAM);
83
84         if (strlen(player) == 0)
85             return goto_name(&st_set, &st_title, 0);
86         else
87             return goto_state(&st_set);
88
89         break;
90
91     case TITLE_HELP: return goto_state(&st_help); break;
92     case TITLE_DEMO: return goto_state(&st_demo); break;
93     case TITLE_CONF: return goto_state(&st_conf); break;
94     case TITLE_EXIT: return 0;                    break;
95
96     default:
97
98         /* Let the queue fill up. */
99
100         if (queue_len < sizeof (queue) - 1)
101         {
102             queue[queue_len]     = (char) i;
103             queue[queue_len + 1] = '\0';
104         }
105
106         /* Advance the queue before adding the new element. */
107
108         else
109         {
110             int k;
111
112             for (k = 1; k < queue_len; k++)
113                 queue[k - 1] = queue[k];
114
115             queue[queue_len - 1] = (char) i;
116         }
117
118         if (strcmp(queue, keyphrase) == 0)
119         {
120             config_set_cheat();
121             gui_set_label(play_id, sgettext("menu^Cheat"));
122             gui_pulse(play_id, 1.2f);
123         }
124         else if (config_cheat())
125         {
126             config_clr_cheat();
127             gui_set_label(play_id, sgettext("menu^Play"));
128             gui_pulse(play_id, 1.2f);
129         }
130
131         break;
132     }
133     return 1;
134 }
135
136 static int title_enter(void)
137 {
138     int id, jd, kd;
139
140     /* Build the title GUI. */
141
142     if ((id = gui_vstack(0)))
143     {
144         gui_label(id, "Neverball", GUI_LRG, GUI_ALL, 0, 0);
145
146         gui_space(id);
147
148         if ((jd = gui_harray(id)))
149         {
150             gui_filler(jd);
151
152             if ((kd = gui_varray(jd)))
153             {
154                 if (config_cheat())
155                     play_id = gui_start(kd, sgettext("menu^Cheat"),
156                                         GUI_MED, TITLE_PLAY, 1);
157                 else
158                     play_id = gui_start(kd, sgettext("menu^Play"),
159                                         GUI_MED, TITLE_PLAY, 1);
160
161                 gui_state(kd, sgettext("menu^Replay"),  GUI_MED, TITLE_DEMO, 0);
162                 gui_state(kd, sgettext("menu^Help"),    GUI_MED, TITLE_HELP, 0);
163                 gui_state(kd, sgettext("menu^Options"), GUI_MED, TITLE_CONF, 0);
164                 gui_state(kd, sgettext("menu^Exit"),    GUI_MED, TITLE_EXIT, 0);
165             }
166
167             gui_filler(jd);
168         }
169         gui_layout(id, 0, 0);
170     }
171
172     /* Start the title screen music. */
173
174     audio_music_fade_to(0.5f, "bgm/title.ogg");
175
176     /* Initialize the title level for display. */
177
178     init_title_level();
179
180     real_time = 0.0f;
181     mode = 0;
182
183     SDL_EnableUNICODE(1);
184
185     return id;
186 }
187
188 static void title_leave(int id)
189 {
190     SDL_EnableUNICODE(0);
191     demo_replay_stop(0);
192     gui_delete(id);
193 }
194
195 static void title_timer(int id, float dt)
196 {
197     static const char *demo = NULL;
198
199     real_time += dt;
200
201     switch (mode)
202     {
203     case 0: /* Mode 0: Pan across title level. */
204
205         if (real_time <= 20.0f)
206         {
207             game_set_fly(fcosf(V_PI * real_time / 20.0f),
208                          game_client_file());
209             game_client_step(NULL);
210         }
211         else
212         {
213             game_fade(+1.0f);
214             real_time = 0.0f;
215             mode = 1;
216         }
217         break;
218
219     case 1: /* Mode 1: Fade out.  Load demo level. */
220
221         if (real_time > 1.0f)
222         {
223             if ((demo = demo_pick()))
224             {
225                 demo_replay_init(demo, NULL, NULL, NULL, NULL, NULL);
226                 game_set_fly(0.0f, game_client_file());
227                 game_client_step(NULL);
228                 real_time = 0.0f;
229                 mode = 2;
230             }
231             else
232             {
233                 game_fade(-1.0f);
234                 real_time = 0.0f;
235                 mode = 0;
236             }
237         }
238         break;
239
240     case 2: /* Mode 2: Run demo. */
241
242         if (!demo_replay_step(dt))
243         {
244             demo_replay_stop(0);
245             game_fade(+1.0f);
246             real_time = 0.0f;
247             mode = 3;
248         }
249         break;
250
251     case 3: /* Mode 3: Fade out.  Load title level. */
252
253         if (real_time > 1.0f)
254         {
255             init_title_level();
256
257             real_time = 0.0f;
258             mode = 0;
259         }
260         break;
261     }
262
263     gui_timer(id, dt);
264     game_step_fade(dt);
265 }
266
267 static int title_keybd(int c, int d)
268 {
269     if (d && (c & 0xFF80) == 0 && c > ' ')
270         return title_action(c);
271     return 1;
272 }
273
274 static int title_buttn(int b, int d)
275 {
276     if (d)
277     {
278         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
279             return title_action(gui_token(gui_click()));
280         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
281             return 0;
282     }
283     return 1;
284 }
285
286 /*---------------------------------------------------------------------------*/
287
288 struct state st_title = {
289     title_enter,
290     title_leave,
291     shared_paint,
292     title_timer,
293     shared_point,
294     shared_stick,
295     shared_angle,
296     shared_click,
297     title_keybd,
298     title_buttn,
299     1, 0
300 };
301