From d39440fa29ba62ceaea90a1780fd3ec33f45c56a Mon Sep 17 00:00:00 2001 From: Kazhnuz Date: Sat, 31 Aug 2019 14:09:48 +0200 Subject: [PATCH] chore(cbs/menu): refactor the menu system to make adding widget simpler --- .../scenes/battlesystem/menu.lua | 288 +++++++++++------- 1 file changed, 174 insertions(+), 114 deletions(-) diff --git a/sonic-radiance.love/scenes/battlesystem/menu.lua b/sonic-radiance.love/scenes/battlesystem/menu.lua index b20a30d..b996938 100644 --- a/sonic-radiance.love/scenes/battlesystem/menu.lua +++ b/sonic-radiance.love/scenes/battlesystem/menu.lua @@ -4,10 +4,11 @@ local Widget = require "core.modules.menusystem.widgets" local MenuConstructor = Object:extend() local CharacterMenu = ListBox:extend() -local CharMenuWidget = Widget.Text:extend() -local SubMenuWidget = CharMenuWidget:extend() -local BackMenuWidget = CharMenuWidget:extend() -local SkillWidget = Widget.Text: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 = 112, 17 @@ -32,12 +33,12 @@ end function MenuConstructor:buildBaseMenu(character) CharacterMenu(self.controller, "BaseMenu", MENUPOS_X1 - 16, MENUPOS_Y) - CharMenuWidget(self.controller, "BaseMenu", "attack", "", character) - SubMenuWidget(self.controller, "BaseMenu", "skills", "SkillMenu", character) - SubMenuWidget(self.controller, "BaseMenu", "objects", "ObjectMenu", character) - CharMenuWidget(self.controller, "BaseMenu", "defend", "", character) - CharMenuWidget(self.controller, "BaseMenu", "flee", "", character) - BackMenuWidget(self.controller, "BaseMenu", "back", character) + 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 @@ -50,9 +51,9 @@ 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(self.controller, "SkillMenu", skill.name, "", character) + SkillWidget(character, "SkillMenu", skill.name, "") end - SubMenuWidget(self.controller, "SkillMenu", "back", "BaseMenu", character) + SubMenuWidget(character, "SkillMenu", "back", "BaseMenu") self.controller.menusystem.menus["SkillMenu"]:setCancelWidget() end @@ -66,16 +67,16 @@ function MenuConstructor:buildObjectMenu(character) CharacterMenu(self.controller, "OtherMenu", MENUPOS_X1 - 16, MENUPOS_Y) - SubMenuWidget(self.controller, "ObjectMenu", "heal", "MedMenu", character) - SubMenuWidget(self.controller, "ObjectMenu", "rings", "RingMenu", character) - SubMenuWidget(self.controller, "ObjectMenu", "wisps", "WispMenu", character) - SubMenuWidget(self.controller, "ObjectMenu", "other", "OtherMenu", character) + SubMenuWidget(character, "ObjectMenu", "heal", "MedMenu") + SubMenuWidget(character, "ObjectMenu", "rings", "RingMenu") + SubMenuWidget(character, "ObjectMenu", "wisps", "WispMenu") + SubMenuWidget(character, "ObjectMenu", "other", "OtherMenu") - SubMenuWidget(self.controller, "ObjectMenu", "back", "BaseMenu", character) - SubMenuWidget(self.controller, "MedMenu", "back", "ObjectMenu", character) - SubMenuWidget(self.controller, "RingMenu", "back", "ObjectMenu", character) - SubMenuWidget(self.controller, "WispMenu", "back", "ObjectMenu", character) - SubMenuWidget(self.controller, "OtherMenu", "back", "ObjectMenu", character) + 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() @@ -125,35 +126,68 @@ end -- WIDGETS -- All widgets used by the Characters menus -function CharMenuWidget:new(scene, menu_name, label1, label2, character) - self.character = character - self.menuname = menu_name - self.scene = scene - self.actionType = label1 +-- Basic Battle Widget +-- The base used by all battle widgets - local menu = scene.menusystem.menus[menu_name] or error("menu " ..menu_name .. " doesn't exist") - local font = scene.assets.fonts["small"] - CharMenuWidget.super.new(self, menu, font, core.lang:translate("battle", label1)) - self.label2 = label2 or "" - self.isSelected = false +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 CharMenuWidget:update(dt) - CharMenuWidget.super.update(self, dt) +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 -function CharMenuWidget:selectAction() - self.isSelected = true - if self.actionType == "attack" then - self.scene.world:resetActiveGrid() - self.scene.world:setEffectGrid(self.character.x + self.character.direction, self.character.y, "point", 1, 1) +-- 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 CharMenuWidget:drawCanvas() +function BattleWidget:drawCanvas() local h local asset = love.graphics.newImage("assets/gui/attacklist.png") love.graphics.draw(asset, 0, (self.height - 13) / 2) @@ -166,18 +200,63 @@ function CharMenuWidget:drawCanvas() self.font:print(self.label2, self.width - 9, h, "right") end -function CharMenuWidget:action() +function BattleWidget:action() self.scene.world:resetActiveGrid() self.scene.world:resetEffectGrid() - self.character:receiveSignal(self.actionType) + + self:sendCharacterData() + self.scene:flushKeys() self.scene.menusystem:reset() end --- Submenu Widget +-- External functions -function SubMenuWidget:new(scene, menu_name, label, newmenu, character) - SubMenuWidget.super.new(self, scene, menu_name, label, "", character) +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) + SubMenuWidget.super.new(self, character, menu_name, label, "") self.newmenu = newmenu or "BaseMenu" end @@ -185,107 +264,88 @@ function SubMenuWidget:action() self.scene.menusystem:switchMenu(self.newmenu) end --- Back Widget +-- BackMenuWidget +-- Quit the menu -function BackMenuWidget:new(scene, menu_name, label, character) - BackMenuWidget.super.new(self, scene, menu_name, "back", "", character) +function BackMenuWidget:new(character, menu_name) + BackMenuWidget.super.new(self, character, menu_name, "back", "") end -function BackMenuWidget:action() - self.scene.world:resetActiveGrid() - self.scene.world:resetEffectGrid() +function BackMenuWidget:sendCharacterData() self.character:receiveBackSignal() - self.scene:flushKeys() - self.scene.menusystem:reset() end --- Skill Widget +-- SkillWidget +-- A widget to handle skills -function SkillWidget:new(scene, menu_name, label1, label2, character) - self.character = character - self.menuname = menu_name - self.scene = scene - self.actionType = label1 +function SkillWidget:new(character, menu_name, skill) + self.skillname = skill + local label2 = "00" - local menu = scene.menusystem.menus[menu_name] or error("menu " ..menu_name .. " doesn't exist") - local font = scene.assets.fonts["small"] - - self.skilldata = game.skills:getSkillData(self.actionType) - - CharMenuWidget.super.new(self, menu, font, core.lang:translate("skills", label1)) + self.skilldata = game.skills:getSkillData(skill) if self.skilldata ~= nil then - self.label2 = self.skilldata.cost or 0 - if self.label2 < 10 then - self.label2 = "0" .. self.label2 + label2 = self.skilldata.cost or 0 + if label2 < 10 then + label2 = "0" .. label2 end - else - self.label2 = "n" end + + SkillWidget.super.new(self, character, menu_name, self.skillname, "-" .. label2, "skills") end function SkillWidget:selectAction() if self.skilldata ~= nil then - if self.skilldata.target == nil then - 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 - self.scene.world:resetActiveGrid() - self.scene.world:setEffectGrid(x, y, shape, size, direction) - else - 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 - self.scene.world:setActiveGrid(x, y, shape, size, direction) - self.scene.world:resetEffectGrid() - end - + SkillWidget.super.selectAction(self) else self.scene.world:resetActiveGrid() self.scene.world:resetEffectGrid() end end - -function SkillWidget:drawCanvas() - local h - local asset = love.graphics.newImage("assets/gui/attacklist.png") - love.graphics.draw(asset, 0, (self.height - 13) / 2) - 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") +function SkillWidget:haveActiveGrid() + return (self.skilldata.target ~= nil) end -function SkillWidget:action() - self.scene.world:resetActiveGrid() - self.scene.world:resetEffectGrid() +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.skilldata.target == nil then - self.character:useSkill(self.actionType, self.character.x, self.character.y) - else - 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 + 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.actionType) + 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.actionType .. " doesn't exist") + core.debug:warning("cbs/menu", "skill " .. self.skillname .. " doesn't exist") self.character:receiveSignal("none") end - self.scene:flushKeys() - self.scene.menusystem:reset() + end return MenuConstructor