Major rewrite of scripting support:
authorMatthias Braun <matze@braunis.de>
Mon, 10 Apr 2006 22:08:23 +0000 (22:08 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 10 Apr 2006 22:08:23 +0000 (22:08 +0000)
  - Add squirrel support to console
  - Reused ScriptManager from windstille (with some modifications now)
  - Added some new scripting commands (display, load_worldmap, load_level,
      wait_for_screenswitch, maybe others which I forgot)
  - Improved miniswig generated wrapper functions to check arguments passed and
    to catch exceptions and transform them into squirrel exceptions
  - All scripts are run as cooperative threads now
  - Sectors have a custom squirrel table now that contains all their objects and
    which has the (real) roottable set as parent. Sectorscripts use this
    sectortable as roottable.

SVN-Revision: 3287

53 files changed:
data/levels/test/default.nut
data/levels/test/intro.stl
data/levels/test/intro2.stl
data/levels/world1/world.nut [new file with mode: 0644]
data/levels/world2/default.nut
data/levels/world2/level2.stl
data/script/default.nut
src/badguy/yeti.cpp
src/console.cpp
src/console.hpp
src/control/controller.hpp
src/exceptions.hpp [deleted file]
src/game_session.cpp
src/gui/menu.cpp
src/main.cpp
src/mainloop.cpp
src/object/camera.cpp
src/object/camera.hpp
src/object/display_effect.cpp
src/object/display_effect.hpp
src/object/player.cpp
src/object/player.hpp
src/object/powerup.cpp
src/object/scripted_object.cpp
src/object/scripted_object.hpp
src/object/text_object.cpp
src/object/text_object.hpp
src/resources.cpp
src/screen.hpp
src/script_interface.hpp [new file with mode: 0644]
src/script_manager.cpp [new file with mode: 0644]
src/script_manager.hpp [new file with mode: 0644]
src/scripting/camera.cpp
src/scripting/functions.cpp
src/scripting/functions.hpp
src/scripting/script_interpreter.cpp [deleted file]
src/scripting/script_interpreter.hpp [deleted file]
src/scripting/sound.hpp
src/scripting/wrapper.cpp
src/scripting/wrapper.interface.hpp
src/scripting/wrapper_util.cpp
src/scripting/wrapper_util.hpp
src/sector.cpp
src/sector.hpp
src/textscroller.cpp
src/title.cpp
src/title.hpp
src/trigger/scripttrigger.cpp
src/video/font.cpp
src/world.cpp
src/worldmap.cpp
src/worldmap.hpp
tools/miniswig/create_wrapper.cpp

index d569d68..34e17f7 100644 (file)
@@ -1,4 +1,5 @@
 /* Default functions for the whole levelset */
+print("default.nut loaded\n");
 
 function intro()
 {  
@@ -7,13 +8,13 @@ function intro()
   RADIO.set_action("quiet");  
   PENNY.set_action("stand-left");
   NOLOK.set_visible(false);
-  local logo = FloatingImage("images/objects/logo/logo.sprite");
+  logo <- FloatingImage("images/objects/logo/logo.sprite");
   Tux.deactivate();
   Tux.set_visible(false);
-  DisplayEffect.sixteen_to_nine(0);
+  Effect.sixteen_to_nine(0);
   
   //begin scrolling sequence
-  DisplayEffect.fade_in(2);
+  Effect.fade_in(2);
   Camera.scroll_to(0, 945, 15);
   Sound.play("music/intro.ogg");
   wait(3);
@@ -53,7 +54,7 @@ function intro()
   //enter Nolok
   NOLOK.set_velocity(-220, 600);
   NOLOK.set_visible(true);
-  DisplayEffect.fade_out(1.3);
+  Effect.fade_out(1.3);
   wait(3);
 
   //darkness
@@ -63,7 +64,7 @@ function intro()
   SUPERTUX.set_pos(3550, SUPERTUX.get_pos_y());
 
   //wake up, Tux...
-  DisplayEffect.fade_in(4);
+  Effect.fade_in(4);
   wait(4);
   Sound.play("speech/tux_upset.ogg");
   wait(3);
@@ -76,7 +77,7 @@ function intro()
   wait(2);
   
   //end intro sequence
-  DisplayEffect.fade_out(2);
+  Effect.fade_out(2);
   wait(3);
   Level.finish(true);
 }
@@ -113,9 +114,9 @@ function intro_scene2()
   NOLOK.set_visible(false);
   Tux.deactivate();
   Tux.set_visible(false);
-  DisplayEffect.sixteen_to_nine(0);
+  Effect.sixteen_to_nine(0);
   Sound.play("music/nolok.ogg");
-  DisplayEffect.fade_in(5);
+  Effect.fade_in(5);
   wait(5);
   Camera.scroll_to(3100, 945, 8);
   NOLOK.set_visible(true);  
index b93450e..7d8dc55 100644 (file)
          (y 510)
          (sprite "images/creatures/dummyguy/dummyguy.sprite")
        )
-       (init-script "intro();")
+       (init-script "
+          import(\"levels/test/default.nut\");
+          intro();
+        ")
    )
  )
 
