Merge 'putt-collisions' branch
[neverball] / putt / st_all.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERPUTT 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 <math.h>
16
17 #include "hud.h"
18 #include "back.h"
19 #include "geom.h"
20 #include "gui.h"
21 #include "vec3.h"
22 #include "game.h"
23 #include "hole.h"
24 #include "audio.h"
25 #include "course.h"
26 #include "config.h"
27
28 #include "st_all.h"
29 #include "st_conf.h"
30
31 /*---------------------------------------------------------------------------*/
32
33 static SDL_Joystick *joystick = NULL;
34
35 void set_joystick(SDL_Joystick *j)
36 {
37     joystick = j;
38 }
39
40 /*---------------------------------------------------------------------------*/
41
42 static char *number(int i)
43 {
44     static char str[MAXSTR];
45
46     sprintf(str, "%02d", i);
47
48     return str;
49 }
50
51 static int score_card(const char  *title,
52                       const float *c0,
53                       const float *c1)
54 {
55     int id, jd, kd, ld;
56
57     int p1 = (curr_party() >= 1) ? 1 : 0, l1 = (curr_party() == 1) ? 1 : 0;
58     int p2 = (curr_party() >= 2) ? 1 : 0, l2 = (curr_party() == 2) ? 1 : 0;
59     int p3 = (curr_party() >= 3) ? 1 : 0, l3 = (curr_party() == 3) ? 1 : 0;
60     int p4 = (curr_party() >= 4) ? 1 : 0, l4 = (curr_party() == 4) ? 1 : 0;
61
62     int i;
63     int n = curr_count() - 1;
64     int m = curr_count() / 2;
65
66     if ((id = gui_vstack(0)))
67     {
68         gui_label(id, title, GUI_MED, GUI_ALL, c0, c1);
69         gui_space(id);
70
71         if ((jd = gui_hstack(id)))
72         {
73             if ((kd = gui_varray(jd)))
74             {
75                 if (p1) gui_label(kd, _("O"),         0, GUI_NE, 0, 0);
76                 if (p1) gui_label(kd, hole_out(0), 0, 0,           gui_wht, gui_wht);
77                 if (p1) gui_label(kd, hole_out(1), 0, GUI_SE * l1, gui_red, gui_wht);
78                 if (p2) gui_label(kd, hole_out(2), 0, GUI_SE * l2, gui_grn, gui_wht);
79                 if (p3) gui_label(kd, hole_out(3), 0, GUI_SE * l3, gui_blu, gui_wht);
80                 if (p4) gui_label(kd, hole_out(4), 0, GUI_SE * l4, gui_yel, gui_wht);
81             }
82
83             if ((kd = gui_harray(jd)))
84                 for (i = m; i > 0; i--)
85                     if ((ld = gui_varray(kd)))
86                     {
87                         if (p1) gui_label(ld, number(i), 0, (i == 1) ? GUI_NW : 0, 0, 0);
88                         if (p1) gui_label(ld, hole_score(i, 0), 0, 0, gui_wht, gui_wht);
89                         if (p1) gui_label(ld, hole_score(i, 1), 0, 0, gui_red, gui_wht);
90                         if (p2) gui_label(ld, hole_score(i, 2), 0, 0, gui_grn, gui_wht);
91                         if (p3) gui_label(ld, hole_score(i, 3), 0, 0, gui_blu, gui_wht);
92                         if (p4) gui_label(ld, hole_score(i, 4), 0, 0, gui_yel, gui_wht);
93                     }
94             if ((kd = gui_varray(jd)))
95             {
96                 gui_filler(kd);
97                 if (p1) gui_label(kd, _("Par"), 0, GUI_NW,      gui_wht, gui_wht);
98                 if (p1) gui_label(kd, _("P1"),  0, GUI_SW * l1, gui_red, gui_wht);
99                 if (p2) gui_label(kd, _("P2"),  0, GUI_SW * l2, gui_grn, gui_wht);
100                 if (p3) gui_label(kd, _("P3"),  0, GUI_SW * l3, gui_blu, gui_wht);
101                 if (p4) gui_label(kd, _("P4"),  0, GUI_SW * l4, gui_yel, gui_wht);
102             }
103         }
104
105         gui_space(id);
106
107         if ((jd = gui_hstack(id)))
108         {
109             if ((kd = gui_varray(jd)))
110             {
111                 if (p1) gui_label(kd, _("Tot"),    0, GUI_TOP, 0, 0);
112                 if (p1) gui_label(kd, hole_tot(0), 0, 0,           gui_wht, gui_wht);
113                 if (p1) gui_label(kd, hole_tot(1), 0, GUI_BOT * l1, gui_red, gui_wht);
114                 if (p2) gui_label(kd, hole_tot(2), 0, GUI_BOT * l2, gui_grn, gui_wht);
115                 if (p3) gui_label(kd, hole_tot(3), 0, GUI_BOT * l3, gui_blu, gui_wht);
116                 if (p4) gui_label(kd, hole_tot(4), 0, GUI_BOT * l4, gui_yel, gui_wht);
117             }
118             if ((kd = gui_varray(jd)))
119             {
120                 if (p1) gui_label(kd, _("I"),     0, GUI_NE, 0, 0);
121                 if (p1) gui_label(kd, hole_in(0), 0, 0,           gui_wht, gui_wht);
122                 if (p1) gui_label(kd, hole_in(1), 0, GUI_SE * l1, gui_red, gui_wht);
123                 if (p2) gui_label(kd, hole_in(2), 0, GUI_SE * l2, gui_grn, gui_wht);
124                 if (p3) gui_label(kd, hole_in(3), 0, GUI_SE * l3, gui_blu, gui_wht);
125                 if (p4) gui_label(kd, hole_in(4), 0, GUI_SE * l4, gui_yel, gui_wht);
126             }
127             if ((kd = gui_harray(jd)))
128                 for (i = n; i > m; i--)
129                     if ((ld = gui_varray(kd)))
130                     {
131                         if (p1) gui_label(ld, number(i), 0, (i == m+1) ? GUI_NW : 0, 0, 0);
132                         if (p1) gui_label(ld, hole_score(i, 0), 0, 0, gui_wht, gui_wht);
133                         if (p1) gui_label(ld, hole_score(i, 1), 0, 0, gui_red, gui_wht);
134                         if (p2) gui_label(ld, hole_score(i, 2), 0, 0, gui_grn, gui_wht);
135                         if (p3) gui_label(ld, hole_score(i, 3), 0, 0, gui_blu, gui_wht);
136                         if (p4) gui_label(ld, hole_score(i, 4), 0, 0, gui_yel, gui_wht);
137                     }
138             if ((kd = gui_varray(jd)))
139             {
140                 gui_filler(kd);
141                 if (p1) gui_label(kd, _("Par"), 0, GUI_NW,      gui_wht, gui_wht);
142                 if (p1) gui_label(kd, _("P1"),  0, GUI_SW * l1, gui_red, gui_wht);
143                 if (p2) gui_label(kd, _("P2"),  0, GUI_SW * l2, gui_grn, gui_wht);
144                 if (p3) gui_label(kd, _("P3"),  0, GUI_SW * l3, gui_blu, gui_wht);
145                 if (p4) gui_label(kd, _("P4"),  0, GUI_SW * l4, gui_yel, gui_wht);
146             }
147         }
148
149         gui_layout(id, 0, 0);
150     }
151
152     return id;
153 }
154
155 /*---------------------------------------------------------------------------*/
156
157 static int shared_stick_basic(int id, int a, int v)
158 {
159     int jd = 0;
160
161     if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
162         jd = gui_stick(id, v, 0);
163     else if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
164         jd = gui_stick(id, 0, v);
165
166     if (jd)
167         gui_pulse(jd, 1.2f);
168
169     return jd;
170 }
171
172 static void shared_stick(int id, int a, int v)
173 {
174     shared_stick_basic(id, a, v);
175 }
176
177 /*---------------------------------------------------------------------------*/
178
179 #define TITLE_PLAY 1
180 #define TITLE_CONF 2
181 #define TITLE_EXIT 3
182
183 static int title_action(int i)
184 {
185     audio_play(AUD_MENU, 1.0f);
186
187     switch (i)
188     {
189     case TITLE_PLAY: return goto_state(&st_course);
190     case TITLE_CONF: return goto_state(&st_conf);
191     case TITLE_EXIT: return 0;
192     }
193     return 1;
194 }
195
196 static int title_enter(void)
197 {
198     int id, jd, kd;
199
200     /* Build the title GUI. */
201
202     if ((id = gui_vstack(0)))
203     {
204         gui_label(id, "Neverputt", GUI_LRG, GUI_ALL, 0, 0);
205         gui_space(id);
206
207         if ((jd = gui_harray(id)))
208         {
209             gui_filler(jd);
210
211             if ((kd = gui_varray(jd)))
212             {
213                 gui_start(kd, sgettext("menu^Play"),    GUI_MED, TITLE_PLAY, 1);
214                 gui_state(kd, sgettext("menu^Options"), GUI_MED, TITLE_CONF, 0);
215                 gui_state(kd, sgettext("menu^Exit"),    GUI_MED, TITLE_EXIT, 0);
216             }
217
218             gui_filler(jd);
219         }
220         gui_layout(id, 0, 0);
221     }
222
223     course_init();
224     course_rand();
225
226     return id;
227 }
228
229 static void title_leave(int id)
230 {
231     gui_delete(id);
232 }
233
234 static void title_paint(int id, float t)
235 {
236     game_draw(0, t);
237     gui_paint(id);
238 }
239
240 static void title_timer(int id, float dt)
241 {
242     float g[3] = { 0.0f, -9.8f, 0.0f };
243
244     game_step(g, dt);
245     game_set_fly(fcosf(time_state() / 10.f));
246
247     gui_timer(id, dt);
248 }
249
250 static void title_point(int id, int x, int y, int dx, int dy)
251 {
252     gui_pulse(gui_point(id, x, y), 1.2f);
253 }
254
255 static int title_click(int b, int d)
256 {
257     return (d && b < 0) ? title_action(gui_token(gui_click())) : 1;
258 }
259
260 static int title_buttn(int b, int d)
261 {
262     if (d)
263     {
264         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
265             return title_action(gui_token(gui_click()));
266         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
267             return title_action(TITLE_EXIT);
268     }
269     return 1;
270 }
271
272 /*---------------------------------------------------------------------------*/
273
274 static int desc_id;
275 static int shot_id;
276
277 #define COURSE_BACK -1
278
279 static int course_action(int i)
280 {
281     if (course_exists(i))
282     {
283         course_goto(i);
284         goto_state(&st_party);
285     }
286     if (i == COURSE_BACK)
287         goto_state(&st_title);
288
289     return 1;
290 }
291
292 static int course_enter(void)
293 {
294     int w = config_get_d(CONFIG_WIDTH);
295     int h = config_get_d(CONFIG_HEIGHT);
296
297     int id, jd, kd, ld, md, i = 0, j, n = course_count();
298     int m = (int)(sqrt(n/2.0)*2);
299
300     if ((id = gui_vstack(0)))
301     {
302         gui_label(id, _("Select Course"), GUI_MED, GUI_ALL, 0, 0);
303         gui_space(id);
304
305         if ((jd = gui_hstack(id)))
306         {
307             shot_id = gui_image(jd, course_shot(0), w / 3, h / 3);
308
309             gui_filler(jd);
310
311             if ((kd = gui_varray(jd)))
312             {
313                 for(i = 0; i < n; i += m)
314                 {
315                     if ((ld = gui_harray(kd)))
316                     {
317                         for (j = (m - 1); j >= 0; j--)
318                         {
319                             if (i + j < n)
320                             {
321                                 md = gui_image(ld, course_shot(i + j),
322                                                w / 3 / m, h / 3 / m);
323                                 gui_active(md, i + j, 0);
324
325                                 if (i + j == 0)
326                                     gui_focus(md);
327                             }
328                             else
329                                 gui_space(ld);
330                         }
331                     }
332                 }
333             }
334         }
335
336         gui_space(id);
337         desc_id = gui_multi(id, _(course_desc(0)), GUI_SML, GUI_ALL, gui_yel, gui_wht);
338         gui_space(id);
339
340         if ((jd = gui_hstack(id)))
341         {
342             gui_filler(jd);
343             gui_state(jd, _("Back"), GUI_SML, COURSE_BACK, 0);
344         }
345
346         gui_layout(id, 0, 0);
347     }
348
349     audio_music_fade_to(0.5f, "bgm/inter.ogg");
350
351     return id;
352 }
353
354 static void course_leave(int id)
355 {
356     gui_delete(id);
357 }
358
359 static void course_paint(int id, float t)
360 {
361     game_draw(0, t);
362     gui_paint(id);
363 }
364
365 static void course_timer(int id, float dt)
366 {
367     gui_timer(id, dt);
368 }
369
370 static void course_point(int id, int x, int y, int dx, int dy)
371 {
372     int jd;
373
374     if ((jd = gui_point(id, x, y)))
375     {
376         int i = gui_token(jd);
377
378         if (course_exists(i))
379         {
380             gui_set_image(shot_id, course_shot(i));
381             gui_set_multi(desc_id, _(course_desc(i)));
382         }
383         gui_pulse(jd, 1.2f);
384     }
385 }
386
387 static void course_stick(int id, int a, int v)
388 {
389     int jd;
390
391     if ((jd = shared_stick_basic(id, a, v)))
392     {
393         int i = gui_token(jd);
394
395         if (course_exists(i))
396         {
397             gui_set_image(shot_id, course_shot(i));
398             gui_set_multi(desc_id, _(course_desc(i)));
399         }
400         gui_pulse(jd, 1.2f);
401     }
402 }
403
404 static int course_click(int b, int d)
405 {
406     return (d && b < 0) ? course_action(gui_token(gui_click())) : 1;
407 }
408
409 static int course_buttn(int b, int d)
410 {
411     if (d)
412     {
413         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
414             return course_action(gui_token(gui_click()));
415         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
416             return course_action(COURSE_BACK);
417     }
418     return 1;
419 }
420
421 /*---------------------------------------------------------------------------*/
422
423 #define PARTY_T 0
424 #define PARTY_1 1
425 #define PARTY_2 2
426 #define PARTY_3 3
427 #define PARTY_4 4
428 #define PARTY_B 5
429
430 static int party_action(int i)
431 {
432     switch (i)
433     {
434     case PARTY_1:
435         audio_play(AUD_MENU, 1.f);
436         hole_goto(1, 1);
437         goto_state(&st_next);
438         break;
439     case PARTY_2:
440         audio_play(AUD_MENU, 1.f);
441         hole_goto(1, 2);
442         goto_state(&st_next);
443         break;
444     case PARTY_3:
445         audio_play(AUD_MENU, 1.f);
446         hole_goto(1, 3);
447         goto_state(&st_next);
448         break;
449     case PARTY_4:
450         audio_play(AUD_MENU, 1.f);
451         hole_goto(1, 4);
452         goto_state(&st_next);
453         break;
454     case PARTY_B:
455         audio_play(AUD_MENU, 1.f);
456         goto_state(&st_course);
457         break;
458     }
459     return 1;
460 }
461
462 static int party_enter(void)
463 {
464     int id, jd;
465
466     if ((id = gui_vstack(0)))
467     {
468         gui_label(id, _("Players?"), GUI_MED, GUI_ALL, 0, 0);
469         gui_space(id);
470
471         if ((jd = gui_harray(id)))
472         {
473             int p4 = gui_state(jd, "4", GUI_LRG, PARTY_4, 0);
474             int p3 = gui_state(jd, "3", GUI_LRG, PARTY_3, 0);
475             int p2 = gui_state(jd, "2", GUI_LRG, PARTY_2, 0);
476             int p1 = gui_state(jd, "1", GUI_LRG, PARTY_1, 0);
477
478             gui_set_color(p1, gui_red, gui_wht);
479             gui_set_color(p2, gui_grn, gui_wht);
480             gui_set_color(p3, gui_blu, gui_wht);
481             gui_set_color(p4, gui_yel, gui_wht);
482
483             gui_focus(p1);
484         }
485
486         gui_space(id);
487
488         if ((jd = gui_hstack(id)))
489         {
490             gui_filler(jd);
491             gui_state(jd, _("Back"), GUI_SML, PARTY_B, 0);
492         }
493
494         gui_layout(id, 0, 0);
495     }
496
497     return id;
498 }
499
500 static void party_leave(int id)
501 {
502     gui_delete(id);
503 }
504
505 static void party_paint(int id, float t)
506 {
507     game_draw(0, t);
508     gui_paint(id);
509 }
510
511 static void party_timer(int id, float dt)
512 {
513     gui_timer(id, dt);
514 }
515
516 static void party_point(int id, int x, int y, int dx, int dy)
517 {
518     gui_pulse(gui_point(id, x, y), 1.2f);
519 }
520
521 static int party_click(int b, int d)
522 {
523     return (d && b < 0) ? party_action(gui_token(gui_click())) : 1;
524 }
525
526 static int party_buttn(int b, int d)
527 {
528     if (d)
529     {
530         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
531             return party_action(gui_token(gui_click()));
532         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
533             return party_action(PARTY_B);
534     }
535     return 1;
536 }
537
538 /*---------------------------------------------------------------------------*/
539
540 static int paused = 0;
541
542 static struct state *st_continue;
543 static struct state *st_quit;
544
545 #define PAUSE_CONTINUE 1
546 #define PAUSE_QUIT     2
547
548 int goto_pause(struct state *s, int e)
549 {
550     if (curr_state() == &st_pause)
551         return 1;
552
553     if (e && (SDL_GetModState() & KMOD_SHIFT))
554         return goto_state(s);
555
556     st_continue = curr_state();
557     st_quit = s;
558     paused = 1;
559
560     return goto_state(&st_pause);
561 }
562
563 static int pause_action(int i)
564 {
565     audio_play(AUD_MENU, 1.0f);
566
567     switch(i)
568     {
569     case PAUSE_CONTINUE:
570         return goto_state(st_continue ? st_continue : &st_title);
571
572     case PAUSE_QUIT:
573         return goto_state(st_quit);
574     }
575     return 1;
576 }
577
578 static int pause_enter(void)
579 {
580     int id, jd, td;
581
582     audio_music_fade_out(0.2f);
583
584     if ((id = gui_vstack(0)))
585     {
586         td = gui_label(id, _("Paused"), GUI_LRG, GUI_ALL, 0, 0);
587         gui_space(id);
588
589         if ((jd = gui_harray(id)))
590         {
591             gui_state(jd, _("Quit"), GUI_SML, PAUSE_QUIT, 0);
592             gui_start(jd, _("Continue"), GUI_SML, PAUSE_CONTINUE, 1);
593         }
594
595         gui_pulse(td, 1.2f);
596         gui_layout(id, 0, 0);
597     }
598
599     hud_init();
600     return id;
601 }
602
603 static void pause_leave(int id)
604 {
605     gui_delete(id);
606     hud_free();
607     audio_music_fade_in(0.5f);
608 }
609
610 static void pause_paint(int id, float t)
611 {
612     game_draw(0, t);
613     gui_paint(id);
614     hud_paint();
615 }
616
617 static void pause_timer(int id, float dt)
618 {
619     gui_timer(id, dt);
620 }
621
622 static void pause_point(int id, int x, int y, int dx, int dy)
623 {
624     gui_pulse(gui_point(id, x, y), 1.2f);
625 }
626
627 static int pause_click(int b, int d)
628 {
629     return (d && b < 0) ? pause_action(gui_token(gui_click())) : 1;
630 }
631
632 static int pause_keybd(int c, int d)
633 {
634     if (d && config_tst_d(CONFIG_KEY_PAUSE, c))
635         return pause_action(PAUSE_CONTINUE);
636     return 1;
637 }
638
639 static int pause_buttn(int b, int d)
640 {
641     if (d)
642     {
643         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
644             return pause_action(gui_token(gui_click()));
645         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
646             return pause_action(PAUSE_CONTINUE);
647     }
648     return 1;
649 }
650
651 /*---------------------------------------------------------------------------*/
652
653 static int shared_keybd(int c, int d)
654 {
655     if (d)
656     {
657         if (c == SDLK_ESCAPE)
658             return goto_pause(&st_over, 1);
659         if (config_tst_d(CONFIG_KEY_PAUSE, c))
660             return goto_pause(&st_over, 0);
661     }
662     return 1;
663 }
664
665 /*---------------------------------------------------------------------------*/
666
667 static int num = 0;
668
669 static int next_enter(void)
670 {
671     int id;
672     char str[MAXSTR];
673
674     sprintf(str, _("Hole %02d"), curr_hole());
675
676     if ((id = gui_vstack(0)))
677     {
678         gui_label(id, str, GUI_MED, GUI_ALL, 0, 0);
679         gui_space(id);
680
681         gui_label(id, _("Player"), GUI_SML, GUI_TOP, 0, 0);
682
683         switch (curr_player())
684         {
685         case 1:
686             gui_label(id, "1", GUI_LRG, GUI_BOT, gui_red, gui_wht);
687             if (curr_party() > 1) audio_play(AUD_PLAYER1, 1.f);
688             break;
689         case 2:
690             gui_label(id, "2", GUI_LRG, GUI_BOT, gui_grn, gui_wht);
691             if (curr_party() > 1) audio_play(AUD_PLAYER2, 1.f);
692             break;
693         case 3:
694             gui_label(id, "3", GUI_LRG, GUI_BOT, gui_blu, gui_wht);
695             if (curr_party() > 1) audio_play(AUD_PLAYER3, 1.f);
696             break;
697         case 4:
698             gui_label(id, "4", GUI_LRG, GUI_BOT, gui_yel, gui_wht);
699             if (curr_party() > 1) audio_play(AUD_PLAYER4, 1.f);
700             break;
701         }
702         gui_layout(id, 0, 0);
703     }
704
705     hud_init();
706     game_set_fly(1.f);
707
708     if (paused)
709         paused = 0;
710
711     if (!config_get_d(CONFIG_BALL_COLLISIONS))
712         game_set_play(-2, 0);
713     game_set_play(0, 1);
714
715     return id;
716 }
717
718 static void next_leave(int id)
719 {
720     hud_free();
721     gui_delete(id);
722 }
723
724 static void next_paint(int id, float t)
725 {
726     game_draw(0, t);
727     hud_paint();
728     gui_paint(id);
729 }
730
731 static void next_timer(int id, float dt)
732 {
733     gui_timer(id, dt);
734 }
735
736 static void next_point(int id, int x, int y, int dx, int dy)
737 {
738     gui_pulse(gui_point(id, x, y), 1.2f);
739 }
740
741 static int next_click(int b, int d)
742 {
743     return (d && b < 0) ? goto_state(&st_flyby) : 1;
744 }
745
746 static int next_keybd(int c, int d)
747 {
748     if (d)
749     {
750         if (c == SDLK_F12)
751             return goto_state(&st_poser);
752         if (config_tst_d(CONFIG_KEY_PAUSE, c))
753             return goto_pause(&st_over, 0);
754         if ('0' <= c && c <= '9')
755             num = num * 10 + c - '0';
756     }
757     return 1;
758 }
759
760 static int next_buttn(int b, int d)
761 {
762     if (d)
763     {
764         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
765         {
766             if (num > 0)
767             {
768                 hole_goto(num, -1);
769                 num = 0;
770                 return goto_state(&st_next);
771             }
772             return goto_state(&st_flyby);
773         }
774         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
775             return goto_pause(&st_over, 1);
776     }
777     return 1;
778 }
779
780 /*---------------------------------------------------------------------------*/
781
782 static int poser_enter(void)
783 {
784     game_set_fly(-1.f);
785     return 0;
786 }
787
788 static void poser_paint(int id, float t)
789 {
790     game_draw(1, t);
791 }
792
793 static int poser_buttn(int b, int d)
794 {
795     if (d)
796     {
797         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
798             return goto_state(&st_next);
799         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
800             return goto_state(&st_next);
801     }
802     return 1;
803 }
804
805 /*---------------------------------------------------------------------------*/
806
807 static int flyby_enter(void)
808 {
809     if (paused)
810         paused = 0;
811     else
812         hud_init();
813
814     return 0;
815 }
816
817 static void flyby_leave(int id)
818 {
819     hud_free();
820 }
821
822 static void flyby_paint(int id, float t)
823 {
824     game_draw(0, t);
825     hud_paint();
826 }
827
828 static void flyby_timer(int id, float dt)
829 {
830     float t = time_state();
831
832     if (dt > 0.f && t > 1.f)
833         goto_state(&st_stroke);
834     else
835         game_set_fly(1.f - t);
836
837     gui_timer(id, dt);
838 }
839
840 static int flyby_click(int b, int d)
841 {
842     if (d && b < 0)
843     {
844         game_set_fly(0.f);
845         return goto_state(&st_stroke);
846     }
847     return 1;
848 }
849
850 static int flyby_buttn(int b, int d)
851 {
852     if (d)
853     {
854         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
855         {
856             game_set_fly(0.f);
857             return goto_state(&st_stroke);
858         }
859         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
860             return goto_pause(&st_over, 1);
861     }
862     return 1;
863 }
864
865 /*---------------------------------------------------------------------------*/
866
867 static int stroke_rotate = 0;
868 static int stroke_mag    = 0;
869
870 static int stroke_enter(void)
871 {
872     hud_init();
873     game_clr_mag();
874     config_set_d(CONFIG_CAMERA, 2);
875     config_set_grab(!paused);
876
877     if (paused)
878         paused = 0;
879
880     return 0;
881 }
882
883 static void stroke_leave(int id)
884 {
885     hud_free();
886     config_clr_grab();
887     config_set_d(CONFIG_CAMERA, 0);
888 }
889
890 static void stroke_paint(int id, float t)
891 {
892     game_draw(0, t);
893     hud_paint();
894 }
895
896 static void stroke_timer(int id, float dt)
897 {
898     float g[3] = { 0.0f, -9.8f, 0.0f };
899
900     float k;
901
902     if (SDL_GetModState() & KMOD_SHIFT ||
903         (joystick && SDL_JoystickGetButton(joystick,
904                                            config_get_d(CONFIG_JOYSTICK_BUTTON_B))))
905         k = 0.25;
906     else
907         k = 1.0;
908
909     game_set_rot(stroke_rotate * k);
910     game_set_mag(stroke_mag * k);
911
912     game_update_view(dt);
913     game_step(g, dt);
914 }
915
916 static void stroke_point(int id, int x, int y, int dx, int dy)
917 {
918     game_set_rot(dx);
919     game_set_mag(dy);
920 }
921
922 static void stroke_stick(int id, int a, int v)
923 {
924     if (v == 1) /* See 'loop' in main.c */
925         v = 0;
926
927     if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
928         stroke_rotate = (6 * v) / JOY_MAX;
929     else if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
930         stroke_mag = -((6 * v) / JOY_MAX);
931 }
932
933 static int stroke_click(int b, int d)
934 {
935     return (d && b < 0) ? goto_state(&st_roll) : 1;
936 }
937
938 static int stroke_buttn(int b, int d)
939 {
940     if (d)
941     {
942         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
943             return goto_state(&st_roll);
944         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
945             return goto_pause(&st_over, 1);
946     }
947     return 1;
948 }
949
950 /*---------------------------------------------------------------------------*/
951
952 static int roll_enter(void)
953 {
954     hud_init();
955
956     if (paused)
957         paused = 0;
958     else
959         game_putt();
960
961     return 0;
962 }
963
964 static void roll_leave(int id)
965 {
966     hud_free();
967 }
968
969 static void roll_paint(int id, float t)
970 {
971     game_draw(0, t);
972     hud_paint();
973 }
974
975 static void roll_timer(int id, float dt)
976 {
977     float g[3] = { 0.0f, -9.8f, 0.0f };
978
979     switch (game_step(g, dt))
980     {
981     case GAME_STOP: goto_state(&st_stop); break;
982     case GAME_GOAL: goto_state(&st_goal); break;
983     case GAME_FALL: goto_state(&st_fall); break;
984     }
985 }
986
987 static int roll_buttn(int b, int d)
988 {
989     if (d)
990     {
991         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
992             return goto_pause(&st_over, 1);
993     }
994     return 1;
995 }
996
997 /*---------------------------------------------------------------------------*/
998
999 static int goal_enter(void)
1000 {
1001     int id;
1002
1003     if ((id = gui_label(0, _("It's In!"), GUI_MED, GUI_ALL, gui_grn, gui_grn)))
1004         gui_layout(id, 0, 0);
1005
1006     if (paused)
1007         paused = 0;
1008     else
1009         hole_goal(0);
1010
1011     hud_init();
1012
1013     return id;
1014 }
1015
1016 static void goal_leave(int id)
1017 {
1018     gui_delete(id);
1019     hud_free();
1020 }
1021
1022 static void goal_paint(int id, float t)
1023 {
1024     game_draw(0, t);
1025     gui_paint(id);
1026     hud_paint();
1027 }
1028
1029 static void goal_timer(int id, float dt)
1030 {
1031     if (time_state() > 3)
1032     {
1033         if (hole_next())
1034             goto_state(&st_next);
1035         else
1036             goto_state(&st_score);
1037     }
1038 }
1039
1040 static int goal_click(int b, int d)
1041 {
1042     if (b < 0 && d == 1)
1043     {
1044         if (hole_next())
1045             goto_state(&st_next);
1046         else
1047             goto_state(&st_score);
1048     }
1049     return 1;
1050 }
1051
1052 static int goal_buttn(int b, int d)
1053 {
1054     if (d)
1055     {
1056         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1057         {
1058             if (hole_next())
1059                 goto_state(&st_next);
1060             else
1061                 goto_state(&st_score);
1062         }
1063         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1064             return goto_pause(&st_over, 1);
1065     }
1066     return 1;
1067 }
1068
1069 /*---------------------------------------------------------------------------*/
1070
1071 static int stop_enter(void)
1072 {
1073     if (paused)
1074         paused = 0;
1075     else
1076         hole_stop();
1077
1078     hud_init();
1079
1080     return 0;
1081 }
1082
1083 static void stop_leave(int id)
1084 {
1085     hud_free();
1086 }
1087
1088 static void stop_paint(int id, float t)
1089 {
1090     game_draw(0, t);
1091     hud_paint();
1092 }
1093
1094 static void stop_timer(int id, float dt)
1095 {
1096     float g[3] = { 0.0f, -9.8f, 0.0f };
1097
1098     game_update_view(dt);
1099     game_step(g, dt);
1100
1101     if (time_state() > 1)
1102     {
1103         if (hole_next())
1104             goto_state(&st_next);
1105         else
1106             goto_state(&st_score);
1107     }
1108 }
1109
1110 static int stop_click(int b, int d)
1111 {
1112     if (b < 0 && d == 1)
1113     {
1114         if (hole_next())
1115             goto_state(&st_next);
1116         else
1117             goto_state(&st_score);
1118     }
1119     return 1;
1120 }
1121
1122 static int stop_buttn(int b, int d)
1123 {
1124     if (d)
1125     {
1126         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1127         {
1128             if (hole_next())
1129                 goto_state(&st_next);
1130             else
1131                 goto_state(&st_score);
1132         }
1133         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1134             return goto_pause(&st_over, 1);
1135     }
1136     return 1;
1137 }
1138
1139 /*---------------------------------------------------------------------------*/
1140
1141 static int fall_enter(void)
1142 {
1143     int id;
1144
1145     if ((id = gui_label(0, _("1 Stroke Penalty"), GUI_MED, GUI_ALL, gui_blk, gui_red)))
1146         gui_layout(id, 0, 0);
1147
1148     if (paused)
1149         paused = 0;
1150     else
1151     {
1152         hole_fall();
1153 /*        game_draw(0);*/ /*TODO: is this call ok? */  /* No, it's not. */
1154     }
1155
1156     hud_init();
1157
1158     return id;
1159 }
1160
1161 static void fall_leave(int id)
1162 {
1163     gui_delete(id);
1164     hud_free();
1165 }
1166
1167 static void fall_paint(int id, float t)
1168 {
1169     game_draw(0, t);
1170     gui_paint(id);
1171     hud_paint();
1172 }
1173
1174 static void fall_timer(int id, float dt)
1175 {
1176     if (time_state() > 3)
1177     {
1178         if (hole_next())
1179             goto_state(&st_next);
1180         else
1181             goto_state(&st_score);
1182     }
1183 }
1184
1185 static int fall_click(int b, int d)
1186 {
1187     if (b < 0 && d == 1)
1188     {
1189         if (hole_next())
1190             goto_state(&st_next);
1191         else
1192             goto_state(&st_score);
1193     }
1194     return 1;
1195 }
1196
1197 static int fall_buttn(int b, int d)
1198 {
1199     if (d)
1200     {
1201         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1202         {
1203             if (hole_next())
1204                 goto_state(&st_next);
1205             else
1206                 goto_state(&st_score);
1207         }
1208         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1209             return goto_pause(&st_over, 1);
1210     }
1211     return 1;
1212 }
1213
1214 /*---------------------------------------------------------------------------*/
1215
1216 static int score_enter(void)
1217 {
1218     audio_music_fade_out(2.f);
1219
1220     if (paused)
1221         paused = 0;
1222
1223     return score_card(_("Scores"), gui_yel, gui_red);
1224 }
1225
1226 static void score_leave(int id)
1227 {
1228     gui_delete(id);
1229 }
1230
1231 static void score_paint(int id, float t)
1232 {
1233     game_draw(0, t);
1234     gui_paint(id);
1235 }
1236
1237 static void score_timer(int id, float dt)
1238 {
1239     gui_timer(id, dt);
1240 }
1241
1242 static int score_click(int b, int d)
1243 {
1244     if (b < 0 && d == 1)
1245     {
1246         if (hole_move())
1247             return goto_state(&st_next);
1248         else
1249             return goto_state(&st_title);
1250     }
1251     return 1;
1252 }
1253
1254 static int score_buttn(int b, int d)
1255 {
1256     if (d)
1257     {
1258         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1259         {
1260             if (hole_move())
1261                 goto_state(&st_next);
1262             else
1263                 goto_state(&st_score);
1264         }
1265         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1266             return goto_pause(&st_over, 1);
1267     }
1268     return 1;
1269 }
1270
1271 /*---------------------------------------------------------------------------*/
1272
1273 static int over_enter(void)
1274 {
1275     audio_music_fade_out(2.f);
1276     return score_card(_("Final Scores"), gui_yel, gui_red);
1277 }
1278
1279 static void over_leave(int id)
1280 {
1281     gui_delete(id);
1282 }
1283
1284 static void over_paint(int id, float t)
1285 {
1286     game_draw(0, t);
1287     gui_paint(id);
1288 }
1289
1290 static void over_timer(int id, float dt)
1291 {
1292     gui_timer(id, dt);
1293 }
1294
1295 static int over_click(int b, int d)
1296 {
1297     return (d && b < 0) ? goto_state(&st_title) : 1;
1298 }
1299
1300 static int over_buttn(int b, int d)
1301 {
1302     if (d)
1303     {
1304         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1305             return goto_state(&st_title);
1306         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1307             return goto_state(&st_title);
1308     }
1309     return 1;
1310 }
1311
1312 /*---------------------------------------------------------------------------*/
1313
1314 struct state st_title = {
1315     title_enter,
1316     title_leave,
1317     title_paint,
1318     title_timer,
1319     title_point,
1320     shared_stick,
1321     NULL,
1322     title_click,
1323     NULL,
1324     title_buttn,
1325     1, 0
1326 };
1327
1328 struct state st_course = {
1329     course_enter,
1330     course_leave,
1331     course_paint,
1332     course_timer,
1333     course_point,
1334     course_stick,
1335     NULL,
1336     course_click,
1337     NULL,
1338     course_buttn,
1339     1, 0
1340 };
1341
1342 struct state st_party = {
1343     party_enter,
1344     party_leave,
1345     party_paint,
1346     party_timer,
1347     party_point,
1348     shared_stick,
1349     NULL,
1350     party_click,
1351     NULL,
1352     party_buttn,
1353     1, 0
1354 };
1355
1356 struct state st_next = {
1357     next_enter,
1358     next_leave,
1359     next_paint,
1360     next_timer,
1361     next_point,
1362     shared_stick,
1363     NULL,
1364     next_click,
1365     next_keybd,
1366     next_buttn,
1367     1, 0
1368 };
1369
1370 struct state st_poser = {
1371     poser_enter,
1372     NULL,
1373     poser_paint,
1374     NULL,
1375     NULL,
1376     NULL,
1377     NULL,
1378     NULL,
1379     NULL,
1380     poser_buttn,
1381     1, 0
1382 };
1383
1384 struct state st_flyby = {
1385     flyby_enter,
1386     flyby_leave,
1387     flyby_paint,
1388     flyby_timer,
1389     NULL,
1390     NULL,
1391     NULL,
1392     flyby_click,
1393     shared_keybd,
1394     flyby_buttn,
1395     1, 0
1396 };
1397
1398 struct state st_stroke = {
1399     stroke_enter,
1400     stroke_leave,
1401     stroke_paint,
1402     stroke_timer,
1403     stroke_point,
1404     stroke_stick,
1405     NULL,
1406     stroke_click,
1407     shared_keybd,
1408     stroke_buttn,
1409     0, 0
1410 };
1411
1412 struct state st_roll = {
1413     roll_enter,
1414     roll_leave,
1415     roll_paint,
1416     roll_timer,
1417     NULL,
1418     NULL,
1419     NULL,
1420     NULL,
1421     shared_keybd,
1422     roll_buttn,
1423     0, 0
1424 };
1425
1426 struct state st_goal = {
1427     goal_enter,
1428     goal_leave,
1429     goal_paint,
1430     goal_timer,
1431     NULL,
1432     NULL,
1433     NULL,
1434     goal_click,
1435     shared_keybd,
1436     goal_buttn,
1437     0, 0
1438 };
1439
1440 struct state st_stop = {
1441     stop_enter,
1442     stop_leave,
1443     stop_paint,
1444     stop_timer,
1445     NULL,
1446     NULL,
1447     NULL,
1448     stop_click,
1449     shared_keybd,
1450     stop_buttn,
1451     0, 0
1452 };
1453
1454 struct state st_fall = {
1455     fall_enter,
1456     fall_leave,
1457     fall_paint,
1458     fall_timer,
1459     NULL,
1460     NULL,
1461     NULL,
1462     fall_click,
1463     shared_keybd,
1464     fall_buttn,
1465     0, 0
1466 };
1467
1468 struct state st_score = {
1469     score_enter,
1470     score_leave,
1471     score_paint,
1472     score_timer,
1473     NULL,
1474     NULL,
1475     NULL,
1476     score_click,
1477     shared_keybd,
1478     score_buttn,
1479     0, 0
1480 };
1481
1482 struct state st_over = {
1483     over_enter,
1484     over_leave,
1485     over_paint,
1486     over_timer,
1487     NULL,
1488     NULL,
1489     NULL,
1490     over_click,
1491     NULL,
1492     over_buttn,
1493     1, 0
1494 };
1495
1496 struct state st_pause = {
1497     pause_enter,
1498     pause_leave,
1499     pause_paint,
1500     pause_timer,
1501     pause_point,
1502     shared_stick,
1503     NULL,
1504     pause_click,
1505     pause_keybd,
1506     pause_buttn,
1507     1, 0
1508 };