Auto-run levels are automatically marked as solved.
[supertux.git] / src / worldmap / worldmap.cpp
index 3d608d5..c74e945 100644 (file)
@@ -39,7 +39,7 @@
 #include "object/background.hpp"
 #include "object/decal.hpp"
 #include "object/tilemap.hpp"
-#include "physfs/ifile_stream.hpp"
+#include "physfs/ifile_streambuf.hpp"
 #include "scripting/squirrel_error.hpp"
 #include "scripting/squirrel_util.hpp"
 #include "sprite/sprite.hpp"
@@ -80,7 +80,7 @@ WorldMap* WorldMap::current_ = NULL;
 WorldMap::WorldMap(const std::string& filename, PlayerStatus* player_status, const std::string& force_spawnpoint) :
   tux(0),
   player_status(player_status),
-  tileset(NULL), 
+  tileset(NULL),
   free_tileset(false),
   worldmap_menu(),
   camera_offset(),
@@ -101,9 +101,9 @@ WorldMap::WorldMap(const std::string& filename, PlayerStatus* player_status, con
   total_stats(),
   worldmap_table(),
   scripts(),
-  ambient_light( 1.0f, 1.0f, 1.0f, 1.0f ), 
+  ambient_light( 1.0f, 1.0f, 1.0f, 1.0f ),
   force_spawnpoint(force_spawnpoint),
-  in_level(false), 
+  in_level(false),
   pan_pos(),
   panning(false)
 {
@@ -134,7 +134,7 @@ WorldMap::WorldMap(const std::string& filename, PlayerStatus* player_status, con
   sq_pop(global_vm, 1);
 
   sound_manager->preload("sounds/warp.wav");
-  
+
   // load worldmap objects
   load(filename);
 }
@@ -364,6 +364,32 @@ WorldMap::get_level_title(LevelTile& level)
   }
 }
 
+void
+WorldMap::get_level_target_time(LevelTile& level)
+{
+  if(last_position == tux->get_tile_pos()) {
+    level.target_time = last_target_time;
+    return;
+  }
+
+  try {
+    lisp::Parser parser;
+    const lisp::Lisp* root = parser.parse(levels_path + level.get_name());
+
+    const lisp::Lisp* level_lisp = root->get_lisp("supertux-level");
+    if(!level_lisp)
+      return;
+
+    level_lisp->get("target-time", level.target_time);
+
+    last_position = level.pos;
+    last_target_time = level.target_time;
+  } catch(std::exception& e) {
+    log_warning << "Problem when reading level target time: " << e.what() << std::endl;
+    return;
+  }
+}
+
 void WorldMap::calculate_total_stats()
 {
   total_stats.zero();
@@ -461,9 +487,11 @@ WorldMap::finished_level(Level* gamelevel)
   // deal with statistics
   level->statistics.merge(gamelevel->stats);
   calculate_total_stats();
-  if(level->statistics.completed(level->statistics)) {
+  get_level_target_time(*level);
+  if(level->statistics.completed(level->statistics, level->target_time)) {
     level->perfect = true;
-    level->sprite->set_action("perfect");
+    if(level->sprite->has_action("perfect"))
+      level->sprite->set_action("perfect");
   }
 
   save_state();
@@ -649,6 +677,8 @@ WorldMap::update(float delta)
     LevelTile* level = at_level();
     if (level && (level->auto_play) && (!level->solved) && (!tux->is_moving())) {
       enter_level = true;
+      // automatically mark these levels as solved in case player aborts
+      level->solved = true;
     }
 
     if (enter_level && !tux->is_moving())
@@ -783,7 +813,7 @@ WorldMap::draw(DrawingContext& context)
   /*
   // FIXME: make this a runtime switch similar to draw_collrects/show_collrects?
   // draw visual indication of possible walk directions
-  static int flipme = 0; 
+  static int flipme = 0;
   if (flipme++ & 0x04)
   for (int x = 0; x < get_width(); x++) {
   for (int y = 0; y < get_height(); y++) {
@@ -823,8 +853,8 @@ WorldMap::draw_status(DrawingContext& context)
 
         context.draw_text(Resources::normal_font, level->title,
                           Vector(SCREEN_WIDTH/2,
-                                 SCREEN_HEIGHT - Resources::normal_font->get_height() - 30),
-                          ALIGN_CENTER, LAYER_FOREGROUND1, WorldMap::level_title_color);
+                                 SCREEN_HEIGHT - Resources::normal_font->get_height() - 10),
+                          ALIGN_CENTER, LAYER_HUD, WorldMap::level_title_color);
 
         // if level is solved, draw level picture behind stats
         /*
@@ -839,7 +869,8 @@ WorldMap::draw_status(DrawingContext& context)
           }
         */
 
-        level->statistics.draw_worldmap_info(context);
+        get_level_target_time(*level);
+        level->statistics.draw_worldmap_info(context, level->target_time);
         break;
       }
     }
@@ -906,7 +937,8 @@ WorldMap::setup()
 
   //Run default.nut just before init script
   try {
-    IFileStream in(levels_path + "/default.nut");
+    IFileStreambuf ins(levels_path + "default.nut");
+    std::istream in(&ins);
     run_script(in, "WorldMap::default.nut");
   } catch(std::exception& ) {
     // doesn't exist or erroneous; do nothing