diff --git a/doc/PACKS.md b/doc/PACKS.md index 6886bf06..93990b5b 100644 --- a/doc/PACKS.md +++ b/doc/PACKS.md @@ -185,6 +185,10 @@ a table representing an enum with the following constants: \ * `.AccessibilityLevel`: read-only, giving one of the AccssibilityLevel constants +### type Location +* `.AccessibilityLevel`: read-only, giving one of the AccssibilityLevel constants (will not give CLEARED at the moment), since 0.25.5 + + ## JSON ### Items @@ -429,12 +433,18 @@ Sections can be addressed from Lua with `Tracker:FindObjectForCode("@location_na **Tracker Lua Interface:** * `Tracker:FindObjectForCode('@location_name/section_name')` returns a Section or nil +* `Tracker:FindObjectForCode('@location_name')` returns a Location or nil **Section Lua Interface:** * `.Owner`: probably points to location, but we return an empty table at the moment. `.Owner.ModifiedByUser` is `nil`. * `.ChestCount`: read how many chests are in the section * `.AvailableChestCount`: read/write how many chests are NOT checked +* `.AccessibilityLevel`: read-only, giving one of the AccssibilityLevel constants + +**Location Lua Interface:** + +* `.AccessibilityLevel`: read-only, giving one of the AccssibilityLevel constants, since 0.25.5 **Future:** We probably want to add a different (additional) interface to Pop for this: diff --git a/src/core/location.cpp b/src/core/location.cpp index 41d90bcd..23dc5099 100644 --- a/src/core/location.cpp +++ b/src/core/location.cpp @@ -6,6 +6,7 @@ using nlohmann::json; const LuaInterface::MethodMap LocationSection::Lua_Methods = {}; +const LuaInterface::MethodMap Location::Lua_Methods = {}; int LocationSection::Lua_Index(lua_State *L, const char *key) { @@ -62,6 +63,28 @@ bool LocationSection::Lua_NewIndex(lua_State *L, const char *key) return false; } +int Location::Lua_Index(lua_State *L, const char *key) +{ + if (strcmp(key, "Owner") == 0) { + lua_newtable(L); // dummy + return 1; + } else if (strcmp(key, "AccessibilityLevel") == 0) { + lua_getglobal(L, "Tracker"); + Tracker* tracker = Tracker::luaL_testthis(L, -1); + if (!tracker) return 0; + int res = (int)tracker->isReachable(*this); + // NOTE: we don't support AccessibilityLevel::CLEARED for Locations yet + lua_pushinteger(L, res); + return 1; + } + return 0; +} + +bool Location::Lua_NewIndex(lua_State *L, const char *key) +{ + return false; +} + static bool parseRule(const json& v, std::list& rule, const char* nodeType, const char* ruleType, const std::string& name) diff --git a/src/core/location.h b/src/core/location.h index ed4ac410..b1dabd35 100644 --- a/src/core/location.h +++ b/src/core/location.h @@ -68,7 +68,8 @@ class LocationSection final : public LuaInterface { virtual bool Lua_NewIndex(lua_State *L, const char *key) override; }; -class Location final { +class Location final : public LuaInterface { + friend class LuaInterface; public: class MapLocation final { public: @@ -123,6 +124,12 @@ class Location final { #ifndef NDEBUG void dump(bool compact=false); #endif + +protected: // lua interface + static constexpr const char Lua_Name[] = "Location"; + static const LuaInterface::MethodMap Lua_Methods; + virtual int Lua_Index(lua_State *L, const char *key) override; + virtual bool Lua_NewIndex(lua_State *L, const char *key) override; }; #endif // _CORE_LOCATION_H diff --git a/src/core/tracker.cpp b/src/core/tracker.cpp index 99a0bcbe..14e3b316 100644 --- a/src/core/tracker.cpp +++ b/src/core/tracker.cpp @@ -402,17 +402,24 @@ Tracker::Object Tracker::FindObjectForCode(const char* code) } } - for (auto& item : _jsonItems) { - if (item.canProvideCode(code)) { - return &item; + if (*code == '@') { // location (not section) + const char *start = code+1; + auto& loc = getLocation(start, true); + if (!loc.getID().empty()) + return &loc; + } else { + for (auto& item : _jsonItems) { + if (item.canProvideCode(code)) { + return &item; + } } - } - for (auto& item : _luaItems) { - if (item.canProvideCode(code)) { - return &item; + for (auto& item : _luaItems) { + if (item.canProvideCode(code)) { + return &item; + } } } - printf("Did not find object for code \"%s\".\n", code); + printf("Did not find object for code \"%s\".\n", sanitize_print(code).c_str()); return nullptr; } diff --git a/src/core/tracker.h b/src/core/tracker.h index 79f00cd3..39f8de43 100644 --- a/src/core/tracker.h +++ b/src/core/tracker.h @@ -35,20 +35,23 @@ class Tracker final : public LuaInterface { struct Object final : public LuaType { // NOTE: we could use (something like) std::variant<...> ? - enum class RT { NIL, JsonItem, LuaItem, Section } type; + enum class RT { NIL, JsonItem, LuaItem, Section, Location } type; union { JsonItem *jsonItem; LuaItem *luaItem; LocationSection *section; + Location *location; }; Object (std::nullptr_t val) : type(RT::NIL) {} Object (JsonItem *val) : type(RT::JsonItem), jsonItem(val) {} Object (LuaItem *val) : type(RT::LuaItem), luaItem(val) {} Object (LocationSection *val) : type(RT::Section), section(val) {} + Object (Location *val) : type(RT::Location), location(val) {} virtual void Lua_Push(lua_State *L) const { // pushes instance to Lua stack if (type == RT::JsonItem) jsonItem->Lua_Push(L); else if (type == RT::LuaItem) luaItem->Lua_Push(L); else if (type == RT::Section) section->Lua_Push(L); + else if (type == RT::Location) location->Lua_Push(L); else lua_pushnil(L); } }; diff --git a/src/poptracker.cpp b/src/poptracker.cpp index adbbc970..9a701a6c 100644 --- a/src/poptracker.cpp +++ b/src/poptracker.cpp @@ -1050,6 +1050,7 @@ bool PopTracker::loadTracker(const std::string& pack, const std::string& variant LuaItem::Lua_Register(_L); // TODO: move this to Tracker or ScriptHost JsonItem::Lua_Register(_L); // ^ LocationSection::Lua_Register(_L); // ^ + Location::Lua_Register(_L); // ^ ImageReference::Lua_Register(_L); _imageReference.Lua_Push(_L);