tennis.map: Texture tweak
[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 #include <assert.h>
17
18 #include "gui.h"
19 #include "vec3.h"
20 #include "demo.h"
21 #include "audio.h"
22 #include "config.h"
23 #include "cmd.h"
24 #include "demo_dir.h"
25
26 #include "game_common.h"
27 #include "game_server.h"
28 #include "game_client.h"
29 #include "game_proxy.h"
30
31 #include "st_title.h"
32 #include "st_help.h"
33 #include "st_demo.h"
34 #include "st_conf.h"
35 #include "st_set.h"
36 #include "st_name.h"
37 #include "st_shared.h"
38
39 /*---------------------------------------------------------------------------*/
40
41 static int init_title_level(void)
42 {
43     if (game_client_init("map-medium/title.sol"))
44     {
45         union cmd cmd;
46
47         cmd.type = CMD_GOAL_OPEN;
48         game_proxy_enq(&cmd);
49         game_client_sync(NULL);
50
51         game_client_fly(1.0f);
52
53         return 1;
54     }
55     return 0;
56 }
57
58 static const char *pick_demo(Array items)
59 {
60     struct dir_item *item;
61     return (item = array_rnd(items)) ? item->path : NULL;
62 }
63
64 /*---------------------------------------------------------------------------*/
65
66 static float real_time = 0.0f;
67 static int   mode      = 0;
68
69 static Array items;
70
71 static int play_id = 0;
72
73 #define TITLE_PLAY 1
74 #define TITLE_HELP 2
75 #define TITLE_DEMO 3
76 #define TITLE_CONF 4
77 #define TITLE_EXIT 5
78
79 static int title_action(int i)
80 {
81     static const char keyphrase[] = "CHEAT";
82     static char queue[sizeof (keyphrase)] = "";
83
84     size_t queue_len = strlen(queue);
85
86     audio_play(AUD_MENU, 1.0f);
87
88     switch (i)
89     {
90     case TITLE_PLAY:
91         if (strlen(config_get_s(CONFIG_PLAYER)) == 0)
92             return goto_name(&st_set, &st_title, 0);
93         else
94             return goto_state(&st_set);
95
96         break;
97
98     case TITLE_HELP: return goto_state(&st_help); break;
99     case TITLE_DEMO: return goto_state(&st_demo); break;
100     case TITLE_CONF: return goto_state(&st_conf); break;
101     case TITLE_EXIT: return 0;                    break;
102
103     default:
104
105         /* Let the queue fill up. */
106
107         if (queue_len < sizeof (queue) - 1)
108         {
109             queue[queue_len]     = (char) i;
110             queue[queue_len + 1] = '\0';
111         }
112
113         /* Advance the queue before adding the new element. */
114
115         else
116         {
117             int k;
118
119             for (k = 1; k < queue_len; k++)
120                 queue[k - 1] = queue[k];
121
122             queue[queue_len - 1] = (char) i;
123         }
124
125         if (strcmp(queue, keyphrase) == 0)
126         {
127             config_set_cheat();
128             gui_set_label(play_id, sgettext("menu^Cheat"));
129             gui_pulse(play_id, 1.2f);
130         }
131         else if (config_cheat())
132         {
133             config_clr_cheat();
134             gui_set_label(play_id, sgettext("menu^Play"));
135             gui_pulse(play_id, 1.2f);
136         }
137
138         break;
139     }
140     return 1;
141 }
142
143 static int title_gui(void)
144 {
145     int id, jd, kd;
146
147     /* Build the title GUI. */
148
149     if ((id = gui_vstack(0)))
150     {
151         gui_label(id, "Neverball", GUI_LRG, GUI_ALL, 0, 0);
152
153         gui_space(id);
154
155         if ((jd = gui_harray(id)))
156         {
157             gui_filler(jd);
158
159             if ((kd = gui_varray(jd)))
160             {
161                 if (config_cheat())
162                     play_id = gui_start(kd, sgettext("menu^Cheat"),
163                                         GUI_MED, TITLE_PLAY, 1);
164                 else
165                     play_id = gui_start(kd, sgettext("menu^Play"),
166                                         GUI_MED, TITLE_PLAY, 1);
167
168                 gui_state(kd, sgettext("menu^Replay"),  GUI_MED, TITLE_DEMO, 0);
169                 gui_state(kd, sgettext("menu^Help"),    GUI_MED, TITLE_HELP, 0);
170                 gui_state(kd, sgettext("menu^Options"), GUI_MED, TITLE_CONF, 0);
171                 gui_state(kd, sgettext("menu^Exit"),    GUI_MED, TITLE_EXIT, 0);
172             }
173
174             gui_filler(jd);
175         }
176         gui_layout(id, 0, 0);
177     }
178
179     return id;
180 }
181
182 static int title_enter(struct state *st, struct state *prev)
183 {
184     /* Start the title screen music. */
185
186     audio_music_fade_to(0.5f, "bgm/title.ogg");
187
188     /* Initialize the title level for display. */
189
190     init_title_level();
191
192     real_time = 0.0f;
193     mode = 0;
194
195     SDL_EnableUNICODE(1);
196
197     return title_gui();
198 }
199
200 static void title_leave(struct state *st, struct state *next, int id)
201 {
202     if (items)
203     {
204         demo_dir_free(items);
205         items = NULL;
206     }
207
208     SDL_EnableUNICODE(0);
209     demo_replay_stop(0);
210     gui_delete(id);
211 }
212
213 static void title_timer(int id, float dt)
214 {
215     static const char *demo = NULL;
216
217     real_time += dt;
218
219     switch (mode)
220     {
221     case 0: /* Mode 0: Pan across title level. */
222
223         if (real_time <= 20.0f)
224         {
225             game_client_fly(fcosf(V_PI * real_time / 20.0f));
226         }
227         else
228         {
229             game_fade(+1.0f);
230             real_time = 0.0f;
231             mode = 1;
232         }
233         break;
234
235     case 1: /* Mode 1: Fade out.  Load demo level. */
236
237         if (real_time > 1.0f)
238         {
239             if (!items)
240                 items = demo_dir_scan();
241
242             if ((demo = pick_demo(items)))
243             {
244                 demo_replay_init(demo, NULL, NULL, NULL, NULL, NULL);
245                 game_client_fly(0.0f);
246                 real_time = 0.0f;
247                 mode = 2;
248             }
249             else
250             {
251                 game_fade(-1.0f);
252                 real_time = 0.0f;
253                 mode = 0;
254             }
255         }
256         break;
257
258     case 2: /* Mode 2: Run demo. */
259
260         if (!demo_replay_step(dt))
261         {
262             demo_replay_stop(0);
263             game_fade(+1.0f);
264             real_time = 0.0f;
265             mode = 3;
266         }
267         else
268             game_client_blend(demo_replay_blend());
269
270         break;
271
272     case 3: /* Mode 3: Fade out.  Load title level. */
273
274         if (real_time > 1.0f)
275         {
276             init_title_level();
277
278             real_time = 0.0f;
279             mode = 0;
280         }
281         break;
282     }
283
284     gui_timer(id, dt);
285     game_step_fade(dt);
286 }
287
288 static int title_keybd(int c, int d)
289 {
290     if (d && (c & 0xFF80) == 0 && c > ' ')
291         return title_action(c);
292     return 1;
293 }
294
295 static int title_buttn(int b, int d)
296 {
297     if (d)
298     {
299         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
300             return title_action(gui_token(gui_click()));
301         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
302             return 0;
303     }
304     return 1;
305 }
306
307 /*---------------------------------------------------------------------------*/
308
309 struct state st_title = {
310     title_enter,
311     title_leave,
312     shared_paint,
313     title_timer,
314     shared_point,
315     shared_stick,
316     shared_angle,
317     shared_click,
318     title_keybd,
319     title_buttn
320 };
321