index 8966665..bcfa100 100644 (file)
@@ -5,7 +5,10 @@
   (author "SuperTux Team")
   (sector
     (name  "main")
-    (init-script "intro()")
+    (init-script "
+      import(\"levels/test/default.nut\");
+      intro(); 
+    ")
     (gravity 10.000000)
     (tilemap
       (layer  "background")
diff --git a/data/levels/world1/world.nut b/data/levels/world1/world.nut
new file mode 100644 (file)
index 0000000..94aac66
--- /dev/null
@@ -0,0 +1,6 @@
+print("Hello World\n");
+display_text_file("levels/world1/intro.txt");
+wait_for_screenswitch();
+wait_for_screenswitch();
+load_worldmap("levels/world1/worldmap.stwm");
+
index ca65fc7..0713e29 100644 (file)
@@ -10,13 +10,13 @@ function level2_init()
   add_key(KEY_BRASS);
   add_key(KEY_IRON);
   Tux.deactivate();
-  DisplayEffect.sixteen_to_nine(2);
+  Effect.sixteen_to_nine(2);
   Text.set_text(translate("---Insert Cutscene Here---"));
   Tux.walk(100);
   Text.fade_in(2);
   wait(4);
   Text.fade_out(1);
   wait(1);
-  DisplayEffect.four_to_three();
+  Effect.four_to_three();
   Tux.activate();
 }
index 757146b..6901b9a 100644 (file)
          (image "images/background/forest1.jpg")
          (speed 0.7)
        )
-       (init-script "level2_init();")
+       (init-script "
+          import(\"levels/world2/default.nut\");
+          import(\"script/default.nut\");
+          level2_init();
+        ")
        (secretarea (x 673.0)
                     (y 1090.0)
                     (width 24.0)
index 95b4f13..6629aae 100644 (file)
@@ -4,15 +4,15 @@ function end_level()
   Sound.play_music("music/leveldone.ogg");
   Tux.deactivate();
   wait(6);
-  DisplayEffect.fade_out(2);
+  Effect.fade_out(2);
   wait(2);
   Level.finish();
 }
 
 function levelflip()
 {
-  DisplayEffect.fade_out(1);
+  Effect.fade_out(1);
   wait(1);
   Level.flip_vertically();
-  DisplayEffect.fade_in(1);
+  Effect.fade_in(1);
 }
index f11a6e2..f34a550 100644 (file)
@@ -27,7 +27,6 @@
 #include "yeti_stalactite.hpp"
 #include "bouncing_snowball.hpp"
 #include "game_session.hpp"
-#include "scripting/script_interpreter.hpp"
 
 static const float JUMP_VEL1 = 250;
 static const float JUMP_VEL2 = 700;
@@ -155,8 +154,8 @@ Yeti::collision_squished(Player& player)
 
     // start script
     if(dead_script != "") {
-      ScriptInterpreter::add_script_object(Sector::current(),
-          "Yeti - dead-script", dead_script);
+      std::istringstream stream(dead_script);
+      Sector::current()->run_script(stream, "Yeti - dead-script");
     }
   } else {
     safe_timer.start(SAFE_TIME);
index 69f8547..da30b22 100644 (file)
 //  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 <iostream>
 #include "console.hpp"
 #include "video/drawing_context.hpp"
 #include "video/surface.hpp"
+#include "scripting/squirrel_error.hpp"
+#include "scripting/wrapper_util.hpp"
 #include "player_status.hpp"
+#include "script_manager.hpp"
 #include "main.hpp"
 #include "resources.hpp"
 
@@ -65,6 +68,39 @@ Console::flush(ConsoleStreamBuffer* buffer)
 }
 
 void
+Console::execute_script(const std::string& command)
+{
+  using namespace Scripting;
+
+  HSQUIRRELVM vm = script_manager->get_global_vm();
+
+  if(command == "")
+    return;
+  
+  int oldtop = sq_gettop(vm); 
+  try {
+    if(SQ_FAILED(sq_compilebuffer(vm, command.c_str(), command.length(),
+                 "", SQTrue)))
+      throw SquirrelError(vm, "Couldn't compile command");
+
+    sq_pushroottable(vm);
+    if(SQ_FAILED(sq_call(vm, 1, SQTrue)))
+      throw SquirrelError(vm, "Problem while executing command");
+
+    if(sq_gettype(vm, -1) != OT_NULL)
+      addLine(squirrel2string(vm, -1));
+  } catch(std::exception& e) {
+    addLine(e.what());
+  }
+  int newtop = sq_gettop(vm);
+  if(newtop < oldtop) {
+    msg_fatal << "Script destroyed squirrel stack..." << std::endl;
+  } else {
+    sq_settop(vm, oldtop);
+  }
+}
+
+void
 Console::backspace()
 {
   std::string s = inputBuffer.str();
@@ -150,7 +186,11 @@ Console::parse(std::string s)
   // look up registered ccr
   std::map<std::string, std::list<ConsoleCommandReceiver*> >::iterator i = commands.find(command);
   if ((i == commands.end()) || (i->second.size() == 0)) {
-    addLine("unknown command: \"" + command + "\"");
+    try {
+      execute_script(s);
+    } catch(std::exception& e) {
+      addLine(e.what());
+    }
     return;
   }
 
index 7834d76..1863309 100644 (file)
@@ -91,6 +91,10 @@ class Console
 
     static void addLine(std::string s); /**< display a line in the console */
     static void parse(std::string s); /**< react to a given command */
+    
+    /** execute squirrel script and output result */
+    static void execute_script(const std::string& s);
+    
     static bool consoleCommand(std::string command, std::vector<std::string> arguments); /**< process internal command; return false if command was unknown, true otherwise */
 
     friend class ConsoleStreamBuffer;
@@ -102,20 +106,25 @@ class ConsoleStreamBuffer : public std::stringbuf
   public:
     int sync() 
     {
+      int result = std::stringbuf::sync();
       Console::flush(this);
-      return std::stringbuf::sync();
+      return result;
     }
 };
 
 class ConsoleCommandReceiver
 {
-  public:
-    ConsoleCommandReceiver() {}
-    virtual bool consoleCommand(std::string command, std::vector<std::string> arguments) = 0; /**< callback from Console; return false if command was unknown, true otherwise */
-    virtual ~ConsoleCommandReceiver()
-    {
-      Console::unregisterCommands(this);
-    }
+public:
+  virtual ~ConsoleCommandReceiver()
+  {
+    Console::unregisterCommands(this);
+  }
+   
+  /**
+   * callback from Console; return false if command was unknown,
+   * true otherwise
+   */
+  virtual bool consoleCommand(std::string command, std::vector<std::string> arguments) = 0;
 };
 
 #endif
index 3e37cf7..026ec2a 100644 (file)
@@ -47,7 +47,7 @@ public:
   bool hold(Control control);
   /** returns true if the control has just been pressed down this frame */
   bool pressed(Control control);
-  /** returns true if the control has just been released down this frame */ 
+  /** returns true if the control has just been released this frame */ 
   bool released(Control control);
 
   virtual void reset();
diff --git a/src/exceptions.hpp b/src/exceptions.hpp
deleted file mode 100644 (file)
index 5fa82a5..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-//  $Id$
-// 
-//  SuperTux
-//  Copyright (C) 2005 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
-//  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 __EXCEPTIONS_H__
-#define __EXCEPTIONS_H__
-
-#include <exception>
-
-/** Throw this exception to gracefully shut SuperTux down.
- */
-class graceful_shutdown : public std::exception
-{
-public:
-  explicit graceful_shutdown() {};
-};
-
-#endif
index bad7bfd..f0da603 100644 (file)
@@ -67,7 +67,7 @@
 #include "file_system.hpp"
 #include "gameconfig.hpp"
 #include "gettext.hpp"
-#include "exceptions.hpp"
+#include "console.hpp"
 #include "flip_level_transformer.hpp"
 
 // the engine will be run with a logical framerate of 64fps.
@@ -696,12 +696,13 @@ GameSession::display_info_box(const std::string& text)
   
   while(running)  {
 
+    // TODO make a screen out of this, another mainloop is ugly
     main_controller->update();
     SDL_Event event;
     while (SDL_PollEvent(&event)) {
       main_controller->process_event(event);
       if(event.type == SDL_QUIT)
-        throw graceful_shutdown();
+        main_loop->quit();
     }
 
     if(main_controller->pressed(Controller::JUMP)
index 052a54d..4e28ff2 100644 (file)
@@ -30,6 +30,7 @@
 #include <stdexcept>
 
 #include "menu.hpp"
+#include "mainloop.hpp"
 #include "video/screen.hpp"
 #include "video/drawing_context.hpp"
 #include "gettext.hpp"
@@ -37,7 +38,6 @@
 #include "main.hpp"
 #include "resources.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
-#include "exceptions.hpp"
 
 static const int MENU_REPEAT_INITIAL = 400;
 static const int MENU_REPEAT_RATE = 200;
@@ -68,12 +68,13 @@ bool confirm_dialog(Surface *background, std::string text)
 
   DrawingContext context;
 
+  // TODO make this a screen and not another mainloop...
   while(true)
     {
       SDL_Event event;
       while (SDL_PollEvent(&event)) {
         if(event.type == SDL_QUIT)
-          throw graceful_shutdown();
+          main_loop->quit();
         main_controller->process_event(event);
         dialog->event(event);
       }
index 2bfbed2..8874b00 100644 (file)
 #include "mainloop.hpp"
 #include "title.hpp"
 #include "game_session.hpp"
+#include "script_manager.hpp"
+#include "scripting/sound.hpp"
+#include "scripting/level.hpp"
+#include "scripting/wrapper_util.hpp"
 #include "file_system.hpp"
 #include "physfs/physfs_sdl.hpp"
-#include "exceptions.hpp"
 
 SDL_Surface* screen = 0;
 JoystickKeyboardController* main_controller = 0;
@@ -193,7 +196,7 @@ static void print_usage(const char* argv0)
             "\n"));
 }
 
-static void parse_commandline(int argc, char** argv)
+static bool parse_commandline(int argc, char** argv)
 {
   for(int i = 1; i < argc; ++i) {
     std::string arg = argv[i];
@@ -232,10 +235,10 @@ static void parse_commandline(int argc, char** argv)
       config->record_demo = argv[++i];
     } else if(arg == "--help") {
       print_usage(argv[0]);
-      throw graceful_shutdown();
+      return true;
     } else if(arg == "--version") {
       msg_info << PACKAGE_NAME << " " << PACKAGE_VERSION << std::endl;
-      throw graceful_shutdown();
+      return true;
     } else if(arg[0] != '-') {
       config->start_level = arg;
     } else {
@@ -243,7 +246,7 @@ static void parse_commandline(int argc, char** argv)
     }
   }
 
-  // TODO joystick switchyes...
+  return false;
 }
 
 static void init_sdl()
@@ -374,11 +377,22 @@ static void init_audio()
   sound_manager->enable_music(config->music_enabled);
 }
 
+static void init_scripting()
+{
+  script_manager = new ScriptManager();
+
+  HSQUIRRELVM vm = script_manager->get_global_vm();
+  sq_pushroottable(vm); 
+  expose_object(vm, -1, new Scripting::Sound(), "Sound", true);
+  expose_object(vm, -1, new Scripting::Level(), "Level", true);
+  sq_pop(vm, 1);
+}
+
 static void quit_audio()
 {
-  if(sound_manager) {
+  if(sound_manager != NULL) {
     delete sound_manager;
-    sound_manager = 0;
+    sound_manager = NULL;
   }
 }
 
@@ -395,7 +409,7 @@ void wait_for_event(float min_delay, float max_delay)
     sound_manager->update();
   }
 
-  // clear even queue
+  // clear event queue
   SDL_Event event;
   while (SDL_PollEvent(&event))
   {}
@@ -407,7 +421,8 @@ void wait_for_event(float min_delay, float max_delay)
     while(SDL_PollEvent(&event)) {
       switch(event.type) {
         case SDL_QUIT:
-          throw graceful_shutdown();
+          main_loop->quit();
+          break;
         case SDL_KEYDOWN:
         case SDL_JOYBUTTONDOWN:
         case SDL_MOUSEBUTTONDOWN:
@@ -455,11 +470,14 @@ int main(int argc, char** argv)
     timelog("tinygettext");
     init_tinygettext();
     timelog("commandline");
-    parse_commandline(argc, argv);
+    if(parse_commandline(argc, argv))
+      return 0;
     timelog("audio");
     init_audio();
     timelog("video");
     init_video();
+    timelog("scripting");
+    init_scripting();
 
     timelog("menu");
     setup_menu();
@@ -489,7 +507,6 @@ int main(int argc, char** argv)
 
     delete main_loop;
     main_loop = NULL;
-  } catch(graceful_shutdown& e) {
   } catch(std::exception& e) {
     msg_fatal << "Unexpected exception: " << e.what() << std::endl;
     return 1;
@@ -499,14 +516,20 @@ int main(int argc, char** argv)
   }
 
   free_menu();
+  delete script_manager;
+  script_manager = NULL;
+  printf("crashunloadshared?\n");
   unload_shared();
   quit_audio();
 
   if(config)
     config->save();
   delete config;
+  config = NULL;
   delete main_controller;
+  main_controller = NULL;
   delete texture_manager;
+  texture_manager = NULL;
   SDL_Quit();
   PHYSFS_deinit();
   
index 1c98cd4..afd60ae 100644 (file)
 #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"
+#include "script_manager.hpp"
 #include "screen.hpp"
 #include "timer.hpp"
 
@@ -97,10 +99,13 @@ MainLoop::run()
   running = true;
   while(running) {
     if(next_screen.get() != NULL) {
-      if(nextpush)
+      if(nextpush && current_screen.get() != NULL) {
+        current_screen->leave();
         screen_stack.push_back(current_screen.release());
+      }
       
       next_screen->setup();
+      script_manager->fire_wakeup_event(ScriptManager::SCREEN_SWITCHED);
       current_screen.reset(next_screen.release());
       next_screen.reset(NULL);
       nextpush = false;
@@ -159,8 +164,9 @@ MainLoop::run()
     elapsed_time *= speed;
 
     game_time += elapsed_time;
+    script_manager->update();
     current_screen->update(elapsed_time);
-
     main_controller->update();
     SDL_Event event;
     while(SDL_PollEvent(&event)) {
index c1077cc..61d404a 100644 (file)
@@ -25,6 +25,8 @@
 #include "lisp/lisp.hpp"
 #include "lisp/writer.hpp"
 #include "lisp/list_iterator.hpp"
+#include "scripting/camera.hpp"
+#include "scripting/wrapper_util.hpp"
 #include "camera.hpp"
 #include "player.hpp"
 #include "tilemap.hpp"
@@ -46,6 +48,19 @@ Camera::~Camera()
 {
 }
 
+void
+Camera::expose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::Camera* interface = new Scripting::Camera(this);
+  expose_object(vm, table_idx, interface, "Camera", true);
+}
+
+void
+Camera::unexpose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::unexpose_object(vm, table_idx, "Camera");
+}
+
 const Vector&
 Camera::get_translation() const
 {
index 0be750e..ed7b5a7 100644 (file)
@@ -28,6 +28,7 @@
 #include "video/drawing_context.hpp"
 #include "serializable.hpp"
 #include "timer.hpp"
+#include "script_interface.hpp"
 
 namespace lisp {
 class Lisp;
@@ -37,7 +38,7 @@ class Sector;
 class Path;
 class PathWalker;
 
-class Camera : public GameObject, public Serializable
+class Camera : public GameObject, public Serializable, public ScriptInterface
 {
 public:
   Camera(Sector* sector);
@@ -60,6 +61,9 @@ public:
   {
   }
 
+  virtual void expose(HSQUIRRELVM vm, int table_idx);
+  virtual void unexpose(HSQUIRRELVM vm, int table_idx);
+
   // shake camera in a direction 1 time
   void shake(float speed, float x, float y);
 
index ffa154d..c2b1538 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <assert.h>
 #include "video/drawing_context.hpp"
+#include "scripting/wrapper_util.hpp"
 #include "main.hpp"
 
 static const float BORDER_SIZE = 75;
@@ -19,6 +20,23 @@ DisplayEffect::~DisplayEffect()
 }
 
 void
+DisplayEffect::expose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::DisplayEffect* interface = static_cast<Scripting::DisplayEffect*> (this);
+  expose_object(vm, table_idx, interface, "Effect", false);
+}
+
+void
+DisplayEffect::unexpose(HSQUIRRELVM vm, int table_idx)
+{
+  try {
+    Scripting::unexpose_object(vm, table_idx, "Effect");
+  } catch(...) {
+    // for now...
+  }
+}
+
+void
 DisplayEffect::update(float elapsed_time)
 {
     switch(screen_fade) {
index 033d8ad..972b5dc 100644 (file)
@@ -3,13 +3,18 @@
 
 #include "scripting/display_effect.hpp"
 #include "game_object.hpp"
+#include "script_interface.hpp"
 
-class DisplayEffect : public GameObject, public Scripting::DisplayEffect
+class DisplayEffect : public GameObject, public Scripting::DisplayEffect,
+                      public ScriptInterface
 {
 public:
     DisplayEffect();
     virtual ~DisplayEffect();
 
+    void expose(HSQUIRRELVM vm, int table_idx);
+    void unexpose(HSQUIRRELVM vm, int table_idx);
+
     void update(float elapsed_time);
     void draw(DrawingContext& context);
 
index 96e10b3..659328d 100644 (file)
@@ -41,6 +41,7 @@
 #include "object/bullet.hpp"
 #include "trigger/trigger_base.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
+#include "scripting/wrapper_util.hpp"
 #include "main.hpp"
 #include "platform.hpp"
 #include "badguy/badguy.hpp"
@@ -107,8 +108,6 @@ Player::Player(PlayerStatus* _player_status)
   smalltux_star = sprite_manager->create("images/creatures/tux_small/smalltux-star.sprite");
   bigtux_star = sprite_manager->create("images/creatures/tux_big/bigtux-star.sprite");
 
-  Console::registerCommand("set_bonus", this);
-
   init();
 }
 
@@ -153,6 +152,19 @@ Player::init()
 }
 
 void
+Player::expose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::Player* interface = static_cast<Scripting::Player*> (this);
+  expose_object(vm, table_idx, interface, "Tux", false);
+}
+
+void
+Player::unexpose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::unexpose_object(vm, table_idx, "Tux");
+}
+
+void
 Player::set_controller(Controller* controller)
 {
   this->controller = controller;
@@ -953,27 +965,3 @@ void Player::walk(float speed)
   physic.set_velocity_x(speed);
 }
 
-bool
-Player::consoleCommand(std::string command, std::vector<std::string> arguments)
-{
-  if (command == "set_bonus") {
-    if (arguments.size() == 1) {
-      if (arguments[0] == "egg") {
-       set_bonus(GROWUP_BONUS, false);
-       return true;
-      }
-      if (arguments[0] == "fire") {
-       set_bonus(FIRE_BONUS, false);
-       return true;
-      }
-      if (arguments[0] == "ice") {
-       set_bonus(ICE_BONUS, false);
-       return true;
-      }
-    }
-    msg_info << "Usage: give {\"egg\" | \"fire\" | \"ice\"}" << std::endl;
-    return true;
-  }
-  return false;
-}
-
index 43cddf9..eb5ab8a 100644 (file)
@@ -32,6 +32,7 @@
 #include "scripting/player.hpp"
 #include "player_status.hpp"
 #include "display_effect.hpp"
+#include "script_interface.hpp"
 #include "console.hpp"
 
 class BadGuy;
@@ -78,7 +79,7 @@ extern TuxBodyParts* big_tux;
 extern TuxBodyParts* fire_tux;
 extern TuxBodyParts* ice_tux;
 
-class Player : public MovingObject, public Scripting::Player, public ConsoleCommandReceiver
+class Player : public MovingObject, public Scripting::Player, public ScriptInterface
 {
 public:
   enum HurtMode { KILL, SHRINK };
@@ -121,6 +122,9 @@ public:
   Player(PlayerStatus* player_status);
   virtual ~Player();
 
+  virtual void expose(HSQUIRRELVM vm, int table_idx);
+  virtual void unexpose(HSQUIRRELVM vm, int table_idx);
+
   void set_controller(Controller* controller);  
 
   virtual void update(float elapsed_time);
@@ -165,8 +169,6 @@ public:
 
   bool on_ground();
 
-  bool consoleCommand(std::string command, std::vector<std::string> arguments); /**< callback from Console; return false if command was unknown, true otherwise */
-  
 private:
   void handle_input();
   bool deactivated;
index 5f28bd7..f731822 100644 (file)
@@ -27,7 +27,6 @@
 #include "audio/sound_manager.hpp"
 #include "object_factory.hpp"
 #include "sector.hpp"
-#include "scripting/script_interpreter.hpp"
 #include "msg.hpp"
 
 PowerUp::PowerUp(const lisp::Lisp& lisp)
@@ -70,8 +69,8 @@ PowerUp::collision(GameObject& other, const CollisionHit& hit)
   remove_me();
 
   if (script != "") {
-    ScriptInterpreter::add_script_object(Sector::current(), "powerup-script",
-        script);
+    std::istringstream stream(script);
+    Sector::current()->run_script(stream, "powerup-script");
     return ABORT_MOVE;
   }
 
index 53ef317..928b350 100644 (file)
@@ -6,6 +6,7 @@
 #include "scripted_object.hpp"
 #include "video/drawing_context.hpp"
 #include "sprite/sprite_manager.hpp"
+#include "scripting/wrapper_util.hpp"
 #include "resources.hpp"
 #include "object_factory.hpp"
 #include "math/vector.hpp"
@@ -46,6 +47,19 @@ ScriptedObject::~ScriptedObject()
 }
 
 void
+ScriptedObject::expose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::ScriptedObject* interface = static_cast<Scripting::ScriptedObject*> (this);
+  expose_object(vm, table_idx, interface, name, false);
+}
+
+void
+ScriptedObject::unexpose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::unexpose_object(vm, table_idx, name);
+}
+
+void
 ScriptedObject::move(float x, float y)
 {
   bbox.move(Vector(x, y));
index 699a054..ac810b2 100644 (file)
@@ -6,14 +6,19 @@
 #include "sprite/sprite.hpp"
 #include "lisp/lisp.hpp"
 #include "moving_object.hpp"
+#include "script_interface.hpp"
 #include "scripting/scripted_object.hpp"
 
-class ScriptedObject : public MovingObject, public Scripting::ScriptedObject
+class ScriptedObject : public MovingObject, public Scripting::ScriptedObject,
+                       public ScriptInterface
 {
 public:
   ScriptedObject(const lisp::Lisp& lisp);
   virtual ~ScriptedObject();
 
+  virtual void expose(HSQUIRRELVM vm, int table_idx);
+  virtual void unexpose(HSQUIRRELVM vm, int table_idx);
+
   void update(float elapsed_time);
   void draw(DrawingContext& context);
   HitResponse collision(GameObject& other, const CollisionHit& hit);
index 8b992cd..8608b9f 100644 (file)
@@ -5,6 +5,7 @@
 #include <iostream>
 #include "resources.hpp"
 #include "video/drawing_context.hpp"
+#include "scripting/wrapper_util.hpp"
 #include "msg.hpp"
 
 TextObject::TextObject()
@@ -19,6 +20,19 @@ TextObject::~TextObject()
 }
 
 void
+TextObject::expose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::Text* interface = static_cast<Scripting::Text*> (this);
+  Scripting::expose_object(vm, table_idx, interface, "Text", false);
+}
+
+void
+TextObject::unexpose(HSQUIRRELVM vm, int table_idx)
+{
+  Scripting::unexpose_object(vm, table_idx, "Text");
+}
+
+void
 TextObject::set_font(const std::string& name)
 {
   if(name == "gold") {
index 194dc94..2f39b1d 100644 (file)
@@ -3,16 +3,21 @@
 
 #include "game_object.hpp"
 #include "scripting/text.hpp"
+#include "script_interface.hpp"
 
 class Font;
 
 /** A text object intended for scripts that want to tell a story */
-class TextObject : public GameObject, public Scripting::Text
+class TextObject : public GameObject, public Scripting::Text,
+                   public ScriptInterface
 {
 public:
   TextObject();
   virtual ~TextObject();
 
+  void expose(HSQUIRRELVM vm, int table_idx);
+  void unexpose(HSQUIRRELVM vm, int table_idx);
+
   void set_text(const std::string& text);
   void set_font(const std::string& name);
   void fade_in(float fadetime);
index 3570e00..b561578 100644 (file)
@@ -112,29 +112,41 @@ 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 fd3b890..6c6ea02 100644 (file)
@@ -27,11 +27,26 @@ public:
   virtual ~Screen()
   {}
 
+  /**
+   * gets called before this screen gets activated (which is at least once
+   * before the first draw or update call
+   */
   virtual void setup()
   {}
+  /** gets called when the current screen is temporarily suspended */
+  virtual void leave()
+  {}
 
+  /**
+   * gets called once per frame. The screen should draw itself in this function.
+   * State changes should not be done in this function, but rather in update
+   */
   virtual void draw(DrawingContext& context) = 0;
 
+  /**
+   * gets called for once (per logical) frame. Screens should do their state
+   * updates and logic here
+   */
   virtual void update(float elapsed_time) = 0;
 };
 
diff --git a/src/script_interface.hpp b/src/script_interface.hpp
new file mode 100644 (file)
index 0000000..bc21c38
--- /dev/null
@@ -0,0 +1,40 @@
+//  $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
+// 
+//  SuperTux
+//  Copyright (C) 2005 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
+//  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 __SCRIPT_INTERFACE_HPP__
+#define __SCRIPT_INTERFACE_HPP__
+
+#include <squirrel.h>
+
+/**
+ * Objects that want to expose themself to the scripting environment
+ * should implement this interface
+ */
+class ScriptInterface
+{
+public:
+  virtual ~ScriptInterface()
+  {}
+  
+  virtual void expose(HSQUIRRELVM vm, int table_idx) = 0;
+  virtual void unexpose(HSQUIRRELVM vm, int table_idx) = 0;
+};
+
+#endif
+
diff --git a/src/script_manager.cpp b/src/script_manager.cpp
new file mode 100644 (file)
index 0000000..d0656a5
--- /dev/null
@@ -0,0 +1,197 @@
+//  $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
+// 
+//  SuperTux
+//  Copyright (C) 2005 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
+//  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 "script_manager.hpp"
+
+#include <stdarg.h>
+#include <stdexcept>
+#include <sstream>
+#include <fstream>
+#include <sqstdio.h>
+#include <sqstdaux.h>
+#include <sqstdblob.h>
+#include <sqstdsystem.h>
+#include <sqstdmath.h>
+#include <sqstdstring.h>
+
+#include "timer.hpp"
+#include "console.hpp"
+#include "scripting/wrapper.hpp"
+#include "scripting/wrapper_util.hpp"
+#include "scripting/squirrel_error.hpp"
+#include "physfs/physfs_stream.hpp"
+
+using namespace Scripting;
+
+ScriptManager* script_manager = 0;
+
+static void printfunc(HSQUIRRELVM, const char* str, ...)
+{
+  char buf[4096];
+  va_list arglist; 
+  va_start(arglist, str); 
+  vsprintf(buf, str, arglist);
+  Console::output << (const char*) buf << std::flush;
+  va_end(arglist); 
+}
+
+ScriptManager::ScriptManager()
+{
+  v = sq_open(1024);
+  if(v == 0)
+    throw std::runtime_error("Couldn't initialize squirrel vm");
+
+  // 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");
+
+  // register print function
+  sq_setprintfunc(v, printfunc);
+  
+  // register supertux API
+  register_supertux_wrapper(v);
+}
+
+ScriptManager::~ScriptManager()
+{
+  for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ++i)
+    sq_release(v, &(i->vm_obj));
+
+  sq_close(v);
+}
+
+HSQUIRRELVM
+ScriptManager::create_thread()
+{
+  HSQUIRRELVM vm = sq_newthread(v, 1024);
+  if(vm == NULL)
+    throw SquirrelError(v, "Couldn't create new VM");
+
+  // 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");
+  }
+  sq_addref(v, &vm_obj);
+  sq_pop(v, 1);
+  
+  squirrel_vms.push_back(SquirrelVM(vm, vm_obj));
+
+  return vm;
+}
+
+void
+ScriptManager::update()
+{
+  for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ) {
+    SquirrelVM& squirrel_vm = *i;
+    int vm_state = sq_getvmstate(squirrel_vm.vm);
+    
+    if(vm_state == SQ_VMSTATE_SUSPENDED && squirrel_vm.wakeup_time > 0 && game_time >= squirrel_vm.wakeup_time) {
+      squirrel_vm.waiting_for_events = WakeupData(NO_EVENT);
+      try {
+        if(SQ_FAILED(sq_wakeupvm(squirrel_vm.vm, false, false))) {
+          throw SquirrelError(squirrel_vm.vm, "Couldn't resume script");
+        }
+      } catch(std::exception& e) {
+        std::cerr << "Problem executing script: " << e.what() << "\n";
+        sq_release(v, &squirrel_vm.vm_obj);
+        i = squirrel_vms.erase(i);
+        continue;
+      }
+    }
+       
+    if (vm_state != SQ_VMSTATE_SUSPENDED) {
+      sq_release(v, &(squirrel_vm.vm_obj));
+      i = squirrel_vms.erase(i);
+    } else {
+      ++i;
+    }
+  }
+}
+
+void
+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) {
+    SquirrelVM& squirrel_vm = *i;
+    if(squirrel_vm.vm == vm) 
+      {
+        squirrel_vm.waiting_for_events = event;
+
+        if(timeout < 0) {
+          squirrel_vm.wakeup_time = -1;
+        } else {
+          squirrel_vm.wakeup_time = game_time + timeout;
+        }
+        return;
+      }
+  }
+}
+
+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;
+        }
+    }
+}
+
+void
+ScriptManager::set_wakeup_event(HSQUIRRELVM vm, WakeupEvent event, float timeout)
+{
+  set_wakeup_event(vm, WakeupData(event), timeout);
+}
+
+void
+ScriptManager::fire_wakeup_event(WakeupEvent event)
+{
+  fire_wakeup_event(WakeupData(event));
+}
+
+ScriptManager::SquirrelVM::SquirrelVM(HSQUIRRELVM arg_vm, HSQOBJECT arg_obj)
+  : vm(arg_vm), vm_obj(arg_obj)
+{
+  waiting_for_events = WakeupData(NO_EVENT);
+  wakeup_time        = 0;
+}
+
diff --git a/src/script_manager.hpp b/src/script_manager.hpp
new file mode 100644 (file)
index 0000000..bbcbbf1
--- /dev/null
@@ -0,0 +1,100 @@
+//  $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
+// 
+//  SuperTux
+//  Copyright (C) 2005 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
+//  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 __SCRIPT_MANAGER_H__
+#define __SCRIPT_MANAGER_H__
+
+#include <vector>
+#include <list>
+#include <squirrel.h>
+#include <iostream>
+#include "timer.hpp"
+
+class GameObject;
+
+/**
+ * This class is responsible for managing all running squirrel threads
+ * (they are cooperative threads or coroutines)
+ * It keeps a list of suspended scripts and receives wakeup events for them
+ */
+class ScriptManager
+{
+public:
+  ScriptManager();
+  ~ScriptManager();
+
+  void update();
+
+  /**
+   * Creates a new thread and registers it with the script manager
+   * (so it can suspend and register for wakeup events)
+   */
+  HSQUIRRELVM create_thread();
+
+  HSQUIRRELVM get_global_vm() const
+  {
+    return v;
+  }
+
+  enum WakeupEvent {
+    NO_EVENT,
+    TIME,
+    SCREEN_SWITCHED,
+    WAKEUP_EVENT_COUNT
+  };
+
+  struct WakeupData {
+    explicit WakeupData() : type(NO_EVENT) {}
+    explicit WakeupData(WakeupEvent type_) : type(type_) {}
+
+    WakeupEvent type;
+    
+    union {
+      // GAMEOBJECT_DONE
+      GameObject* game_object;
+    };
+  };
+
+  void set_wakeup_event(HSQUIRRELVM vm, WakeupEvent event, float timeout = -1);
+  void set_wakeup_event(HSQUIRRELVM vm, WakeupData  event, float timeout = -1);
+  void fire_wakeup_event(WakeupEvent event);
+  void fire_wakeup_event(WakeupData  event);
+  
+private:
+  class SquirrelVM
+  {
+  public:
+    SquirrelVM(HSQUIRRELVM arg_vm, HSQOBJECT arg_obj);
+
+    HSQUIRRELVM vm;
+    HSQOBJECT   vm_obj;
+    float       wakeup_time;
+    WakeupData  waiting_for_events;
+  };
+  
+  typedef std::list<SquirrelVM> SquirrelVMs;
+  SquirrelVMs squirrel_vms;
+
+  HSQUIRRELVM v;
+};
+
+extern ScriptManager* script_manager;
+
+#endif
+
index d96b5a4..93b9104 100644 (file)
@@ -6,7 +6,7 @@
 #include "scripting/camera.hpp"
 #include "math/vector.hpp"
 
