hopefully fixed the crash on exit, keep sectors script bundled in the sector and...
authorMatthias Braun <matze@braunis.de>
Tue, 11 Apr 2006 17:48:50 +0000 (17:48 +0000)
committerMatthias Braun <matze@braunis.de>
Tue, 11 Apr 2006 17:48:50 +0000 (17:48 +0000)
SVN-Revision: 3300

27 files changed:
configure.ac
data/levels/misc/menu.stl
src/console.cpp
src/game_session.cpp
src/main.cpp
src/mainloop.cpp
src/misc.cpp
src/misc.hpp
src/object/floating_image.cpp
src/object/floating_image.hpp
src/object/player.cpp
src/options_menu.cpp [new file with mode: 0644]
src/options_menu.hpp [new file with mode: 0644]
src/resources.cpp
src/resources.hpp
src/script_manager.cpp
src/script_manager.hpp
src/scripting/floating_image.cpp
src/scripting/functions.cpp
src/scripting/wrapper.cpp
src/sector.cpp
src/sector.hpp
src/title.cpp
src/world.cpp
src/world.hpp
src/worldmap.cpp
tools/miniswig/create_wrapper.cpp

index f591dee..21cc765 100644 (file)
@@ -26,6 +26,11 @@ CXXFLAGS="$CXXFLAGS -ffast-math"
 AC_PROG_CC
 AC_PROG_CXX
 AC_PROG_INSTALL
+AC_PATH_PROG(AR, ar)
+if test "$AR" = "" ; then
+  AC_MSG_ERROR([Couldn't find ar])
+fi
+AR="$AR ru"
 
 AC_C_BIGENDIAN
 
index 144b133..cfdc5fb 100644 (file)
@@ -10,7 +10,8 @@ logo <- FloatingImage(\"images/objects/logo/logo.sprite\");
 logo.set_anchor_point(ANCHOR_TOP);
 logo.set_pos(0, 30);
 logo.set_visible(true);
-wait(10000);
+// Suspend (this is needed so that logo doesn't get deleted)
+suspend();
 ")
     (background
       (image "images/background/arctis.jpg")
index 091619c..257172c 100644 (file)
@@ -72,7 +72,7 @@ Console::execute_script(const std::string& command)
 {
   using namespace Scripting;
 
-  HSQUIRRELVM vm = script_manager->get_global_vm();
+  HSQUIRRELVM vm = ScriptManager::instance->get_vm();
 
   if(command == "")
     return;
index f0da603..6fc8fb3 100644 (file)
@@ -473,8 +473,6 @@ GameSession::process_menu()
           main_loop->exit_screen();
           break;
       }
-    } else if(menu == options_menu) {
-      process_options_menu();
     }
   }
 }
index 8874b00..900079e 100644 (file)
@@ -379,9 +379,9 @@ static void init_audio()
 
 static void init_scripting()
 {
-  script_manager = new ScriptManager();
+  ScriptManager::instance = new ScriptManager();
 
-  HSQUIRRELVM vm = script_manager->get_global_vm();
+  HSQUIRRELVM vm = ScriptManager::instance->get_vm();
   sq_pushroottable(vm); 
   expose_object(vm, -1, new Scripting::Sound(), "Sound", true);
   expose_object(vm, -1, new Scripting::Level(), "Level", true);
@@ -516,9 +516,8 @@ int main(int argc, char** argv)
   }
 
   free_menu();
-  delete script_manager;
-  script_manager = NULL;
-  printf("crashunloadshared?\n");
+  delete ScriptManager::instance;
+  ScriptManager::instance = NULL;
   unload_shared();
   quit_audio();
 
index afd60ae..575005b 100644 (file)
@@ -26,7 +26,6 @@
 #include "control/joystickkeyboardcontroller.hpp"
 #include "gui/menu.hpp"
 #include "audio/sound_manager.hpp"
-#include "script_manager.hpp"
 #include "gameconfig.hpp"
 #include "main.hpp"
 #include "resources.hpp"
@@ -105,7 +104,7 @@ MainLoop::run()
       }
       
       next_screen->setup();
-      script_manager->fire_wakeup_event(ScriptManager::SCREEN_SWITCHED);
+      ScriptManager::instance->fire_wakeup_event(ScriptManager::SCREEN_SWITCHED);
       current_screen.reset(next_screen.release());
       next_screen.reset(NULL);
       nextpush = false;
@@ -164,7 +163,7 @@ MainLoop::run()
     elapsed_time *= speed;
 
     game_time += elapsed_time;
-    script_manager->update();
+    ScriptManager::instance->update();
     current_screen->update(elapsed_time);
  
     main_controller->update();
index 047ab3e..2004302 100644 (file)
 #include "resources.hpp"
 #include "worldmap.hpp"
 #include "gettext.hpp"
