diff --git a/src/worldmap/tux.cpp b/src/worldmap/tux.cpp index 7d3091483a..ee94825dce 100644 --- a/src/worldmap/tux.cpp +++ b/src/worldmap/tux.cpp @@ -48,6 +48,10 @@ Tux::Tux(WorldMap* worldmap) : m_direction(Direction::NONE), m_initial_tile_pos(), m_tile_pos(), + m_last_stable_tile_pos(), + m_last_level_tile_pos(), + m_last_stable_back_direction(Direction::NONE), + m_last_level_back_direction(Direction::NONE), m_offset(0), m_moving(false), m_ghost_mode(false) @@ -300,9 +304,20 @@ Tux::try_continue_walking(float dt_sec) (teleporter) || m_ghost_mode) { - if (special_tile && !special_tile->get_map_message().empty() && !special_tile->is_passive_message()) { - m_worldmap->set_passive_message({}, 0.0f); - } + if (special_tile && !special_tile->get_map_message().empty() && !special_tile->is_passive_message()) + { + m_worldmap->set_passive_message("", 0.0f); + } + + if (worldmap_sector->at_object() != nullptr) + { + m_last_level_tile_pos = m_tile_pos; + m_last_level_back_direction = m_back_direction; + } + + m_last_stable_tile_pos = m_ghost_mode ? m_last_level_tile_pos : m_tile_pos; + m_last_stable_back_direction = m_ghost_mode ? m_last_level_back_direction : m_back_direction; + } stop(); return; @@ -392,6 +407,20 @@ Tux::setup() if (m_initial_tile_pos != Vector()) m_tile_pos = m_initial_tile_pos; + m_last_stable_tile_pos = m_tile_pos; + m_last_stable_back_direction = m_back_direction; + + if (m_worldmap->get_sector().at_object(m_tile_pos)) + { + m_last_level_tile_pos = m_tile_pos; + m_last_level_back_direction = m_back_direction; + } + else + { + m_last_level_tile_pos = m_last_stable_tile_pos; + m_last_level_back_direction = m_last_stable_back_direction; + } + // check if we already touch a SpriteChange object auto sprite_change = m_worldmap->get_sector().at_object(m_tile_pos); change_sprite(sprite_change); diff --git a/src/worldmap/tux.hpp b/src/worldmap/tux.hpp index 28ef439a5e..f9e4a06438 100644 --- a/src/worldmap/tux.hpp +++ b/src/worldmap/tux.hpp @@ -54,6 +54,18 @@ class Tux final : public GameObject inline void set_initial_pos(const Vector& pos) { m_initial_tile_pos = pos / 32.f; } inline void set_tile_pos(const Vector& pos) { m_tile_pos = pos; } + inline Vector get_last_stable_tile_pos() const { return m_last_stable_tile_pos; } + inline void set_last_stable_tile_pos(const Vector& pos) { m_last_stable_tile_pos = pos; } + + inline Vector get_last_level_tile_pos() const { return m_last_level_tile_pos; } + inline void set_last_level_tile_pos(const Vector& pos) { m_last_level_tile_pos = pos; } + + inline Direction get_last_stable_back_direction() const { return m_last_stable_back_direction; } + inline void set_last_stable_back_direction(Direction dir) { m_last_stable_back_direction = dir; } + + inline Direction get_last_level_back_direction() const { return m_last_level_back_direction; } + inline void set_last_level_back_direction(Direction dir) { m_last_level_back_direction = dir; } + void process_special_tile(SpecialTile* special_tile); private: @@ -78,6 +90,10 @@ class Tux final : public GameObject Direction m_direction; Vector m_initial_tile_pos; Vector m_tile_pos; + Vector m_last_stable_tile_pos; + Vector m_last_level_tile_pos; + Direction m_last_stable_back_direction; + Direction m_last_level_back_direction; /** Length by which tux is away from its current tile, length is in input_direction direction */ float m_offset; diff --git a/src/worldmap/worldmap_state.cpp b/src/worldmap/worldmap_state.cpp index 25289337c1..cc60f3ecc8 100644 --- a/src/worldmap/worldmap_state.cpp +++ b/src/worldmap/worldmap_state.cpp @@ -152,15 +152,16 @@ WorldMapState::load_tux(const ssq::Table& table) Vector p(0.0f, 0.0f); if (!tux.get("x", p.x) || !tux.get("y", p.y)) { - log_warning << "Player position not set, respawning." << std::endl; sector.move_to_spawnpoint(DEFAULT_SPAWNPOINT_NAME); m_position_was_reset = true; + return; } std::string back_str; tux.get("back", back_str); sector.m_tux->m_back_direction = string_to_direction(back_str); sector.m_tux->set_tile_pos(p); + Direction back_dir = string_to_direction(back_str); int tile_data = sector.tile_data_at(p); if (!(tile_data & (Tile::WORLDMAP_NORTH | Tile::WORLDMAP_SOUTH | Tile::WORLDMAP_WEST | Tile::WORLDMAP_EAST))) @@ -168,6 +169,18 @@ WorldMapState::load_tux(const ssq::Table& table) log_warning << "Player at illegal position " << p.x << ", " << p.y << " respawning." << std::endl; sector.move_to_spawnpoint(DEFAULT_SPAWNPOINT_NAME); m_position_was_reset = true; + return; + } + + sector.m_tux->m_back_direction = back_dir; + sector.m_tux->set_tile_pos(p); + sector.m_tux->set_last_stable_tile_pos(p); + sector.m_tux->set_last_stable_back_direction(back_dir); + + if (sector.at_object(p)) + { + sector.m_tux->set_last_level_tile_pos(p); + sector.m_tux->set_last_level_back_direction(back_dir); } } @@ -296,10 +309,13 @@ WorldMapState::save_state(bool initial) const sector_table.set("music", music_object.get_music()); /** Save Tux **/ + const Vector save_pos = sector.m_tux->get_last_stable_tile_pos(); + const Direction save_back = sector.m_tux->get_last_stable_back_direction(); + ssq::Table tux = sector_table.addTable("tux"); - tux.set("x", sector.m_tux->get_tile_pos().x); - tux.set("y", sector.m_tux->get_tile_pos().y); - tux.set("back", direction_to_string(sector.m_tux->m_back_direction)); + tux.set("x", save_pos.x); + tux.set("y", save_pos.y); + tux.set("back", direction_to_string(save_back)); /** Save levels **/ ssq::Table levels = sector_table.addTable("levels");