Split the "play end" state back into "goal", "fall out" and "time out"
authorparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Thu, 27 Sep 2007 22:29:22 +0000 (22:29 +0000)
committerparasti <parasti@78b8d119-cf0a-0410-b17c-f493084dd1d7>
Thu, 27 Sep 2007 22:29:22 +0000 (22:29 +0000)
states.  It's better to be redundant than incomprehensible.

git-svn-id: https://s.snth.net/svn/neverball/trunk@1167 78b8d119-cf0a-0410-b17c-f493084dd1d7

Makefile
ball/st_fall_out.c [new file with mode: 0644]
ball/st_fall_out.h [new file with mode: 0644]
ball/st_goal.c [new file with mode: 0644]
ball/st_goal.h [new file with mode: 0644]
ball/st_play.c
ball/st_play_end.c [deleted file]
ball/st_play_end.h [deleted file]
ball/st_time_out.c [new file with mode: 0644]
ball/st_time_out.h [new file with mode: 0644]

index 977c8f3..ce85f06 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -97,7 +97,9 @@ BALL_OBJS := \
        ball/st_conf.o      \
        ball/st_demo.o      \
        ball/st_save.o      \
-       ball/st_play_end.o  \
+       ball/st_goal.o      \
+       ball/st_fall_out.o  \
+       ball/st_time_out.o  \
        ball/st_done.o      \
        ball/st_level.o     \
        ball/st_over.o      \
