local ListBox = require "core.modules.menusystem.listbox" local Widget = require "core.modules.menusystem.widgets" local MenuConstructor = Object:extend() local CharacterMenu = ListBox:extend() local BattleWidget = Widget.Text:extend() local ActionWidget = BattleWidget:extend() local SubMenuWidget = BattleWidget:extend() local BackMenuWidget = BattleWidget:extend() local SkillWidget = BattleWidget:extend() local MENUPOS_X1, MENUPOS_X2, MENUPOS_Y = 32, 32, 110 local MENU_WIDTH, MENU_ITEM_HEIGHT = 148, 17 local MENU_ITEM_NUMBER = 6 function MenuConstructor:new( controller ) self.controller = controller end function MenuConstructor:reconstruct(character) self.controller.menusystem:reset() self:build(character) self.controller.menusystem:switchMenu("BaseMenu") end function MenuConstructor:build(character) self:buildBaseMenu(character) self:buildSkillMenu(character) self:buildObjectMenu(character) end function MenuConstructor:buildBaseMenu(character) CharacterMenu(self.controller, "BaseMenu", MENUPOS_X1 - 16, MENUPOS_Y) ActionWidget(character, "BaseMenu", "attack") SubMenuWidget(character, "BaseMenu", "skills", "SkillMenu") SubMenuWidget(character, "BaseMenu", "objects", "ObjectMenu") ActionWidget(character, "BaseMenu", "defend") ActionWidget(character, "BaseMenu", "flee") BackMenuWidget(character, "BaseMenu") self.controller.menusystem.menus["BaseMenu"]:setCancelWidget() end function MenuConstructor:set(currentCharacter) self:reconstruct(currentCharacter) end function MenuConstructor:buildSkillMenu(character) CharacterMenu(self.controller, "SkillMenu", MENUPOS_X1 - 16, MENUPOS_Y) local list = game.characters:getSkillList(character.charid) for k, skill in pairs(list) do SkillWidget(character, "SkillMenu", skill.name, "") end SubMenuWidget(character, "SkillMenu", "back", "BaseMenu") self.controller.menusystem.menus["SkillMenu"]:setCancelWidget() end function MenuConstructor:buildObjectMenu(character) CharacterMenu(self.controller, "ObjectMenu", MENUPOS_X1 - 16, MENUPOS_Y) CharacterMenu(self.controller, "MedMenu", MENUPOS_X1 - 16, MENUPOS_Y) CharacterMenu(self.controller, "RingMenu", MENUPOS_X1 - 16, MENUPOS_Y) CharacterMenu(self.controller, "WispMenu", MENUPOS_X1 - 16, MENUPOS_Y) CharacterMenu(self.controller, "OtherMenu", MENUPOS_X1 - 16, MENUPOS_Y) SubMenuWidget(character, "ObjectMenu", "heal", "MedMenu") SubMenuWidget(character, "ObjectMenu", "rings", "RingMenu") SubMenuWidget(character, "ObjectMenu", "wisps", "WispMenu") SubMenuWidget(character, "ObjectMenu", "other", "OtherMenu") SubMenuWidget(character, "ObjectMenu", "back", "BaseMenu") SubMenuWidget(character, "MedMenu", "back", "ObjectMenu") SubMenuWidget(character, "RingMenu", "back", "ObjectMenu") SubMenuWidget(character, "WispMenu", "back", "ObjectMenu") SubMenuWidget(character, "OtherMenu", "back", "ObjectMenu") self.controller.menusystem.menus["ObjectMenu"]:setCancelWidget() self.controller.menusystem.menus["MedMenu"]:setCancelWidget() self.controller.menusystem.menus["RingMenu"]:setCancelWidget() self.controller.menusystem.menus["WispMenu"]:setCancelWidget() self.controller.menusystem.menus["OtherMenu"]:setCancelWidget() end function MenuConstructor:unset( ) self.isActive = false end -- CHARACTER_MENU -- The actuals menus in the character menu function CharacterMenu:new(scene, name, x, y) self.scene = scene local w, h = MENU_WIDTH, MENU_ITEM_NUMBER * MENU_ITEM_HEIGHT CharacterMenu.super.new(self, scene.menusystem, name, x, y, w, h, MENU_ITEM_NUMBER) self.cursorTexture = love.graphics.newImage("assets/gui/cursor-menulist.png") self.cursorTransition = 1 end function CharacterMenu:update(dt) CharacterMenu.super.update(self, dt) local relativecursor = self.widget.selected - self.view.firstSlot local transition = self.cursorTransition - relativecursor if math.abs(transition) < 0.1 then self.cursorTransition = relativecursor else self.cursorTransition = (self.cursorTransition) + ((relativecursor) - (self.cursorTransition)) * dt*45 end end function CharacterMenu:drawCursor() local addition = 17 love.graphics.draw(self.cursorTexture, self.x + 4, self.y + (self.cursorTransition) * addition ) end -- WIDGETS -- All widgets used by the Characters menus -- Basic Battle Widget -- The base used by all battle widgets function BattleWidget:new(character, menu_name, label1, label2, translationdata) local menu = self:getControllers(character, menu_name) local translationdata = translationdata or "battle" local label1 = label1 or "" local label2 = label2 or "" label1 = core.lang:translate(translationdata, label1) local font = self.assets.fonts["small"] BattleWidget.super.new(self, menu, font, label1) self.label2 = label2 end function BattleWidget:getControllers(character, menu_name) self.character = character or core.debug:error("cbs/widget", "character must not be nil") self.scene = self.character.scene self.assets = self.character.assets self.menusystem = self.scene.menusystem self.menuname = menu_name local menu = self.menusystem.menus[menu_name] or error("menu " ..menu_name .. " doesn't exist") return menu end -- Internal functions function BattleWidget:update(dt) BattleWidget.super.update(self, dt) end function BattleWidget:selectAction() self:setActiveGrid() self:setEffectGrid() end function BattleWidget:setActiveGrid() if (self:haveActiveGrid()) then local ox, oy, shape, size, idk = self:getActiveGrid() self.scene.world:setActiveGrid(ox, oy, shape, size, idk) else self.scene.world:resetActiveGrid() end end function BattleWidget:setEffectGrid() if (self:haveEffectGrid()) then local ox, oy, shape, size, idk = self:getEffectGrid() self.scene.world:setEffectGrid(ox, oy, shape, size, idk) else self.scene.world:resetEffectGrid() end end function BattleWidget:drawCanvas() local h local asset = love.graphics.newImage("assets/gui/attacklist.png") local sw, sh = asset:getDimensions() local startAsset = love.graphics.newQuad(0, 0, 16, sh, sw, sh) local midAsset = love.graphics.newQuad(16, 0, 1, sh, sw, sh) local endAsset = love.graphics.newQuad(sw-16, 0, 16, sh, sw, sh) love.graphics.draw(asset, startAsset, 0, (self.height - 13) / 2) love.graphics.draw(asset, endAsset, self.width-16, (self.height - 13) / 2) local iterations = self.width-32 for i=0,iterations do love.graphics.draw(asset, midAsset, 16+i, (self.height - 13) / 2) end h = math.floor(self.height / 2) - (self.font:getHeight() / 2) love.graphics.setColor(0, 0, 0, .8) self.font:print(self.label, 17, h, "left") self.font:print(self.label2, self.width - 8, h, "right") utils.graphics.resetColor() self.font:print(self.label, 16, h, "left") self.font:print(self.label2, self.width - 9, h, "right") end function BattleWidget:action() self.scene.world:resetActiveGrid() self.scene.world:resetEffectGrid() self:sendCharacterData() self.scene:flushKeys() self.scene.menusystem:reset() end -- External functions function BattleWidget:haveActiveGrid() return false end function BattleWidget:getActiveGrid() return 0, 0, "point", 0, 0 end function BattleWidget:haveEffectGrid() return false end function BattleWidget:getEffectGrid() return 0, 0, "point", 0, 0 end function BattleWidget:sendCharacterData() self.character:receiveSignal() end -- ActionWidget -- The basic action widget function ActionWidget:new(character, menu_name, action) self.actionType = action or "" ActionWidget.super.new(self, character, menu_name, action, "") end function ActionWidget:haveEffectGrid() return (self.actionType == "attack") end function ActionWidget:getEffectGrid() return self.character.x + self.character.direction, self.character.y, "point", 1, 1 end function ActionWidget:sendCharacterData() self.character:receiveSignal(self.actionType) end -- SubMenuWidget -- A simple widget to change menu function SubMenuWidget:new(character, menu_name, label, newmenu) local label2 = "" if label ~= "back" then label2 = ">" end SubMenuWidget.super.new(self, character, menu_name, label, label2) self.newmenu = newmenu or "BaseMenu" end function SubMenuWidget:action() self.scene.menusystem:switchMenu(self.newmenu) end -- BackMenuWidget -- Quit the menu function BackMenuWidget:new(character, menu_name) BackMenuWidget.super.new(self, character, menu_name, "back", "") end function BackMenuWidget:sendCharacterData() self.character:receiveBackSignal() end -- SkillWidget -- A widget to handle skills function SkillWidget:new(character, menu_name, skill) self.skillname = skill local label2 = "00" self.skilldata = game.skills:getSkillData(skill) if self.skilldata ~= nil then label2 = self.skilldata.cost or 0 if label2 < 10 then label2 = "0" .. label2 end end SkillWidget.super.new(self, character, menu_name, self.skillname, "-" .. label2, "skills") end function SkillWidget:selectAction() if self.skilldata ~= nil then SkillWidget.super.selectAction(self) else self.scene.world:resetActiveGrid() self.scene.world:resetEffectGrid() end end function SkillWidget:haveActiveGrid() return (self.skilldata.target ~= nil) end function SkillWidget:haveEffectGrid() return ((self.skilldata.target == nil) and (self.skilldata.effectArea ~= nil)) end function SkillWidget:getActiveGrid() local x = self.character.x + self.skilldata.target[1] local y = self.character.y + self.skilldata.target[2] local shape = self.skilldata.target[3] local size = self.skilldata.target[4] local direction = self.character.direction return x, y, shape, size, direction end function SkillWidget:getEffectGrid() local x = self.character.x + self.skilldata.effectArea[1] local y = self.character.y + self.skilldata.effectArea[2] local shape = self.skilldata.effectArea[3] local size = self.skilldata.effectArea[4] local direction = self.character.direction return x, y, shape, size, direction end function SkillWidget:sendCharacterData() if self.skilldata ~= nil then if self:haveActiveGrid() then local x, y, shape, size, direction = self:getActiveGrid() self.scene.world.cursor:setGridIgnoreActor(x, y, shape, size, direction) self.scene.world.cursor:set(self.character.x, self.character.y, "skill", self.skillname) else self.character:useSkill(self.skillname, self.character.x, self.character.y) end else core.debug:warning("cbs/menu", "skill " .. self.skillname .. " doesn't exist") self.character:receiveSignal("none") end end return MenuConstructor