-#define NOIMPL      printf("%s not implemented.\n", __PRETTY_FUNCTION__);
+#define NOIMPL      msg_fatal << __PRETTY_FUNCTION__ << " not implemented."
 
 namespace Scripting
 {
@@ -30,9 +30,15 @@ namespace Scripting
   }
 
   void
-  Camera::set_mode(const std::string& )
+  Camera::set_mode(const std::string& mode)
   {
-    NOIMPL;
+    if(mode == "normal") {
+      camera->mode = ::Camera::NORMAL;
+    } else if(mode == "manual") {
+      camera->mode = ::Camera::MANUAL;
+    } else {
+      msg_fatal << "Camera mode '" << mode << "' unknown.";
+    }
   }
 
   void
index 5c1d6ff..21712a6 100644 (file)
@@ -1,22 +1,61 @@
+//  $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
+// 
+//  SuperTux
+//  Copyright (C) 2005 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
+//  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 <memory>
 #include <stdio.h>
 #include <string>
 #include <squirrel.h>
 #include <sqstdio.h>
 #include "textscroller.hpp"
 #include "functions.hpp"
-#include "script_interpreter.hpp"
+#include "game_session.hpp"
 #include "tinygettext/tinygettext.hpp"
+#include "physfs/physfs_stream.hpp"
+#include "script_manager.hpp"
 #include "resources.hpp"
 #include "gettext.hpp"
 #include "msg.hpp"
 #include "mainloop.hpp"
+#include "worldmap.hpp"
+
+#include "squirrel_error.hpp"
+#include "wrapper_util.hpp"
 
 namespace Scripting
 {
 
-void wait(float seconds)
+int display(HSQUIRRELVM vm)
+{
+  Console::output << squirrel2string(vm, -1) << std::endl;
+  return 0;
+}
+
+void wait(HSQUIRRELVM vm, float seconds)
+{
+  script_manager->set_wakeup_event(vm, ScriptManager::TIME, seconds);
+}
+
+void wait_for_screenswitch(HSQUIRRELVM vm)
 {
-  ScriptInterpreter::current()->set_wakeup_time(seconds);
+  script_manager->set_wakeup_event(vm, ScriptManager::SCREEN_SWITCHED);
 }
 
 std::string translate(const std::string& text)
@@ -26,25 +65,48 @@ std::string translate(const std::string& text)
 
 void display_text_file(const std::string& filename)
 {
-  std::string file 
-      = ScriptInterpreter::current()->get_working_directory() + filename;
-  main_loop->push_screen(new TextScroller(file));
+  main_loop->push_screen(new TextScroller(filename));
 }
 
-void import(HSQUIRRELVM v, const std::string& filename)
+void load_worldmap(const std::string& filename)
 {
-  std::string file 
-    = ScriptInterpreter::current()->get_working_directory() + filename;
-  if(sqstd_loadfile(v, file.c_str(), true) < 0) {
-    msg_warning << "couldn't load script '" << filename << "' (" << file << ")" << std::endl;
-    return;
-  }
+  using namespace WorldMapNS;
+
+  std::auto_ptr<WorldMap> worldmap(new WorldMap());
+  worldmap->loadmap(filename);
+  main_loop->push_screen(worldmap.release());
+}
+
+void load_level(const std::string& filename)
+{
+  main_loop->push_screen(new GameSession(filename, ST_GL_PLAY));
+}
+
+static SQInteger squirrel_read_char(SQUserPointer file)
+{
+  std::istream* in = reinterpret_cast<std::istream*> (file);
+  char c = in->get();
+  if(in->eof())
+    return 0;
+
+  return c;
+}
 
-  sq_push(v, -2);
-  if(sq_call(v, 1, false) < 0) {
-    msg_warning << "Couldn't execute script '" << filename << "' (" << file << ")" << std::endl;
-    return;
+
+void import(HSQUIRRELVM vm, const std::string& filename)
+{
+  IFileStream in(filename);
+    
+  if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in,
+          filename.c_str(), SQTrue)))
+    throw SquirrelError(vm, "Couldn't parse script");
+    
+  sq_pushroottable(vm);
+  if(SQ_FAILED(sq_call(vm, 1, SQFalse))) {
+    sq_pop(vm, 1);
+    throw SquirrelError(vm, "Couldn't execute script");
   }
+  sq_pop(vm, 1);
 }
 
 void add_key(int new_key)
index 7321c79..ccf0e62 100644 (file)
@@ -1,8 +1,29 @@
+//  $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
+// 
+//  SuperTux
+//  Copyright (C) 2005 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
+//  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 __FUNCTIONS_H__
 #define __FUNCTIONS_H__
 
 #ifndef SCRIPTING_API
 #define __suspend
+#define __custom
+#include <string>
 #include "player_status.hpp"
 #endif
 
@@ -16,25 +37,50 @@ static const int KEY_BRONZE = 0x004;
 static const int KEY_SILVER = 0x008;
 static const int KEY_GOLD   = 0x010;
 
-/** displays a text file and scrolls it over the screen */
+/**
+ * Display the value of the argument. This is usefull for inspecting tables.
+ */
+int display(HSQUIRRELVM vm) __custom;
+
+/**
+ * Display a text file and scrolls it over the screen (on next screenswitch)
+ */
 void display_text_file(const std::string& filename);
 
 /**
- * Suspends the script execution for the specified number of seconds
+ * Load and display a worldmap (on next screenswitch)
  */
-void wait(float seconds) __suspend;
+void load_worldmap(const std::string& filename);
 
-/** translates a give text into the users language (by looking it up in the .po
+/**
+ * Load and display a level (on next screenswitch)
+ */
+void load_level(const std::string& filename);
+
+/**
+ * Suspend the script execution for the specified number of seconds
+ */
+void wait(HSQUIRRELVM vm, float seconds) __suspend;
+
+/**
+ * Suspend the script execution until the current screen has been changed
+ */
+void wait_for_screenswitch(HSQUIRRELVM vm) __suspend;
+
+/**
+ * Translate a text into the users language (by looking it up in the .po
  * files)
  */
 std::string translate(const std::string& text);
 
-/** load a script file and executes it 
- * This is typically used to import functions from external files.
+/**
+ * Load a script file and executes it. This is typically used to import
+ * functions from external files.
  */
 void import(HSQUIRRELVM v, const std::string& filename);
 
-/** add a key to the inventory
+/**
+ * Add a key to the inventory
  */
 void add_key(int new_key);
 
