diff --git a/data/resources.json b/data/resources.json index c243e6f8..4599022f 100644 --- a/data/resources.json +++ b/data/resources.json @@ -58665,7 +58665,7 @@ ] } ], - "name": "SWITCH1.BAN_1009_AePc_0" + "name": "SwitchDeactivateRight" }, { "blend_mode": 1, @@ -58691,7 +58691,7 @@ ] } ], - "name": "SWITCH1.BAN_1009_AePc_1" + "name": "SwitchIdle" }, { "blend_mode": 1, @@ -58717,7 +58717,7 @@ ] } ], - "name": "SWITCH1.BAN_1009_AePc_2" + "name": "SwitchActivateLeft" }, { "blend_mode": 1, @@ -58743,7 +58743,7 @@ ] } ], - "name": "SWITCH1.BAN_1009_AePc_3" + "name": "SwitchDeactivateLeft" }, { "blend_mode": 1, @@ -58769,7 +58769,7 @@ ] } ], - "name": "SWITCH1.BAN_1009_AePc_4" + "name": "SwitchActivateRight" }, { "blend_mode": 1, diff --git a/data/scripts/abe.lua b/data/scripts/abe.lua index 8f5de2b7..51e962f8 100644 --- a/data/scripts/abe.lua +++ b/data/scripts/abe.lua @@ -34,7 +34,8 @@ local function Run(s) MoveX(s, kRunSpeed) end function init(self) self.states = {} - + self.states.name = "abe" + self.states.SayHelloPart1 = { animation = 'AbeStandSpeak1', @@ -184,7 +185,24 @@ function init(self) end if (i:InputAction()) then - return 'PullLever' + local xpos = self.mXPos + if self:FacingLeft() then + xpos = xpos - (kGridWidth + 5) + else + xpos = xpos + (kGridWidth + 5) + end + + local lever = GetMapObject(xpos, self.mYPos, "lever") + if (lever == nil) then + print("No lever at " .. xpos .. "," .. self.mYPos) + else + if (lever.states.CanBeActivated()) then + lever.states.Activate(self:FacingLeft()) + return 'PullLever' + else + print("Lever is not in right state") + end + end end if (InputSameAsDirection(s, i)) then diff --git a/data/scripts/background_animation.lua b/data/scripts/background_animation.lua index a23a893c..55f0300d 100644 --- a/data/scripts/background_animation.lua +++ b/data/scripts/background_animation.lua @@ -1,7 +1,7 @@ -function init_with_data(self, stream) +function init_with_data(self, rect, stream) self.states = {} - + self.states.name = "background_animation" local animId = stream:ReadU32() diff --git a/data/scripts/door.lua b/data/scripts/door.lua index 9588a70c..e10c047e 100644 --- a/data/scripts/door.lua +++ b/data/scripts/door.lua @@ -1,7 +1,7 @@ -function init_with_data(self, stream) +function init_with_data(self, rect, stream) self.states = {} - + self.states.name = "door" self.states.Closed = { diff --git a/data/scripts/mine.lua b/data/scripts/mine.lua index a0c73ea9..876b5e58 100644 --- a/data/scripts/mine.lua +++ b/data/scripts/mine.lua @@ -1,7 +1,8 @@ -function init_with_data(self, stream) +function init_with_data(self, rect, stream) self.states = {} - + self.states.name = "mine" + stream:ReadU32() -- Skip unused "num patterns" stream:ReadU32() -- Skip unused "patterns" local scale = stream:ReadU32() diff --git a/data/scripts/slam_door.lua b/data/scripts/slam_door.lua index 665f241a..1a1ec345 100644 --- a/data/scripts/slam_door.lua +++ b/data/scripts/slam_door.lua @@ -1,7 +1,7 @@ -function init_with_data(self, stream) +function init_with_data(self, rect, stream) self.states = {} - + self.states.name = "slam_door" self.states.Closed = { diff --git a/data/scripts/switch.lua b/data/scripts/switch.lua index 60f07442..90d748b2 100644 --- a/data/scripts/switch.lua +++ b/data/scripts/switch.lua @@ -1,18 +1,53 @@ -function init_with_data(self, stream) - +function init_with_data(self, rect, stream) + self.mXPos = rect.x + 37 + self.mYPos = rect.y + rect.h - 5 self.states = {} - - self.states.WaitForActivate = { - animation = "SWITCH1.BAN_1009_AePc_0", - tick = function(s, i) - -- TODO: Detect if activated and from which direction - end + animation = "SwitchIdle", + -- Do nothing, other objects will query CanBeActivated and call Activate + tick = function(s, i) end + } + self.states.DoActivateLeft = + { + animation = "SwitchActivateLeft", + tick = function(s, i) if (s:IsLastFrame()) then return 'DoDeactivateLeft' end end + } + self.states.DoDeactivateLeft = + { + animation = "SwitchDeactivateLeft", + tick = function(s, i) if (s:IsLastFrame()) then return 'WaitForActivate' end end } + self.states.DoActivateRight = + { + animation = "SwitchActivateRight", + tick = function(s, i) if (s:IsLastFrame()) then return 'DoDeactivateRight' end end + } + self.states.DoDeactivateRight = + { + animation = "SwitchDeactivateRight", + tick = function(s, i) if (s:IsLastFrame()) then return 'WaitForActivate' end end + } + self.states.CanBeActivated = function() + print("CanBeActivated") + -- TODO: Only allow activate in certain states + --return self.states.Activate == self.states.WaitForActivate + return true + end + self.states.Activate = function(facingLeft) + print("Activate") + -- TODO: Activate whatever we are linked to + --GetObjectWithId(self.states.mId).Activate() + if facingLeft then + self.states.Active = self.states.DoActivateRight + else + self.states.Active = self.states.DoActivateLeft + end + self:SetAnimation(self.states.Active.animation) + end + self.states.name = "lever" self:ScriptLoadAnimations() - self.states.Active = self.states.WaitForActivate self:SetAnimation(self.states.Active.animation) end diff --git a/include/gridmap.hpp b/include/gridmap.hpp index 22316181..44bac5b5 100644 --- a/include/gridmap.hpp +++ b/include/gridmap.hpp @@ -29,17 +29,39 @@ namespace Physics } class Animation; + + +struct ObjRect +{ + s32 x; + s32 y; + s32 w; + s32 h; + + static void RegisterLuaBindings(sol::state& state) + { + state.new_usertype("ObjRect", + "x", &ObjRect::x, + "y", &ObjRect::y, + "w", &ObjRect::h, + "h", &ObjRect::h); + } +}; + class MapObject { public: MapObject(sol::state& luaState, ResourceLocator& locator, const std::string& scriptName); void Init(); - void Init(Oddlib::IStream& objData); + void Init(const ObjRect& rect, Oddlib::IStream& objData); void Update(const InputState& input); void Render(Renderer& rend, GuiContext& gui, int x, int y, float scale); void Input(const InputState& input); static void RegisterLuaBindings(sol::state& state); + bool ContainsPoint(s32 x, s32 y) const; + const std::string& Name() const { return mName; } + // TODO: Shouldn't be part of this object void SnapToGrid(); @@ -53,8 +75,7 @@ class MapObject sol::state& mLuaState; sol::table mStates; - void LoadScript(Oddlib::IStream* objData); - + void LoadScript(const ObjRect* rect, Oddlib::IStream* objData); private: // Actions void SetAnimation(const std::string& animation); @@ -73,6 +94,7 @@ class MapObject ResourceLocator& mLocator; std::string mScriptName; + std::string mName; }; class Level @@ -125,6 +147,7 @@ class GridMap void Update(const InputState& input); void Render(Renderer& rend, GuiContext& gui); private: + MapObject* GetMapObject(s32 x, s32 y, const char* type); void RenderDebug(Renderer& rend); void RenderEditor(Renderer& rend, GuiContext& gui); void RenderGame(Renderer& rend, GuiContext& gui); diff --git a/include/resourcemapper.hpp b/include/resourcemapper.hpp index 98e69871..3ab8e4dc 100644 --- a/include/resourcemapper.hpp +++ b/include/resourcemapper.hpp @@ -1902,8 +1902,8 @@ class Animation u32 mCounter = 0; s32 mFrameNum = -1; - s32 mXPos = 500; - s32 mYPos = 800; + s32 mXPos = 100; + s32 mYPos = 100; f32 mScale = 3; bool mIsLastFrame = false; diff --git a/src/engine.cpp b/src/engine.cpp index a6b6511f..34956a86 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -273,7 +273,7 @@ void Engine::InitSubSystems() mInputState.AddControllers(); - mLuaState.open_libraries(sol::lib::base, sol::lib::string, sol::lib::jit, sol::lib::table, sol::lib::debug); + mLuaState.open_libraries(sol::lib::base, sol::lib::string, sol::lib::jit, sol::lib::table, sol::lib::debug, sol::lib::math); // Redirect lua print() mLuaState.set_function("print", LuaLog); @@ -281,6 +281,7 @@ void Engine::InitSubSystems() Oddlib::IStream::RegisterLuaBindings(mLuaState); Actions::RegisterLuaBindings(mLuaState); MapObject::RegisterLuaBindings(mLuaState); + ObjRect::RegisterLuaBindings(mLuaState); } // TODO: Using averaging value or anything that is more accurate than this diff --git a/src/gridmap.cpp b/src/gridmap.cpp index 4845e99b..32421411 100644 --- a/src/gridmap.cpp +++ b/src/gridmap.cpp @@ -115,12 +115,12 @@ MapObject::MapObject(sol::state& luaState, ResourceLocator& locator, const std:: void MapObject::Init() { - LoadScript(nullptr); + LoadScript(nullptr, nullptr); } -void MapObject::Init(Oddlib::IStream& objData) +void MapObject::Init(const ObjRect& rect, Oddlib::IStream& objData) { - LoadScript(&objData); + LoadScript(&rect, &objData); } void MapObject::ScriptLoadAnimations() @@ -130,7 +130,11 @@ void MapObject::ScriptLoadAnimations() mStates.for_each([&](const sol::object& key, const sol::object& value) { std::string stateName = key.as(); - if (value.is()) + if (stateName == "name") + { + mName = value.as(); + } + else if (value.is()) { const sol::table& state = value.as(); state.for_each([&](const sol::object& key, const sol::object& value) @@ -155,7 +159,7 @@ void MapObject::ScriptLoadAnimations() }); } -void MapObject::LoadScript(Oddlib::IStream* objData) +void MapObject::LoadScript(const ObjRect* rect, Oddlib::IStream* objData) { // Load FSM script const std::string script = mLocator.LocateScript(mScriptName.c_str()); @@ -173,7 +177,7 @@ void MapObject::LoadScript(Oddlib::IStream* objData) if (objData) { sol::protected_function f = mLuaState["init_with_data"]; - auto ret = f(this, *objData); + auto ret = f(this, *rect, *objData); if (!ret.valid()) { sol::error err = ret; @@ -216,7 +220,7 @@ void MapObject::Update(const InputState& input) static float prevY = 0.0f; if (prevX != mXPos || prevY != mYPos) { - LOG_INFO("Player X Delta " << mXPos - prevX << " Y Delta " << mYPos - prevY << " frame " << mAnim->FrameNumber()); + //LOG_INFO("Player X Delta " << mXPos - prevX << " Y Delta " << mYPos - prevY << " frame " << mAnim->FrameNumber()); } prevX = mXPos; prevY = mYPos; @@ -264,6 +268,16 @@ void MapObject::Render(Renderer& rend, GuiContext& /*gui*/, int x, int y, float } } +bool MapObject::ContainsPoint(s32 x, s32 y) const +{ + if (!mAnim) + { + return false; + } + + return mAnim->Collision(x, y); +} + void MapObject::SnapToGrid() { //25x20 grid hack @@ -373,6 +387,9 @@ GridMap::GridMap(Oddlib::Path& path, ResourceLocator& locator, sol::state& luaSt mCollisionItemsSorted = mCollisionItems; mIsAo = path.IsAo(); + + luaState.set_function("GetMapObject", &GridMap::GetMapObject, this); + mScreens.resize(path.XSize()); for (auto& col : mScreens) { @@ -447,14 +464,20 @@ GridMap::GridMap(Oddlib::Path& path, ResourceLocator& locator, sol::state& luaSt } auto tmp = std::make_unique(luaState, locator, scriptName.c_str()); + + // Default "best guess" positioning tmp->mXPos = obj.mRectTopLeft.mX; tmp->mYPos = obj.mRectTopLeft.mY; - //tmp->mXPos = obj.mRectBottomRight.mX; - //tmp->mYPos = obj.mRectBottomRight.mY; + const ObjRect rect = { + obj.mRectTopLeft.mX, + obj.mRectTopLeft.mY, + obj.mRectBottomRight.mX - obj.mRectTopLeft.mX, + obj.mRectBottomRight.mY - obj.mRectTopLeft.mY + }; Oddlib::MemoryStream ms(std::vector(obj.mData.data(), obj.mData.data() + obj.mData.size())); - tmp->Init(ms); + tmp->Init(rect, ms); mObjs.push_back(std::move(tmp)); } @@ -535,6 +558,21 @@ bool GridMap::raycast_map(const glm::vec2& line1p1, const glm::vec2& line1p2, in return false; } +MapObject* GridMap::GetMapObject(s32 x, s32 y, const char* type) +{ + for (std::unique_ptr& obj : mObjs) + { + if (obj->Name() == type) + { + if (obj->ContainsPoint(x, y)) + { + return obj.get(); + } + } + } + return nullptr; +} + void GridMap::RenderDebug(Renderer& rend) { // Draw collisions