Fixed a problem with Makefile.mingw where make wasn't rebuilding targets
[neverball] / ball / st_start.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 "gui.h"
16 #include "set.h"
17 #include "util.h"
18 #include "game.h"
19 #include "levels.h"
20 #include "audio.h"
21 #include "config.h"
22 #include "st_shared.h"
23
24 #include "st_set.h"
25 #include "st_over.h"
26 #include "st_level.h"
27 #include "st_start.h"
28 #include "st_title.h"
29
30 /*---------------------------------------------------------------------------*/
31
32 int goto_end_level(void)
33 {
34     switch (curr_lg()->mode)
35     {
36     case MODE_SINGLE:
37         return 0;
38     case MODE_CHALLENGE:
39         return goto_state(&st_over);
40     default:
41         return goto_state(&st_start);
42     }
43 }
44
45
46 /*---------------------------------------------------------------------------*/
47
48 #define START_BACK -1
49 #define START_PRACTICE -2
50 #define START_NORMAL -3
51 #define START_CHALLENGE -4
52
53 static int shot_id;
54 static int status_id;
55
56 /*---------------------------------------------------------------------------*/
57
58 /* Create a level selector button based upon its existence and status. */
59
60 static void gui_level(int id, int i)
61 {
62     const GLfloat *fore, *back;
63
64     const struct set *s = curr_set();
65     const struct level *l;
66
67     int jd;
68
69     if (!set_level_exists(s, i))
70     {
71         gui_space(id);
72         return;
73     }
74
75     l = get_level(i);
76
77     if (!l->is_locked)
78     {
79         fore = l->is_bonus     ? gui_grn : gui_wht;
80         back = l->is_completed ? fore    : gui_yel;
81     }
82     else
83         fore = back = gui_gry;
84
85     jd = gui_label(id, l->repr, GUI_SML, GUI_ALL, back, fore);
86
87     gui_active(jd, i, 0);
88 }
89
90 static void start_over_level(i)
91 {
92     const struct level *l = get_level(i);
93     if (!l->is_locked || config_get_d(CONFIG_CHEAT))
94     {
95         gui_set_image(shot_id, l->shot);
96
97         set_most_coins(&l->score.most_coins, -1);
98
99         if (config_get_d(CONFIG_MODE) == MODE_PRACTICE)
100         {
101             set_best_times(&l->score.best_times, -1, 0);
102             if (l->is_bonus)
103                 gui_set_label(status_id,
104                               _("Play this bonus level in practice mode"));
105             else
106                 gui_set_label(status_id,
107                               _("Play this level in practice mode"));
108         }
109         else
110         {
111             set_best_times(&l->score.unlock_goal, -1, 1);
112             if (l->is_bonus)
113                 gui_set_label(status_id,
114                               _("Play this bonus level in normal mode"));
115             else
116                 gui_set_label(status_id, _("Play this level in normal mode"));
117         }
118         if (config_get_d(CONFIG_CHEAT))
119         {
120             gui_set_label(status_id, l->file);
121         }
122         return;
123     }
124     else if (l->is_bonus)
125         gui_set_label(status_id,
126                       _("Play in challenge mode to unlock extra bonus levels"));
127     else
128         gui_set_label(status_id,
129                       _("Finish previous levels to unlock this level"));
130 }
131
132 static void start_over(id)
133 {
134     int i;
135
136     gui_pulse(id, 1.2f);
137     if (id == 0)
138         return;
139
140     i = gui_token(id);
141
142
143     switch (i)
144     {
145     case START_CHALLENGE:
146         gui_set_image(shot_id, curr_set()->shot);
147         set_most_coins(&curr_set()->coin_score, -1);
148         set_best_times(&curr_set()->time_score, -1, 0);
149         gui_set_label(status_id, _("Challenge all levels from the first one"));
150         break;
151
152     case START_NORMAL:
153         gui_set_label(status_id, _("Collect coins and unlock next level"));
154         break;
155
156     case START_PRACTICE:
157         gui_set_label(status_id, _("Train yourself without time nor coin"));
158         break;
159     }
160
161     if (i >= 0)
162         start_over_level(i);
163 }
164
165 /*---------------------------------------------------------------------------*/
166
167 static int start_action(int i)
168 {
169     int mode = config_get_d(CONFIG_MODE);
170
171     audio_play(AUD_MENU, 1.0f);
172
173     switch (i)
174     {
175     case START_BACK:
176         return goto_state(&st_set);
177     case START_NORMAL:
178         config_set_d(CONFIG_MODE, MODE_NORMAL);
179         return goto_state(&st_start);
180     case START_PRACTICE:
181         config_set_d(CONFIG_MODE, MODE_PRACTICE);
182         return goto_state(&st_start);
183     }
184
185     if (i == START_CHALLENGE)
186     {
187         /* On cheat, start challenge mode where you want */
188         if (config_get_d(CONFIG_CHEAT))
189         {
190             config_set_d(CONFIG_MODE, MODE_CHALLENGE);
191             return goto_state(&st_start);
192         }
193         i = 0;
194         mode = MODE_CHALLENGE;
195     }
196
197     if (i >= 0)
198     {
199         const struct level *l = get_level(i);
200
201         if (!l->is_locked || config_get_d(CONFIG_CHEAT))
202         {
203             level_play(l, mode);
204             return goto_state(&st_level);
205         }
206     }
207     return 1;
208 }
209
210 static int start_enter(void)
211 {
212     int w = config_get_d(CONFIG_WIDTH);
213     int h = config_get_d(CONFIG_HEIGHT);
214     int m = config_get_d(CONFIG_MODE);
215     int i, j;
216
217     int id, jd, kd, ld;
218
219     /* Deactivate cheat */
220     if (m == MODE_CHALLENGE && !config_get_d(CONFIG_CHEAT))
221     {
222         m = MODE_NORMAL;
223         config_set_d(CONFIG_MODE, m);
224     }
225
226     if ((id = gui_vstack(0)))
227     {
228         if ((jd = gui_hstack(id)))
229         {
230
231             gui_label(jd, _(curr_set()->name), GUI_SML, GUI_ALL,
232                       gui_yel, gui_red);
233             gui_filler(jd);
234             gui_start(jd, _("Back"),  GUI_SML, START_BACK, 0);
235         }
236
237
238         if ((jd = gui_harray(id)))
239         {
240             shot_id = gui_image(jd, curr_set()->shot, 7 * w / 16, 7 * h / 16);
241
242             if ((kd = gui_varray(jd)))
243             {
244                 if ((ld = gui_harray(kd)))
245                 {
246                     gui_state(ld, _("Practice"), GUI_SML, START_PRACTICE,
247                               m == MODE_PRACTICE);
248                     gui_state(ld, _("Normal"),   GUI_SML, START_NORMAL,
249                               m == MODE_NORMAL);
250                 }
251                 for (i = 0; i < 5; i++)
252                     if ((ld = gui_harray(kd)))
253                         for (j = 4; j >= 0; j--)
254                             gui_level(ld, i * 5 + j);
255
256                 gui_state(kd, _("Challenge"), GUI_SML, START_CHALLENGE,
257                           m == MODE_CHALLENGE);
258             }
259         }
260         gui_space(id);
261
262         if ((jd = gui_harray(id)))
263         {
264             gui_most_coins(jd, 0);
265             gui_best_times(jd, 0);
266         }
267         gui_space(id);
268
269         status_id = gui_label(id, _("Choose a level to play"), GUI_SML, GUI_ALL,
270                               gui_yel, gui_wht);
271
272         gui_layout(id, 0, 0);
273
274         set_most_coins(NULL, -1);
275         set_best_times(NULL, -1, m != MODE_PRACTICE);
276     }
277
278     audio_music_fade_to(0.5f, "bgm/inter.ogg");
279
280     return id;
281 }
282
283 static void start_point(int id, int x, int y, int dx, int dy)
284 {
285     start_over(gui_point(id, x, y));
286 }
287
288 static void start_stick(int id, int a, int v)
289 {
290     int x = (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a)) ? v : 0;
291     int y = (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a)) ? v : 0;
292
293     start_over(gui_stick(id, x, y));
294 }
295
296 static int start_keybd(int c, int d)
297 {
298     if (d && c == SDLK_c && config_get_d(CONFIG_CHEAT))
299     {
300         set_cheat();
301         return goto_state(&st_start);
302     }
303
304     if (d && c == SDLK_F12)
305     {
306         int i;
307
308         /* Iterate over all levels, taking a screenshot of each. */
309
310         for (i = 0; i < MAXLVL; i++)
311             if (set_level_exists(curr_set(), i))
312                 level_snap(i);
313     }
314
315     return 1;
316 }
317
318 static int start_buttn(int b, int d)
319 {
320     if (d)
321     {
322         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
323             return start_action(gui_token(gui_click()));
324         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
325             return start_action(START_BACK);
326     }
327     return 1;
328 }
329
330 /*---------------------------------------------------------------------------*/
331
332 struct state st_start = {
333     start_enter,
334     shared_leave,
335     shared_paint,
336     shared_timer,
337     start_point,
338     start_stick,
339     shared_click,
340     start_keybd,
341     start_buttn,
342     1, 0
343 };