diff --git a/modules/game_walk/walk.lua b/modules/game_walk/walk.lua index fa79039dfb..db63fedab3 100644 --- a/modules/game_walk/walk.lua +++ b/modules/game_walk/walk.lua @@ -48,24 +48,28 @@ end --- Generalized floor change check. local function canChangeFloor(pos, deltaZ) + if deltaZ == 0 then + return false + end local player = g_game.getLocalPlayer() if not player then return false end - local fromTile = g_map.getTile(player:getPosition()) local toPos = {x = pos.x, y = pos.y, z = pos.z + deltaZ} local toTile = g_map.getTile(toPos) + if not toTile then + return false + end if deltaZ > 0 then - -- Going DOWN: just check if destination is walkable (can step down onto it) - return toTile and toTile:isWalkable() and toTile:hasElevation(3) - elseif deltaZ < 0 then - -- Going UP: check if current tile has elevation (stairs to climb) AND destination is walkable - return fromTile and fromTile:hasElevation(3) and toTile and toTile:isWalkable() + -- Going DOWN + return toTile:isWalkable() and (toTile:hasElevation(3) or toTile:hasFloorChange()) end - - return false + -- deltaZ < 0 + -- Going UP: check if current tile has elevation (stairs to climb) AND destination is walkable + local fromTile = g_map.getTile(player:getPosition()) + return fromTile and fromTile:hasElevation(3) and toTile:isWalkable() end --- Makes the player walk in the given direction. diff --git a/src/client/const.h b/src/client/const.h index 083aa54558..1bf3024df8 100644 --- a/src/client/const.h +++ b/src/client/const.h @@ -1030,6 +1030,7 @@ enum ThingFlagAttr :uint64_t ThingFlagAttrDecoKit = static_cast(1) << 45, ThingFlagAttrNPC = static_cast(1) << 46, ThingFlagAttrAmmo = static_cast(1) << 47, + ThingFlagAttrFloorChange = static_cast(1) << 48, }; enum STACK_PRIORITY : uint8_t diff --git a/src/client/luafunctions.cpp b/src/client/luafunctions.cpp index 4327a43e3b..f88d0dadc8 100644 --- a/src/client/luafunctions.cpp +++ b/src/client/luafunctions.cpp @@ -702,6 +702,7 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("isTranslucent", &ThingType::isTranslucent); g_lua.bindClassMemberFunction("hasDisplacement", &ThingType::hasDisplacement); g_lua.bindClassMemberFunction("hasElevation", &ThingType::hasElevation); + g_lua.bindClassMemberFunction("hasFloorChange", &ThingType::hasFloorChange); g_lua.bindClassMemberFunction("isLyingCorpse", &ThingType::isLyingCorpse); g_lua.bindClassMemberFunction("isAnimateAlways", &ThingType::isAnimateAlways); g_lua.bindClassMemberFunction("hasMiniMapColor", &ThingType::hasMiniMapColor); @@ -926,6 +927,7 @@ void Client::registerLuaFunctions() g_lua.bindClassMemberFunction("getGround", &Tile::getGround); g_lua.bindClassMemberFunction("isWalkable", &Tile::isWalkable); g_lua.bindClassMemberFunction("hasElevation", &Tile::hasElevation); + g_lua.bindClassMemberFunction("hasFloorChange", &Tile::hasFloorChange); g_lua.bindClassMemberFunction("isCovered", &Tile::isCovered); g_lua.bindClassMemberFunction("isCompletelyCovered", &Tile::isCompletelyCovered); diff --git a/src/client/thing.cpp b/src/client/thing.cpp index a52931a926..1d7f826647 100644 --- a/src/client/thing.cpp +++ b/src/client/thing.cpp @@ -498,6 +498,13 @@ bool Thing::hasElevation() const { return t->hasElevation(); return false; } +bool Thing::hasFloorChange() const +{ + if (const auto t = getThingType(); t) + return t->hasFloorChange(); + return false; +} + bool Thing::hasAction() const { if (const auto t = getThingType(); t) return t->hasAction(); @@ -571,4 +578,4 @@ const Color& Thing::getHighlightColor() { m_highlightColor.setAlpha(0.1f + std::abs(500 - g_clock.millis() % 1000) / 1000.0f); return m_highlightColor; -} \ No newline at end of file +} diff --git a/src/client/thing.h b/src/client/thing.h index 1188fda726..f07402457e 100644 --- a/src/client/thing.h +++ b/src/client/thing.h @@ -149,6 +149,7 @@ class Thing : public AttachableObject bool hasLensHelp() const; bool hasDisplacement() const; bool hasElevation() const; + bool hasFloorChange() const; bool hasAction() const; bool hasWearOut() const; bool hasClockExpire() const; @@ -242,4 +243,4 @@ class Thing : public AttachableObject friend class Client; friend class Tile; }; -#pragma pack(pop) \ No newline at end of file +#pragma pack(pop) diff --git a/src/client/thingtype.cpp b/src/client/thingtype.cpp index 501af6384c..359a2f330c 100644 --- a/src/client/thingtype.cpp +++ b/src/client/thingtype.cpp @@ -113,6 +113,10 @@ void ThingType::unserializeAppearance(const uint16_t clientId, const ThingCatego void ThingType::applyAppearanceFlags(const appearances::AppearanceFlags& flags) { + if (flags.floorchange()) { + m_flags |= ThingFlagAttrFloorChange; + } + if (flags.has_bank()) { m_groundSpeed = flags.bank().waypoints(); m_flags |= ThingFlagAttrGround; @@ -946,6 +950,7 @@ ThingFlagAttr ThingType::thingAttrToThingFlagAttr(const ThingAttr attr) { case ThingAttrDisplacement: return ThingFlagAttrDisplacement; case ThingAttrLight: return ThingFlagAttrLight; case ThingAttrElevation: return ThingFlagAttrElevation; + case ThingAttrFloorChange: return ThingFlagAttrFloorChange; case ThingAttrGround: return ThingFlagAttrGround; case ThingAttrWritable: return ThingFlagAttrWritable; case ThingAttrWritableOnce: return ThingFlagAttrWritableOnce; @@ -1139,4 +1144,4 @@ void ThingType::exportImage(const std::string& fileName) image->savePNG(fileName); } -#endif \ No newline at end of file +#endif diff --git a/src/client/thingtype.h b/src/client/thingtype.h index ac44b50183..d71d5e18ac 100644 --- a/src/client/thingtype.h +++ b/src/client/thingtype.h @@ -120,6 +120,7 @@ class ThingType final : public LuaObject bool isTranslucent() { return (m_flags & ThingFlagAttrTranslucent); } bool hasDisplacement() { return (m_flags & ThingFlagAttrDisplacement); } bool hasElevation() { return (m_flags & ThingFlagAttrElevation); } + bool hasFloorChange() const { return (m_flags & ThingFlagAttrFloorChange); } bool isLyingCorpse() { return (m_flags & ThingFlagAttrLyingCorpse); } bool isAnimateAlways() { return (m_flags & ThingFlagAttrAnimateAlways); } bool hasMiniMapColor() { return (m_flags & ThingFlagAttrMinimapColor); } diff --git a/src/client/tile.cpp b/src/client/tile.cpp index cd32537620..ba9ed36d81 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -484,6 +484,14 @@ ThingPtr Tile::getTopThing() bool Tile::hasGround() { return (getGround() && getGround()->isSingleGround()) || m_thingTypeFlag & HAS_GROUND_BORDER; }; bool Tile::hasTopGround(const bool ignoreBorder) { return (getGround() && getGround()->isTopGround()) || (!ignoreBorder && m_thingTypeFlag & HAS_TOP_GROUND_BORDER); } +bool Tile::hasFloorChange() const +{ + for (const auto& thing : m_things) { + if (thing->hasFloorChange()) + return true; + } + return false; +} ItemPtr Tile::getGround() { const auto& ground = getThing(0); return ground && ground->isGround() ? ground->static_self_cast() : nullptr; } std::vector Tile::getItems() @@ -1109,4 +1117,4 @@ bool Tile::isLoading() const { } return false; -} \ No newline at end of file +} diff --git a/src/client/tile.h b/src/client/tile.h index 3aa40b18ec..26cc8619bc 100644 --- a/src/client/tile.h +++ b/src/client/tile.h @@ -126,6 +126,7 @@ class Tile final : public AttachableObject } bool hasElevation(const int elevation = 1) { return m_elevation >= elevation; } + bool hasFloorChange() const; #ifdef FRAMEWORK_EDITOR void overwriteMinimapColor(uint8_t color) { m_minimapColor = color; } diff --git a/src/protobuf/appearances.proto b/src/protobuf/appearances.proto index 465c08b67e..78f06295ad 100644 --- a/src/protobuf/appearances.proto +++ b/src/protobuf/appearances.proto @@ -190,6 +190,7 @@ message AppearanceFlags { optional bool hook_south = 70; optional bool hook_east = 71; optional AppearanceFlagTransparencyLevel transparencylevel = 72; + optional bool floorchange = 73; } message AppearanceFlagUpgradeClassification {