+#include "options_menu.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
 
 Menu* main_menu      = 0;
 Menu* game_menu      = 0;
-Menu* options_menu   = 0;
-
-void process_options_menu()
-{
-  switch (options_menu->check()) {
-    case MNID_FULLSCREEN:
-      if(config->use_fullscreen != options_menu->is_toggled(MNID_FULLSCREEN)) {
-        config->use_fullscreen = !config->use_fullscreen;
-        init_video();
-        config->save();
-      }
-      break;
-    case MNID_SOUND:
-      if(config->sound_enabled != options_menu->is_toggled(MNID_SOUND)) {
-        config->sound_enabled = !config->sound_enabled;
-        sound_manager->enable_sound(config->sound_enabled);
-        config->save();
-      }
-      break;
-    case MNID_MUSIC:
-      if(config->music_enabled != options_menu->is_toggled(MNID_MUSIC)) {
-        config->music_enabled = !config->music_enabled;
-        sound_manager->enable_music(config->music_enabled);
-        config->save();
-      }
-      break;
-    default:
-      break;
-  }
-}
 
 void setup_menu()
 {
   main_menu      = new Menu();
-  options_menu   = new Menu();
   game_menu      = new Menu();
   worldmap_menu  = new Menu();
 
   main_menu->set_pos(SCREEN_WIDTH/2, 335);
   main_menu->add_entry(MNID_STARTGAME, _("Start Game"));
   main_menu->add_entry(MNID_LEVELS_CONTRIB, _("Contrib Levels"));
-  main_menu->add_submenu(_("Options"), options_menu);
-  //main_menu->add_entry(MNID_LEVELEDITOR, _("Level Editor"));
+  main_menu->add_submenu(_("Options"), get_options_menu());
   main_menu->add_entry(MNID_CREDITS, _("Credits"));
   main_menu->add_entry(MNID_QUITMAINMENU, _("Quit"));
   
-  options_menu->add_label(_("Options"));
-  options_menu->add_hl();
-  options_menu->add_toggle(MNID_FULLSCREEN,_("Fullscreen"), config->use_fullscreen);
-  options_menu->add_toggle(MNID_SOUND, _("Sound"), config->sound_enabled);
-  options_menu->add_toggle(MNID_MUSIC, _("Music"), config->music_enabled);
-  options_menu->add_submenu(_("Setup Keys"),
-                            main_controller->get_key_options_menu());
-  options_menu->add_submenu(_("Setup Joystick"),
-                            main_controller->get_joystick_options_menu());
-  options_menu->add_hl();
-  options_menu->add_back(_("Back"));
-  
   game_menu->add_label(_("Pause"));
   game_menu->add_hl();
   game_menu->add_entry(MNID_CONTINUE, _("Continue"));
-  game_menu->add_submenu(_("Options"), options_menu);
+  game_menu->add_submenu(_("Options"), get_options_menu());
   game_menu->add_hl();
   game_menu->add_entry(MNID_ABORTLEVEL, _("Abort Level"));
 
   worldmap_menu->add_label(_("Pause"));
   worldmap_menu->add_hl();
   worldmap_menu->add_entry(WorldMapNS::MNID_RETURNWORLDMAP, _("Continue"));
-  worldmap_menu->add_submenu(_("Options"), options_menu);
+  worldmap_menu->add_submenu(_("Options"), get_options_menu());
   worldmap_menu->add_hl();
   worldmap_menu->add_entry(WorldMapNS::MNID_QUITWORLDMAP, _("Quit Game"));
 }
@@ -109,6 +66,6 @@ void free_menu()
   delete worldmap_menu;
   delete main_menu;
   delete game_menu;
-  delete options_menu;
+  free_options_menu();
 }
 
index 7b97edd..a158a77 100644 (file)
@@ -26,15 +26,6 @@ enum MainMenuIDs {
   MNID_QUITMAINMENU
 };
 
-enum OptionsMenuIDs {
-  MNID_FULLSCREEN,
-  MNID_SOUND,
-  MNID_MUSIC
-};
-
-/* Handle changes made to global settings in the options menu. */
-void process_options_menu();
-
 /* Create and setup menus. */
 void setup_menu();
 void free_menu();
index 1933b9b..b8fb087 100644 (file)
 #include "floating_image.hpp"
 
 FloatingImage::FloatingImage(const std::string& spritefile) 
-  : sprite(NULL), layer(LAYER_FOREGROUND1 + 1), visible(false),
-    anchor(ANCHOR_MIDDLE)
+  : layer(LAYER_FOREGROUND1 + 1), visible(false), anchor(ANCHOR_MIDDLE)
 {
-  sprite = sprite_manager->create(spritefile);
+  sprite.reset(sprite_manager->create(spritefile));
 }
 
 FloatingImage::~FloatingImage()
 {
-  delete sprite;
 }
 
 void