diff --git a/src/scripting/script_interpreter.cpp b/src/scripting/script_interpreter.cpp
deleted file mode 100644 (file)
index 3226559..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-#include <config.h>
-
-#include "script_interpreter.hpp"
-
-#include <stdarg.h>
-#include <stdexcept>
-#include <sstream>
-#include <fstream>
-#include <sqstdio.h>
-#include <sqstdaux.h>
-#include <sqstdblob.h>
-#include <sqstdsystem.h>
-#include <sqstdmath.h>
-#include <sqstdstring.h>
-
-#include "msg.hpp"
-#include "wrapper.hpp"
-#include "wrapper_util.hpp"
-#include "sector.hpp"
-#include "file_system.hpp"
-#include "game_session.hpp"
-#include "resources.hpp"
-#include "physfs/physfs_stream.hpp"
-#include "object/text_object.hpp"
-#include "object/scripted_object.hpp"
-#include "object/display_effect.hpp"
-#include "object/player.hpp"
-#include "scripting/sound.hpp"
-#include "scripting/scripted_object.hpp"
-#include "scripting/display_effect.hpp"
-#include "scripting/squirrel_error.hpp"
-
-static void printfunc(HSQUIRRELVM, const char* str, ...)
-{
-  va_list arglist;
-  va_start(arglist, str);
-  vprintf(str, arglist);
-  va_end(arglist);
-}
-
-ScriptInterpreter* ScriptInterpreter::_current = 0;
-
-ScriptInterpreter::ScriptInterpreter(const std::string& new_working_directory)
-  : working_directory(new_working_directory), sound(0), level(0), camera(0)
-{
-  v = sq_open(1024);
-  if(v == 0)
-    throw std::runtime_error("Couldn't initialize squirrel vm");
-
-  // register default error handlers
-  sqstd_seterrorhandlers(v);
-  // register squirrel libs
-  sq_pushroottable(v);
-  if(sqstd_register_bloblib(v) < 0)
-    throw Scripting::SquirrelError(v, "Couldn't register blob lib");
-  if(sqstd_register_iolib(v) < 0)
-    throw Scripting::SquirrelError(v, "Couldn't register io lib");
-  if(sqstd_register_systemlib(v) < 0)
-    throw Scripting::SquirrelError(v, "Couldn't register system lib");
-  if(sqstd_register_mathlib(v) < 0)
-    throw Scripting::SquirrelError(v, "Couldn't register math lib");
-  if(sqstd_register_stringlib(v) < 0)
-    throw Scripting::SquirrelError(v, "Couldn't register string lib");
-
-  // register print function
-  sq_setprintfunc(v, printfunc);
-  
-  // register supertux API
-  Scripting::register_supertux_wrapper(v);
-
-  // expose some "global" objects
-  sound = new Scripting::Sound();
-  expose_object(sound, "Sound");
-  
-  level = new Scripting::Level();
-  expose_object(level, "Level");
-}
-
-void
-ScriptInterpreter::register_sector(Sector* sector)
-{
-  // expose ScriptedObjects to the script
-  for(Sector::GameObjects::iterator i = sector->gameobjects.begin();
-      i != sector->gameobjects.end(); ++i) {
-    GameObject* object = *i;
-    Scripting::ScriptedObject* scripted_object
-      = dynamic_cast<Scripting::ScriptedObject*> (object);
-    if(!scripted_object)
-      continue;
-    
-    expose_object(scripted_object, scripted_object->get_name());
-  }
-  
-  expose_object(static_cast<Scripting::Player*> (sector->player), "Tux");
-  TextObject* text_object = new TextObject();
-  sector->add_object(text_object);
-  Scripting::Text* text = static_cast<Scripting::Text*> (text_object);
-  expose_object(text, "Text");
-  
-  DisplayEffect* display_effect = new DisplayEffect();
-  sector->add_object(display_effect);
-  Scripting::DisplayEffect* display_effect_api
-    = static_cast<Scripting::DisplayEffect*> (display_effect);
-  expose_object(display_effect_api, "DisplayEffect");
-
-  Scripting::Camera* camera = new Scripting::Camera(sector->camera);
-  expose_object(camera, "Camera");
-}
-
-ScriptInterpreter::~ScriptInterpreter()
-{
-  sq_close(v);
-  delete sound;
-  delete level;
-  delete camera;
-}
-
-static SQInteger squirrel_read_char(SQUserPointer file)
-{
-  std::istream* in = reinterpret_cast<std::istream*> (file);
-  char c = in->get();
-  if(in->eof())
-    return 0;    
-  return c;
-}
-
-void
-ScriptInterpreter::run_script(std::istream& in, const std::string& sourcename,
-        bool remove_when_terminated)
-{
-  if(sq_compile(v, squirrel_read_char, &in, sourcename.c_str(), true) < 0)
-    throw Scripting::SquirrelError(v, "Couldn't parse script");
-  _current = this;
-  sq_push(v, -2);
-  if(sq_call(v, 1, false) < 0)
-    throw Scripting::SquirrelError(v, "Couldn't start script");
-  _current = 0;
-  if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) {
-    if(remove_when_terminated) {
-      remove_me();
-    }
-    // remove closure from stack
-    sq_pop(v, 1);
-  }
-}
-
-void
-ScriptInterpreter::set_wakeup_time(float seconds)
-{
-  wakeup_timer.start(seconds);
-}
-
-void
-ScriptInterpreter::update(float )
-{
-  if(!wakeup_timer.check())
-    return;
-  
-  _current = this;
-  if(sq_wakeupvm(v, false, false) < 0)
-    throw Scripting::SquirrelError(v, "Couldn't resume script");
-  _current = 0;
-  if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) {
-    printf("script ended...\n");
-    remove_me();
-  }
-}
-
-void
-ScriptInterpreter::draw(DrawingContext& )
-{
-}
-
-void
-ScriptInterpreter::add_script_object(Sector* sector, const std::string& name,
-    const std::string& script)
-{
-  try {
-    std::string workdir = GameSession::current()->get_working_directory();
-    std::auto_ptr<ScriptInterpreter> interpreter(
-               new ScriptInterpreter(workdir));
-    interpreter->register_sector(sector);
-    
-    // load global default.nut file if it exists
-    //TODO: Load all .nut files from that directory
-    try {
-      std::string filename = "script/default.nut";
-      IFileStream in(filename);
-      interpreter->run_script(in, filename, false);
-    } catch(std::exception& e) {
-      // nothing
-    }
-
-    // load world-specific default.nut file if it exists
-    try {
-      std::string filename = workdir + "/default.nut";
-      IFileStream in(filename);
-      interpreter->run_script(in, filename, false);
-    } catch(std::exception& e) {
-      // nothing
-    }
-       
-    std::istringstream in(script);
-    interpreter->run_script(in, name);
-    sector->add_object(interpreter.release());
-  } catch(std::exception& e) {
-    msg_warning << "Couldn't start '" << name << "' script: " << e.what() << std::endl;
-  }
-}
-
diff --git a/src/scripting/script_interpreter.hpp b/src/scripting/script_interpreter.hpp
deleted file mode 100644 (file)
index de86f87..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef __SCRIPT_INTERPRETER_H__
-#define __SCRIPT_INTERPRETER_H__
-
-#include <squirrel.h>
-#include <iostream>
-#include <sstream>
-#include <string>
-#include "timer.hpp"
-#include "game_object.hpp"
-#include "scripting/wrapper.hpp"
-#include "scripting/wrapper_util.hpp"
-#include "scripting/sound.hpp"
-#include "scripting/level.hpp"
-#include "scripting/squirrel_error.hpp"
-#include "scripting/camera.hpp"
-
-class Sector;
-
-class ScriptInterpreter : public GameObject
-{
-public:
-  ScriptInterpreter(const std::string& working_dir);
-  ~ScriptInterpreter();
-
-  void register_sector(Sector* sector);
-
-  void draw(DrawingContext& );
-  void update(float );
-
-  void run_script(std::istream& in, const std::string& sourcename = "",
-          bool remove_when_terminated = true);
-
-  template<typename T>
-  void expose_object(T* object, const std::string& name, bool free = false)
-  {
-    sq_pushroottable(v);
-    sq_pushstring(v, name.c_str(), -1);
-
-    sq_pushroottable(v);
-    Scripting::create_squirrel_instance(v, object, free);
-    sq_remove(v, -2);
-                        
-    // register instance in root table
-    if(sq_createslot(v, -3) < 0) {
-      std::ostringstream msg;
-      msg << "Couldn't register object '" << name << "' in squirrel root table";
-      throw Scripting::SquirrelError(v, msg.str());
-    }
-    
-    sq_pop(v, 1);
-  }
-
-  void set_wakeup_time(float seconds);
-
-  /** helper function that parses a script, starts it and adds it to the sector
-   * specified
-   */
-  static void add_script_object(Sector* sector, const std::string& scriptname,
-      const std::string& script);
-
-  static ScriptInterpreter* current()
-  {
-    return _current;
-  }
-
-  const std::string& get_working_directory() const
-  {
-      return working_directory;
-  }
-
-private:
-  HSQUIRRELVM v;
-  static ScriptInterpreter* _current;
-  Timer wakeup_timer;
-
-  /// this directory is used as base for all filenames used in scripts
-  std::string working_directory;
-  Scripting::Sound* sound;
-  Scripting::Level* level;
-  Scripting::Camera* camera;
-};
-
-#endif
-
index 51aa7b9..ac97f25 100644 (file)
@@ -16,9 +16,10 @@ public:
    */
   void play(const std::string& soundfile);
 
+  ~Sound();
+
 #ifndef SCRIPTING_API
   Sound();
-  ~Sound();
 #endif
 };
 
index 944c7b6..b31ccce 100644 (file)
@@ -25,75 +25,168 @@ static int DisplayEffect_release_hook(SQUserPointer ptr, int )
   return 0;
 }
 
