Those sets haven't been merged.
[neverball] / ball / st_goal.c
index a97da55..96f5f98 100644 (file)
@@ -1,5 +1,5 @@
-/*   
- * Copyright (C) 2003 Robert Kooima
+/*
+ * 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
  * General Public License for more details.
  */
 
-#include <string.h>
+#include <stdio.h>
 
 #include "gui.h"
-#include "set.h"
 #include "game.h"
 #include "util.h"
-#include "demo.h"
-#include "level.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_title.h"
+#include "st_start.h"
 #include "st_level.h"
+#include "st_name.h"
+#include "st_shared.h"
 
 /*---------------------------------------------------------------------------*/
 
-#define GOAL_NEXT 2
-#define GOAL_SAME 3
-#define GOAL_SAVE 4
+#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 high;
-static int time_i;
-static int coin_i;
-    
 static int balls_id;
 static int coins_id;
 static int score_id;
 
+/* Bread crumbs. */
+
+static int new_name;
+static int be_back_soon;
+
 static int goal_action(int i)
 {
-    char player[MAXNAM];
-    size_t l;
-
     audio_play(AUD_MENU, 1.0f);
 
-    config_get_s(CONFIG_PLAYER, player, MAXNAM);
-    l = strlen(player);
-
     switch (i)
     {
-    case GOAL_SAVE:
-        while (level_count())
-            ;
-        return goto_state(&st_save);
+    case GOAL_BACK:
+        /* Fall through. */
 
-    case GOAL_NEXT:
-        while (level_count())
-            ;
-        if (level_exit(NULL, 1))
-            return goto_state(&st_level);
-        else
-            return goto_state(&st_done);
+    case GOAL_OVER:
+        level_stop();
+        return goto_state(&st_over);
 
-    case GOAL_SAME:
-        while (level_count())
-            ;
-        if (level_exit(NULL, 0))
-            return goto_state(&st_level);
-        else
-            return goto_state(&st_done);
+    case GOAL_SAVE:
+        be_back_soon = 1;
 
-    case GUI_CL:
-        gui_keyboard_lock();
-        break;
+        level_stop();
+        return goto_save(&st_goal, &st_goal);
 
-    case GUI_BS:
-        if (l > 0)
-        {
-            player[l - 1] = 0;
+    case GOAL_NAME:
+        new_name = 1;
+        be_back_soon = 1;
 
-            config_set_s(CONFIG_PLAYER, player);
-            level_name(curr_level(), player, time_i, coin_i);
-            set_most_coins(curr_level(), 4);
-            set_best_times(curr_level(), 4);
-        }
-        break;
+        level_stop();
+        return goto_name(&st_goal, &st_goal, 0);
 
-    default:
-        if (l < MAXNAM - 1)
-        {
-            player[l + 0] = gui_keyboard_char((char) i);
-            player[l + 1] = 0;
+    case GOAL_DONE:
+        level_stop();
+        return goto_state(&st_done);
 
-            config_set_s(CONFIG_PLAYER, player);
-            level_name(curr_level(), player, time_i, coin_i);
-            set_most_coins(curr_level(), 4);
-            set_best_times(curr_level(), 4);
-        }
+    case GOAL_NEXT:
+        level_next();
+        return goto_state(&st_level);
+
+    case GOAL_SAME:
+        level_same();
+        return goto_state(&st_level);
     }
+
     return 1;
 }
 
@@ -112,17 +96,44 @@ static int goal_enter(void)
 {
     const char *s1 = _("New Record");
     const char *s2 = _("GOAL");
+    const char *s3 = _("Congratulations!");
 
     int id, jd, kd;
 
-    time_i = 3;
-    coin_i = 3;
-    high   = level_sort(&time_i, &coin_i);
+    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 (lg->mode == MODE_CHALLENGE && lg->bonus)
+        {
+            char buf[MAXSTR];
+
+            sprintf(buf, _("You have unlocked bonus level %s!"),
+                    lg->bonus_repr);
+
+            gid = gui_label(id, s3,  GUI_MED, GUI_ALL, gui_grn, gui_red);
+            gid = gui_label(id, buf, GUI_SML, GUI_ALL, gui_blu, gui_grn);
+
+            lg->bonus = 0;
+            lg->bonus_repr = NULL;
+        }
+
         if (high)
             gid = gui_label(id, s1, GUI_MED, GUI_ALL, gui_grn, gui_grn);
         else
@@ -130,148 +141,141 @@ static int goal_enter(void)
 
         gui_space(id);
 
-        if ((jd = gui_harray(id)))
+        if (lg->mode == MODE_CHALLENGE)
         {
-            if ((kd = gui_harray(jd)))
-            {
-                balls_id = gui_count(kd,  10, 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, 100, GUI_MED, GUI_RGT);
-                gui_label(kd, _("Score"), GUI_SML, GUI_LFT, gui_wht, gui_wht);
-            }
-            if ((kd = gui_harray(jd)))
+            int coins = lg->coins;
+            int score = lg->score - coins;
+            int balls = lg->balls - count_extra_balls(score, coins);
+
+            if ((jd = gui_hstack(id)))
             {
-                coins_id = gui_count(kd, 100, GUI_MED, GUI_RGT);
-                gui_label(kd, _("Coins"), GUI_SML, GUI_LFT, gui_wht, gui_wht);
-            }
+                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, curr_balls());
-            gui_set_count(score_id, curr_score());
-            gui_set_count(coins_id, curr_coins());
+                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, 4, coin_i);
-            gui_best_times(jd, 4, time_i);
+            gui_most_coins(jd, 1);
+            gui_best_times(jd, 1);
         }
 
         gui_space(id);
 
         if ((jd = gui_harray(id)))
         {
-            gui_state(jd, _("Save Replay"), GUI_SML, GOAL_SAVE, 0);
-            gui_state(jd, _("Retry Level"), GUI_SML, GOAL_SAME, 0);
+            int next_id = 0, retry_id = 0;
 
-            if (level_last())
-                gui_start(jd, _("Finish"),  GUI_SML, GOAL_NEXT, 0);
+            if (lg->win)
+                gui_start(jd, _("Finish"), GUI_SML, GOAL_DONE, 0);
             else
-                gui_start(jd, _("Next Level"), GUI_SML, GOAL_NEXT, 0);
+                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_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);
         }
 
