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