index 917f3f1..0f46d93 100644 (file)
@@ -4,6 +4,7 @@
 #include "game_object.hpp"
 #include "math/vector.hpp"
 #include "anchor_point.hpp"
+#include <memory>
 
 class Sprite;
 
@@ -46,7 +47,7 @@ public:
   void draw(DrawingContext& context);
 
 private:
-  Sprite* sprite;
+  std::auto_ptr<Sprite> sprite;
   int layer;
   bool visible;
   AnchorPoint anchor;
index 659328d..1769811 100644 (file)
@@ -122,9 +122,9 @@ void
 Player::init()
 {
   if(is_big())
-    bbox.set_size(31.8, 63.8);
+    bbox.set_size(31.8, 62.8);
   else
-    bbox.set_size(31.8, 31.8);
+    bbox.set_size(31.8, 30.8);
   adjust_height = 0;
 
   dir = RIGHT;
@@ -540,7 +540,7 @@ Player::set_bonus(BonusType type, bool animate)
     return;
   
   if(player_status->bonus == NO_BONUS) {
-    adjust_height = 63.8;
+    adjust_height = 62.8;
     if(animate)
       growing_timer.start(GROWING_TIME);
   }
@@ -849,7 +849,7 @@ Player::kill(HurtMode mode)
         {
           //growing_timer.start(GROWING_TIME);
           safe_timer.start(TUX_SAFE_TIME /* + GROWING_TIME */);
-          adjust_height = 31.8;
+          adjust_height = 30.8;
           duck = false;
           player_status->bonus = NO_BONUS;
         }
diff --git a/src/options_menu.cpp b/src/options_menu.cpp
new file mode 100644 (file)
index 0000000..495e0f7
--- /dev/null
@@ -0,0 +1,103 @@
+//  $Id$
+//  Copyright (C) 2004 Tobas Glaesser <tobi.web@gmx.de>
+//
+//  This program 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.
+// 
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#include <config.h>
+
+#include "options_menu.hpp"
+#include "gui/menu.hpp"
+#include "audio/sound_manager.hpp"
+#include "control/joystickkeyboardcontroller.hpp"
+#include "main.hpp"
+#include "gettext.hpp"
+#include "gameconfig.hpp"
+
+Menu* options_menu   = 0;
+
+enum OptionsMenuIDs {
+  MNID_FULLSCREEN,
+  MNID_SOUND,
+  MNID_MUSIC
+};
+
+class OptionsMenu : public Menu
+{
+public:
+  OptionsMenu();
+  virtual ~OptionsMenu();
+
+  virtual void menu_action(MenuItem* item);
+};
+
+OptionsMenu::OptionsMenu()
+{
+  add_label(_("Options"));
+  add_hl();
+  add_toggle(MNID_FULLSCREEN,_("Fullscreen"), config->use_fullscreen);
+  add_toggle(MNID_SOUND, _("Sound"), config->sound_enabled);
+  add_toggle(MNID_MUSIC, _("Music"), config->music_enabled);
+  add_submenu(_("Setup Keys"), main_controller->get_key_options_menu());
+  add_submenu(_("Setup Joystick"),main_controller->get_joystick_options_menu());
+  add_hl();
+  add_back(_("Back"));
+}
+
+OptionsMenu::~OptionsMenu()
+{
+}
+
+void
+OptionsMenu::menu_action(MenuItem* item)
+{
+  switch (item->id) {
+    case MNID_FULLSCREEN:
+      if(config->use_fullscreen != options_menu->is_toggled(MNID_FULLSCREEN)) {
+        config->use_fullscreen = !config->use_fullscreen;
+        init_video();
+        config->save();
+      }
+      break;
+    case MNID_SOUND:
+      if(config->sound_enabled != options_menu->is_toggled(MNID_SOUND)) {
+        config->sound_enabled = !config->sound_enabled;
+        sound_manager->enable_sound(config->sound_enabled);
+        config->save();
+      }
+      break;
+    case MNID_MUSIC:
+      if(config->music_enabled != options_menu->is_toggled(MNID_MUSIC)) {
+        config->music_enabled = !config->music_enabled;
+        sound_manager->enable_music(config->music_enabled);
+        config->save();
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+Menu* get_options_menu()
+{
+  if(options_menu == NULL)
+    options_menu = new OptionsMenu();
+
+  return options_menu;
+}
+
+void free_options_menu()
+{
+  delete options_menu;
+  options_menu = NULL;
+}
diff --git a/src/options_menu.hpp b/src/options_menu.hpp
new file mode 100644 (file)
index 0000000..5a11e8e
--- /dev/null
@@ -0,0 +1,24 @@
+//  $Id$
+//  Copyright (C) 2004 Tobas Glaesser <tobi.web@gmx.de>
+//
+//  This program 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.
+// 
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#ifndef __OPTIONS_MENU_HPP__
+#define __OPTIONS_MENU_HPP__
+
+class Menu;
+Menu* get_options_menu();
+void free_options_menu();
+
+#endif
index b561578..fdb043f 100644 (file)
@@ -112,41 +112,29 @@ void load_shared()
 /* Free shared data: */
 void unload_shared()
 {
-  printf("0\n");
-  
   /* Free global images: */
   delete gold_text;
-  printf("first\n");
   delete white_text;
   delete blue_text;
   delete gray_text;
   delete white_small_text;
-  printf("last\n");
   delete white_big_text;
 
-  printf("1\n");
-  
   delete small_tux;
   delete big_tux;
   delete fire_tux;
   delete ice_tux;
 
-  printf("2\n");
-
   for (int i = 0; i < GROWING_FRAMES; i++) {
     delete growingtux_left[i];
     delete growingtux_right[i];
   }
 
-  printf("3\n");
-
   delete sprite_manager;
   sprite_manager = 0;
   delete tile_manager;
   tile_manager = 0;
 
-  printf("4\n");
-
   /* Free mouse-cursor */
   delete mouse_cursor;
 }
index 811ff53..9885ef7 100644 (file)
@@ -32,7 +32,6 @@ extern TileManager* tile_manager;
 
 extern Menu* main_menu;
 extern Menu* game_menu;
-extern Menu* options_menu;
 
 extern MouseCursor* mouse_cursor;
 
index d0656a5..2cd0842 100644 (file)
 #include <stdexcept>
 #include <sstream>
 #include <fstream>
-#include <sqstdio.h>
 #include <sqstdaux.h>
 #include <sqstdblob.h>
-#include <sqstdsystem.h>
 #include <sqstdmath.h>
 #include <sqstdstring.h>
 
@@ -41,7 +39,7 @@
 
 using namespace Scripting;
 
-ScriptManager* script_manager = 0;
+ScriptManager* ScriptManager::instance = NULL;
 
 static void printfunc(HSQUIRRELVM, const char* str, ...)
 {
@@ -54,60 +52,75 @@ static void printfunc(HSQUIRRELVM, const char* str, ...)
 }
 
 ScriptManager::ScriptManager()
+  : parent(NULL)
 {
-  v = sq_open(1024);
-  if(v == 0)
+  vm = sq_open(1024);
+  if(vm == 0)
     throw std::runtime_error("Couldn't initialize squirrel vm");
+  sq_setforeignptr(vm, (SQUserPointer) this);
 
-  // register default error handlers
-  sqstd_seterrorhandlers(v);
   // register squirrel libs
-  sq_pushroottable(v);
-  if(sqstd_register_bloblib(v) < 0)
-    throw SquirrelError(v, "Couldn't register blob lib");
-  if(sqstd_register_iolib(v) < 0)
-    throw SquirrelError(v, "Couldn't register io lib");
-  if(sqstd_register_systemlib(v) < 0)
-    throw SquirrelError(v, "Couldn't register system lib");
-  if(sqstd_register_mathlib(v) < 0)
-    throw SquirrelError(v, "Couldn't register math lib");
-  if(sqstd_register_stringlib(v) < 0)
-    throw SquirrelError(v, "Couldn't register string lib");
+  sq_pushroottable(vm);
+  if(sqstd_register_bloblib(vm) < 0)
+    throw SquirrelError(vm, "Couldn't register blob lib");
+  if(sqstd_register_mathlib(vm) < 0)
+    throw SquirrelError(vm, "Couldn't register math lib");
+  if(sqstd_register_stringlib(vm) < 0)
+    throw SquirrelError(vm, "Couldn't register string lib");
+  // register supertux API
+  register_supertux_wrapper(vm);
+  sq_pop(vm, 1);
 
   // register print function
-  sq_setprintfunc(v, printfunc);
-  
-  // register supertux API
-  register_supertux_wrapper(v);
+  sq_setprintfunc(vm, printfunc);
+  // register default error handlers
+  sqstd_seterrorhandlers(vm); 
 }
 
-ScriptManager::~ScriptManager()
+ScriptManager::ScriptManager(ScriptManager* parent)
 {
-  for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i)
-    sq_release(v, &(i->vm_obj));
+  this->parent = parent;
+  vm = parent->vm;
+  parent->childs.push_back(this);
+}
 
-  sq_close(v);
+ScriptManager::~ScriptManager()
+{
+  for(SquirrelVMs::iterator i = squirrel_vms.begin();
+      i != squirrel_vms.end(); ++i)
+    sq_release(vm, &(i->vm_obj));
+
+  if(parent != NULL) {
+    parent->childs.erase(
+        std::remove(parent->childs.begin(), parent->childs.end(), this),
+        parent->childs.end());
+  } else {
+    sq_close(vm);
+  }
 }
 
 HSQUIRRELVM
-ScriptManager::create_thread()
+ScriptManager::create_thread(bool leave_thread_on_stack)
 {
-  HSQUIRRELVM vm = sq_newthread(v, 1024);
-  if(vm == NULL)
-    throw SquirrelError(v, "Couldn't create new VM");
+  HSQUIRRELVM new_vm = sq_newthread(vm, 1024);
+  if(new_vm == NULL)
+    throw SquirrelError(vm, "Couldn't create new VM");
+  sq_setforeignptr(new_vm, (SQUserPointer) this);
 
   // retrieve reference to thread from stack and increase refcounter
   HSQOBJECT vm_obj;
   sq_resetobject(&vm_obj);
-  if(SQ_FAILED(sq_getstackobj(v, -1, &vm_obj))) {
-    throw SquirrelError(v, "Couldn't get coroutine vm from stack");
+  if(SQ_FAILED(sq_getstackobj(vm, -1, &vm_obj))) {
+    throw SquirrelError(vm, "Couldn't get coroutine vm from stack");
   }
-  sq_addref(v, &vm_obj);
-  sq_pop(v, 1);
+  sq_addref(vm, &vm_obj);
+
+  if(!leave_thread_on_stack)
+    sq_pop(vm, 1);
   
-  squirrel_vms.push_back(SquirrelVM(vm, vm_obj));
+  squirrel_vms.push_back(SquirrelVM(new_vm, vm_obj));
 
-  return vm;
+  return new_vm;
 }
 
 void
@@ -125,14 +138,14 @@ ScriptManager::update()
         }
       } catch(std::exception& e) {
         std::cerr << "Problem executing script: " << e.what() << "\n";
-        sq_release(v, &squirrel_vm.vm_obj);
+        sq_release(vm, &squirrel_vm.vm_obj);
         i = squirrel_vms.erase(i);
         continue;
       }
     }
        
     if (vm_state != SQ_VMSTATE_SUSPENDED) {
-      sq_release(v, &(squirrel_vm.vm_obj));
+      sq_release(vm, &(squirrel_vm.vm_obj));
       i = squirrel_vms.erase(i);
     } else {
       ++i;
@@ -145,7 +158,8 @@ ScriptManager::set_wakeup_event(HSQUIRRELVM vm, WakeupData event, float timeout)
 {
   assert(event.type >= 0 && event.type < WAKEUP_EVENT_COUNT);
   // find the VM in the list and update it
-  for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i) {
+  for(SquirrelVMs::iterator i = squirrel_vms.begin();
+      i != squirrel_vms.end(); ++i) {
     SquirrelVM& squirrel_vm = *i;
     if(squirrel_vm.vm == vm) 
       {
@@ -165,15 +179,21 @@ void
 ScriptManager::fire_wakeup_event(WakeupData  event)
 {
   assert(event.type >= 0 && event.type < WAKEUP_EVENT_COUNT);
-  for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i) 
-    {
-      SquirrelVM& vm = *i;
-      if(vm.waiting_for_events.type == event.type && vm.waiting_for_events.type != NO_EVENT)
-        {
-          vm.wakeup_time = game_time;
-          break;
-        }
+  for(SquirrelVMs::iterator i = squirrel_vms.begin();
+      i != squirrel_vms.end(); ++i) {
+    SquirrelVM& vm = *i;
+    if(vm.waiting_for_events.type == event.type
+        && vm.waiting_for_events.type != NO_EVENT) {
+      vm.wakeup_time = game_time;
+      break;
     }
+  }
+
+  for(std::vector<ScriptManager*>::iterator i = childs.begin();
+      i != childs.end(); ++i) {
+    ScriptManager* child = *i;
+    child->fire_wakeup_event(event);
+  }
 }
 
 void
index bbcbbf1..90906c8 100644 (file)
@@ -37,6 +37,7 @@ class ScriptManager
 {
 public:
   ScriptManager();
+  ScriptManager(ScriptManager* parent);
   ~ScriptManager();
 
   void update();
@@ -45,11 +46,11 @@ public:
    * Creates a new thread and registers it with the script manager
    * (so it can suspend and register for wakeup events)
    */
-  HSQUIRRELVM create_thread();
+  HSQUIRRELVM create_thread(bool leave_thread_on_stack = false);
 
-  HSQUIRRELVM get_global_vm() const
+  HSQUIRRELVM get_vm() const
   {
-    return v;
+    return vm;
   }
 
   enum WakeupEvent {
@@ -75,6 +76,9 @@ public:
   void set_wakeup_event(HSQUIRRELVM vm, WakeupData  event, float timeout = -1);
   void fire_wakeup_event(WakeupEvent event);
   void fire_wakeup_event(WakeupData  event);
+
+  // global (root) instance of the ScriptManager
+  static ScriptManager* instance;
   
 private:
   class SquirrelVM
@@ -91,10 +95,10 @@ private:
   typedef std::list<SquirrelVM> SquirrelVMs;
   SquirrelVMs squirrel_vms;
 
-  HSQUIRRELVM v;
+  HSQUIRRELVM vm;
+  ScriptManager* parent;
+  std::vector<ScriptManager*> childs;
 };
 
-extern ScriptManager* script_manager;
-
 #endif
 
index bfb7db9..1139358 100644 (file)
@@ -9,6 +9,7 @@ namespace Scripting
 
 FloatingImage::FloatingImage(const std::string& spritefile)
 {
+  assert(Sector::current() != NULL);
   floating_image = new _FloatingImage(spritefile); 
   Sector::current()->add_object(floating_image);
 }
index 21712a6..c3a4bf8 100644 (file)
@@ -50,11 +50,15 @@ int display(HSQUIRRELVM vm)
 
 void wait(HSQUIRRELVM vm, float seconds)
 {
+  SQUserPointer ptr = sq_getforeignptr(vm);
+  ScriptManager* script_manager = reinterpret_cast<ScriptManager*> (ptr);
   script_manager->set_wakeup_event(vm, ScriptManager::TIME, seconds);
 }
 
 void wait_for_screenswitch(HSQUIRRELVM vm)
 {
+  SQUserPointer ptr = sq_getforeignptr(vm);
+  ScriptManager* script_manager = reinterpret_cast<ScriptManager*> (ptr);
   script_manager->set_wakeup_event(vm, ScriptManager::SCREEN_SWITCHED);
 }
 
index b31ccce..532ad14 100644 (file)
@@ -1822,7 +1822,6 @@ void register_supertux_wrapper(HSQUIRRELVM v)
 {
   using namespace Wrapper;
 
-  sq_pushroottable(v);
   sq_pushstring(v, "KEY_BRASS", -1);
   sq_pushinteger(v, 1);
   if(SQ_FAILED(sq_createslot(v, -3))) {
@@ -2343,7 +2342,6 @@ void register_supertux_wrapper(HSQUIRRELVM v)
     throw SquirrelError(v, "Couldn't register class 'FloatingImage'");
   }
 
-  sq_pop(v, 1);
 }
 
 } // end of namespace Scripting
index a710145..69571e1 100644 (file)
@@ -76,13 +76,13 @@ Sector::Sector()
   add_object(new TextObject());
 
 #ifdef USE_GRID
-  grid = new CollisionGrid(32000, 32000);
-#else
-  grid = 0;
+  grid.reset(new CollisionGrid(32000, 32000));
 #endif
 
+  script_manager.reset(new ScriptManager(ScriptManager::instance));
+
   // create a new squirrel table for the sector
-  HSQUIRRELVM vm = script_manager->get_global_vm();
+  HSQUIRRELVM vm = ScriptManager::instance->get_vm();
   
   sq_newtable(vm);
   sq_pushroottable(vm);
@@ -98,13 +98,14 @@ Sector::Sector()
 
 Sector::~Sector()
 {
+  deactivate();
+  
+  script_manager.reset(NULL);
+  sq_release(ScriptManager::instance->get_vm(), &sector_table);
   update_game_objects();
   assert(gameobjects_new.size() == 0);
 
-  deactivate();
-
-  delete grid;
-
   for(GameObjects::iterator i = gameobjects.begin(); i != gameobjects.end();
       ++i) {
     before_object_remove(*i);
@@ -114,8 +115,6 @@ Sector::~Sector()
   for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end();
       ++i)
     delete *i;
-
-  sq_release(script_manager->get_global_vm(), &sector_table);
 }
 
 GameObject*
@@ -390,9 +389,13 @@ Sector::write(lisp::Writer& writer)
 HSQUIRRELVM
 Sector::run_script(std::istream& in, const std::string& sourcename)
 {
+  // create new thread and keep a weakref
   HSQUIRRELVM vm = script_manager->create_thread();
+
+  // set sector_table as roottable for the thread
   sq_pushobject(vm, sector_table);
   sq_setroottable(vm);
+
   Scripting::compile_and_run(vm, in, sourcename);
 
   return vm;
@@ -452,12 +455,12 @@ Sector::activate(const Vector& player_pos)
     _current = this;
 
     // register sectortable as current_sector in scripting
-    HSQUIRRELVM vm = script_manager->get_global_vm();
+    HSQUIRRELVM vm = ScriptManager::instance->get_vm();
     sq_pushroottable(vm);
-    sq_pushstring(vm, "current_sector", -1);
+    sq_pushstring(vm, "sector", -1);
     sq_pushobject(vm, sector_table);
     if(SQ_FAILED(sq_createslot(vm, -3)))
-      throw Scripting::SquirrelError(vm, "Couldn't set current_sector in roottable");
+      throw Scripting::SquirrelError(vm, "Couldn't set sector in roottable");
     sq_pop(vm, 1);
 
     for(GameObjects::iterator i = gameobjects.begin();
@@ -484,11 +487,12 @@ Sector::deactivate()
   if(_current != this)
     return;
 
-  HSQUIRRELVM vm = script_manager->get_global_vm();
+  // remove sector entry from global vm
+  HSQUIRRELVM vm = ScriptManager::instance->get_vm();
   sq_pushroottable(vm);
-  sq_pushstring(vm, "current_sector", -1);
+  sq_pushstring(vm, "sector", -1);
   if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse)))
-    throw Scripting::SquirrelError(vm, "Couldn't unset current_sector in roottable");
+    throw Scripting::SquirrelError(vm, "Couldn't unset sector in roottable");
   sq_pop(vm, 1);
   
   for(GameObjects::iterator i = gameobjects.begin();
@@ -512,6 +516,8 @@ Sector::get_active_region()
 void
 Sector::update(float elapsed_time)
 {
+  script_manager->update();
+
   player->check_bounds(camera);
 
 #if 0
@@ -649,7 +655,7 @@ Sector::try_expose(GameObject* object)
 {
   ScriptInterface* interface = dynamic_cast<ScriptInterface*> (object);
   if(interface != NULL) {
-    HSQUIRRELVM vm = script_manager->get_global_vm();
+    HSQUIRRELVM vm = script_manager->get_vm();
     sq_pushobject(vm, sector_table);
     interface->expose(vm, -1);
     sq_pop(vm, 1);
@@ -668,7 +674,7 @@ Sector::try_unexpose(GameObject* object)
 {
   ScriptInterface* interface = dynamic_cast<ScriptInterface*> (object);
   if(interface != NULL) {
-    HSQUIRRELVM vm = script_manager->get_global_vm();
+    HSQUIRRELVM vm = script_manager->get_vm();
     sq_pushobject(vm, sector_table);
     interface->unexpose(vm, -1);
     sq_pop(vm, 1);
index 80ed734..67efe38 100644 (file)
 
 #include <string>
 #include <vector>
+#include <memory>
 #include <squirrel.h>
 
 #include "direction.hpp"
+#include "script_manager.hpp"
 #include "math/vector.hpp"
 #include "video/drawing_context.hpp"
 
@@ -50,8 +52,9 @@ enum MusicType {
   HERRING_MUSIC
 };
 
-/** This class holds a sector (a part of a level) and all the game objects
- * (badguys, player, background, tilemap, ...)
+/**
+ * This class holds a sector (a part of a level) and all the game objects in
+ * the sector
  */
 class Sector
 {
@@ -160,9 +163,11 @@ private:
  
   MusicType currentmusic;
 
-  CollisionGrid* grid;
+  std::auto_ptr<CollisionGrid> grid;
 
   HSQOBJECT sector_table;
+  /// sector scripts
+  std::auto_ptr<ScriptManager> script_manager;
 
 public: // TODO make this private again
   GameObjects gameobjects;
index d2ed7da..1d11114 100644 (file)
@@ -163,6 +163,8 @@ TitleScreen::check_levels_contrib_menu()
   if(!world.is_levelset) {
     // TODO fade out
     world.run();
+    world.set_savegame_filename("save/test.save");
+    world.save();
   }
 
   if (current_world != index) {
@@ -265,16 +267,8 @@ TitleScreen::TitleScreen()
   controller.reset(new CodeController());
   titlesession.reset(new GameSession("levels/misc/menu.stl", ST_GL_DEMO_GAME));
 
-  // delete contrib_world_menu;
-  // contrib_world_menu = new Menu();
-
-  titlesession->get_current_sector()->activate("main");
-  titlesession->set_current();
-
   Player* player = titlesession->get_current_sector()->player;
   player->set_controller(controller.get());
-
-  Menu::set_current(main_menu); 
 }
 
 TitleScreen::~TitleScreen()
@@ -287,8 +281,10 @@ TitleScreen::setup()
   player_status->reset();
 
   Sector* sector = titlesession->get_current_sector();
-  sector->play_music(LEVEL_MUSIC);
-  sector->activate(sector->player->get_pos());
+  if(Sector::current() != sector) {
+    sector->play_music(LEVEL_MUSIC);
+    sector->activate(sector->player->get_pos());
+  }
 
   Menu::set_current(main_menu);
 }
@@ -357,8 +353,6 @@ TitleScreen::update(float elapsed_time)
           main_loop->quit();
           break;
       }
-    } else if(menu == options_menu) {
-      process_options_menu();
     } else if(menu == load_game_menu.get()) {
       /*
       if(event.key.keysym.sym == SDLK_DELETE) {
index 71d60cf..bdd4407 100644 (file)
@@ -30,6 +30,7 @@
 #include "physfs/physfs_stream.hpp"
 #include "script_manager.hpp"
 #include "scripting/wrapper_util.hpp"
+#include "scripting/serialize.hpp"
 #include "msg.hpp"
 
 static bool has_suffix(const std::string& data, const std::string& suffix)
@@ -51,6 +52,12 @@ World::~World()
 }
 
 void
+World::set_savegame_filename(const std::string& filename)
+{
+  this->savegame_filename = filename;
+}
+
+void
 World::load(const std::string& filename)
 {
   basedir = FileSystem::dirname(filename);
@@ -94,15 +101,47 @@ World::load(const std::string& filename)
 void
 World::run()
 {
+  // create new squirrel table for persisten game state
+  HSQUIRRELVM vm = ScriptManager::instance->get_vm();
+
+  sq_pushroottable(vm);
+  sq_pushstring(vm, "state", -1);
+  sq_newtable(vm);
+  if(SQ_FAILED(sq_createslot(vm, -3)))
+    throw Scripting::SquirrelError(vm, "Couldn't create state table");
+  sq_pop(vm, 1);
+  
   std::string filename = basedir + "/world.nut";
-  std::cout << filename << std::endl;
-  if (!PHYSFS_exists(filename.c_str()))
-    return;
-
   IFileStream in(filename);
 
-  HSQUIRRELVM vm = script_manager->create_thread();
-  Scripting::compile_and_run(vm, in, filename);
+  HSQUIRRELVM new_vm = ScriptManager::instance->create_thread();
+  Scripting::compile_and_run(new_vm, in, filename);
+}
+
+void
+World::save()
+{
+  lisp::Writer writer(savegame_filename);
+
+  writer.start_list("supertux-savegame");
+  writer.write_int("version", 1);
+
+  writer.start_list("tux");
+  player_status->write(writer);
+  writer.end_list("tux");
+
+  writer.start_list("state");
+  HSQUIRRELVM vm = ScriptManager::instance->get_vm();
+  sq_pushroottable(vm);
+  sq_pushstring(vm, "state", -1);
+  if(SQ_SUCCEEDED(sq_get(vm, -2))) {
+    Scripting::save_squirrel_table(vm, -1, writer);
+    sq_pop(vm, 1);
+  }
+  sq_pop(vm, 1);
+  writer.end_list("state");
+  
+  writer.end_list("supertux-savegame");
 }
 
 const std::string&
index 12e7759..60ec26b 100644 (file)
@@ -1,7 +1,7 @@
-//  $Id: worldmap.hpp 2800 2005-10-02 22:57:31Z matzebraun $
+//  $Id$
 // 
 //  SuperTux
-//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
 //
 //  This program is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU General Public License
 
 #include <vector>
 #include <string>
+#include <squirrel.h>
 
 class World
 {
 private:
   std::vector<std::string> levels;
   std::string basedir;
+  std::string savegame_filename;
+  /// squirrel table that saves persistent state (about the world)
+  HSQOBJECT state_table;
 
 public:
   World();
   ~World();
 
+  void set_savegame_filename(const std::string& filename);
   void load(const std::string& filename);
+
+  void save();
+  void load();
   
   const std::string& get_level_filename(unsigned int i) const;
   unsigned int get_num_levels() const;
index 3a08067..209ea14 100644 (file)
@@ -748,8 +748,6 @@ WorldMap::update(float delta)
           main_loop->exit_screen();
           break;
       }
-    } else if(menu == options_menu) {
-      process_options_menu();
     }
 
     return;
index d0c9131..e072b6f 100644 (file)
@@ -100,15 +100,13 @@ WrapperCreator::create_wrapper(Namespace* ns)
     out << "void register_" << modulename << "_wrapper(HSQUIRRELVM v)\n"
         << "{\n"
         << ind << "using namespace Wrapper;\n"
-        << "\n"
-        << ind << "sq_pushroottable(v);\n";
+        << "\n";
 
     create_register_constants_code(ns);
     create_register_functions_code(ns);
     create_register_classes_code(ns);
 
-    out << ind << "sq_pop(v, 1);\n"
-        << "}\n"
+    out << "}\n"
         << "\n"
         << "} // end of namespace Scripting\n"
         << "\n";