Added special "edit" mode to GameSession and Player to playtest levels.
authorChristoph Sommer <mail@christoph-sommer.de>
Thu, 27 Dec 2007 02:49:12 +0000 (02:49 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Thu, 27 Dec 2007 02:49:12 +0000 (02:49 +0000)
In "edit" mode, Tux will not die and sequences will not play, but Tux will become a ghost instead.

SVN-Revision: 5239

data/scripts/console.nut
src/game_session.cpp
src/game_session.hpp
src/object/player.cpp
src/object/player.hpp
src/scripting/level.cpp
src/scripting/level.hpp
src/scripting/wrapper.cpp

index cdb190e..dc4e05d 100644 (file)
@@ -14,6 +14,16 @@ function finish()
        Level.finish(true);
 }
 
+function edit()
+{
+       Level.edit(true);
+}
+
+function play()
+{
+       Level.edit(false);
+}
+
 function worldmapfinish()
 {
        save_state();
index 8fe62b5..ee036eb 100644 (file)
@@ -92,7 +92,7 @@ GameSession::GameSession(const std::string& levelfile_, Statistics* statistics)
     end_sequence(0),
     levelfile(levelfile_), best_level_statistics(statistics),
     capture_demo_stream(0), playback_demo_stream(0), demo_controller(0),
-    play_time(0)
+    play_time(0), edit_mode(false)
 {
   current_ = this;
   currentsector = NULL;
@@ -116,6 +116,12 @@ GameSession::GameSession(const std::string& levelfile_, Statistics* statistics)
 void
 GameSession::restart_level()
 {
+
+  if (edit_mode) {
+    force_ghost_mode();
+    return;
+  }
+
   game_pause   = false;
   end_sequence = 0;
 
@@ -311,6 +317,32 @@ GameSession::toggle_pause()
   }
 }
 
+void
+GameSession::set_editmode(bool edit_mode)
+{
+  if (this->edit_mode == edit_mode) return;
+  this->edit_mode = edit_mode;
+
+  currentsector->get_players()[0]->set_edit_mode(edit_mode);
+
+  if (edit_mode) {
+
+    // entering edit mode
+
+  } else {
+
+    // leaving edit mode
+    restart_level();
+
+  }
+}
+
+void
+GameSession::force_ghost_mode()
+{
+  currentsector->get_players()[0]->set_ghost_mode(true);
+}
+
 HSQUIRRELVM
 GameSession::run_script(std::istream& in, const std::string& sourcename)
 {
@@ -518,6 +550,11 @@ GameSession::finish(bool win)
 {
   using namespace WorldMapNS;
 
+  if (edit_mode) {
+    force_ghost_mode();
+    return;
+  }
+
   if(win) {
     if(WorldMap::current())
       WorldMap::current()->finished_level(level.get());
@@ -549,6 +586,12 @@ GameSession::get_working_directory()
 void
 GameSession::start_sequence(const std::string& sequencename)
 {
+  // do not play sequences when in edit mode
+  if (edit_mode) {
+    force_ghost_mode();
+    return;
+  }
+
   // handle special "stoptux" sequence
   if (sequencename == "stoptux") {
     if (!end_sequence) {
index 54d0dde..edae3a6 100644 (file)
@@ -84,6 +84,16 @@ public:
 
   void toggle_pause();
 
+  /**
+   * Enters or leaves level editor mode
+   */
+  void set_editmode(bool edit_mode = true);
+
+  /**
+   * Forces all Players to enter ghost mode
+   */
+  void force_ghost_mode();
+
 private:
   void check_end_conditions();
   void process_events();
@@ -136,6 +146,8 @@ private:
   std::auto_ptr<Menu> game_menu;
 
   float play_time; /**< total time in seconds that this session ran interactively */
+
+  bool edit_mode; /**< true if GameSession runs in level editor mode */
 };
 
 #endif /*SUPERTUX_GAMELOOP_H*/
index d82bed2..dc484c5 100644 (file)
@@ -130,7 +130,7 @@ Player::Player(PlayerStatus* _player_status, const std::string& name)
   : scripting_controller(0), 
     player_status(_player_status), 
     scripting_controller_old(0),
-    grabbed_object(NULL), ghost_mode(false), climbing(0)
+    grabbed_object(NULL), ghost_mode(false), edit_mode(false), climbing(0)
 {
   this->name = name;
   controller = main_controller;
@@ -1161,6 +1161,7 @@ Player::kill(bool completely)
     return;
 
   sound_manager->play("sounds/hurt.wav");
+
   if (climbing) stop_climbing(*climbing);
 
   physic.set_velocity_x(0);
@@ -1183,6 +1184,13 @@ Player::kill(bool completely)
       duck = false;
     }
   } else {
+
+    // do not die when in edit mode
+    if (edit_mode) {
+      set_ghost_mode(true);
+      return;
+    }
+
     if (player_status->coins >= 25 && !GameSession::current()->get_reset_point_sectorname().empty())
     {
       for (int i = 0; i < 5; i++)
@@ -1241,7 +1249,7 @@ Player::check_bounds(Camera* camera)
   }
 
   /* fallen out of the level? */
-  if (get_pos().y > Sector::current()->get_height()) {
+  if ((get_pos().y > Sector::current()->get_height()) && (!ghost_mode)) {
     kill(true);
     return;
   }
@@ -1336,6 +1344,12 @@ Player::set_ghost_mode(bool enable)
 }
 
 
+void
+Player::set_edit_mode(bool enable)
+{
+  edit_mode = enable;
+}
+
 void 
 Player::start_climbing(Climbable& climbable)
 {
index 9fcda0d..4eea2cc 100644 (file)
@@ -252,6 +252,12 @@ public:
   void set_ghost_mode(bool enable);
 
   /**
+   * Switches edit mode on/off.
+   * In edit mode, Tux will enter ghost_mode instead of dying.
+   */
+  void set_edit_mode(bool enable);
+
+  /**
    * Returns whether ghost mode is currently enabled
    */
   bool get_ghost_mode() { return ghost_mode; }
@@ -311,6 +317,7 @@ private:
   void try_grab();
 
   bool ghost_mode; /**< indicates if Tux should float around and through solid objects */
+  bool edit_mode; /**< indicates if Tux should switch to ghost mode rather than dying */
 
   Timer unduck_hurt_timer; /**< if Tux wants to stand up again after ducking and cannot, this timer is started */
 
index f780ee2..8967741 100644 (file)
@@ -65,4 +65,12 @@ namespace Scripting
       return;
     GameSession::current()->toggle_pause();
   }
+
+  void
+  Level::edit(bool edit_mode)
+  {
+    if(GameSession::current() == NULL) return;
+    GameSession::current()->set_editmode(edit_mode);
+  }
+
 }
index 2cdc258..b7d91a2 100644 (file)
@@ -39,6 +39,9 @@ public:
     void flip_vertically();
     /** toggle pause */
     void toggle_pause();
+
+    /** Switch to and from edit mode */
+    void edit(bool edit_mode);
 };
 
 }
index cda1f24..d001bbb 100644 (file)
@@ -485,6 +485,35 @@ static SQInteger Level_toggle_pause_wrapper(HSQUIRRELVM vm)
 
 }
 
+static SQInteger Level_edit_wrapper(HSQUIRRELVM vm)
+{
+  SQUserPointer data;
+  if(SQ_FAILED(sq_getinstanceup(vm, 1, &data, 0))) {
+    sq_throwerror(vm, _SC("'edit' called without instance"));
+    return SQ_ERROR;
+  }
+  Scripting::Level* _this = reinterpret_cast<Scripting::Level*> (data);
+  SQBool arg0;
+  if(SQ_FAILED(sq_getbool(vm, 2, &arg0))) {
+    sq_throwerror(vm, _SC("Argument 1 not a bool"));
+    return SQ_ERROR;
+  }
+
+  try {
+    _this->edit(arg0 == SQTrue);
+
+    return 0;
+
+  } catch(std::exception& e) {
+    sq_throwerror(vm, e.what());
+    return SQ_ERROR;
+  } catch(...) {
+    sq_throwerror(vm, _SC("Unexpected exception while executing function 'edit'"));
+    return SQ_ERROR;
+  }
+
+}
+
 static SQInteger ScriptedObject_release_hook(SQUserPointer ptr, SQInteger )
 {
   Scripting::ScriptedObject* _this = reinterpret_cast<Scripting::ScriptedObject*> (ptr);
@@ -4477,6 +4506,12 @@ void register_supertux_wrapper(HSQUIRRELVM v)
     throw SquirrelError(v, "Couldn't register function 'toggle_pause'");
   }
 
+  sq_pushstring(v, "edit", -1);
+  sq_newclosure(v, &Level_edit_wrapper, 0);
+  if(SQ_FAILED(sq_createslot(v, -3))) {
+    throw SquirrelError(v, "Couldn't register function 'edit'");
+  }
+
   if(SQ_FAILED(sq_createslot(v, -3))) {
     throw SquirrelError(v, "Couldn't register class 'Level'");
   }