diff --git a/game/engine/Quest.lua b/game/engine/Quest.lua index e05e859559e6bd554ec1a5a5ed25e97592bd9559..7e8f431fb0615ecc2fa5a093170f7cedde337950 100644 --- a/game/engine/Quest.lua +++ b/game/engine/Quest.lua @@ -43,11 +43,11 @@ function _M:check(prop, ...) end end ---- Sets the quets status or sub-objective status +--- Sets the quests status or sub-objective status -- @param status one of the possible quest status (PENDING, COMPLETED, DONE, FAILED) function _M:setStatus(status, sub, who) if sub then - if self.objectives[sub] == status then return false end + if self.objectives[sub] and self.objectives[sub] == status then return false end self.objectives[sub] = status self:check("on_status_change", who, status, sub) return true @@ -58,3 +58,15 @@ function _M:setStatus(status, sub, who) return true end end + +--- Checks the quests status or sub-objective status +-- @param status one of the possible quest status (PENDING, COMPLETED, DONE, FAILED) +function _M:isStatus(status, sub) + if sub then + if self.objectives[sub] and self.objectives[sub] == status then return true end + return false + else + if self.status == status then return true end + return false + end +end diff --git a/game/engine/interface/ActorInventory.lua b/game/engine/interface/ActorInventory.lua index 53cc8d83ba85b227c28cfa3517ace29428e8d05d..920d5018735d5127be32c3126642ca721b009a1d 100644 --- a/game/engine/interface/ActorInventory.lua +++ b/game/engine/interface/ActorInventory.lua @@ -68,6 +68,8 @@ function _M:addObject(inven_id, o) -- No room ? if #inven >= inven.max then return false end + if o:check("on_preaddobject", self, inven) then return false end + -- Ok add it table.insert(inven, o) @@ -111,7 +113,11 @@ end -- @return the object removed or nil if no item existed function _M:removeObject(inven, item, no_unstack) if type(inven) == "number" then inven = self.inven[inven] end + local o, finish = inven[item], true + + if o:check("on_preremoveobject", self, inven) then return false end + if not no_unstack then o, finish = o:unstack() end @@ -139,14 +145,16 @@ end -- @param item the item id to drop -- @return the object removed or nil if no item existed function _M:dropFloor(inven, item, vocal, all) - local o = self:removeObject(inven, item, all) + local o = self:getInven(inven)[item] if not o then if vocal then game.logSeen(self, "There is nothing to drop.") end return end - if o:check("on_drop", self) then return end + if o:check("on_drop", self) then return false end + o = self:removeObject(inven, item, all) game.level.map:addObject(self.x, self.y, o) if vocal then game.logSeen(self, "%s drops on the floor: %s.", self.name:capitalize(), o:getName{do_color=true}) end + return true end --- Show inventory dialog @@ -231,6 +239,7 @@ function _M:wearObject(o, replace, vocal) if vocal then game.logSeen(self, "%s can not wear: %s (%s).", self.name:capitalize(), o:getName{do_color=true}, err) end return false end + if o:check("on_canwear", self, inven) then return false end if self:addObject(inven, o) then if vocal then game.logSeen(self, "%s wears: %s.", self.name:capitalize(), o:getName{do_color=true}) end @@ -258,7 +267,10 @@ end --- Takeoff item function _M:takeoffObject(inven, item) - local o = self:removeObject(inven, item, true) + local o = self:getInven(inven)[item] + if o:check("on_cantakeoff", self, inven) then return false end + + o = self:removeObject(inven, item, true) return o end @@ -317,8 +329,22 @@ function _M:sortInven(inven) end --- Finds an object by name in an inventory -function _M:findInInventory(inven, name) +-- @param inven the inventory to look into +-- @param name the name to look for +-- @param getname the parameters to pass to getName(), if nil the default is {no_count=true, force_id=true} +function _M:findInInventory(inven, name, getname) + getname = getname or {no_count=true, force_id=true} for item, o in ipairs(inven) do - if o:getName{no_count=true} == name then return o, item end + if o:getName(getname) == name then return o, item end + end +end + +--- Finds an object by name in all the actor's inventories +-- @param name the name to look for +-- @param getname the parameters to pass to getName(), if nil the default is {no_count=true, force_id=true} +function _M:findInAllInventories(name, getname) + for inven_id, inven in pairs(self.inven) do + local o, item = self:findInInventory(inven, name, getname) + if o and item then return o, item, inven_id end end end diff --git a/game/engine/interface/ActorQuest.lua b/game/engine/interface/ActorQuest.lua index 27fb2dc031d7daf12369bc56128988ce848b3358..3e65ba41585cab3a18e0d19b43ab3c4172c39302 100644 --- a/game/engine/interface/ActorQuest.lua +++ b/game/engine/interface/ActorQuest.lua @@ -45,3 +45,12 @@ function _M:hasQuest(id) if not self.quests then return false end return self.quests[id] and true or false end + +--- Checks the status of the given quest +-- If the actor does not have the quest, does nothing +function _M:isQuestStatus(quest, status, sub) + if not self.quests then return end + local q = self.quests[quest] + if not q then return end + return q:isStatus(status, sub) +end diff --git a/game/modules/tome/data/chats/minas-tirith-elder.lua b/game/modules/tome/data/chats/minas-tirith-elder.lua index 31c78b4a431e05ab025356af27f233d0ef6e53a4..988aaa66b2c2aa9e3ba3e169bdede4f7a067ace6 100644 --- a/game/modules/tome/data/chats/minas-tirith-elder.lua +++ b/game/modules/tome/data/chats/minas-tirith-elder.lua @@ -2,7 +2,7 @@ newChat{ id="welcome", text = [[Welcome @playername@ to Minas Tirith traveler, please be quick my time is precious.]], answers = { {"Nothing, excuse me. Bye!"}, - {"I have found this staff in my travels, it looks really old and powerful. I dare not use it.", jump="found_staff"}, + {"I have found this staff in my travels, it looks really old and powerful. I dare not use it.", jump="found_staff", cond=function(npc, player) return player:isQuestStatus("staff-absorption", engine.Quest.PENDING) and player:findInAllInventories("Staff of Absorption") end}, } } @@ -12,6 +12,10 @@ Please surrender the staff to the protection of the King while we work to learn This could be related to the rumours we hear from the far east...]], answers = { {"Take it Sir.", action=function(npc, player) + local o, item, inven_id = player:findInAllInventories("Staff of Absorption") + player:removeObject(inven_id, item, true) + o:removed() + player:setQuestStatus("staff-absorption", engine.Quest.DONE) player.winner = true local D = require "engine.Dialog" diff --git a/game/modules/tome/data/general/objects/quest-artifacts.lua b/game/modules/tome/data/general/objects/quest-artifacts.lua index 4158a938782bc636e6d27e2672c56a608d5fb145..93f4feda02f8db1c714bdbdc2e70b84d68ae802a 100644 --- a/game/modules/tome/data/general/objects/quest-artifacts.lua +++ b/game/modules/tome/data/general/objects/quest-artifacts.lua @@ -36,4 +36,10 @@ newEntity{ define_as = "STAFF_ABSORPTION", who:grantQuest("staff-absorption") end end, + on_drop = function(self, who) + if who == game.player then + game.logPlayer(who, "You cannot bring yourself to drop the %s", self:getName()) + return true + end + end, }