Correct logic of BSP back/front tests
[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 int title_enter(void)
114 {
115     int id, jd, kd;
116
117     /* Build the title GUI. */
118
119     if ((id = gui_vstack(0)))
120     {
121         gui_label(id, "Neverball", GUI_LRG, GUI_ALL, 0, 0);
122
123         gui_space(id);
124
125         if ((jd = gui_harray(id)))
126         {
127             gui_filler(jd);
128
129             if ((kd = gui_varray(jd)))
130             {
131                 if (config_cheat())
132                     play_id = gui_start(kd, sgettext("menu^Cheat"),
133                                         GUI_MED, TITLE_PLAY, 1);
134                 else
135                     play_id = gui_start(kd, sgettext("menu^Play"),
136                                         GUI_MED, TITLE_PLAY, 1);
137
138                 gui_state(kd, sgettext("menu^Replay"),  GUI_MED, TITLE_DEMO, 0);
139                 gui_state(kd, sgettext("menu^Help"),    GUI_MED, TITLE_HELP, 0);
140                 gui_state(kd, sgettext("menu^Options"), GUI_MED, TITLE_CONF, 0);
141                 gui_state(kd, sgettext("menu^Exit"),    GUI_MED, TITLE_EXIT, 0);
142             }
143
144             gui_filler(jd);
145         }
146         gui_layout(id, 0, 0);
147     }
148
149     /* Start the title screen music. */
150
151     audio_music_fade_to(0.5f, "bgm/title.ogg");
152
153     /* Initialize the title level for display. */
154
155     game_init("map-medium/title.sol", 0, 1);
156
157     real_time = 0.0f;
158     mode = 0;
159
160     SDL_EnableUNICODE(1);
161
162     return id;
163 }
164
165 static void title_leave(int id)
166 {
167     SDL_EnableUNICODE(0);
168     demo_replay_stop(0);
169     gui_delete(id);
170 }
171
172 static void title_timer(int id, float dt)
173 {
174     static const char *demo = NULL;
175
176     real_time += dt;
177
178     switch (mode)
179     {
180     case 0: /* Mode 0: Pan across title level. */
181
182         if (real_time <= 20.0f)
183             game_set_fly(fcosf(V_PI * real_time / 20.0f));
184         else
185         {
186             game_fade(+1.0f);
187             real_time = 0.0f;
188             mode = 1;
189         }
190         break;
191
192     case 1: /* Mode 1: Fade out.  Load demo level. */
193
194         if (real_time > 1.0f)
195         {
196             if ((demo = demo_pick()))
197             {
198                 demo_replay_init(demo, NULL, NULL, NULL, NULL, NULL);
199                 game_set_fly(0.0f);
200                 real_time = 0.0f;
201                 mode = 2;
202             }
203             else
204             {
205                 game_fade(-1.0f);
206                 real_time = 0.0f;
207                 mode = 0;
208             }
209         }
210         break;
211
212     case 2: /* Mode 2: Run demo. */
213
214         if (!demo_replay_step(dt))
215         {
216             demo_replay_stop(0);
217             game_fade(+1.0f);
218             real_time = 0.0f;
219             mode = 3;
220         }
221         break;
222
223     case 3: /* Mode 3: Fade out.  Load title level. */
224
225         if (real_time > 1.0f)
226         {
227             game_init("map-medium/title.sol", 0, 1);
228
229             real_time = 0.0f;
230             mode = 0;
231         }
232         break;
233     }
234
235     gui_timer(id, dt);
236     game_step_fade(dt);
237 }
238
239 static int title_keybd(int c, int d)
240 {
241     if (d && (c & 0xFF80) == 0 && c > ' ')
242         return title_action(c);
243     return 1;
244 }
245
246 static int title_buttn(int b, int d)
247 {
248     if (d)
249     {
250         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
251             return title_action(gui_token(gui_click()));
252         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
253             return 0;
254     }
255     return 1;
256 }
257
258 /*---------------------------------------------------------------------------*/
259
260 struct state st_title = {
261     title_enter,
262     title_leave,
263     shared_paint,
264     title_timer,
265     shared_point,
266     shared_stick,
267     shared_angle,
268     shared_click,
269     title_keybd,
270     title_buttn,
271     1, 0
272 };
273