diff --git a/game/engine/dialogs/ShowEquipInven.lua b/game/engine/dialogs/ShowEquipInven.lua new file mode 100644 index 0000000000000000000000000000000000000000..24f9427740f6111e359fde84206b6e1bfa40b2ed --- /dev/null +++ b/game/engine/dialogs/ShowEquipInven.lua @@ -0,0 +1,115 @@ +require "engine.class" +require "engine.Dialog" + +module(..., package.seeall, class.inherit(engine.Dialog)) + +function _M:init(title, actor, filter, action) + self.action = action + self.filter = filter + self.actor = actor + engine.Dialog.init(self, title or "Inventory", game.w * 0.8, game.h * 0.8, nil, nil, nil, core.display.newFont("/data/font/VeraMono.ttf", 12)) + + self:generateList() + + self.list = self.inven_list + self.sel = 1 + self.scroll = 1 + self.max = math.floor((self.ih * 0.8 - 5) / self.font_h) - 1 + + self:keyCommands({ + __TEXTINPUT = function(c) + if self.list.chars[c] then + self.sel = self.list.chars[c] + self:use() + end + end, + },{ + MOVE_UP = function() self.sel = util.boundWrap(self.sel - 1, 1, #self.list) self.scroll = util.scroll(self.sel, self.scroll, self.max) self.changed = true end, + MOVE_DOWN = function() self.sel = util.boundWrap(self.sel + 1, 1, #self.list) self.scroll = util.scroll(self.sel, self.scroll, self.max) self.changed = true end, + MOVE_LEFT = function() self.list = self.equip_list self.sel = util.bound(self.sel, 1, #self.list) self.scroll = util.scroll(self.sel, self.scroll, self.max) self.changed = true end, + MOVE_RIGHT = function() self.list = self.inven_list self.sel = util.bound(self.sel, 1, #self.list) self.scroll = util.scroll(self.sel, self.scroll, self.max) self.changed = true end, + ACCEPT = function() self:use() end, + EXIT = function() game:unregisterDialog(self) end, + }) + self:mouseZones{ + { x=2, y=5, w=350, h=self.font_h*self.max, fct=function(button, x, y, xrel, yrel, tx, ty) + self.sel = util.bound(self.scroll + math.floor(ty / self.font_h), 1, #self.list) + if button == "left" then self:use() + elseif button == "right" then + end + end }, + } +end + +function _M:use() + if self.list[self.sel] and self.list[self.sel].item then + if self.action(self.list[self.sel].object, self.list[self.sel].inven, self.list[self.sel].item) then + game:unregisterDialog(self) + end + end +end + +function _M:generateList() + -- Makes up the list + local list = {} + local chars = {} + local i = 0 + for inven_id = 1, #self.actor.inven_def do + if self.actor.inven[inven_id] and self.actor.inven_def[inven_id].is_worn then + list[#list+1] = { name=self.actor.inven_def[inven_id].name, color={0x90, 0x90, 0x90}, inven=inven_id } + + for item, o in ipairs(self.actor.inven[inven_id]) do + if not self.filter or self.filter(o) then + local char = string.char(string.byte('a') + i) + list[#list+1] = { name=char..") "..o:getName(), color=o:getDisplayColor(), object=o, inven=inven_id, item=item } + chars[char] = #list + i = i + 1 + end + end + end + end + list.chars = chars + self.equip_list = list + + -- Makes up the list + local list = {} + local chars = {} + local i = 0 + for item, o in ipairs(self.actor:getInven("INVEN")) do + if not self.filter or self.filter(o) then + local char = string.char(string.byte('a') + i) + list[#list+1] = { name=char..") "..o:getName(), color=o:getDisplayColor(), object=o, inven=self.actor.INVEN_INVEN, item=item } + chars[char] = #list + i = i + 1 + end + end + list.chars = chars + self.inven_list = list + self.changed = true + + self.list = self.inven_list + self.sel = 1 + self.scroll = 1 +end + +function _M:drawDialog(s) + if not self.list[self.sel].item then + lines = self.actor.inven_def[self.list[self.sel].inven].description:splitLines(self.iw / 2 - 10, self.font) + elseif self.list[self.sel] and self.list[self.sel].object then + lines = self.list[self.sel].object:getDesc():splitLines(self.iw - 10, self.font) + else + lines = {} + end + + local sh = self.ih - 4 - #lines * self.font:lineSkip() + h = sh + self:drawWBorder(s, 3, sh, self.iw - 6) + for i = 1, #lines do + s:drawColorString(self.font, lines[i], 5, 2 + h) + h = h + self.font:lineSkip() + end + + self:drawSelectionList(s, 2, 5, self.font_h, self.equip_list, self.list == self.equip_list and self.sel or -1, "name", self.scroll, self.max) + self:drawHBorder(s, self.iw / 2, 2, sh - 4) + self:drawSelectionList(s, self.iw / 2 + 5, 5, self.font_h, self.inven_list, self.list == self.inven_list and self.sel or -1, "name", self.scroll, self.max) +end diff --git a/game/engine/dialogs/ShowStore.lua b/game/engine/dialogs/ShowStore.lua index 73392ca187583b472321f99d3e8d10ed63d9eaf8..00add3aeab506570ca6125d91807c76b3e10dd8c 100644 --- a/game/engine/dialogs/ShowStore.lua +++ b/game/engine/dialogs/ShowStore.lua @@ -89,20 +89,21 @@ function _M:generateList() end function _M:drawDialog(s) - h = self.ih * 0.80 + 4 if self.list[self.sel] then lines = self.desc(self.list == self.store_list and "buy" or "sell", self.list[self.sel].object):splitLines(self.iw - 10, self.font) else lines = {} end - self:drawWBorder(s, 3, self.ih * 0.80, self.iw - 6) + local sh = self.ih - 4 - #lines * self.font:lineSkip() + h = sh + self:drawWBorder(s, 3, sh, self.iw - 6) for i = 1, #lines do s:drawColorString(self.font, lines[i], 5, 2 + h) h = h + self.font:lineSkip() end self:drawSelectionList(s, 2, 5, self.font_h, self.store_list, self.list == self.store_list and self.sel or -1, "name", self.scroll, self.max) - self:drawHBorder(s, self.iw / 2, 2, self.ih * 0.80 - 4) + self:drawHBorder(s, self.iw / 2, 2, sh - 4) self:drawSelectionList(s, self.iw / 2 + 5, 5, self.font_h, self.actor_list, self.list == self.actor_list and self.sel or -1, "name", self.scroll, self.max) end diff --git a/game/engine/interface/ActorInventory.lua b/game/engine/interface/ActorInventory.lua index 920d5018735d5127be32c3126642ca721b009a1d..3ae2e741bb11ab64c458a204c55f2ce592c4f35e 100644 --- a/game/engine/interface/ActorInventory.lua +++ b/game/engine/interface/ActorInventory.lua @@ -2,6 +2,7 @@ require "engine.class" local Map = require "engine.Map" local ShowInventory = require "engine.dialogs.ShowInventory" local ShowEquipment = require "engine.dialogs.ShowEquipment" +local ShowEquipInven = require "engine.dialogs.ShowEquipInven" local ShowPickupFloor = require "engine.dialogs.ShowPickupFloor" --- Handles actors stats @@ -157,6 +158,16 @@ function _M:dropFloor(inven, item, vocal, all) return true end +--- Show combined equipment/inventory dialog +-- @param inven the inventory (from self:getInven()) +-- @param filter nil or a function that filters the objects to list +-- @param action a function called when an object is selected +function _M:showEquipInven(title, filter, action, allow_keybind) + local d = ShowEquipInven.new(title, self, filter, action, allow_keybind and self) + game:registerDialog(d) + return d +end + --- Show inventory dialog -- @param inven the inventory (from self:getInven()) -- @param filter nil or a function that filters the objects to list @@ -164,6 +175,7 @@ end function _M:showInventory(title, inven, filter, action, allow_keybind) local d = ShowInventory.new(title, inven, filter, action, allow_keybind and self) game:registerDialog(d) + return d end --- Show equipment dialog @@ -172,6 +184,7 @@ end function _M:showEquipment(title, filter, action, allow_keybind) local d = ShowEquipment.new(title, self, filter, action, allow_keybind and self) game:registerDialog(d) + return d end --- Show floor pickup dialog @@ -180,6 +193,7 @@ end function _M:showPickupFloor(title, filter, action) local d = ShowPickupFloor.new(title, self.x, self.y, filter, action) game:registerDialog(d) + return d end --- Can we wear this item? diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 3ec6a511a08c2fd5ffd24dec0c3fb3ed04d20f3a..6e49ee8f47a569e2a8ecde434ad087d7c4c28f06 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -459,7 +459,13 @@ function _M:setupCommands() self.player:playerDrop() end, SHOW_INVENTORY = function() - self.player:showInventory(nil, self.player:getInven(self.player.INVEN_INVEN), nil, function() end) + local d + d = self.player:showEquipInven(nil, nil, function(o, inven, item) + local ud = require("mod.dialogs.UseItemDialog").new(self.player, o, item, inven, function() + d:generateList() + end) + self:registerDialog(ud) + end) end, SHOW_EQUIPMENT = function() self.player:showEquipment(nil, nil, function() end) diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 6adcbfb0a0df6ae148c48f09f3066eae2d480b63..c99f202e2c104006a9103877edcf46bd7efeffce 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -214,6 +214,32 @@ function _M:runCheck() return engine.interface.PlayerRun.runCheck(self) end +function _M:doDrop(inven, item) + self:dropFloor(inven, item, true, true) + self:sortInven() + self:useEnergy() +end + +function _M:doWear(inven, item, o) + self:removeObject(self.INVEN_INVEN, item, true) + local ro = self:wearObject(o, true, true) + if ro then + if type(ro) == "table" then self:addObject(self.INVEN_INVEN, ro) end + else + self:addObject(self.INVEN_INVEN, o) + end + self:sortInven() + self:useEnergy() +end + +function _M:doTakeoff(inven, item, o) + if self:takeoffObject(inven, item) then + self:addObject(self.INVEN_INVEN, o) + end + self:sortInven() + self:useEnergy() +end + function _M:playerPickup() -- If 2 or more objects, display a pickup dialog, otehrwise just picks up if game.level.map:getObject(self.x, self.y, 2) then @@ -231,9 +257,7 @@ end function _M:playerDrop() local inven = self:getInven(self.INVEN_INVEN) self:showInventory("Drop object", inven, nil, function(o, item) - self:dropFloor(inven, item, true, true) - self:sortInven() - self:useEnergy() + self:doDrop(inven, item) end) end @@ -242,25 +266,13 @@ function _M:playerWear() self:showInventory("Wield/wear object", inven, function(o) return o:wornInven() and true or false end, function(o, item) - self:removeObject(self.INVEN_INVEN, item, true) - local ro = self:wearObject(o, true, true) - if ro then - if type(ro) == "table" then self:addObject(self.INVEN_INVEN, ro) end - else - self:addObject(self.INVEN_INVEN, o) - end - self:sortInven() - self:useEnergy() + self:doWear(inven, item, o) end) end function _M:playerTakeoff() self:showEquipment("Take off object", nil, function(o, inven, item) - if self:takeoffObject(inven, item) then - self:addObject(self.INVEN_INVEN, o) - end - self:sortInven() - self:useEnergy() + self:doTakeoff(inven, item, o) end) end diff --git a/game/modules/tome/dialogs/UseItemDialog.lua b/game/modules/tome/dialogs/UseItemDialog.lua new file mode 100644 index 0000000000000000000000000000000000000000..27ddb8d9e8edc523452ebb0889e1f4b7ee3e9088 --- /dev/null +++ b/game/modules/tome/dialogs/UseItemDialog.lua @@ -0,0 +1,81 @@ +require "engine.class" +require "engine.Dialog" +local Savefile = require "engine.Savefile" +local Map = require "engine.Map" + +module(..., package.seeall, class.inherit(engine.Dialog)) + +function _M:init(actor, object, item, inven, onuse) + self.actor = actor + self.object = object + self.inven = inven + self.item = item + self.onuse = onuse + + self.font = core.display.newFont("/data/font/Vera.ttf", 12) + self:generateList() + local name = object:getName() + local nw, nh = self.font:size(name) + engine.Dialog.init(self, name, math.max(nw, self.max) + 10, self.maxh + 10 + 25, nil, nil, nil, self.font) + + self.sel = 1 + self.scroll = 1 + self.max = math.floor((self.ih - 45) / self.font_h) - 1 + + self:keyCommands(nil, { + MOVE_UP = function() self.sel = util.boundWrap(self.sel - 1, 1, #self.list) self.scroll = util.scroll(self.sel, self.scroll, self.max) self.changed = true end, + MOVE_DOWN = function() self.sel = util.boundWrap(self.sel + 1, 1, #self.list) self.scroll = util.scroll(self.sel, self.scroll, self.max) self.changed = true end, + ACCEPT = function() self:use() end, + EXIT = function() game:unregisterDialog(self) end, + }) + self:mouseZones{ + { x=2, y=45, w=350, h=self.font_h*self.max, fct=function(button, x, y, xrel, yrel, tx, ty) + self.changed = true + self.sel = util.bound(self.scroll + math.floor(ty / self.font_h), 1, #self.list) + if button == "left" then self:learn(true) + elseif button == "right" then self:learn(false) + end + self.changed = true + end }, + } +end + +function _M:use() + if not self.list[self.sel] then return end + local act = self.list[self.sel].action + + if act == "use" then self.actor:playerUseItem(self.object, self.item) + elseif act == "drop" then self.actor:doDrop(self.inven, self.item) + elseif act == "wear" then self.actor:doWear(self.inven, self.item, self.object) + elseif act == "takeoff" then self.actor:doTakeoff(self.inven, self.item, self.object) + end + + self.onuse(self.inven, self.item, self.object) + + game:unregisterDialog(self) +end + +function _M:generateList() + local list = {} + + if self.object:canUseObject() then list[#list+1] = {name="Use", action="use"} end + if self.inven == self.actor.INVEN_INVEN and self.object:wornInven() then list[#list+1] = {name="Wield/Wear", action="wear"} end + if self.inven ~= self.actor.INVEN_INVEN and self.object:wornInven() then list[#list+1] = {name="Take off", action="takeoff"} end + if self.inven == self.actor.INVEN_INVEN then list[#list+1] = {name="Drop", action="drop"} end + + self.max = 0 + self.maxh = 0 + for i, v in ipairs(list) do + local w, h = self.font:size(v.name) + self.max = math.max(self.max, w) + self.maxh = self.maxh + h + end + + self.list = list +end + +function _M:drawDialog(s) + local h = 2 + self:drawSelectionList(s, 2, h, self.font_h, self.list, self.sel, "name") + self.changed = false +end diff --git a/ideas/cunning.ods b/ideas/cunning.ods index 4f3b823ab01ac7fe9959d7d006d265c14ab24e8c..fd21ddd66f6c4ce4568cc6e60885ee0ffc5feaca 100644 Binary files a/ideas/cunning.ods and b/ideas/cunning.ods differ