-static int DisplayEffect_fade_out_wrapper(HSQUIRRELVM v)
+static int DisplayEffect_fade_out_wrapper(HSQUIRRELVM vm)
 {
   Scripting::DisplayEffect* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'fade_out' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->fade_out(arg0);
+  try {
+    _this->fade_out(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'fade_out'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int DisplayEffect_fade_in_wrapper(HSQUIRRELVM v)
+static int DisplayEffect_fade_in_wrapper(HSQUIRRELVM vm)
 {
   Scripting::DisplayEffect* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'fade_in' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->fade_in(arg0);
+  try {
+    _this->fade_in(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'fade_in'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int DisplayEffect_set_black_wrapper(HSQUIRRELVM v)
+static int DisplayEffect_set_black_wrapper(HSQUIRRELVM vm)
 {
   Scripting::DisplayEffect* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_black' called without instance"));
+    return SQ_ERROR;
+  }
   SQBool arg0;
-  sq_getbool(v, 2, &arg0);
+  if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a bool"));
+    return SQ_ERROR;
+  }
   
-  _this->set_black(arg0);
+  try {
+    _this->set_black(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_black'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int DisplayEffect_is_black_wrapper(HSQUIRRELVM v)
+static int DisplayEffect_is_black_wrapper(HSQUIRRELVM vm)
 {
   Scripting::DisplayEffect* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'is_black' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    bool return_value = _this->is_black();
   
-  bool return_value = _this->is_black();
+    sq_pushbool(vm, return_value);
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'is_black'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushbool(v, return_value);
-  return 1;
 }
 
-static int DisplayEffect_sixteen_to_nine_wrapper(HSQUIRRELVM v)
+static int DisplayEffect_sixteen_to_nine_wrapper(HSQUIRRELVM vm)
 {
   Scripting::DisplayEffect* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'sixteen_to_nine' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->sixteen_to_nine(arg0);
+  try {
+    _this->sixteen_to_nine(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'sixteen_to_nine'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int DisplayEffect_four_to_three_wrapper(HSQUIRRELVM v)
+static int DisplayEffect_four_to_three_wrapper(HSQUIRRELVM vm)
 {
   Scripting::DisplayEffect* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'four_to_three' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->four_to_three(arg0);
+  try {
+    _this->four_to_three(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'four_to_three'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
 static int Camera_release_hook(SQUserPointer ptr, int )
@@ -103,62 +196,141 @@ static int Camera_release_hook(SQUserPointer ptr, int )
   return 0;
 }
 
-static int Camera_shake_wrapper(HSQUIRRELVM v)
+static int Camera_shake_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Camera* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'shake' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   float arg1;
-  sq_getfloat(v, 3, &arg1);
+  if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 2 not a float"));
+    return SQ_ERROR;
+  }
   float arg2;
-  sq_getfloat(v, 4, &arg2);
+  if(SQ_FAILED(sq_getfloat(vm, 4, &arg2))) {
+    sq_throwerror(vm, _SC("Argument 3 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->shake(arg0, arg1, arg2);
+  try {
+    _this->shake(arg0, arg1, arg2);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'shake'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Camera_set_pos_wrapper(HSQUIRRELVM v)
+static int Camera_set_pos_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Camera* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_pos' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   float arg1;
-  sq_getfloat(v, 3, &arg1);
+  if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 2 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->set_pos(arg0, arg1);
+  try {
+    _this->set_pos(arg0, arg1);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_pos'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Camera_set_mode_wrapper(HSQUIRRELVM v)
+static int Camera_set_mode_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Camera* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_mode' called without instance"));
+    return SQ_ERROR;
+  }
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  _this->set_mode(arg0);
+  try {
+    _this->set_mode(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_mode'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Camera_scroll_to_wrapper(HSQUIRRELVM v)
+static int Camera_scroll_to_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Camera* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'scroll_to' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   float arg1;
-  sq_getfloat(v, 3, &arg1);
+  if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 2 not a float"));
+    return SQ_ERROR;
+  }
   float arg2;
-  sq_getfloat(v, 4, &arg2);
+  if(SQ_FAILED(sq_getfloat(vm, 4, &arg2))) {
+    sq_throwerror(vm, _SC("Argument 3 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->scroll_to(arg0, arg1, arg2);
+  try {
+    _this->scroll_to(arg0, arg1, arg2);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'scroll_to'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
 static int Level_release_hook(SQUserPointer ptr, int )
@@ -168,40 +340,88 @@ static int Level_release_hook(SQUserPointer ptr, int )
   return 0;
 }
 
-static int Level_finish_wrapper(HSQUIRRELVM v)
+static int Level_finish_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Level* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'finish' called without instance"));
+    return SQ_ERROR;
+  }
   SQBool arg0;
-  sq_getbool(v, 2, &arg0);
+  if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a bool"));
+    return SQ_ERROR;
+  }
   
-  _this->finish(arg0);
+  try {
+    _this->finish(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'finish'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Level_spawn_wrapper(HSQUIRRELVM v)
+static int Level_spawn_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Level* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'spawn' called without instance"));
+    return SQ_ERROR;
+  }
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   const char* arg1;
-  sq_getstring(v, 3, &arg1);
+  if(SQ_FAILED(sq_getstring(vm, 3, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 2 not a string"));
+    return SQ_ERROR;
+  }
   
-  _this->spawn(arg0, arg1);
+  try {
+    _this->spawn(arg0, arg1);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'spawn'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Level_flip_vertically_wrapper(HSQUIRRELVM v)
+static int Level_flip_vertically_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Level* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'flip_vertically' called without instance"));
+    return SQ_ERROR;
+  }
   
-  _this->flip_vertically();
+  try {
+    _this->flip_vertically();
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'flip_vertically'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
 static int ScriptedObject_release_hook(SQUserPointer ptr, int )
@@ -211,147 +431,327 @@ static int ScriptedObject_release_hook(SQUserPointer ptr, int )
   return 0;
 }
 
-static int ScriptedObject_set_action_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_set_action_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_action' called without instance"));
+    return SQ_ERROR;
+  }
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  _this->set_action(arg0);
+  try {
+    _this->set_action(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_action'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int ScriptedObject_get_action_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_get_action_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_action' called without instance"));
+    return SQ_ERROR;
+  }
   
-  std::string return_value = _this->get_action();
+  try {
+    std::string return_value = _this->get_action();
+  
+    sq_pushstring(vm, return_value.c_str(), return_value.size());
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_action'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushstring(v, return_value.c_str(), return_value.size());
-  return 1;
 }
 
-static int ScriptedObject_move_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_move_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'move' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   float arg1;
-  sq_getfloat(v, 3, &arg1);
+  if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 2 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->move(arg0, arg1);
+  try {
+    _this->move(arg0, arg1);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'move'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int ScriptedObject_set_pos_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_set_pos_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_pos' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   float arg1;
-  sq_getfloat(v, 3, &arg1);
+  if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 2 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->set_pos(arg0, arg1);
+  try {
+    _this->set_pos(arg0, arg1);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_pos'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int ScriptedObject_get_pos_x_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_get_pos_x_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_pos_x' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    float return_value = _this->get_pos_x();
+  
+    sq_pushfloat(vm, return_value);
+    return 1;
   
-  float return_value = _this->get_pos_x();
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_pos_x'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushfloat(v, return_value);
-  return 1;
 }
 
-static int ScriptedObject_get_pos_y_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_get_pos_y_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_pos_y' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    float return_value = _this->get_pos_y();
+  
+    sq_pushfloat(vm, return_value);
+    return 1;
   
-  float return_value = _this->get_pos_y();
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_pos_y'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushfloat(v, return_value);
-  return 1;
 }
 
-static int ScriptedObject_set_velocity_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_set_velocity_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_velocity' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   float arg1;
-  sq_getfloat(v, 3, &arg1);
+  if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 2 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->set_velocity(arg0, arg1);
+  try {
+    _this->set_velocity(arg0, arg1);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_velocity'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int ScriptedObject_get_velocity_x_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_get_velocity_x_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_velocity_x' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    float return_value = _this->get_velocity_x();
+  
+    sq_pushfloat(vm, return_value);
+    return 1;
   
-  float return_value = _this->get_velocity_x();
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_velocity_x'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushfloat(v, return_value);
-  return 1;
 }
 
-static int ScriptedObject_get_velocity_y_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_get_velocity_y_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_velocity_y' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    float return_value = _this->get_velocity_y();
+  
+    sq_pushfloat(vm, return_value);
+    return 1;
   
-  float return_value = _this->get_velocity_y();
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_velocity_y'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushfloat(v, return_value);
-  return 1;
 }
 
-static int ScriptedObject_set_visible_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_set_visible_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_visible' called without instance"));
+    return SQ_ERROR;
+  }
   SQBool arg0;
-  sq_getbool(v, 2, &arg0);
+  if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a bool"));
+    return SQ_ERROR;
+  }
   
-  _this->set_visible(arg0);
+  try {
+    _this->set_visible(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_visible'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int ScriptedObject_is_visible_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_is_visible_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'is_visible' called without instance"));
+    return SQ_ERROR;
+  }
   
-  bool return_value = _this->is_visible();
+  try {
+    bool return_value = _this->is_visible();
+  
+    sq_pushbool(vm, return_value);
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'is_visible'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushbool(v, return_value);
-  return 1;
 }
 
-static int ScriptedObject_get_name_wrapper(HSQUIRRELVM v)
+static int ScriptedObject_get_name_wrapper(HSQUIRRELVM vm)
 {
   Scripting::ScriptedObject* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_name' called without instance"));
+    return SQ_ERROR;
+  }
   
-  std::string return_value = _this->get_name();
+  try {
+    std::string return_value = _this->get_name();
+  
+    sq_pushstring(vm, return_value.c_str(), return_value.size());
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_name'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushstring(v, return_value.c_str(), return_value.size());
-  return 1;
 }
 
 static int Sound_release_hook(SQUserPointer ptr, int )
@@ -361,28 +761,60 @@ static int Sound_release_hook(SQUserPointer ptr, int )
   return 0;
 }
 
-static int Sound_play_music_wrapper(HSQUIRRELVM v)
+static int Sound_play_music_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Sound* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'play_music' called without instance"));
+    return SQ_ERROR;
+  }
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  _this->play_music(arg0);
+  try {
+    _this->play_music(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'play_music'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Sound_play_wrapper(HSQUIRRELVM v)
+static int Sound_play_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Sound* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'play' called without instance"));
+    return SQ_ERROR;
+  }
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  _this->play(arg0);
+  try {
+    _this->play(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'play'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
 static int Text_release_hook(SQUserPointer ptr, int )
@@ -392,76 +824,172 @@ static int Text_release_hook(SQUserPointer ptr, int )
   return 0;
 }
 
-static int Text_set_text_wrapper(HSQUIRRELVM v)
+static int Text_set_text_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Text* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_text' called without instance"));
+    return SQ_ERROR;
+  }
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  _this->set_text(arg0);
+  try {
+    _this->set_text(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_text'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Text_set_font_wrapper(HSQUIRRELVM v)
+static int Text_set_font_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Text* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_font' called without instance"));
+    return SQ_ERROR;
+  }
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  _this->set_font(arg0);
+  try {
+    _this->set_font(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_font'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Text_fade_in_wrapper(HSQUIRRELVM v)
+static int Text_fade_in_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Text* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'fade_in' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->fade_in(arg0);
+  try {
+    _this->fade_in(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'fade_in'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Text_fade_out_wrapper(HSQUIRRELVM v)
+static int Text_fade_out_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Text* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'fade_out' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->fade_out(arg0);
+  try {
+    _this->fade_out(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'fade_out'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Text_set_visible_wrapper(HSQUIRRELVM v)
+static int Text_set_visible_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Text* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_visible' called without instance"));
+    return SQ_ERROR;
+  }
   SQBool arg0;
-  sq_getbool(v, 2, &arg0);
+  if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a bool"));
+    return SQ_ERROR;
+  }
   
-  _this->set_visible(arg0);
+  try {
+    _this->set_visible(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_visible'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Text_set_centered_wrapper(HSQUIRRELVM v)
+static int Text_set_centered_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Text* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_centered' called without instance"));
+    return SQ_ERROR;
+  }
   SQBool arg0;
-  sq_getbool(v, 2, &arg0);
+  if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a bool"));
+    return SQ_ERROR;
+  }
   
-  _this->set_centered(arg0);
+  try {
+    _this->set_centered(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_centered'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
 static int Player_release_hook(SQUserPointer ptr, int )
@@ -471,69 +999,153 @@ static int Player_release_hook(SQUserPointer ptr, int )
   return 0;
 }
 
-static int Player_make_invincible_wrapper(HSQUIRRELVM v)
+static int Player_make_invincible_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Player* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'make_invincible' called without instance"));
+    return SQ_ERROR;
+  }
   
-  _this->make_invincible();
+  try {
+    _this->make_invincible();
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'make_invincible'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Player_deactivate_wrapper(HSQUIRRELVM v)
+static int Player_deactivate_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Player* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'deactivate' called without instance"));
+    return SQ_ERROR;
+  }
   
-  _this->deactivate();
+  try {
+    _this->deactivate();
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'deactivate'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Player_activate_wrapper(HSQUIRRELVM v)
+static int Player_activate_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Player* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'activate' called without instance"));
+    return SQ_ERROR;
+  }
   
-  _this->activate();
+  try {
+    _this->activate();
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'activate'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Player_walk_wrapper(HSQUIRRELVM v)
+static int Player_walk_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Player* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'walk' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->walk(arg0);
+  try {
+    _this->walk(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'walk'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Player_set_visible_wrapper(HSQUIRRELVM v)
+static int Player_set_visible_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Player* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_visible' called without instance"));
+    return SQ_ERROR;
+  }
   SQBool arg0;
-  sq_getbool(v, 2, &arg0);
+  if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a bool"));
+    return SQ_ERROR;
+  }
   
-  _this->set_visible(arg0);
+  try {
+    _this->set_visible(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_visible'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int Player_get_visible_wrapper(HSQUIRRELVM v)
+static int Player_get_visible_wrapper(HSQUIRRELVM vm)
 {
   Scripting::Player* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_visible' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    bool return_value = _this->get_visible();
+  
+    sq_pushbool(vm, return_value);
+    return 1;
   
-  bool return_value = _this->get_visible();
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_visible'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushbool(v, return_value);
-  return 1;
 }
 
 static int FloatingImage_release_hook(SQUserPointer ptr, int )
@@ -543,173 +1155,457 @@ static int FloatingImage_release_hook(SQUserPointer ptr, int )
   return 0;
 }
 
-static int FloatingImage_constructor_wrapper(HSQUIRRELVM v)
+static int FloatingImage_constructor_wrapper(HSQUIRRELVM vm)
 {
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  Scripting::FloatingImage* _this = new Scripting::FloatingImage(arg0);
-  sq_setinstanceup(v, 1, _this);
-  sq_setreleasehook(v, 1, FloatingImage_release_hook);
+  try {
+    Scripting::FloatingImage* _this = new Scripting::FloatingImage(arg0);
+  if(SQ_FAILED(sq_setinstanceup(vm, 1, _this))) {
+    sq_throwerror(vm, _SC("Couldn't setup instance of 'FloatingImage' class"));
+    return SQ_ERROR;
+  }
+  sq_setreleasehook(vm, 1, FloatingImage_release_hook);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'constructor'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int FloatingImage_set_layer_wrapper(HSQUIRRELVM v)
+static int FloatingImage_set_layer_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_layer' called without instance"));
+    return SQ_ERROR;
+  }
   int arg0;
-  sq_getinteger(v, 2, &arg0);
+  if(SQ_FAILED(sq_getinteger(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not an integer"));
+    return SQ_ERROR;
+  }
   
-  _this->set_layer(arg0);
+  try {
+    _this->set_layer(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_layer'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int FloatingImage_get_layer_wrapper(HSQUIRRELVM v)
+static int FloatingImage_get_layer_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_layer' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    int return_value = _this->get_layer();
   
-  int return_value = _this->get_layer();
+    sq_pushinteger(vm, return_value);
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_layer'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushinteger(v, return_value);
-  return 1;
 }
 
-static int FloatingImage_set_pos_wrapper(HSQUIRRELVM v)
+static int FloatingImage_set_pos_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_pos' called without instance"));
+    return SQ_ERROR;
+  }
   float arg0;
-  sq_getfloat(v, 2, &arg0);
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
   float arg1;
-  sq_getfloat(v, 3, &arg1);
+  if(SQ_FAILED(sq_getfloat(vm, 3, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 2 not a float"));
+    return SQ_ERROR;
+  }
   
-  _this->set_pos(arg0, arg1);
+  try {
+    _this->set_pos(arg0, arg1);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_pos'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int FloatingImage_get_pos_x_wrapper(HSQUIRRELVM v)
+static int FloatingImage_get_pos_x_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_pos_x' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    float return_value = _this->get_pos_x();
   
-  float return_value = _this->get_pos_x();
+    sq_pushfloat(vm, return_value);
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_pos_x'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushfloat(v, return_value);
-  return 1;
 }
 
-static int FloatingImage_get_pos_y_wrapper(HSQUIRRELVM v)
+static int FloatingImage_get_pos_y_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_pos_y' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    float return_value = _this->get_pos_y();
   
-  float return_value = _this->get_pos_y();
+    sq_pushfloat(vm, return_value);
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_pos_y'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushfloat(v, return_value);
-  return 1;
 }
 
-static int FloatingImage_set_anchor_point_wrapper(HSQUIRRELVM v)
+static int FloatingImage_set_anchor_point_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_anchor_point' called without instance"));
+    return SQ_ERROR;
+  }
   int arg0;
-  sq_getinteger(v, 2, &arg0);
+  if(SQ_FAILED(sq_getinteger(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not an integer"));
+    return SQ_ERROR;
+  }
   
-  _this->set_anchor_point(arg0);
+  try {
+    _this->set_anchor_point(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_anchor_point'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int FloatingImage_get_anchor_point_wrapper(HSQUIRRELVM v)
+static int FloatingImage_get_anchor_point_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_anchor_point' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    int return_value = _this->get_anchor_point();
   
-  int return_value = _this->get_anchor_point();
+    sq_pushinteger(vm, return_value);
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_anchor_point'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushinteger(v, return_value);
-  return 1;
 }
 
-static int FloatingImage_set_visible_wrapper(HSQUIRRELVM v)
+static int FloatingImage_set_visible_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'set_visible' called without instance"));
+    return SQ_ERROR;
+  }
   SQBool arg0;
-  sq_getbool(v, 2, &arg0);
+  if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a bool"));
+    return SQ_ERROR;
+  }
   
-  _this->set_visible(arg0);
+  try {
+    _this->set_visible(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'set_visible'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int FloatingImage_get_visible_wrapper(HSQUIRRELVM v)
+static int FloatingImage_get_visible_wrapper(HSQUIRRELVM vm)
 {
   Scripting::FloatingImage* _this;
-  sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {
+    sq_throwerror(vm, _SC("'get_visible' called without instance"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    bool return_value = _this->get_visible();
   
-  bool return_value = _this->get_visible();
+    sq_pushbool(vm, return_value);
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_visible'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushbool(v, return_value);
-  return 1;
 }
 
-static int display_text_file_wrapper(HSQUIRRELVM v)
+static int display_wrapper(HSQUIRRELVM vm)
+{
+  return Scripting::display(vm);
+}
+
+static int display_text_file_wrapper(HSQUIRRELVM vm)
 {
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  Scripting::display_text_file(arg0);
+  try {
+    Scripting::display_text_file(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'display_text_file'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int wait_wrapper(HSQUIRRELVM v)
+static int load_worldmap_wrapper(HSQUIRRELVM vm)
 {
-  float arg0;
-  sq_getfloat(v, 2, &arg0);
+  const char* arg0;
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    Scripting::load_worldmap(arg0);
+  
+    return 0;
   
-  Scripting::wait(arg0);
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'load_worldmap'"));
+    return SQ_ERROR;
+  }
   
-  return sq_suspendvm(v);
 }
 
-static int translate_wrapper(HSQUIRRELVM v)
+static int load_level_wrapper(HSQUIRRELVM vm)
 {
   const char* arg0;
-  sq_getstring(v, 2, &arg0);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    Scripting::load_level(arg0);
+  
+    return 0;
   
-  std::string return_value = Scripting::translate(arg0);
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'load_level'"));
+    return SQ_ERROR;
+  }
+  
+}
+
+static int wait_wrapper(HSQUIRRELVM vm)
+{
+  HSQUIRRELVM arg0 = vm;
+  float arg1;
+  if(SQ_FAILED(sq_getfloat(vm, 2, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 1 not a float"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    Scripting::wait(arg0, arg1);
+  
+    return sq_suspendvm(vm);
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'wait'"));
+    return SQ_ERROR;
+  }
+  
+}
+
+static int wait_for_screenswitch_wrapper(HSQUIRRELVM vm)
+{
+  HSQUIRRELVM arg0 = vm;
+  
+  try {
+    Scripting::wait_for_screenswitch(arg0);
+  
+    return sq_suspendvm(vm);
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'wait_for_screenswitch'"));
+    return SQ_ERROR;
+  }
   
-  sq_pushstring(v, return_value.c_str(), return_value.size());
-  return 1;
 }
 
-static int import_wrapper(HSQUIRRELVM v)
+static int translate_wrapper(HSQUIRRELVM vm)
 {
-  HSQUIRRELVM arg0 = v;
+  const char* arg0;
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
+  
+  try {
+    std::string return_value = Scripting::translate(arg0);
+  
+    sq_pushstring(vm, return_value.c_str(), return_value.size());
+    return 1;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'translate'"));
+    return SQ_ERROR;
+  }
+  
+}
+
+static int import_wrapper(HSQUIRRELVM vm)
+{
+  HSQUIRRELVM arg0 = vm;
   const char* arg1;
-  sq_getstring(v, 2, &arg1);
+  if(SQ_FAILED(sq_getstring(vm, 2, &arg1))) {
+    sq_throwerror(vm, _SC("Argument 1 not a string"));
+    return SQ_ERROR;
+  }
   
-  Scripting::import(arg0, arg1);
+  try {
+    Scripting::import(arg0, arg1);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'import'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
-static int add_key_wrapper(HSQUIRRELVM v)
+static int add_key_wrapper(HSQUIRRELVM vm)
 {
   int arg0;
-  sq_getinteger(v, 2, &arg0);
+  if(SQ_FAILED(sq_getinteger(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not an integer"));
+    return SQ_ERROR;
+  }
   
-  Scripting::add_key(arg0);
+  try {
+    Scripting::add_key(arg0);
+  
+    return 0;
+  
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'add_key'"));
+    return SQ_ERROR;
+  }
   
-  return 0;
 }
 
 } // end of namespace Wrapper
@@ -930,153 +1826,139 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "KEY_BRASS", -1);
   sq_pushinteger(v, 1);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'KEY_BRASS'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'KEY_BRASS'");
   }
 
   sq_pushstring(v, "KEY_IRON", -1);
   sq_pushinteger(v, 2);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'KEY_IRON'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'KEY_IRON'");
   }
 
   sq_pushstring(v, "KEY_BRONZE", -1);
   sq_pushinteger(v, 4);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'KEY_BRONZE'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'KEY_BRONZE'");
   }
 
   sq_pushstring(v, "KEY_SILVER", -1);
   sq_pushinteger(v, 8);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'KEY_SILVER'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'KEY_SILVER'");
   }
 
   sq_pushstring(v, "KEY_GOLD", -1);
   sq_pushinteger(v, 16);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'KEY_GOLD'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'KEY_GOLD'");
   }
 
   sq_pushstring(v, "ANCHOR_TOP", -1);
   sq_pushinteger(v, 16);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_TOP'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP'");
   }
 
   sq_pushstring(v, "ANCHOR_BOTTOM", -1);
   sq_pushinteger(v, 32);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_BOTTOM'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM'");
   }
 
   sq_pushstring(v, "ANCHOR_LEFT", -1);
   sq_pushinteger(v, 1);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_LEFT'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_LEFT'");
   }
 
   sq_pushstring(v, "ANCHOR_RIGHT", -1);
   sq_pushinteger(v, 2);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_RIGHT'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_RIGHT'");
   }
 
   sq_pushstring(v, "ANCHOR_MIDDLE", -1);
   sq_pushinteger(v, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_MIDDLE'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_MIDDLE'");
   }
 
   sq_pushstring(v, "ANCHOR_TOP_LEFT", -1);
   sq_pushinteger(v, 17);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_TOP_LEFT'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP_LEFT'");
   }
 
   sq_pushstring(v, "ANCHOR_TOP_RIGHT", -1);
   sq_pushinteger(v, 18);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_TOP_RIGHT'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP_RIGHT'");
   }
 
   sq_pushstring(v, "ANCHOR_BOTTOM_LEFT", -1);
   sq_pushinteger(v, 33);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_BOTTOM_LEFT'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM_LEFT'");
   }
 
   sq_pushstring(v, "ANCHOR_BOTTOM_RIGHT", -1);
   sq_pushinteger(v, 34);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register constant'ANCHOR_BOTTOM_RIGHT'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM_RIGHT'");
+  }
+
+  sq_pushstring(v, "display", -1);
+  sq_newclosure(v, &display_wrapper, 0);
+  if(SQ_FAILED(sq_createslot(v, -3))) {
+    throw SquirrelError(v, "Couldn't register function 'display'");
   }
 
   sq_pushstring(v, "display_text_file", -1);
   sq_newclosure(v, &display_text_file_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'display_text_file'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'display_text_file'");
+  }
+
+  sq_pushstring(v, "load_worldmap", -1);
+  sq_newclosure(v, &load_worldmap_wrapper, 0);
+  if(SQ_FAILED(sq_createslot(v, -3))) {
+    throw SquirrelError(v, "Couldn't register function 'load_worldmap'");
+  }
+
+  sq_pushstring(v, "load_level", -1);
+  sq_newclosure(v, &load_level_wrapper, 0);
+  if(SQ_FAILED(sq_createslot(v, -3))) {
+    throw SquirrelError(v, "Couldn't register function 'load_level'");
   }
 
   sq_pushstring(v, "wait", -1);
   sq_newclosure(v, &wait_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'wait'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'wait'");
+  }
+
+  sq_pushstring(v, "wait_for_screenswitch", -1);
+  sq_newclosure(v, &wait_for_screenswitch_wrapper, 0);
+  if(SQ_FAILED(sq_createslot(v, -3))) {
+    throw SquirrelError(v, "Couldn't register function 'wait_for_screenswitch'");
   }
 
   sq_pushstring(v, "translate", -1);
   sq_newclosure(v, &translate_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'translate'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'translate'");
   }
 
   sq_pushstring(v, "import", -1);
   sq_newclosure(v, &import_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'import'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'import'");
   }
 
   sq_pushstring(v, "add_key", -1);
   sq_newclosure(v, &add_key_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'add_key'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'add_key'");
   }
 
   // Register class DisplayEffect
@@ -1089,55 +1971,41 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "fade_out", -1);
   sq_newclosure(v, &DisplayEffect_fade_out_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'fade_out'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'fade_out'");
   }
 
   sq_pushstring(v, "fade_in", -1);
   sq_newclosure(v, &DisplayEffect_fade_in_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'fade_in'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'fade_in'");
   }
 
   sq_pushstring(v, "set_black", -1);
   sq_newclosure(v, &DisplayEffect_set_black_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_black'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_black'");
   }
 
   sq_pushstring(v, "is_black", -1);
   sq_newclosure(v, &DisplayEffect_is_black_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'is_black'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'is_black'");
   }
 
   sq_pushstring(v, "sixteen_to_nine", -1);
   sq_newclosure(v, &DisplayEffect_sixteen_to_nine_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'sixteen_to_nine'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'sixteen_to_nine'");
   }
 
   sq_pushstring(v, "four_to_three", -1);
   sq_newclosure(v, &DisplayEffect_four_to_three_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'four_to_three'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'four_to_three'");
   }
 
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register class'DisplayEffect'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register class 'DisplayEffect'");
   }
 
   // Register class Camera
@@ -1150,39 +2018,29 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "shake", -1);
   sq_newclosure(v, &Camera_shake_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'shake'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'shake'");
   }
 
   sq_pushstring(v, "set_pos", -1);
   sq_newclosure(v, &Camera_set_pos_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_pos'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_pos'");
   }
 
   sq_pushstring(v, "set_mode", -1);
   sq_newclosure(v, &Camera_set_mode_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_mode'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_mode'");
   }
 
   sq_pushstring(v, "scroll_to", -1);
   sq_newclosure(v, &Camera_scroll_to_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'scroll_to'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'scroll_to'");
   }
 
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register class'Camera'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register class 'Camera'");
   }
 
   // Register class Level
@@ -1195,31 +2053,23 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "finish", -1);
   sq_newclosure(v, &Level_finish_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'finish'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'finish'");
   }
 
   sq_pushstring(v, "spawn", -1);
   sq_newclosure(v, &Level_spawn_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'spawn'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'spawn'");
   }
 
   sq_pushstring(v, "flip_vertically", -1);
   sq_newclosure(v, &Level_flip_vertically_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'flip_vertically'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'flip_vertically'");
   }
 
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register class'Level'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register class 'Level'");
   }
 
   // Register class ScriptedObject
@@ -1232,103 +2082,77 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "set_action", -1);
   sq_newclosure(v, &ScriptedObject_set_action_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_action'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_action'");
   }
 
   sq_pushstring(v, "get_action", -1);
   sq_newclosure(v, &ScriptedObject_get_action_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_action'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_action'");
   }
 
   sq_pushstring(v, "move", -1);
   sq_newclosure(v, &ScriptedObject_move_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'move'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'move'");
   }
 
   sq_pushstring(v, "set_pos", -1);
   sq_newclosure(v, &ScriptedObject_set_pos_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_pos'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_pos'");
   }
 
   sq_pushstring(v, "get_pos_x", -1);
   sq_newclosure(v, &ScriptedObject_get_pos_x_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_pos_x'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_pos_x'");
   }
 
   sq_pushstring(v, "get_pos_y", -1);
   sq_newclosure(v, &ScriptedObject_get_pos_y_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_pos_y'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_pos_y'");
   }
 
   sq_pushstring(v, "set_velocity", -1);
   sq_newclosure(v, &ScriptedObject_set_velocity_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_velocity'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_velocity'");
   }
 
   sq_pushstring(v, "get_velocity_x", -1);
   sq_newclosure(v, &ScriptedObject_get_velocity_x_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_velocity_x'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_velocity_x'");
   }
 
   sq_pushstring(v, "get_velocity_y", -1);
   sq_newclosure(v, &ScriptedObject_get_velocity_y_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_velocity_y'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_velocity_y'");
   }
 
   sq_pushstring(v, "set_visible", -1);
   sq_newclosure(v, &ScriptedObject_set_visible_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_visible'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_visible'");
   }
 
   sq_pushstring(v, "is_visible", -1);
   sq_newclosure(v, &ScriptedObject_is_visible_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'is_visible'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'is_visible'");
   }
 
   sq_pushstring(v, "get_name", -1);
   sq_newclosure(v, &ScriptedObject_get_name_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_name'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_name'");
   }
 
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register class'ScriptedObject'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register class 'ScriptedObject'");
   }
 
   // Register class Sound
@@ -1341,23 +2165,17 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "play_music", -1);
   sq_newclosure(v, &Sound_play_music_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'play_music'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'play_music'");
   }
 
   sq_pushstring(v, "play", -1);
   sq_newclosure(v, &Sound_play_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'play'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'play'");
   }
 
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register class'Sound'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register class 'Sound'");
   }
 
   // Register class Text
@@ -1370,55 +2188,41 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "set_text", -1);
   sq_newclosure(v, &Text_set_text_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_text'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_text'");
   }
 
   sq_pushstring(v, "set_font", -1);
   sq_newclosure(v, &Text_set_font_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_font'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_font'");
   }
 
   sq_pushstring(v, "fade_in", -1);
   sq_newclosure(v, &Text_fade_in_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'fade_in'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'fade_in'");
   }
 
   sq_pushstring(v, "fade_out", -1);
   sq_newclosure(v, &Text_fade_out_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'fade_out'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'fade_out'");
   }
 
   sq_pushstring(v, "set_visible", -1);
   sq_newclosure(v, &Text_set_visible_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_visible'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_visible'");
   }
 
   sq_pushstring(v, "set_centered", -1);
   sq_newclosure(v, &Text_set_centered_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_centered'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_centered'");
   }
 
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register class'Text'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register class 'Text'");
   }
 
   // Register class Player
@@ -1431,55 +2235,41 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "make_invincible", -1);
   sq_newclosure(v, &Player_make_invincible_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'make_invincible'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'make_invincible'");
   }
 
   sq_pushstring(v, "deactivate", -1);
   sq_newclosure(v, &Player_deactivate_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'deactivate'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'deactivate'");
   }
 
   sq_pushstring(v, "activate", -1);
   sq_newclosure(v, &Player_activate_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'activate'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'activate'");
   }
 
   sq_pushstring(v, "walk", -1);
   sq_newclosure(v, &Player_walk_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'walk'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'walk'");
   }
 
   sq_pushstring(v, "set_visible", -1);
   sq_newclosure(v, &Player_set_visible_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_visible'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_visible'");
   }
 
   sq_pushstring(v, "get_visible", -1);
   sq_newclosure(v, &Player_get_visible_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_visible'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_visible'");
   }
 
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register class'Player'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register class 'Player'");
   }
 
   // Register class FloatingImage
@@ -1492,87 +2282,65 @@ void register_supertux_wrapper(HSQUIRRELVM v)
   sq_pushstring(v, "constructor", -1);
   sq_newclosure(v, &FloatingImage_constructor_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'constructor'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'constructor'");
   }
 
   sq_pushstring(v, "set_layer", -1);
   sq_newclosure(v, &FloatingImage_set_layer_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_layer'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_layer'");
   }
 
   sq_pushstring(v, "get_layer", -1);
   sq_newclosure(v, &FloatingImage_get_layer_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_layer'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_layer'");
   }
 
   sq_pushstring(v, "set_pos", -1);
   sq_newclosure(v, &FloatingImage_set_pos_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_pos'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_pos'");
   }
 
   sq_pushstring(v, "get_pos_x", -1);
   sq_newclosure(v, &FloatingImage_get_pos_x_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_pos_x'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_pos_x'");
   }
 
   sq_pushstring(v, "get_pos_y", -1);
   sq_newclosure(v, &FloatingImage_get_pos_y_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_pos_y'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_pos_y'");
   }
 
   sq_pushstring(v, "set_anchor_point", -1);
   sq_newclosure(v, &FloatingImage_set_anchor_point_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_anchor_point'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_anchor_point'");
   }
 
   sq_pushstring(v, "get_anchor_point", -1);
   sq_newclosure(v, &FloatingImage_get_anchor_point_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_anchor_point'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_anchor_point'");
   }
 
   sq_pushstring(v, "set_visible", -1);
   sq_newclosure(v, &FloatingImage_set_visible_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'set_visible'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'set_visible'");
   }
 
   sq_pushstring(v, "get_visible", -1);
   sq_newclosure(v, &FloatingImage_get_visible_wrapper, 0);
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register function'get_visible'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register function 'get_visible'");
   }
 
   if(SQ_FAILED(sq_createslot(v, -3))) {
-    std::ostringstream msg;
-    msg << "Couldn't register class'FloatingImage'";
-    throw SquirrelError(v, msg.str());
+    throw SquirrelError(v, "Couldn't register class 'FloatingImage'");
   }
 
   sq_pop(v, 1);
index 68a98a1..823db49 100644 (file)
@@ -1,4 +1,4 @@
-/* This file is processes by miniswig to produce the scripting API */
+/* This file is processed by miniswig to produce the scripting API */
 #include "display_effect.hpp"
 #include "camera.hpp"
 #include "level.hpp"
index 605ff1b..2244a8d 100644 (file)
@@ -1,9 +1,31 @@
+//  $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
+// 
+//  SuperTux
+//  Copyright (C) 2005 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
+//  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 <stdexcept>
 #include <sstream>
 #include "wrapper_util.hpp"
 
+namespace Scripting
+{
+
 std::string squirrel2string(HSQUIRRELVM v, int i)
 {
   std::ostringstream os;
@@ -180,4 +202,37 @@ void print_squirrel_stack(HSQUIRRELVM v)
     printf("--------------------------------------------------------------\n");
 }
 
-/* EOF */
+static SQInteger squirrel_read_char(SQUserPointer file)
+{
+  std::istream* in = reinterpret_cast<std::istream*> (file);
+  char c = in->get();
+  if(in->eof())
+    return 0;
+  return c;
+}
+
+void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename)
+{
+  if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, sourcename.c_str(), true)))
+    throw SquirrelError(vm, "Couldn't parse script");  
+}
+
+void compile_and_run(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename)
+{
+  compile_script(vm, in, sourcename);
+  
+  int oldtop = sq_gettop(vm);
+
+  try {
+    sq_pushroottable(vm);
+    if(SQ_FAILED(sq_call(vm, 1, false)))
+      throw SquirrelError(vm, "Couldn't start script");
+  } catch(...) {
+    sq_settop(vm, oldtop);
+    throw;
+  }
+
+  sq_settop(vm, oldtop);
+}
+
+}
index a6cfa23..f183086 100644 (file)
@@ -1,11 +1,72 @@
+//  $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
+// 
+//  SuperTux
+//  Copyright (C) 2005 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
+//  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 __WRAPPERUTIL_HPP__
 #define __WRAPPERUTIL_HPP__
 
 #include <squirrel.h>
 #include <sstream>
+#include <stdexcept>
 #include <string>
+#include "wrapper.hpp"
+#include "squirrel_error.hpp"
 
-std::string squirrel2string(HSQUIRRELVM v, int i);
-void print_squirrel_stack(HSQUIRRELVM v);
+namespace Scripting
+{
+
+std::string squirrel2string(HSQUIRRELVM vm, int i);
+void print_squirrel_stack(HSQUIRRELVM vm);
+void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename);
+void compile_and_run(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename);
+
+template<typename T>
+void expose_object(HSQUIRRELVM v, int table_idx, T* object,
+                   const std::string& name, bool free = false)
+{
+  sq_pushstring(v, name.c_str(), -1);
+  Scripting::create_squirrel_instance(v, object, free);
+
+  if(table_idx < 0)
+    table_idx -= 2;
+
+  // register instance in root table
+  if(SQ_FAILED(sq_createslot(v, table_idx))) {
+    std::ostringstream msg;
+    msg << "Couldn't register object '" << name << "' in squirrel table";
+    throw Scripting::SquirrelError(v, msg.str());
+  }
+}
+
+static inline void unexpose_object(HSQUIRRELVM v, int table_idx, const std::string& name)
+{
+  sq_pushstring(v, name.c_str(), name.length());
+  
+  if(table_idx < 0)
+    table_idx -= 1;
+  
+  if(SQ_FAILED(sq_deleteslot(v, table_idx, SQFalse))) {
+    std::ostringstream msg;
+    msg << "Couldn't unregister object '" << name << "' in squirrel root table";
+    throw Scripting::SquirrelError(v, msg.str());
+  }
+}
+
+}
 
 #endif
index 3b1926f..a710145 100644 (file)
 #include "badguy/jumpy.hpp"
 #include "trigger/sequence_trigger.hpp"
 #include "player_status.hpp"
-#include "scripting/script_interpreter.hpp"
-#include "scripting/sound.hpp"
-#include "scripting/scripted_object.hpp"
-#include "scripting/text.hpp"
+#include "script_manager.hpp"
+#include "scripting/wrapper_util.hpp"
+#include "script_interface.hpp"
 #include "msg.hpp"
 
 Sector* Sector::_current = 0;
 
 Sector::Sector()
-  : gravity(10), player(0), solids(0), camera(0),
-    currentmusic(LEVEL_MUSIC)
+  : currentmusic(LEVEL_MUSIC), gravity(10),
+    player(0), solids(0), camera(0)
 {
-  player = new Player(player_status);
-  add_object(player);
+  add_object(new Player(player_status));
+  add_object(new DisplayEffect());
+  add_object(new TextObject());
 
 #ifdef USE_GRID
   grid = new CollisionGrid(32000, 32000);
 #else
   grid = 0;
 #endif
+
+  // create a new squirrel table for the sector
+  HSQUIRRELVM vm = script_manager->get_global_vm();
+  
+  sq_newtable(vm);
+  sq_pushroottable(vm);
+  if(SQ_FAILED(sq_setdelegate(vm, -2)))
+    throw Scripting::SquirrelError(vm, "Couldn't set sector_table delegate");
+
+  sq_resetobject(&sector_table);
+  if(SQ_FAILED(sq_getstackobj(vm, -1, &sector_table)))
+    throw Scripting::SquirrelError(vm, "Couldn't get sector table");
+  sq_addref(vm, &sector_table);
+  sq_pop(vm, 1);
 }
 
 Sector::~Sector()
@@ -87,19 +101,21 @@ Sector::~Sector()
   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);
     delete *i;
   }
 
   for(SpawnPoints::iterator i = spawnpoints.begin(); i != spawnpoints.end();
       ++i)
     delete *i;
-    
-  if(_current == this)
-    _current = 0;
+
+  sq_release(script_manager->get_global_vm(), &sector_table);
 }
 
 GameObject*
@@ -144,9 +160,7 @@ Sector::parse_object(const std::string& name, const lisp::Lisp& reader)
 
 void
 Sector::parse(const lisp::Lisp& sector)
-{
-  _current = this;
-  
+{  
   lisp::ListIterator iter(&sector);
   while(iter.next()) {
     const std::string& token = iter.item();
@@ -187,8 +201,6 @@ Sector::parse(const lisp::Lisp& sector)
 void
 Sector::parse_old_format(const lisp::Lisp& reader)
 {
-  _current = this;
-  
   name = "main";
   reader.get("gravity", gravity);
 
@@ -375,6 +387,17 @@ Sector::write(lisp::Writer& writer)
   }
 }
 
+HSQUIRRELVM
+Sector::run_script(std::istream& in, const std::string& sourcename)
+{
+  HSQUIRRELVM vm = script_manager->create_thread();
+  sq_pushobject(vm, sector_table);
+  sq_setroottable(vm);
+  Scripting::compile_and_run(vm, in, sourcename);
+
+  return vm;
+}
+
 void
 Sector::add_object(GameObject* object)
 {
@@ -418,21 +441,64 @@ Sector::activate(const std::string& spawnpoint)
   } else {
     activate(sp->pos);
   }
+}
+
+void
+Sector::activate(const Vector& player_pos)
+{
+  if(_current != this) {
+    if(_current != NULL)
+      _current->deactivate();
+    _current = this;
+
+    // register sectortable as current_sector in scripting
+    HSQUIRRELVM vm = script_manager->get_global_vm();
+    sq_pushroottable(vm);
+    sq_pushstring(vm, "current_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");
+    sq_pop(vm, 1);
+
+    for(GameObjects::iterator i = gameobjects.begin();
+        i != gameobjects.end(); ++i) {
+      GameObject* object = *i;
+
+      try_expose(object);
+    }
+  }
+
+  player->move(player_pos);
+  camera->reset(player->get_pos());
 
   // Run init script
   if(init_script != "") {
-    ScriptInterpreter::add_script_object(this,
-        std::string("Sector(") + name + ") - init", init_script);
+    std::istringstream in(init_script);
+    run_script(in, std::string("Sector(") + name + ") - init");
   }
 }
 
 void
-Sector::activate(const Vector& player_pos)
+Sector::deactivate()
 {
-  _current = this;
+  if(_current != this)
+    return;
+
+  HSQUIRRELVM vm = script_manager->get_global_vm();
+  sq_pushroottable(vm);
+  sq_pushstring(vm, "current_sector", -1);
+  if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse)))
+    throw Scripting::SquirrelError(vm, "Couldn't unset current_sector in roottable");
+  sq_pop(vm, 1);
+  
+  for(GameObjects::iterator i = gameobjects.begin();
+      i != gameobjects.end(); ++i) {
+    GameObject* object = *i;
+    
+    try_unexpose(object);
+  }
 
-  player->move(player_pos);
-  camera->reset(player->get_pos());
+  _current = NULL;
 }
 
 Rect