diff --git a/ball/st_fall_out.c b/ball/st_fall_out.c
new file mode 100644 (file)
index 0000000..bd49d3c
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2007 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#include "gui.h"
+#include "game.h"
+#include "util.h"
+#include "levels.h"
+#include "audio.h"
+#include "config.h"
+#include "demo.h"
+
+#include "st_fall_out.h"
+#include "st_save.h"
+#include "st_over.h"
+#include "st_start.h"
+#include "st_level.h"
+#include "st_shared.h"
+
+/*---------------------------------------------------------------------------*/
+
+#define FALL_OUT_NEXT 1
+#define FALL_OUT_SAME 2
+#define FALL_OUT_SAVE 3
+#define FALL_OUT_BACK 4
+#define FALL_OUT_OVER 5
+
+static int be_back_soon;
+
+static int fall_out_action(int i)
+{
+    audio_play(AUD_MENU, 1.0f);
+
+    switch (i)
+    {
+    case FALL_OUT_BACK:
+        /* Fall through. */
+
+    case FALL_OUT_OVER:
+        if (curr_lg()->mode == MODE_CHALLENGE)
+            return goto_state(&st_over);
+        else
+            return goto_state(&st_start);
+
+    case FALL_OUT_SAVE:
+        be_back_soon = 1;
+        return goto_save(&st_fall_out, &st_fall_out);
+
+    case FALL_OUT_NEXT:
+        level_next();
+        level_play(curr_lg()->level, curr_lg()->mode);
+        return goto_state(&st_level);
+
+    case FALL_OUT_SAME:
+        level_play(curr_lg()->level, curr_lg()->mode);
+        return goto_state(&st_level);
+    }
+
+    return 1;
+}
+
+static int fall_out_enter(void)
+{
+    int id, jd, kd;
+
+    const struct level_game *lg = curr_lg();
+
+    /* Reset hack. */
+    be_back_soon = 0;
+
+    if ((id = gui_vstack(0)))
+    {
+        kd = gui_label(id, _("Fall-out!"), GUI_LRG, GUI_ALL, gui_gry, gui_red);
+
+        gui_space(id);
+
+        if ((jd = gui_harray(id)))
+        {
+            int next_id = 0, retry_id = 0;
+
+            next_id = gui_maybe(jd, _("Next Level"), FALL_OUT_NEXT,
+                                lg->next_level != NULL);
+
+            if (lg->dead)
+            {
+                gui_start(jd, _("Game Over"), GUI_SML, FALL_OUT_OVER, 0);
+            }
+            else
+            {
+                retry_id = gui_maybe(jd, _("Retry Level"), FALL_OUT_SAME,
+                                     lg->mode != MODE_CHALLENGE);
+            }
+
+            gui_maybe(jd, _("Save Replay"), FALL_OUT_SAVE, demo_play_saved());
+
+            /* Default is next if the next level is newly unlocked. */
+
+            if (next_id && lg->unlock)
+                gui_focus(next_id);
+            else if (lg->mode != MODE_CHALLENGE)
+                gui_focus(retry_id);
+        }
+
+        gui_space(id);
+
+        gui_pulse(kd, 1.2f);
+        gui_layout(id, 0, 0);
+    }
+
+    audio_music_fade_out(2.0f);
+    /* audio_play(AUD_FALL, 1.0f); */
+
+    config_clr_grab();
+
+    return id;
+}
+
+static void fall_out_timer(int id, float dt)
+{
+    float g[3] = { 0.0f, -9.8f, 0.0f };
+
+    if (time_state() < 2.f)
+    {
+        game_step(g, dt, 0);
+        /* demo_play_step(dt); */
+    }
+
+    gui_timer(id, dt);
+    audio_timer(dt);
+}
+
+static int fall_out_buttn(int b, int d)
+{
+    if (d)
+    {
+        if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
+            return fall_out_action(gui_token(gui_click()));
+        if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
+            return fall_out_action(FALL_OUT_BACK);
+    }
+    return 1;
+}
+
+void fall_out_leave(int id)
+{
+    /* HACK:  don't run animation if only "visiting" a state. */
+    st_fall_out.timer = be_back_soon ? shared_timer : fall_out_timer;
+
+    gui_delete(id);
+}
+
+/*---------------------------------------------------------------------------*/
+
+struct state st_fall_out = {
+    fall_out_enter,
+    fall_out_leave,
+    shared_paint,
+    fall_out_timer,
+    shared_point,
+    shared_stick,
+    shared_click,
+    NULL,
+    fall_out_buttn,
+    1, 0
+};
+
diff --git a/ball/st_fall_out.h b/ball/st_fall_out.h
new file mode 100644 (file)
index 0000000..7c88914
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef ST_FALL_OUT_H
+#define ST_FALL_OUT_H
+
+#include "state.h"
+
+extern struct state st_fall_out;
+
+#endif
+
diff --git a/ball/st_goal.c b/ball/st_goal.c
new file mode 100644 (file)
index 0000000..9992aa6
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2007 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#include "gui.h"
+#include "game.h"
+#include "util.h"
+#include "levels.h"
+#include "audio.h"
+#include "config.h"
+#include "demo.h"
+
+#include "st_goal.h"
+#include "st_save.h"
+#include "st_over.h"
+#include "st_done.h"
+#include "st_start.h"
+#include "st_level.h"
+#include "st_name.h"
+#include "st_shared.h"
+
+/*---------------------------------------------------------------------------*/
+
+#define GOAL_NEXT 1
+#define GOAL_SAME 2
+#define GOAL_SAVE 3
+#define GOAL_BACK 4
+#define GOAL_DONE 5
+#define GOAL_NAME 6
+#define GOAL_OVER 7
+
+static int balls_id;
+static int coins_id;
+static int score_id;
+
+static int new_name;
+static int be_back_soon;
+
+static int goal_action(int i)
+{
+    audio_play(AUD_MENU, 1.0f);
+
+    switch (i)
+    {
+    case GOAL_BACK:
+        /* Fall through. */
+
+    case GOAL_OVER:
+        if (curr_lg()->mode == MODE_CHALLENGE)
+            return goto_state(&st_over);
+        else
+            return goto_state(&st_start);
+
+    case GOAL_SAVE:
+        be_back_soon = 1;
+        return goto_save(&st_goal, &st_goal);
+
+    case GOAL_NAME:
+        new_name = 1;
+        be_back_soon = 1;
+        return goto_name(&st_goal, &st_goal);
+
+    case GOAL_DONE:
+        return goto_state(&st_done);
+
+    case GOAL_NEXT:
+        level_next();
+        level_play(curr_lg()->level, curr_lg()->mode);
+        return goto_state(&st_level);
+
+    case GOAL_SAME:
+        level_play(curr_lg()->level, curr_lg()->mode);
+        return goto_state(&st_level);
+    }
+
+    return 1;
+}
+
+static int goal_enter(void)
+{
+    int id, jd, kd;
+
+    const struct level_game *lg = curr_lg();
+    const struct level *l = lg->level;
+
+    int high;
+
+    high = (lg->time_rank < 3) || (lg->goal_rank < 3) || (lg->coin_rank < 3);
+
+    /* Reset hack. */
+    be_back_soon = 0;
+
+    if (new_name)
+    {
+        level_update_player_name();
+        new_name = 0;
+    }
+
+    if ((id = gui_vstack(0)))
+    {
+        int gid;
+
+        if (high)
+            gid = gui_label(id, _("New Record"), GUI_MED, GUI_ALL, gui_grn, gui_grn);
+        else
+            gid = gui_label(id, _("GOAL"), GUI_LRG, GUI_ALL, gui_blu, gui_grn);
+
+        gui_space(id);
+
+        if (lg->mode == MODE_CHALLENGE)
+        {
+            int coins = lg->coins;
+            int score = lg->score - coins;
+            int balls = lg->balls - count_extra_balls(score, coins);
+
+            if ((jd = gui_hstack(id)))
+            {
+                if ((kd = gui_harray(jd)))
+                {
+                    balls_id = gui_count(kd, 100, GUI_MED, GUI_RGT);
+                    gui_label(kd, _("Balls"), GUI_SML, GUI_LFT, gui_wht, gui_wht);
+                }
+                if ((kd = gui_harray(jd)))
+                {
+                    score_id = gui_count(kd, 1000, GUI_MED, GUI_RGT);
+                    gui_label(kd, _("Score"), GUI_SML, GUI_LFT, gui_wht, gui_wht);
+                }
+                if ((kd = gui_harray(jd)))
+                {
+                    coins_id = gui_count(kd, 100, GUI_MED, GUI_RGT);
+                    gui_label(kd, _("Coins"), GUI_SML, GUI_LFT, gui_wht, gui_wht);
+                }
+
+                gui_set_count(balls_id, balls);
+                gui_set_count(score_id, score);
+                gui_set_count(coins_id, coins);
+            }
+        }
+        else
+        {
+            balls_id = score_id = coins_id = 0;
+        }
+
+        gui_space(id);
+
+        if ((jd = gui_harray(id)))
+        {
+            gui_most_coins(jd, 1);
+            gui_best_times(jd, 1);
+        }
+
+        gui_space(id);
+
+        if ((jd = gui_harray(id)))
+        {
+            int next_id = 0, retry_id = 0;
+
+            if (lg->win)
+                gui_start(jd, _("Finish"), GUI_SML, GOAL_DONE, 0);
+            else
+                next_id = gui_maybe(jd, _("Next Level"),  GOAL_NEXT,
+                                    lg->next_level != NULL);
+
+            if (lg->dead)
+                gui_start(jd, _("Game Over"), GUI_SML, GOAL_OVER, 0);
+            else
+            {
+                retry_id = gui_maybe(jd, _("Retry Level"), GOAL_SAME,
+                                     lg->mode != MODE_CHALLENGE);
+            }
+
+            gui_maybe(jd, _("Save Replay"), GOAL_SAVE, demo_play_saved());
+
+            /* Default is next if the next level is newly unlocked. */
+
+            if (next_id && lg->unlock)
+                gui_focus(next_id);
+            else if (lg->mode != MODE_CHALLENGE)
+                gui_focus(retry_id);
+        }
+
+        /* FIXME, I'm ugly. */
+
+        if (high)
+            gui_state(id, _("Change Player Name"),  GUI_SML, GOAL_NAME, 0);
+
+        gui_pulse(gid, 1.2f);
+        gui_layout(id, 0, 0);
+
+    }
+
+    set_most_coins(&l->score.most_coins, lg->coin_rank);
+
+    if (lg->mode == MODE_CHALLENGE || lg->mode == MODE_NORMAL)
+        set_best_times(&l->score.unlock_goal, lg->goal_rank, 1);
+    else
+        set_best_times(&l->score.best_times, lg->time_rank, 0);
+
+    audio_music_fade_out(2.0f);
+
+    config_clr_grab();
+
+    return id;
+}
+
+static void goal_timer(int id, float dt)
+{
+    static float DT = 0.0f;
+
+    float g[3] = { 0.0f, 9.8f, 0.0f };
+
+    DT += dt;
+
+    if (time_state() < 1.f)
+    {
+        game_step(g, dt, 0);
+        /* demo_play_step(dt); */
+    }
+    else if (DT > 0.05f && coins_id)
+    {
+        int coins = gui_value(coins_id);
+
+        if (coins > 0)
+        {
+            int score = gui_value(score_id);
+            int balls = gui_value(balls_id);
+
+            gui_set_count(coins_id, coins - 1);
+            gui_pulse(coins_id, 1.1f);
+
+            gui_set_count(score_id, score + 1);
+            gui_pulse(score_id, 1.1f);
+
+            if ((score + 1) % 100 == 0)
+            {
+                gui_set_count(balls_id, balls + 1);
+                gui_pulse(balls_id, 2.0f);
+                audio_play(AUD_BALL, 1.0f);
+            }
+        }
+        DT = 0.0f;
+    }
+
+    gui_timer(id, dt);
+    audio_timer(dt);
+}
+
+static int goal_buttn(int b, int d)
+{
+    if (d)
+    {
+        if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
+            return goal_action(gui_token(gui_click()));
+        if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
+            return goal_action(GOAL_BACK);
+    }
+    return 1;
+}
+
+
+void goal_leave(int id)
+{
+    /* HACK:  don't run animation if only "visiting" a state. */
+    st_goal.timer = be_back_soon ? shared_timer : goal_timer;
+
+    gui_delete(id);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+struct state st_goal = {
+    goal_enter,
+    goal_leave,
+    shared_paint,
+    goal_timer,
+    shared_point,
+    shared_stick,
+    shared_click,
+    NULL,
+    goal_buttn,
+    1, 0
+};
+
diff --git a/ball/st_goal.h b/ball/st_goal.h
new file mode 100644 (file)
index 0000000..0e01abb
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ST_GOAL_H
+#define ST_GOAL_H
+
+#include "state.h"
+
+extern struct state st_goal;
+
+#endif
index 96e0f55..c52b7c3 100644 (file)
@@ -22,7 +22,9 @@
 #include "st_shared.h"
 
 #include "st_play.h"
-#include "st_play_end.h"
+#include "st_goal.h"
+#include "st_fall_out.h"
+#include "st_time_out.h"
 #include "st_start.h"
 #include "st_pause.h"
 
@@ -200,6 +202,7 @@ static int play_loop_enter(void)
 static void play_loop_paint(int id, float st)
 {
     game_draw(0, st);
+
     if (!nohud)
         hud_paint();
 
@@ -219,25 +222,36 @@ static void play_loop_timer(int id, float dt)
 
     float g[3] = { 0.0f, -9.8f, 0.0f };
 
-    int state;
-
     at = (7 * at + dt) / 8;
 
     gui_timer(id, at);
     hud_timer(at);
     game_set_rot(view_rotate * k);
 
-    state = game_step(g, at, 1);
+    switch (game_step(g, at, 1))
+    {
+    case GAME_GOAL:
+        level_stop(GAME_GOAL, curr_clock(), curr_coins());
+        goto_state(&st_goal);
+        break;
+
+    case GAME_FALL:
+        level_stop(GAME_FALL, curr_clock(), curr_coins());
+        goto_state(&st_fall_out);
+        break;
+
+    case GAME_TIME:
+        level_stop(GAME_TIME, curr_clock(), curr_coins());
+        goto_state(&st_time_out);
+        break;
+
+    default:
+        break;
+    }
 
     game_step_fade(dt);
     demo_play_step(at);
     audio_timer(dt);
-
-    if (state)
-    {
-        level_stop(state, curr_clock(), curr_coins());
-        goto_state(&st_play_end);
-    }
 }
 
 static void play_loop_point(int id, int x, int y, int dx, int dy)
@@ -311,7 +325,7 @@ static int play_loop_keybd(int c, int d)
     if (d && c == SDLK_c && config_get_d(CONFIG_CHEAT))
     {
         level_stop(GAME_GOAL, curr_clock(), curr_coins());
-        return goto_state(&st_play_end);
+        return goto_state(&st_goal);
     }
     return 1;
 }