-        if (high) gui_keyboard(id);
+        /* FIXME, I'm ugly. */
+
+        if (high)
+            gui_state(id, _("Change Player Name"),  GUI_SML, GOAL_NAME, 0);
 
-        gui_layout(id, 0, 0);
         gui_pulse(gid, 1.2f);
+        gui_layout(id, 0, 0);
+
     }
 
-    set_most_coins(curr_level(), 4);
-    set_best_times(curr_level(), 4);
+    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);
-    audio_play(AUD_GOAL, 1.0f);
 
     config_clr_grab();
 
     return id;
 }
 
-static void goal_leave(int id)
-{
-    gui_delete(id);
-}
-
-static void goal_paint(int id, float st)
-{
-    game_draw(0, st);
-    gui_paint(id);
-}
-
 static void goal_timer(int id, float dt)
 {
-    static float DT = 0.0f;
+    static float t = 0.0f;
 
     float g[3] = { 0.0f, 9.8f, 0.0f };
 
-    DT += dt;
+    t += dt;
 
     if (time_state() < 1.f)
     {
+        demo_play_step();
         game_step(g, dt, 0);
-        demo_play_step(dt);
     }
-    else if (DT > 0.05f)
+    else if (t > 0.05f && coins_id)
     {
-        if (level_count())
+        int coins = gui_value(coins_id);
+
+        if (coins > 0)
         {
-            int coins = curr_coins();
-            int score = curr_score();
-            int balls = curr_balls();
+            int score = gui_value(score_id);
+            int balls = gui_value(balls_id);
 
-            if (gui_value(coins_id) != coins)
-            {
-                gui_set_count(coins_id, coins);
-                gui_pulse(coins_id, 1.1f);
-            }
-            if (gui_value(score_id) != score)
-            {
-                gui_set_count(score_id, score);
-                gui_pulse(score_id, 1.1f);
-            }
-            if (gui_value(balls_id) != balls)
+            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);
+                gui_set_count(balls_id, balls + 1);
                 gui_pulse(balls_id, 2.0f);
+                audio_play(AUD_BALL, 1.0f);
             }
         }
-
-        DT = 0.0f;
+        t = 0.0f;
     }
 
     gui_timer(id, dt);
-    audio_timer(dt);
-}
-
-static void goal_point(int id, int x, int y, int dx, int dy)
-{
-    gui_pulse(gui_point(id, x, y), 1.2f);
-}
-
-static void goal_stick(int id, int a, int v)
-{
-    if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
-        gui_pulse(gui_stick(id, v, 0), 1.2f);
-    if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
-        gui_pulse(gui_stick(id, 0, v), 1.2f);
-}
-
-static int goal_click(int b, int d)
-{
-    if (b <= 0 && d == 1)
-        return goal_action(gui_token(gui_click()));
-    return 1;
-}
-
-static int goal_keybd(int c, int d)
-{
-    if (d && c == SDLK_ESCAPE)
-        goto_state(&st_over);
-    return 1;
 }
 
 static int goal_buttn(int b, int d)
@@ -279,24 +283,33 @@ static int goal_buttn(int b, int d)
     if (d)
     {
         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
-            return goal_click(0, 1);
+            return goal_action(gui_token(gui_click()));
         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
-            return goto_state(&st_over);
+            return goal_action(GOAL_BACK);
     }
     return 1;
 }
 
+static 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,
-    goal_paint,
+    shared_paint,
     goal_timer,
-    goal_point,
-    goal_stick,
-    goal_click,
-    goal_keybd,
+    shared_point,
+    shared_stick,
+    shared_angle,
+    shared_click,
+    NULL,
     goal_buttn,
     1, 0
 };