@@ -509,6 +575,8 @@ Sector::update_game_objects()
       ++i;
       continue;
     }
+
+    before_object_remove(object);
     
     delete *i;
     i = gameobjects.erase(i);
@@ -519,43 +587,95 @@ Sector::update_game_objects()
       i != gameobjects_new.end(); ++i)
   {
     GameObject* object = *i;
+
+    before_object_add(object);
     
-    Bullet* bullet = dynamic_cast<Bullet*> (object);
-    if(bullet)
-      bullets.push_back(bullet);
-
-    MovingObject* movingobject = dynamic_cast<MovingObject*> (object);
-    if(movingobject) {
-      moving_objects.push_back(movingobject);
- #ifdef USE_GRID
-      grid->add_object(movingobject);
+    gameobjects.push_back(object);
+  }
+  gameobjects_new.clear();
+}
+
+bool
+Sector::before_object_add(GameObject* object)
+{
+  Bullet* bullet = dynamic_cast<Bullet*> (object);
+  if(bullet)
+    bullets.push_back(bullet);
+
+  MovingObject* movingobject = dynamic_cast<MovingObject*> (object);
+  if(movingobject) {
+    moving_objects.push_back(movingobject);
+#ifdef USE_GRID
+    grid->add_object(movingobject);
 #endif
+  }
+  
+  TileMap* tilemap = dynamic_cast<TileMap*> (object);
+  if(tilemap && tilemap->is_solid()) {
+    if(solids == 0) {
+      solids = tilemap;
+    } else {
+      msg_warning << "Another solid tilemaps added. Ignoring" << std::endl;
     }
-    
-    TileMap* tilemap = dynamic_cast<TileMap*> (object);
-    if(tilemap && tilemap->is_solid()) {
-      if(solids == 0) {
-        solids = tilemap;
-      } else {
-        msg_warning << "Another solid tilemaps added. Ignoring" << std::endl;
-      }
+  }
+
+  Camera* camera = dynamic_cast<Camera*> (object);
+  if(camera) {
+    if(this->camera != 0) {
+      msg_warning << "Multiple cameras added. Ignoring" << std::endl;
+      return false;
     }
+    this->camera = camera;
+  }
 
-    Camera* camera = dynamic_cast<Camera*> (object);
-    if(camera) {
-      if(this->camera != 0) {
-        msg_warning << "Multiple cameras added. Ignoring" << std::endl;
-        continue;
-      }
-      this->camera = camera;
+  Player* player = dynamic_cast<Player*> (object);
+  if(player) {
+    if(this->player != 0) {
+      msg_warning << "Multiple players added. Ignoring" << std::endl;
+      return false;
     }
+    this->player = player;
+  }
 
-    gameobjects.push_back(object);
+  if(_current == this) {
+    try_expose(object);
+  }
+  
+  return true;
+}
+
+void
+Sector::try_expose(GameObject* object)
+{
+  ScriptInterface* interface = dynamic_cast<ScriptInterface*> (object);
+  if(interface != NULL) {
+    HSQUIRRELVM vm = script_manager->get_global_vm();
+    sq_pushobject(vm, sector_table);
+    interface->expose(vm, -1);
+    sq_pop(vm, 1);
   }
-  gameobjects_new.clear();
 }
 
 void
+Sector::before_object_remove(GameObject* object)
+{
+  if(_current == this)
+    try_unexpose(object);
+}
+
+void
+Sector::try_unexpose(GameObject* object)
+{
+  ScriptInterface* interface = dynamic_cast<ScriptInterface*> (object);
+  if(interface != NULL) {
+    HSQUIRRELVM vm = script_manager->get_global_vm();
+    sq_pushobject(vm, sector_table);
+    interface->unexpose(vm, -1);
+    sq_pop(vm, 1);
+  }
+} 
+
+void
 Sector::draw(DrawingContext& context)
 {
   context.push_transform();
index 5bf497a..80ed734 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <vector>
+#include <squirrel.h>
 
 #include "direction.hpp"
 #include "math/vector.hpp"
@@ -67,12 +68,19 @@ public:
   /// activates this sector (change music, intialize player class, ...)
   void activate(const std::string& spawnpoint);
   void activate(const Vector& player_pos);
+  void deactivate();
 
   void update(float elapsed_time);
   void update_game_objects();
 
   void draw(DrawingContext& context);
 
+  /**
+   * runs a script in the context of the sector (sector_table will be the
+   * roottable of this squirrel VM)
+   */
+  HSQUIRRELVM run_script(std::istream& in, const std::string& sourcename);
+
   /// adds a gameobject
   void add_object(GameObject* object);
 
@@ -112,8 +120,16 @@ public:
     return std::vector<Player*>(1, this->player);
   }
 
+  Rect get_active_region();
+
 private:
   uint32_t collision_tile_attributes(const Rect& dest) const;
+
+  void before_object_remove(GameObject* object);
+  bool before_object_add(GameObject* object);
+
+  void try_expose(GameObject* object);
+  void try_unexpose(GameObject* object);
   
   bool collision_static(MovingObject* object, const Vector& movement);
   
@@ -124,44 +140,43 @@ private:
   
   void collision_object(MovingObject* object1, MovingObject* object2) const;
   GameObject* parse_object(const std::string& name, const lisp::Lisp& lisp);
-  
+
+  void fix_old_tiles();
+
+  typedef std::vector<GameObject*> GameObjects;
+  typedef std::vector<MovingObject*> MovingObjects;
+  typedef std::vector<SpawnPoint*> SpawnPoints;
+
   static Sector* _current;
   
   std::string name;
 
-public:
-  std::string music;
-  float gravity;
-
-  // some special objects, where we need direct access
-  Player* player;
-  TileMap* solids;
-  Camera* camera;
-  
-private:
   std::vector<Bullet*> bullets;
 
   std::string init_script;
 
-public: // TODO make this private again
-  typedef std::vector<GameObject*> GameObjects;
-  GameObjects gameobjects;
-  typedef std::vector<MovingObject*> MovingObjects;
-  MovingObjects moving_objects;
-  typedef std::vector<SpawnPoint*> SpawnPoints;
-  SpawnPoints spawnpoints;                       
-
-  Rect get_active_region();
-
-private:
-  void fix_old_tiles();
-  
   /// container for newly created objects, they'll be added in Sector::update
   GameObjects gameobjects_new;
  
   MusicType currentmusic;
 
   CollisionGrid* grid;
+
+  HSQOBJECT sector_table;
+
+public: // TODO make this private again
+  GameObjects gameobjects;
+  MovingObjects moving_objects;
+  SpawnPoints spawnpoints;                       
+
+  std::string music;
+  float gravity;
+
+  // some special objects, where we need direct access
+  // (try to avoid accessing them directly)
+  Player* player;
+  TileMap* solids;
+  Camera* camera;
 };
 
 #endif
index 45b092c..5b05d2a 100644 (file)
@@ -35,7 +35,6 @@
 #include "audio/sound_manager.hpp"
 #include "main.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
-#include "exceptions.hpp"
 
 static const float DEFAULT_SPEED = 20;
 static const float LEFT_BORDER = 50;
@@ -84,8 +83,9 @@ TextScroller::TextScroller(const std::string& filename)
     text_lisp->get("speed", defaultspeed);
     text_lisp->get("music", music);
   } catch(std::exception& e) {
-    msg_warning << "Couldn't load file '" << filename << "': " << e.what() << std::endl;
-    return;
+    std::ostringstream msg;
+    msg << "Couldn't load file '" << filename << "': " << e.what() << std::endl;
+    throw std::runtime_error(msg.str());
   }
 
   // Split text string lines into a vector
