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 "audio.h"
17 #include "config.h"
18 #include "demo.h"
19 #include "video.h"
20 
21 #include "game_common.h"
22 #include "game_server.h"
23 #include "game_client.h"
24 
25 #include "st_title.h"
26 #include "st_help.h"
27 #include "st_shared.h"
28 
29 /*---------------------------------------------------------------------------*/
30 
31 enum
32 {
33     HELP_PAGE = GUI_LAST,
34     HELP_DEMO
35 };
36 
37 enum
38 {
39     PAGE_RULES,
40     PAGE_CONTROLS,
41     PAGE_MODES,
42     PAGE_TRICKS
43 };
44 
45 static const char demos[][16] = {
46     "gui/demo1.nbr",
47     "gui/demo2.nbr"
48 };
49 
50 static int page = PAGE_RULES;
51 
52 /*---------------------------------------------------------------------------*/
53 
help_action(int tok,int val)54 static int help_action(int tok, int val)
55 {
56     audio_play(AUD_MENU, 1.0f);
57 
58     switch (tok)
59     {
60     case GUI_BACK:
61         page = PAGE_RULES;
62         return goto_state(&st_title);
63 
64     case HELP_DEMO:
65         if (demo_replay_init(demos[val], NULL, NULL, NULL, NULL, NULL))
66             return goto_state(&st_help_demo);
67         break;
68 
69     case HELP_PAGE:
70         page = val;
71         return goto_state(&st_help);
72 
73     }
74     return 1;
75 }
76 
77 /* -------------------------------------------------------------------------- */
78 
help_button(int id,const char * text,int token,int value)79 static int help_button(int id, const char *text, int token, int value)
80 {
81     int jd = gui_state(id, text, GUI_SML, token, value);
82 
83     /* Hilight current page. */
84 
85     if (token == HELP_PAGE && value == page)
86     {
87         gui_set_hilite(jd, 1);
88         gui_focus(jd);
89     }
90 
91     return jd;
92 }
93 
help_menu(int id)94 static int help_menu(int id)
95 {
96     int jd;
97 
98     gui_space(id);
99 
100     if ((jd = gui_harray(id)))
101     {
102         help_button(jd, _("Tricks"),   HELP_PAGE, PAGE_TRICKS);
103         help_button(jd, _("Modes"),    HELP_PAGE, PAGE_MODES);
104         help_button(jd, _("Controls"), HELP_PAGE, PAGE_CONTROLS);
105         help_button(jd, _("Rules"),    HELP_PAGE, PAGE_RULES);
106         help_button(jd, _("Back"),     GUI_BACK, 0);
107     }
108     return jd;
109 }
110 
111 /* -------------------------------------------------------------------------- */
112 
page_rules(int id)113 static int page_rules(int id)
114 {
115     const char *s0 = _(
116         "Move the mouse or joystick\\"
117         "or use keyboard arrows to\\"
118         "tilt the floor causing the\\"
119         "ball to roll.\\");
120     const char *s1 = _(
121         "Roll over coins to collect\\"
122         "them.  Collect coins to\\"
123         "unlock the goal and finish\\"
124         "the level.\\");
125 
126     int w = video.device_w;
127     int h = video.device_h;
128 
129     int jd, kd, ld;
130 
131     if ((jd = gui_hstack(id)))
132     {
133         gui_filler(jd);
134 
135         if ((kd = gui_varray(jd)))
136         {
137             if ((ld = gui_vstack(kd)))
138             {
139                 gui_space(ld);
140                 gui_multi(ld, s0, GUI_SML, gui_wht, gui_wht);
141                 gui_filler(ld);
142             }
143 
144             if ((ld = gui_vstack(kd)))
145             {
146                 gui_space(ld);
147                 gui_multi(ld, s1, GUI_SML, gui_wht, gui_wht);
148                 gui_filler(ld);
149             }
150         }
151 
152         gui_space(jd);
153 
154         if ((kd = gui_varray(jd)))
155         {
156             if ((ld = gui_vstack(kd)))
157             {
158                 gui_space(ld);
159                 gui_image(ld, "gui/help1.jpg", 5 * w / 16, 5 * h / 16);
160                 gui_filler(ld);
161             }
162 
163             if ((ld = gui_vstack(kd)))
164             {
165                 gui_space(ld);
166                 gui_image(ld, "gui/help2.jpg", 5 * w / 16, 5 * h / 16);
167                 gui_filler(ld);
168             }
169         }
170 
171         gui_filler(jd);
172     }
173     return id;
174 }
175 
page_controls(int id)176 static int page_controls(int id)
177 {
178     const char *s_rotate  = _("Left and right mouse buttons rotate the view.\\"
179                               "Hold Shift for faster view rotation.");
180     const char *s_exit    = _("Exit / Pause");
181     const char *s_camera1 = _("Chase Camera");
182     const char *s_camera2 = _("Lazy Camera");
183     const char *s_camera3 = _("Manual Camera");
184     const char *s_shot    = _("Screenshot");
185 
186     /*
187      * SDL_GetKeyName overwrites some of its results, that's why we
188      * don't cache the pointers anymore.
189      */
190 
191     const SDL_Keycode k_exit = KEY_EXIT;
192     const SDL_Keycode k_cam1 = config_get_d(CONFIG_KEY_CAMERA_1);
193     const SDL_Keycode k_cam2 = config_get_d(CONFIG_KEY_CAMERA_2);
194     const SDL_Keycode k_cam3 = config_get_d(CONFIG_KEY_CAMERA_3);
195     const SDL_Keycode k_shot = KEY_SCREENSHOT;
196 
197     int jd, kd;
198 
199     gui_space(id);
200 
201     if ((jd = gui_vstack(id)))
202     {
203         if ((kd = gui_harray(jd)))
204         {
205             gui_label(kd, s_exit,   GUI_SML, gui_wht, gui_wht);
206             gui_label(kd, SDL_GetKeyName(k_exit), GUI_SML, gui_yel, gui_yel);
207         }
208         if ((kd = gui_harray(jd)))
209         {
210             gui_label(kd, s_camera1, GUI_SML, gui_wht, gui_wht);
211             gui_label(kd, SDL_GetKeyName(k_cam1), GUI_SML, gui_yel, gui_yel);
212         }
213         if ((kd = gui_harray(jd)))
214         {
215             gui_label(kd, s_camera2, GUI_SML, gui_wht, gui_wht);
216             gui_label(kd, SDL_GetKeyName(k_cam2), GUI_SML, gui_yel, gui_yel);
217         }
218         if ((kd = gui_harray(jd)))
219         {
220             gui_label(kd, s_camera3, GUI_SML, gui_wht, gui_wht);
221             gui_label(kd, SDL_GetKeyName(k_cam3), GUI_SML, gui_yel, gui_yel);
222         }
223         if ((kd = gui_harray(jd)))
224         {
225             gui_label(kd, s_shot, GUI_SML, gui_wht, gui_wht);
226             gui_label(kd, SDL_GetKeyName(k_shot), GUI_SML, gui_yel, gui_yel);
227         }
228 
229         gui_set_rect(jd, GUI_ALL);
230     }
231 
232     gui_space(id);
233 
234     gui_multi(id, s_rotate, GUI_SML, gui_wht, gui_wht);
235 
236     return id;
237 }
238 
page_modes(int id)239 static int page_modes(int id)
240 {
241     int jd;
242 
243     gui_space(id);
244 
245     if ((jd = gui_vstack(id)))
246     {
247         gui_label(jd, _("Normal Mode"), GUI_SML, 0, 0);
248         gui_multi(jd,
249                   _("Finish a level before the time runs out.\\"
250                     "You need to collect coins in order to open the goal."),
251                   GUI_SML, gui_wht, gui_wht);
252 
253         gui_set_rect(jd, GUI_ALL);
254     }
255 
256     gui_space(id);
257 
258     if ((jd = gui_vstack(id)))
259     {
260         gui_label(jd, _("Challenge Mode"), GUI_SML, 0, 0);
261         gui_multi(jd,
262                   _("Start playing from the first level of the set.\\"
263                     "You start with only three balls, do not lose them.\\"
264                     "Earn an extra ball for each 100 coins collected."),
265                   GUI_SML, gui_wht, gui_wht);
266 
267         gui_set_rect(jd, GUI_ALL);
268     }
269 
270     return id;
271 }
272 
page_tricks(int id)273 static int page_tricks(int id)
274 {
275     const char *s0 = _(
276         "Corners can be used to jump.\\"
277         "Get rolling and take aim\\"
278         "at the angle. You may be able\\"
279         "to reach new places.\\");
280     const char *s1 = _(
281         "Tilting in 2 directions increases\\"
282         "the slope. Use the manual camera\\"
283         "and turn the camera by 45\\"
284         "degrees for best results.\\");
285 
286     int w = video.device_w;
287     int h = video.device_h;
288 
289     int jd, kd, ld;
290 
291     if ((jd = gui_hstack(id)))
292     {
293         gui_filler(jd);
294 
295         if ((kd = gui_varray(jd)))
296         {
297             if ((ld = gui_vstack(kd)))
298             {
299                 gui_space(ld);
300                 gui_image(ld, "gui/help3.jpg", w / 4, h / 4);
301                 gui_state(ld, _("Watch demo"), GUI_SML, 0, 0);
302                 gui_filler(ld);
303 
304                 gui_set_state(ld, HELP_DEMO, 0);
305             }
306 
307             if ((ld = gui_vstack(kd)))
308             {
309                 gui_space(ld);
310                 gui_image(ld, "gui/help4.jpg", w / 4, h / 4);
311                 gui_state(ld, _("Watch demo"), GUI_SML, 0, 0);
312                 gui_filler(ld);
313 
314                 gui_set_state(ld, HELP_DEMO, 1);
315             }
316         }
317 
318         gui_space(jd);
319 
320         if ((kd = gui_varray(jd)))
321         {
322             if ((ld = gui_vstack(kd)))
323             {
324                 gui_space(ld);
325                 gui_multi(ld, s0, GUI_SML, gui_wht, gui_wht);
326                 gui_filler(ld);
327             }
328 
329             if ((ld = gui_vstack(kd)))
330             {
331                 gui_space(ld);
332                 gui_multi(ld, s1, GUI_SML, gui_wht, gui_wht);
333                 gui_filler(ld);
334             }
335         }
336 
337         gui_filler(jd);
338     }
339     return id;
340 }
341 
342 /* -------------------------------------------------------------------------- */
343 
help_gui(void)344 static int help_gui(void)
345 {
346     int id;
347 
348     if ((id = gui_vstack(0)))
349     {
350         help_menu(id);
351 
352         switch (page)
353         {
354         case PAGE_RULES:    page_rules(id);    break;
355         case PAGE_CONTROLS: page_controls(id); break;
356         case PAGE_MODES:    page_modes(id);    break;
357         case PAGE_TRICKS:   page_tricks(id);   break;
358         }
359 
360         gui_layout(id, 0, +1);
361     }
362 
363     return id;
364 }
365 
help_enter(struct state * st,struct state * prev)366 static int help_enter(struct state *st, struct state *prev)
367 {
368     return help_gui();
369 }
370 
help_keybd(int c,int d)371 static int help_keybd(int c, int d)
372 {
373     if (d)
374     {
375         if (c == KEY_EXIT)
376             return help_action(GUI_BACK, 0);
377     }
378     return 1;
379 }
380 
help_buttn(int b,int d)381 static int help_buttn(int b, int d)
382 {
383     if (d)
384     {
385         int active = gui_active();
386 
387         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
388             return help_action(gui_token(active), gui_value(active));
389         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_B, b))
390             return help_action(GUI_BACK, 0);
391     }
392     return 1;
393 }
394 
395 /*---------------------------------------------------------------------------*/
396 
help_demo_enter(struct state * st,struct state * prev)397 static int help_demo_enter(struct state *st, struct state *prev)
398 {
399     game_client_fly(0.0f);
400     return 0;
401 }
402 
help_demo_leave(struct state * st,struct state * next,int id)403 static void help_demo_leave(struct state *st, struct state *next, int id)
404 {
405     demo_replay_stop(0);
406 }
407 
help_demo_paint(int id,float t)408 static void help_demo_paint(int id, float t)
409 {
410     game_client_draw(0, t);
411 }
412 
help_demo_timer(int id,float dt)413 static void help_demo_timer(int id, float dt)
414 {
415     game_step_fade(dt);
416 
417     if (!demo_replay_step(dt))
418         goto_state(&st_help);
419 
420     game_client_blend(demo_replay_blend());
421 }
422 
help_demo_keybd(int c,int d)423 static int help_demo_keybd(int c, int d)
424 {
425     if (d)
426     {
427         if (c == KEY_EXIT)
428             return goto_state(&st_help);
429     }
430     return 1;
431 }
432 
help_demo_buttn(int b,int d)433 static int help_demo_buttn(int b, int d)
434 {
435     if (d)
436     {
437         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_B, b))
438             return goto_state(&st_help);
439     }
440     return 1;
441 }
442 /*---------------------------------------------------------------------------*/
443 
444 struct state st_help = {
445     help_enter,
446     shared_leave,
447     shared_paint,
448     shared_timer,
449     shared_point,
450     shared_stick,
451     shared_angle,
452     shared_click,
453     help_keybd,
454     help_buttn
455 };
456 
457 struct state st_help_demo = {
458     help_demo_enter,
459     help_demo_leave,
460     help_demo_paint,
461     help_demo_timer,
462     NULL,
463     NULL,
464     NULL,
465     NULL,
466     help_demo_keybd,
467     help_demo_buttn
468 };
469