add magic to sol files and allow simple loading without texture and other things...
[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 /* Action once the level sequence is ended (from goal or fail states) */
34 {
35     int mode = curr_lg()->mode;
36     if (mode == MODE_SINGLE)
37         return 0;
38     else if (mode == MODE_CHALLENGE)
39         return goto_state(&st_over);
40     else
41         return goto_state(&st_start);
42 }
43
44
45 /*---------------------------------------------------------------------------*/
46
47 #define START_BACK -1
48 #define START_PRACTICE -2
49 #define START_NORMAL -3
50 #define START_CHALLENGE -4
51
52 static int shot_id;
53 static int status_id;
54
55 /*---------------------------------------------------------------------------*/
56
57 /* Create a level selector button based upon its existence and status. */
58
59 static void gui_level(int id, int i)
60 {
61     const struct set *s = curr_set();
62     const struct level *l;
63     int jd = 0;
64     
65     const char * text; /*= _(level_number_name(i));*/
66
67     if (! set_level_exists(s, i))
68     {
69         gui_space(id);
70         return;
71     }
72     
73     l = get_level(i);
74     text = _(l->numbername);
75     if (! l->is_locked)
76     {
77         if (! l->is_bonus)
78             jd = gui_label(id, text, GUI_SML, GUI_ALL, gui_wht, gui_wht);
79         else
80             jd = gui_label(id, text, GUI_SML, GUI_ALL, gui_wht, gui_grn);
81     }
82     else
83     {
84         if (! l->is_bonus)
85             jd = gui_label(id, text, GUI_SML, GUI_ALL, gui_gry, gui_gry);
86         else if (set_extra_bonus_opened(s))
87             jd = gui_label(id, text, GUI_SML, GUI_ALL, gui_gry, gui_grn);
88         else
89             jd = gui_label(id, text, GUI_SML, GUI_ALL, gui_gry, gui_gry);
90     }
91     
92     gui_active(jd, i, 0);
93 }
94
95 static void start_over_level(i)
96 {
97     const struct set *s   = curr_set();
98     const struct level *l = get_level(i);
99     if (! l->is_locked)
100     {
101         gui_set_image(shot_id, l->shot);
102
103         set_most_coins(&l->coin_score, -1);
104
105         if (config_get_d(CONFIG_MODE) == MODE_PRACTICE)
106         {
107             set_best_times(&l->time_score, -1, 0);
108             if (l->is_bonus)
109                 gui_set_label(status_id, _("Play this bonus level in practice mode"));
110             else
111                 gui_set_label(status_id, _("Play this level in practice mode"));
112         }
113         else
114         {
115             set_best_times(&l->goal_score, -1, 1);
116             if (l->is_bonus)
117                 gui_set_label(status_id, _("Play this bonus level in normal mode"));
118             else
119                 gui_set_label(status_id, _("Play this level in normal mode"));
120         }
121         if (config_get_d(CONFIG_CHEAT))
122         {
123             gui_set_label(status_id, l->file);
124         }
125         return;
126     }
127     else if (l->is_bonus && !set_extra_bonus_opened(s))
128         gui_set_label(status_id, _("Finish challenge mode to unlock extra bonus levels"));
129     else
130         gui_set_label(status_id, _("Finish previous levels to unlock this level"));
131 }
132
133 static void start_over(id)
134 {
135     int i;
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     audio_play(AUD_MENU, 1.0f);
171
172     if (i == START_BACK)
173         return goto_state(&st_set);
174     else if (i == START_NORMAL)
175     {
176         config_set_d(CONFIG_MODE, MODE_NORMAL);
177         return goto_state(&st_start);
178     }
179     else if (i == START_PRACTICE)
180     {
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         if (!l->is_locked || config_get_d(CONFIG_CHEAT))
201         {
202             level_play(l, mode);
203             return goto_state(&st_level);
204         }
205     }
206     return 1;
207 }
208
209 static int start_enter(void)
210 {
211     int w = config_get_d(CONFIG_WIDTH);
212     int h = config_get_d(CONFIG_HEIGHT);
213     int m = config_get_d(CONFIG_MODE);
214     int i, j;
215
216     int id, jd, kd, ld;
217
218     /* Desactivate cheat */
219     if (m == MODE_CHALLENGE && !config_get_d(CONFIG_CHEAT))
220     {
221         m = MODE_NORMAL;
222         config_set_d(CONFIG_MODE, m);
223     }
224     
225     if ((id = gui_vstack(0)))
226     {
227         if ((jd = gui_hstack(id)))
228         {
229             
230             gui_label(jd, _(curr_set()->name), GUI_SML, GUI_ALL, gui_yel, gui_red);
231             gui_filler(jd);
232             if (set_completed(curr_set()))
233             {
234                 gui_label(jd, _("Set Complete"), GUI_SML, GUI_ALL, gui_yel, gui_grn);
235                 gui_filler(jd);
236             }
237             gui_start(jd, _("Back"),  GUI_SML, START_BACK, 0);
238         }
239
240         
241         if ((jd = gui_harray(id)))
242         {
243             shot_id = gui_image(jd, curr_set()->shot, 7 * w / 16, 7 * h / 16);
244
245             if ((kd = gui_varray(jd)))
246             {
247                 if ((ld = gui_harray(kd)))
248                 {
249                     gui_state(ld, _("Practice"), GUI_SML, START_PRACTICE, m == MODE_PRACTICE);
250                     gui_state(ld, _("Normal"),   GUI_SML, START_NORMAL,   m == MODE_NORMAL);
251                 }
252                 gui_state(kd, _("Challenge"), GUI_SML, START_CHALLENGE , m == MODE_CHALLENGE);
253                 for (i=0; i <5; i++)
254                     if ((ld = gui_harray(kd)))
255                         for (j=4; j>=0; j--)
256                             gui_level(ld, i*5 + j);
257             }
258         }
259         gui_space(id);
260
261         if ((jd = gui_harray(id)))
262         {
263             gui_most_coins(jd, 0);
264             gui_best_times(jd, 0);
265         }
266         
267         gui_space(id);
268         
269         status_id = gui_label(id, _("Choose a level to play"), GUI_SML, GUI_ALL, gui_yel, gui_wht);
270         
271         gui_layout(id, 0, 0);
272         
273         set_most_coins(NULL, -1);
274         set_best_times(NULL, -1, m != MODE_PRACTICE);
275     }
276
277     return id;
278 }
279
280 static void start_point(int id, int x, int y, int dx, int dy)
281 {
282     start_over(gui_point(id, x, y));
283 }
284
285 static void start_stick(int id, int a, int v)
286 {
287     int x = (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a)) ? v : 0;
288     int y = (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a)) ? v : 0;
289     
290     start_over(gui_stick(id, x, y));
291 }
292
293 static int start_keybd(int c, int d)
294 {
295     if (d && c == SDLK_c && config_get_d(CONFIG_CHEAT))
296     {
297         set_cheat();
298         return goto_state(&st_start);
299     }
300                          
301     if (d && c == SDLK_F12)
302     {
303         int i;
304
305         /* Iterate over all levels, taking a screenshot of each. */
306
307         for (i = 1; i < MAXLVL; i++)
308             if (set_level_exists(curr_set(), i))
309                 level_snap(i);
310     }
311
312     return 1;
313 }
314
315 static int start_buttn(int b, int d)
316 {
317     if (d)
318     {
319         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
320             return start_action(gui_token(gui_click()));
321         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
322             return start_action(START_BACK);
323     }
324     return 1;
325 }
326
327 /*---------------------------------------------------------------------------*/
328
329 struct state st_start = {
330     start_enter,
331     shared_leave,
332     shared_paint,
333     shared_timer,
334     start_point,
335     start_stick,
336     shared_click,
337     start_keybd,
338     start_buttn,
339     1, 0
340 };