index f95c2a8..d2ed7da 100644 (file)
@@ -61,7 +61,6 @@
 #include "control/joystickkeyboardcontroller.hpp"
 #include "control/codecontroller.hpp"
 #include "main.hpp"
-#include "exceptions.hpp"
 #include "msg.hpp"
 #include "console.hpp"
 
@@ -295,6 +294,13 @@ TitleScreen::setup()
 }
 
 void
+TitleScreen::leave()
+{
+  Sector* sector = titlesession->get_current_sector();
+  sector->deactivate();
+}
+
+void
 TitleScreen::draw(DrawingContext& context)
 {
   Sector* sector  = titlesession->get_current_sector();
index aa26473..5ff13a1 100644 (file)
@@ -37,6 +37,7 @@ public:
   virtual ~TitleScreen();
 
   virtual void setup();
+  virtual void leave();
 
   virtual void draw(DrawingContext& context);
 
index 0793992..b9e5e10 100644 (file)
@@ -29,7 +29,6 @@
 #include "lisp/lisp.hpp"\r
 #include "lisp/writer.hpp"\r
 #include "object_factory.hpp"\r
-#include "scripting/script_interpreter.hpp"\r
 #include "sector.hpp"\r
 \r
 ScriptTrigger::ScriptTrigger(const lisp::Lisp& reader)\r
@@ -87,8 +86,8 @@ ScriptTrigger::event(Player& , EventType type)
   if(type != triggerevent)\r
     return;\r
 \r
-  ScriptInterpreter::add_script_object(Sector::current(), "trigger - scritp",\r
-      script);\r
+  std::istringstream stream(script);\r
+  Sector::current()->run_script(stream, "ScriptTrigger");\r
 }\r
 \r
 IMPLEMENT_FACTORY(ScriptTrigger, "scripttrigger");\r
