From 09dd59bebfd668732d02819bef9d53de757e4a98 Mon Sep 17 00:00:00 2001 From: notify Date: Wed, 5 Apr 2023 00:49:54 +0800 Subject: [PATCH] Extra interaction (#100) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为主动技/视为技提供了自定义额外交互的能力 可以在交互时候进行额外的UI操作 以及提供了一个UI组件,总之参考谋徐盛 --- lua/client/client_util.lua | 12 +++++++ lua/core/skill_type/active.lua | 1 + lua/core/skill_type/view_as.lua | 1 + lua/fk_ex.lua | 2 ++ lua/freekill.lua | 1 + lua/ui-util.lua | 33 +++++++++++++++++++ packages/test/init.lua | 12 +++++-- qml/Pages/Room.qml | 32 ++++++++++++++++++ .../SkillInteraction/SkillCombo.qml | 30 +++++++++++++++++ 9 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 lua/ui-util.lua create mode 100644 qml/Pages/RoomElement/SkillInteraction/SkillCombo.qml diff --git a/lua/client/client_util.lua b/lua/client/client_util.lua index 6eee0b18..b095038e 100644 --- a/lua/client/client_util.lua +++ b/lua/client/client_util.lua @@ -395,4 +395,16 @@ function GetGameModes() return json.encode(ret) end +function GetInteractionOfSkill(skill_name) + local skill = Fk.skills[skill_name] + return skill and json.encode(skill.interaction) or "null" +end + +function SetInteractionDataOfSkill(skill_name, data) + local skill = Fk.skills[skill_name] + if skill and type(skill.interaction) == "table" then + skill.interaction.data = json.decode(data) + end +end + dofile "lua/client/i18n/init.lua" diff --git a/lua/core/skill_type/active.lua b/lua/core/skill_type/active.lua index 7e81ed87..b1a09ffc 100644 --- a/lua/core/skill_type/active.lua +++ b/lua/core/skill_type/active.lua @@ -7,6 +7,7 @@ ---@field public max_card_num integer ---@field public card_num integer ---@field public card_num_table integer[] +---@field public interaction any local ActiveSkill = UsableSkill:subclass("ActiveSkill") function ActiveSkill:initialize(name) diff --git a/lua/core/skill_type/view_as.lua b/lua/core/skill_type/view_as.lua index efcc5513..92d795ef 100644 --- a/lua/core/skill_type/view_as.lua +++ b/lua/core/skill_type/view_as.lua @@ -1,5 +1,6 @@ ---@class ViewAsSkill : UsableSkill ---@field public pattern string @ cards that can be viewAs'ed by this skill +---@field public interaction any local ViewAsSkill = UsableSkill:subclass("ViewAsSkill") function ViewAsSkill:initialize(name) diff --git a/lua/fk_ex.lua b/lua/fk_ex.lua index 6e3c6bbb..0127d92a 100644 --- a/lua/fk_ex.lua +++ b/lua/fk_ex.lua @@ -167,6 +167,7 @@ function fk.CreateActiveSkill(spec) if spec.about_to_effect then skill.aboutToEffect = spec.about_to_effect end if spec.on_effect then skill.onEffect = spec.on_effect end if spec.on_nullified then skill.onNullified = spec.on_nullified end + skill.interaction = spec.interaction return skill end @@ -200,6 +201,7 @@ function fk.CreateViewAsSkill(spec) skill.enabledAtResponse = spec.enabled_at_response end + skill.interaction = spec.interaction return skill end diff --git a/lua/freekill.lua b/lua/freekill.lua index 2e95a516..13551d88 100644 --- a/lua/freekill.lua +++ b/lua/freekill.lua @@ -26,6 +26,7 @@ UsableSkill = require "core.skill_type.usable_skill" StatusSkill = require "core.skill_type.status_skill" Player = require "core.player" GameMode = require "core.game_mode" +UI = require "ui-util" -- load config local function loadConf() diff --git a/lua/ui-util.lua b/lua/ui-util.lua new file mode 100644 index 00000000..e5e1eb20 --- /dev/null +++ b/lua/ui-util.lua @@ -0,0 +1,33 @@ +-- 主动技/视为技用。 +-- 能创造一个简单的组件供UI使用。 + +-- 前端的应答/修改最终会被保存到xxx.data中。 + +local UI = {} + +--[[--------------------- + + ComboBox: 下拉对话框。 + + +-------------+ + | choices V | + +-------------+ + | choice1 | + +---------+ + | choice2 | + +---------+ + +--]]--------------------- + +-- 可以赋值的属性有: +-- * choices: string[] 类型,保存着可选项,会被前端翻译 +-- * default: string,默认的选项,默认为choices的第一个 +UI.ComboBox = function(spec) + assert(type(spec.choices) == "table", "Choices is not a table") + assert(#spec.choices > 0, "Choices is empty") + spec.default = spec.default or spec.choices[1] + spec.type = "combo" + return spec +end + +return UI diff --git a/packages/test/init.lua b/packages/test/init.lua index 3135f256..d876f235 100644 --- a/packages/test/init.lua +++ b/packages/test/init.lua @@ -61,10 +61,18 @@ local test_active = fk.CreateActiveSkill{ return true end, card_filter = function(self, card) - local c = Fk:getCardById(card) - return Self:getPileNameOfId(card) == self.name and c.color == Card.Red + if self.interaction.data == "joy" then + --local c = Fk:getCardById(card) + --return Self:getPileNameOfId(card) == self.name and c.color == Card.Red + return true + end end, + card_num = 2, target_filter = function() return true end, + interaction = UI.ComboBox { + choices = Fk.package_names, + -- default = "guanyu", + }, on_use = function(self, room, effect) --room:doSuperLightBox("packages/test/qml/Test.qml") local from = room:getPlayerById(effect.from) diff --git a/qml/Pages/Room.qml b/qml/Pages/Room.qml index ad0199e9..b9e59edf 100644 --- a/qml/Pages/Room.qml +++ b/qml/Pages/Room.qml @@ -26,6 +26,7 @@ Item { property alias cancelButton: cancelButton property alias dynamicCardArea: dynamicCardArea property alias tableCards: tablePile.cards + property alias dashboard: dashboard property var selected_targets: [] property string responding_card @@ -89,6 +90,7 @@ Item { from: "*"; to: "notactive" ScriptAction { script: { + skillInteraction.source = ""; promptText = ""; progress.visible = false; okCancel.visible = false; @@ -114,6 +116,7 @@ Item { from: "*"; to: "playing" ScriptAction { script: { + skillInteraction.source = ""; dashboard.enableCards(); dashboard.enableSkills(); progress.visible = true; @@ -128,6 +131,7 @@ Item { from: "*"; to: "responding" ScriptAction { script: { + skillInteraction.source = ""; dashboard.enableCards(responding_card); dashboard.enableSkills(responding_card); progress.visible = true; @@ -140,6 +144,7 @@ Item { from: "*"; to: "replying" ScriptAction { script: { + skillInteraction.source = ""; dashboard.disableAllCards(); dashboard.disableSkills(); progress.visible = true; @@ -383,6 +388,14 @@ Item { } } + Loader { + id: skillInteraction + visible: dashboard.pending_skill !== "" + anchors.bottom: parent.bottom + anchors.bottomMargin: 8 + anchors.right: okCancel.left + anchors.rightMargin: 20 + } Row { id: okCancel @@ -469,9 +482,28 @@ Item { function activateSkill(skill_name, pressed) { if (pressed) { + let data = JSON.parse(Backend.callLuaFunction("GetInteractionOfSkill", [skill_name])); + if (data) { + Backend.callLuaFunction("SetInteractionDataOfSkill", [skill_name, "null"]); + switch (data.type) { + case "combo": + skillInteraction.source = "RoomElement/SkillInteraction/SkillCombo.qml"; + skillInteraction.item.skill = skill_name; + skillInteraction.item.default_choice = data["default"]; + skillInteraction.item.choices = data.choices; + break; + default: + skillInteraction.source = ""; + break; + } + } else { + skillInteraction.source = ""; + } + dashboard.startPending(skill_name); cancelButton.enabled = true; } else { + skillInteraction.source = ""; Logic.doCancelButton(); } } diff --git a/qml/Pages/RoomElement/SkillInteraction/SkillCombo.qml b/qml/Pages/RoomElement/SkillInteraction/SkillCombo.qml new file mode 100644 index 00000000..4ab12eec --- /dev/null +++ b/qml/Pages/RoomElement/SkillInteraction/SkillCombo.qml @@ -0,0 +1,30 @@ +import QtQuick +import "../.." + +MetroButton { + id: root + property string skill + property var choices: [] + property string default_choice + property string answer: default_choice + text: Backend.translate(answer) + + onAnswerChanged: { + if (!answer) return; + Backend.callLuaFunction( + "SetInteractionDataOfSkill", + [skill, JSON.stringify(answer)] + ); + roomScene.dashboard.startPending(skill); + } + + onClicked: { + roomScene.popupBox.source = "RoomElement/ChoiceBox.qml"; + let box = roomScene.popupBox.item; + box.options = choices; + box.accepted.connect(() => { + answer = choices[box.result]; + }); + } + +}