Extra interaction (#100)

为主动技/视为技提供了自定义额外交互的能力
可以在交互时候进行额外的UI操作
以及提供了一个UI组件,总之参考谋徐盛
This commit is contained in:
notify 2023-04-05 00:49:54 +08:00 committed by GitHub
parent 2e37b46234
commit 09dd59bebf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 122 additions and 2 deletions

View File

@ -395,4 +395,16 @@ function GetGameModes()
return json.encode(ret) return json.encode(ret)
end 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" dofile "lua/client/i18n/init.lua"

View File

@ -7,6 +7,7 @@
---@field public max_card_num integer ---@field public max_card_num integer
---@field public card_num integer ---@field public card_num integer
---@field public card_num_table integer[] ---@field public card_num_table integer[]
---@field public interaction any
local ActiveSkill = UsableSkill:subclass("ActiveSkill") local ActiveSkill = UsableSkill:subclass("ActiveSkill")
function ActiveSkill:initialize(name) function ActiveSkill:initialize(name)

View File

@ -1,5 +1,6 @@
---@class ViewAsSkill : UsableSkill ---@class ViewAsSkill : UsableSkill
---@field public pattern string @ cards that can be viewAs'ed by this skill ---@field public pattern string @ cards that can be viewAs'ed by this skill
---@field public interaction any
local ViewAsSkill = UsableSkill:subclass("ViewAsSkill") local ViewAsSkill = UsableSkill:subclass("ViewAsSkill")
function ViewAsSkill:initialize(name) function ViewAsSkill:initialize(name)

View File

@ -167,6 +167,7 @@ function fk.CreateActiveSkill(spec)
if spec.about_to_effect then skill.aboutToEffect = spec.about_to_effect end 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_effect then skill.onEffect = spec.on_effect end
if spec.on_nullified then skill.onNullified = spec.on_nullified end if spec.on_nullified then skill.onNullified = spec.on_nullified end
skill.interaction = spec.interaction
return skill return skill
end end
@ -200,6 +201,7 @@ function fk.CreateViewAsSkill(spec)
skill.enabledAtResponse = spec.enabled_at_response skill.enabledAtResponse = spec.enabled_at_response
end end
skill.interaction = spec.interaction
return skill return skill
end end

View File

@ -26,6 +26,7 @@ UsableSkill = require "core.skill_type.usable_skill"
StatusSkill = require "core.skill_type.status_skill" StatusSkill = require "core.skill_type.status_skill"
Player = require "core.player" Player = require "core.player"
GameMode = require "core.game_mode" GameMode = require "core.game_mode"
UI = require "ui-util"
-- load config -- load config
local function loadConf() local function loadConf()

33
lua/ui-util.lua Normal file
View File

@ -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

View File

@ -61,10 +61,18 @@ local test_active = fk.CreateActiveSkill{
return true return true
end, end,
card_filter = function(self, card) card_filter = function(self, card)
local c = Fk:getCardById(card) if self.interaction.data == "joy" then
return Self:getPileNameOfId(card) == self.name and c.color == Card.Red --local c = Fk:getCardById(card)
--return Self:getPileNameOfId(card) == self.name and c.color == Card.Red
return true
end
end, end,
card_num = 2,
target_filter = function() return true end, target_filter = function() return true end,
interaction = UI.ComboBox {
choices = Fk.package_names,
-- default = "guanyu",
},
on_use = function(self, room, effect) on_use = function(self, room, effect)
--room:doSuperLightBox("packages/test/qml/Test.qml") --room:doSuperLightBox("packages/test/qml/Test.qml")
local from = room:getPlayerById(effect.from) local from = room:getPlayerById(effect.from)

View File

@ -26,6 +26,7 @@ Item {
property alias cancelButton: cancelButton property alias cancelButton: cancelButton
property alias dynamicCardArea: dynamicCardArea property alias dynamicCardArea: dynamicCardArea
property alias tableCards: tablePile.cards property alias tableCards: tablePile.cards
property alias dashboard: dashboard
property var selected_targets: [] property var selected_targets: []
property string responding_card property string responding_card
@ -89,6 +90,7 @@ Item {
from: "*"; to: "notactive" from: "*"; to: "notactive"
ScriptAction { ScriptAction {
script: { script: {
skillInteraction.source = "";
promptText = ""; promptText = "";
progress.visible = false; progress.visible = false;
okCancel.visible = false; okCancel.visible = false;
@ -114,6 +116,7 @@ Item {
from: "*"; to: "playing" from: "*"; to: "playing"
ScriptAction { ScriptAction {
script: { script: {
skillInteraction.source = "";
dashboard.enableCards(); dashboard.enableCards();
dashboard.enableSkills(); dashboard.enableSkills();
progress.visible = true; progress.visible = true;
@ -128,6 +131,7 @@ Item {
from: "*"; to: "responding" from: "*"; to: "responding"
ScriptAction { ScriptAction {
script: { script: {
skillInteraction.source = "";
dashboard.enableCards(responding_card); dashboard.enableCards(responding_card);
dashboard.enableSkills(responding_card); dashboard.enableSkills(responding_card);
progress.visible = true; progress.visible = true;
@ -140,6 +144,7 @@ Item {
from: "*"; to: "replying" from: "*"; to: "replying"
ScriptAction { ScriptAction {
script: { script: {
skillInteraction.source = "";
dashboard.disableAllCards(); dashboard.disableAllCards();
dashboard.disableSkills(); dashboard.disableSkills();
progress.visible = true; 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 { Row {
id: okCancel id: okCancel
@ -469,9 +482,28 @@ Item {
function activateSkill(skill_name, pressed) { function activateSkill(skill_name, pressed) {
if (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); dashboard.startPending(skill_name);
cancelButton.enabled = true; cancelButton.enabled = true;
} else { } else {
skillInteraction.source = "";
Logic.doCancelButton(); Logic.doCancelButton();
} }
} }

View File

@ -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];
});
}
}