diff --git a/ball/st_play_end.c b/ball/st_play_end.c
deleted file mode 100644 (file)
index 766050e..0000000
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2003 Robert Kooima
- *
- * NEVERBALL is  free software; you can redistribute  it and/or modify
- * it under the  terms of the GNU General  Public License as published
- * by the Free  Software Foundation; either version 2  of the License,
- * or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
- * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
- * General Public License for more details.
- */
-
-#include <string.h>
-
-#include "gui.h"
-#include "set.h"
-#include "game.h"
-#include "util.h"
-#include "levels.h"
-#include "audio.h"
-#include "config.h"
-#include "demo.h"
-#include "st_shared.h"
-
-#include "st_play_end.h"
-#include "st_save.h"
-#include "st_over.h"
-#include "st_done.h"
-#include "st_start.h"
-#include "st_level.h"
-#include "st_name.h"
-
-/*---------------------------------------------------------------------------*/
-
-#define PLAY_END_NEXT 2
-#define PLAY_END_SAME 3
-#define PLAY_END_SAVE 4
-#define PLAY_END_BACK 5
-#define PLAY_END_DONE 6
-#define PLAY_END_NAME 7
-#define PLAY_END_OVER 8
-
-static int balls_id;
-static int coins_id;
-static int score_id;
-static int status_id;
-
-extern struct state st_play_end_bis;
-
-static int play_end_action(int i)
-{
-    audio_play(AUD_MENU, 1.0f);
-
-    switch (i)
-    {
-    case PLAY_END_BACK:
-    case PLAY_END_OVER:
-        return goto_end_level();
-
-    case PLAY_END_SAVE:
-        return goto_save(&st_play_end_bis, &st_play_end_bis);
-
-    case PLAY_END_NAME:
-        return goto_name(&st_play_end_bis, &st_play_end_bis);
-
-    case PLAY_END_DONE:
-        return goto_state(&st_done);
-
-    case PLAY_END_NEXT:
-        level_next();
-        level_play(curr_lg()->level, curr_lg()->mode);
-        return goto_state(&st_level);
-
-    case PLAY_END_SAME:
-        level_play(curr_lg()->level, curr_lg()->mode);
-        return goto_state(&st_level);
-    }
-
-    return 1;
-}
-
-static void play_end_over(int id)
-{
-    if (id == 0)
-        return;
-
-    switch (gui_token(id))
-    {
-        case 0:
-            break;
-
-        case PLAY_END_SAVE:
-            gui_set_label(status_id, _("Save a replay file"));
-            break;
-
-        case PLAY_END_SAVE | GUI_NULL_MASK:
-            gui_set_label(status_id, _("Replay file already saved"));
-            break;
-
-        case PLAY_END_NAME:
-            gui_set_label(status_id, _("Change the player's name"));
-            break;
-
-        case PLAY_END_DONE:
-            gui_set_label(status_id, _("You complete the set"));
-            break;
-
-        case PLAY_END_NEXT:
-            gui_set_label(status_id, _("Play the next level"));
-            break;
-
-        case PLAY_END_NEXT | GUI_NULL_MASK:
-            if (curr_lg()->mode == MODE_PRACTICE)
-                gui_set_label(status_id, 
-                        _("Cannot unlock in practice mode"));
-            else
-                gui_set_label(status_id, 
-                        _("Finish this level to unlock the next one"));
-            break;
-
-        case PLAY_END_SAME:
-            gui_set_label(status_id, _("Replay this level"));
-            break;
-
-        case PLAY_END_SAME | GUI_NULL_MASK:
-            gui_set_label(status_id, _("You cannot replay in challenge mode"));
-            break;
-
-        default:
-            gui_set_label(status_id, "");
-    }
-}
-
-
-static int play_end_init(int *gidp)
-{
-    const struct level_game *lg = curr_lg();
-    int mode  = lg->mode;
-    int state = lg->state;
-    const struct level *l = lg->level;
-
-    int id, jd, kd;
-    int high;
-
-    high = (lg->time_rank < 3) || (lg->goal_rank < 3) || (lg->coin_rank < 3);
-
-    if ((id = gui_vstack(0)))
-    {
-        int gid;
-
-        if (state == GAME_FALL)
-            gid = gui_label(id, _("Fall-out!"), GUI_MED, GUI_ALL,
-                            gui_gry, gui_red);
-        else if (state == GAME_TIME)
-            gid = gui_label(id, _("Time's Up!"), GUI_MED, GUI_ALL,
-                            gui_gry, gui_red);
-        else if (high)
-            gid = gui_label(id, _("New Record"), GUI_MED, GUI_ALL,
-                            gui_grn, gui_grn);
-        else
-            gid = gui_label(id, _("GOAL"), GUI_LRG, GUI_ALL,
-                            gui_blu, gui_grn);
-
-        gui_space(id);
-
-        if (mode == MODE_CHALLENGE &&
-            (lg->state == GAME_GOAL || l->is_bonus))
-        {
-            int coins = lg->coins;
-            int score = lg->score - coins;
-            int balls = lg->balls - count_extra_balls(score, coins);
-            if ((jd = gui_hstack(id)))
-            {
-                if ((kd = gui_harray(jd)))
-                {
-                    balls_id = gui_count(kd,  100, GUI_MED, GUI_RGT);
-                    gui_label(kd, _("Balls"), GUI_SML, GUI_LFT, gui_wht, gui_wht);
-                }
-                if ((kd = gui_harray(jd)))
-                {
-                    score_id = gui_count(kd, 1000, GUI_MED, GUI_RGT);
-                    gui_label(kd, _("Score"), GUI_SML, GUI_LFT, gui_wht, gui_wht);
-                }
-                if ((kd = gui_harray(jd)))
-                {
-                    coins_id = gui_count(kd, 100, GUI_MED, GUI_RGT);
-                    gui_label(kd, _("Coins"), GUI_SML, GUI_LFT, gui_wht, gui_wht);
-                }
-
-                gui_set_count(balls_id, balls);
-                gui_set_count(score_id, score);
-                gui_set_count(coins_id, coins);
-            }
-        }
-        else
-        {
-            balls_id = score_id = coins_id = 0;
-        }
-
-        if (state == GAME_GOAL)
-        {
-            gui_space(id);
-            if ((jd = gui_harray(id)))
-            {
-                gui_most_coins(jd, 1);
-                gui_best_times(jd, 1);
-            }
-        }
-
-        gui_space(id);
-
-        if ((jd = gui_harray(id)))
-        {
-            int nlid = 0, rlid = 0;
-            int b = 0;
-
-            if (lg->win)
-                gui_start(jd, _("Finish"), GUI_SML, PLAY_END_DONE, 0);
-            else
-                nlid = gui_maybe(jd, _("Next Level"),  PLAY_END_NEXT,
-                                 lg->next_level != NULL);
-
-            if (lg->dead)
-                gui_start(jd, _("Game Over"), GUI_SML, PLAY_END_OVER, 0);
-            else
-            {
-                b = mode != MODE_CHALLENGE || ((state == GAME_FALL || state == GAME_TIME) && !lg->dead && !l->is_bonus);
-                rlid = gui_maybe(jd, _("Retry Level"), PLAY_END_SAME, b);
-            }
-
-            gui_maybe(jd, _("Save Replay"), PLAY_END_SAVE, demo_play_saved());
-
-            /* default is next if the next level is newly unlocked */
-            if (nlid != 0 && lg->unlock)
-                 gui_focus(nlid);
-            else if (b)
-                 gui_focus(rlid);
-        }
-
-        if (high)
-            gui_state(id, _("Change Player Name"),  GUI_SML, PLAY_END_NAME, 0);
-
-        gui_space(id);
-        status_id = gui_label(id, "Neverball", GUI_SML, GUI_ALL, 0, 0);
-
-        gui_layout(id, 0, 0);
-        if (gidp) *gidp = gid;
-    }
-
-    if (state == GAME_GOAL)
-    {
-        set_most_coins(&l->score.most_coins, lg->coin_rank);
-        if (mode == MODE_CHALLENGE || mode == MODE_NORMAL)
-            set_best_times(&l->score.unlock_goal, lg->goal_rank, 1);
-        else
-            set_best_times(&l->score.best_times, lg->time_rank, 0);
-    }
-
-    config_clr_grab();
-
-    return id;
-}
-
-static int play_end_enter(void)
-{
-    int gid;
-    int r;
-
-    r = play_end_init(&gid);
-
-    gui_pulse(gid, 1.2f);
-    audio_music_fade_out(2.0f);
-    return r;
-}
-
-static int play_end_bis_enter(void)
-{
-    level_update_player_name();
-    return play_end_init(NULL);
-}
-
-static void play_end_timer(int id, float dt)
-{
-    static float DT = 0.0f;
-
-    float gg[3] = { 0.0f, 9.8f, 0.0f };
-    float gf[3] = { 0.0f, -9.8f, 0.0f };
-    int state = curr_lg()->state;
-
-    DT += dt;
-
-    if (state != GAME_TIME)
-    {
-        if (time_state() < 2.f)
-            game_step(state == GAME_GOAL ? gg : gf, dt, 0);
-    }
-
-    if (time_state() > 1.f && DT > 0.05f && coins_id != 0)
-    {
-        int coins = gui_value(coins_id);
-        if (coins > 0)
-        {
-            int score = gui_value(score_id);
-            int balls = gui_value(balls_id);
-
-            gui_set_count(coins_id, coins - 1);
-            gui_pulse(coins_id, 1.1f);
-
-            gui_set_count(score_id, score + 1);
-            gui_pulse(score_id, 1.1f);
-
-            if ((score + 1) % 100 == 0)
-            {
-                gui_set_count(balls_id, balls + 1);
-                gui_pulse(balls_id, 2.0f);
-                audio_play(AUD_BALL, 1.0f);
-            }
-        }
-
-        DT = 0.0f;
-    }
-
-    gui_timer(id, dt);
-    audio_timer(dt);
-}
-
-void play_end_stick(int id, int a, int v)
-{
-        play_end_over(shared_stick_basic(id, a, v));
-}
-
-void play_end_point(int id, int x, int y, int dx, int dy)
-{
-        play_end_over(shared_point_basic(id, x, y));
-}
-
-static int play_end_buttn(int b, int d)
-{
-    if (d)
-    {
-        if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
-            return play_end_action(gui_token(gui_click()));
-        if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
-            return play_end_action(PLAY_END_BACK);
-    }
-    return 1;
-}
-
-/*---------------------------------------------------------------------------*/
-
-struct state st_play_end = {
-    play_end_enter,
-    shared_leave,
-    shared_paint,
-    play_end_timer,
-    play_end_point,
-    play_end_stick,
-    shared_click,
-    NULL,
-    play_end_buttn,
-    1, 0
-};
-
-struct state st_play_end_bis = {
-    play_end_bis_enter,
-    shared_leave,
-    shared_paint,
-    shared_timer,
-    play_end_point,
-    play_end_stick,
-    shared_click,
-    NULL,
-    play_end_buttn,
-    1, 0
-};
diff --git a/ball/st_play_end.h b/ball/st_play_end.h
deleted file mode 100644 (file)
index 06ea3bb..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef ST_PLAY_END_H
-#define ST_PLAY_END_H
-
-#include "state.h"
-
-extern struct state st_play_end;
-
-#endif
diff --git a/ball/st_time_out.c b/ball/st_time_out.c
new file mode 100644 (file)
index 0000000..d5c92f7
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Robert Kooima
+ *
+ * NEVERBALL is  free software; you can redistribute  it and/or modify
+ * it under the  terms of the GNU General  Public License as published
+ * by the Free  Software Foundation; either version 2  of the License,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
+ * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
+ * General Public License for more details.
+ */
+
+#include "game.h"
+#include "util.h"
+#include "levels.h"
+#include "demo.h"
+#include "audio.h"
+#include "gui.h"
+#include "config.h"
+
+#include "st_over.h"
+#include "st_start.h"
+#include "st_save.h"
+#include "st_time_out.h"
+#include "st_level.h"
+#include "st_shared.h"
+
+/*---------------------------------------------------------------------------*/
+
+#define TIME_OUT_NEXT 1
+#define TIME_OUT_SAME 2
+#define TIME_OUT_SAVE 3
+#define TIME_OUT_BACK 4
+#define TIME_OUT_OVER 5
+
+static int time_out_action(int i)
+{
+    audio_play(AUD_MENU, 1.0f);
+
+    switch (i)
+    {
+    case TIME_OUT_BACK:
+        /* Fall through. */
+
+    case TIME_OUT_OVER:
+        if (curr_lg()->mode == MODE_CHALLENGE)
+            return goto_state(&st_over);
+        else
+            return goto_state(&st_start);
+
+    case TIME_OUT_SAVE:
+        return goto_save(&st_time_out, &st_time_out);
+
+    case TIME_OUT_NEXT:
+        level_next();
+        level_play(curr_lg()->level, curr_lg()->mode);
+        return goto_state(&st_level);
+
+    case TIME_OUT_SAME:
+        level_play(curr_lg()->level, curr_lg()->mode);
+        return goto_state(&st_level);
+    }
+
+    return 1;
+}
+
+static int time_out_enter(void)
+{
+    int id, jd, kd;
+
+    const struct level_game *lg = curr_lg();
+
+    if ((id = gui_vstack(0)))
+    {
+        kd = gui_label(id, _("Time's Up!"), GUI_LRG, GUI_ALL, gui_gry, gui_red);
+
+        gui_space(id);
+
+        if ((jd = gui_harray(id)))
+        {
+            int next_id = 0, retry_id = 0;
+
+            next_id = gui_maybe(jd, _("Next Level"),  TIME_OUT_NEXT,
+                                lg->next_level != NULL);
+
+            if (lg->dead)
+                gui_start(jd, _("Game Over"), GUI_SML, TIME_OUT_OVER, 0);
+            else
+            {
+                retry_id = gui_maybe(jd, _("Retry Level"), TIME_OUT_SAME,
+                                     lg->mode != MODE_CHALLENGE);
+            }
+
+            gui_maybe(jd, _("Save Replay"), TIME_OUT_SAVE, demo_play_saved());
+
+            /* Default is next if the next level is newly unlocked. */
+
+            if (next_id && lg->unlock)
+                gui_focus(next_id);
+            else if (lg->mode != MODE_CHALLENGE)
+                gui_focus(retry_id);
+        }
+        gui_space(id);
+
+        gui_pulse(kd, 1.2f);
+        gui_layout(id, 0, 0);
+    }
+
+    audio_music_fade_out(2.0f);
+    /* audio_play(AUD_TIME, 1.0f); */
+
+    config_clr_grab();
+
+    return id;
+}
+
+static int time_out_buttn(int b, int d)
+{
+    if (d)
+    {
+        if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
+            return time_out_action(gui_token(gui_click()));
+        if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
+            return time_out_action(TIME_OUT_BACK);
+    }
+    return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+
+struct state st_time_out = {
+    time_out_enter,
+    shared_leave,
+    shared_paint,
+    shared_timer,
+    shared_point,
+    shared_stick,
+    shared_click,
+    NULL,
+    time_out_buttn,
+    1, 0
+};
+
diff --git a/ball/st_time_out.h b/ball/st_time_out.h
new file mode 100644 (file)
index 0000000..6bc4b3c
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef ST_TIME_OUT_H
+#define ST_TIME_OUT_H
+
+#include "state.h"
+
+extern struct state st_time_out;
+
+#endif