index 7394441..f007dab 100644 (file)
@@ -114,6 +114,9 @@ Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
       l = text.size();
       done = true;
     }
+
+    if(l > sizeof(temp)-1)
+      l = sizeof(temp)-1;
     
     temp[text.copy(temp, l - i, i)] = '\0';
     
index 04c2de5..7999097 100644 (file)
@@ -27,7 +27,8 @@
 #include "lisp/parser.hpp"
 #include "lisp/lisp.hpp"
 #include "physfs/physfs_stream.hpp"
-#include "scripting/script_interpreter.hpp"
+#include "script_manager.hpp"
+#include "scripting/wrapper_util.hpp"
 #include "msg.hpp"
 
 static bool has_suffix(const std::string& data, const std::string& suffix)
@@ -92,15 +93,11 @@ World::load(const std::string& filename)
 void
 World::run()
 {
-  try {
-    std::string filename = basedir + "/world.nut";
-    std::auto_ptr<ScriptInterpreter> interpeter (new ScriptInterpreter(basedir));
-    IFileStream in(filename);
-  
-    interpeter->run_script(in, filename, true);
-  } catch(std::exception& e) {
-    msg_warning << "Problem running world script: " << e.what() << std::endl;
-  }
+  std::string filename = basedir + "/world.nut";
+  IFileStream in(filename);
+
+  HSQUIRRELVM vm = script_manager->create_thread();
+  Scripting::compile_and_run(vm, in, filename);
 }
 
 const std::string&
index b4b6f1f..3a08067 100644 (file)
@@ -56,8 +56,6 @@
 #include "control/joystickkeyboardcontroller.hpp"
 #include "object/background.hpp"
 #include "object/tilemap.hpp"
-#include "scripting/script_interpreter.hpp"
-#include "exceptions.hpp"
 
 Menu* worldmap_menu  = 0;
 
@@ -608,21 +606,6 @@ WorldMap::on_escape_press()
   }
 }
 
-void
-WorldMap::get_input()
-{
-  main_controller->update();
-
-  SDL_Event event;
-  while (SDL_PollEvent(&event)) {
-    if (Menu::current())
-      Menu::current()->event(event);
-    main_controller->process_event(event);
-    if(event.type == SDL_QUIT)
-      throw graceful_shutdown();
-  }
-}
-
 Vector
 WorldMap::get_next_tile(Vector pos, Direction direction)
 {
@@ -726,6 +709,7 @@ WorldMap::finished_level(const std::string& filename)
   }
 
   if (level->extro_script != "") {
+    /* TODO
     try {
       std::auto_ptr<ScriptInterpreter> interpreter
         (new ScriptInterpreter(levels_path));
@@ -735,6 +719,7 @@ WorldMap::finished_level(const std::string& filename)
     } catch(std::exception& e) {
       msg_fatal << "Couldn't run level-extro-script:" << e.what() << std::endl;
     }
+    */
   }
   
   if (!level->next_worldmap.empty()) {
index 0833c38..a643e41 100644 (file)
@@ -229,8 +229,6 @@ public:
 
   void load_map();
   
-  void get_input();
-
   void add_object(GameObject* object);
   void clear_objects();
 
index c279fa4..d0c9131 100644 (file)
@@ -242,10 +242,8 @@ WrapperCreator::create_register_slot_code(const std::string& what,
                                           const std::string& name)
 {
     out << ind << "if(SQ_FAILED(sq_createslot(v, -3))) {\n";
-    out << ind << ind << "std::ostringstream msg;\n";
-    out << ind << ind << "msg << \"Couldn't register " << what << "'"
-        << name << "'\";\n";
-    out << ind << ind << "throw SquirrelError(v, msg.str());\n";
+    out << ind << ind << "throw SquirrelError(v, \""
+        << "Couldn't register " << what << " '" << name << "'\");\n";
     out << ind << "}\n";
 }
 
@@ -265,19 +263,22 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function)
     if(_class != 0) {
         out << _class->name << "_";
     }
-    out << function->name << "_wrapper(HSQUIRRELVM v)\n"
+    out << function->name << "_wrapper(HSQUIRRELVM vm)\n"
         << "{\n";
     // avoid warning...
     if(_class == 0 && function->parameters.empty() 
             && function->return_type.is_void()
             && function->type != Function::CONSTRUCTOR) {
-        out << ind << "(void) v;\n";
+        out << ind << "(void) vm;\n";
     }
     
-    // eventually retrieve pointer to class instance
+    // retrieve pointer to class instance
     if(_class != 0 && function->type != Function::CONSTRUCTOR) {
         out << ind << ns_prefix <<  _class->name << "* _this;\n";
-        out << ind << "sq_getinstanceup(v, 1, (SQUserPointer*) &_this, 0);\n";
+        out << ind << "if(SQ_FAILED(sq_getinstanceup(vm, 1, reinterpret_cast<SQUserPointer*> (&_this), 0))) {\n";
+        out << ind << ind << "sq_throwerror(vm, _SC(\"'" << function->name << "' called without instance\"));\n";
+        out << ind << ind << "return SQ_ERROR;\n";
+        out << ind << "}\n";
     }
 
     // custom function?
@@ -296,7 +297,7 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function)
             out << "_this->";
         else
             out << ns_prefix;
-        out << function->name << "(v);\n";
+        out << function->name << "(vm);\n";
         out << "}\n";
         out << "\n";
         return;
@@ -308,7 +309,7 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function)
     for(std::vector<Parameter>::iterator p = function->parameters.begin();
             p != function->parameters.end(); ++p) {
         if(i == 0 && p->type.atomic_type == HSQUIRRELVMType::instance()) {
-            out << ind << "HSQUIRRELVM arg0 = v;\n";
+            out << ind << "HSQUIRRELVM arg0 = vm;\n";
             arg_offset--;
         } else {
             char argname[64];
@@ -320,7 +321,8 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function)
     
     // call function
     out << ind << "\n";
-    out << ind;
+    out << ind << "try {\n";
+    out << ind << ind;
     if(!function->return_type.is_void()) {
         function->return_type.write_c_type(out);
         out << " return_value = ";
@@ -346,8 +348,11 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function)
     }
     out << ");\n";
     if(function->type == Function::CONSTRUCTOR) {
-        out << ind << "sq_setinstanceup(v, 1, _this);\n";
-        out << ind << "sq_setreleasehook(v, 1, " 
+        out << ind << "if(SQ_FAILED(sq_setinstanceup(vm, 1, _this))) {\n";
+        out << ind << ind << "sq_throwerror(vm, _SC(\"Couldn't setup instance of '" << _class->name << "' class\"));\n";
+        out << ind << ind << "return SQ_ERROR;\n";
+        out << ind << "}\n";
+        out << ind << "sq_setreleasehook(vm, 1, " 
             << _class->name << "_release_hook);\n";
     }
     out << ind << "\n";
@@ -359,13 +364,24 @@ WrapperCreator::create_function_wrapper(Class* _class, Function* function)
                 << " but has a return value.";
             throw std::runtime_error(msg.str());
         }
-        out << ind << "return sq_suspendvm(v);\n";
+        out << ind << ind << "return sq_suspendvm(vm);\n";
     } else if(function->return_type.is_void()) {
-        out << ind << "return 0;\n";
+        out << ind << ind << "return 0;\n";
     } else {
         push_to_stack(function->return_type, "return_value");
-        out << ind << "return 1;\n";
+        out << ind << ind << "return 1;\n";
     }
+
+    out << ind << "\n";
+    out << ind << "} catch(std::exception& e) {\n";
+    out << ind << ind << "sq_throwerror(vm, e.what());\n";
+    out << ind << ind << "return SQ_ERROR;\n";
+    out << ind << "} catch(...) {\n";
+    out << ind << ind << "sq_throwerror(vm, _SC(\"Unexpected exception while executing function '" << function->name << "'\"));\n";
+    out << ind << ind << "return SQ_ERROR;\n";
+    out << ind << "}\n";
+    out << ind << "\n";
+    
     out << "}\n";
     out << "\n";
 }
@@ -380,16 +396,28 @@ WrapperCreator::prepare_argument(const Type& type, size_t index,
         throw std::runtime_error("Pointers not handled yet");
     if(type.atomic_type == &BasicType::INT) {
         out << ind << "int " << var << ";\n";
-        out << ind << "sq_getinteger(v, " << index << ", &" << var << ");\n";
+        out << ind << "if(SQ_FAILED(sq_getinteger(vm, " << index << ", &" << var << "))) {\n";
+        out << ind << ind << "sq_throwerror(vm, _SC(\"Argument " << (index-1) << " not an integer\"));\n";
+        out << ind << ind << "return SQ_ERROR;\n";
+        out << ind << "}\n";
     } else if(type.atomic_type == &BasicType::FLOAT) {
         out << ind << "float " << var << ";\n";
-        out << ind << "sq_getfloat(v, " << index << ", &" << var << ");\n";
+        out << ind << "if(SQ_FAILED(sq_getfloat(vm, " << index << ", &" << var << "))) {\n";
+        out << ind << ind << "sq_throwerror(vm, _SC(\"Argument " << (index-1) << " not a float\"));\n";
+        out << ind << ind << "return SQ_ERROR;\n";
+        out << ind << "}\n";
     } else if(type.atomic_type == &BasicType::BOOL) {
         out << ind << "SQBool " << var << ";\n";
-        out << ind << "sq_getbool(v, " << index << ", &" << var << ");\n";
+        out << ind << "if(SQ_FAILED(sq_getbool(vm, " << index << ", &" << var << "))) {\n";
+        out << ind << ind << "sq_throwerror(vm, _SC(\"Argument " << (index-1) << " not a bool\"));\n";
+        out << ind << ind << "return SQ_ERROR;\n";
+        out << ind << "}\n";
     } else if(type.atomic_type == StringType::instance()) {
         out << ind << "const char* " << var << ";\n";
-        out << ind << "sq_getstring(v, " << index << ", &" << var << ");\n";
+        out << ind << "if(SQ_FAILED(sq_getstring(vm, " << index << ", &" << var << "))) {\n";
+        out << ind << ind << "sq_throwerror(vm, _SC(\"Argument " << (index-1) << " not a string\"));\n";
+        out << ind << ind << "return SQ_ERROR;\n";
+        out << ind << "}\n";
     } else {
         std::ostringstream msg;
         msg << "Type '" << type.atomic_type->name << "' not supported yet.";
@@ -404,15 +432,15 @@ WrapperCreator::push_to_stack(const Type& type, const std::string& var)
         throw std::runtime_error("References not handled yet");
     if(type.pointer > 0)
         throw std::runtime_error("Pointers not handled yet");
-    out << ind;
+    out << ind << ind;
     if(type.atomic_type == &BasicType::INT) {
-        out << "sq_pushinteger(v, " << var << ");\n";
+        out << "sq_pushinteger(vm, " << var << ");\n";
     } else if(type.atomic_type == &BasicType::FLOAT) {
-        out << "sq_pushfloat(v, " << var << ");\n";
+        out << "sq_pushfloat(vm, " << var << ");\n";
     } else if(type.atomic_type == &BasicType::BOOL) {
-        out << "sq_pushbool(v, " << var << ");\n";
+        out << "sq_pushbool(vm, " << var << ");\n";
     } else if(type.atomic_type == StringType::instance()) {
-        out << "sq_pushstring(v, " << var << ".c_str(), " 
+        out << "sq_pushstring(vm, " << var << ".c_str(), " 
             << var << ".size());\n";
     } else {
         std::ostringstream msg;