选择性删除Interaction等各种功能 (#193)

- 给interaction喂nil或者空choices可以禁止出interaction小黑框
- 可以给主动技/视为技上prompt
- 装备的技能现在会独立显示在最下方
This commit is contained in:
YoumuKon 2023-06-16 10:58:28 +08:00 committed by GitHub
parent b75d8afe62
commit e2c4d326c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 14 deletions

View File

@ -25,6 +25,7 @@ Item {
property alias manualBox: manualBox property alias manualBox: manualBox
property alias bigAnim: bigAnim property alias bigAnim: bigAnim
property alias promptText: prompt.text property alias promptText: prompt.text
property var currentPrompt
property alias okCancel: okCancel property alias okCancel: okCancel
property alias okButton: okButton property alias okButton: okButton
property alias cancelButton: cancelButton property alias cancelButton: cancelButton
@ -146,6 +147,7 @@ Item {
script: { script: {
skillInteraction.sourceComponent = undefined; skillInteraction.sourceComponent = undefined;
promptText = ""; promptText = "";
currentPrompt = "";
progress.visible = false; progress.visible = false;
okCancel.visible = false; okCancel.visible = false;
endPhaseButton.visible = false; endPhaseButton.visible = false;
@ -900,6 +902,15 @@ Item {
mainStack.currentItem.loadPlayerData(datalist); mainStack.currentItem.loadPlayerData(datalist);
} }
function setPrompt(text, iscur) {
promptText = text;
if (iscur) currentPrompt = text;
}
function resetPrompt() {
promptText = currentPrompt;
}
function loadPlayerData(datalist) { function loadPlayerData(datalist) {
datalist.forEach(d => { datalist.forEach(d => {
if (d.id == Self.id) { if (d.id == Self.id) {

View File

@ -708,7 +708,7 @@ callbacks["AskForGeneral"] = (jsonData) => {
const generals = data[0]; const generals = data[0];
const n = data[1]; const n = data[1];
const heg = data[2]; const heg = data[2];
roomScene.promptText = Backend.translate("#AskForGeneral"); roomScene.setPrompt(Backend.translate("#AskForGeneral"), true);
roomScene.state = "replying"; roomScene.state = "replying";
roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/ChooseGeneralBox.qml"); roomScene.popupBox.sourceComponent = Qt.createComponent("../RoomElement/ChooseGeneralBox.qml");
const box = roomScene.popupBox.item; const box = roomScene.popupBox.item;
@ -810,7 +810,7 @@ callbacks["AskForChoice"] = (jsonData) => {
roomScene.promptText = Backend.translate("#AskForChoice") roomScene.promptText = Backend.translate("#AskForChoice")
.arg(Backend.translate(skill_name)); .arg(Backend.translate(skill_name));
} else { } else {
roomScene.promptText = processPrompt(prompt); roomScene.setPrompt(processPrompt(prompt), true);
} }
roomScene.state = "replying"; roomScene.state = "replying";
let qmlSrc; let qmlSrc;
@ -952,7 +952,7 @@ callbacks["PlayCard"] = (jsonData) => {
// jsonData: int playerId // jsonData: int playerId
const playerId = parseInt(jsonData); const playerId = parseInt(jsonData);
if (playerId === Self.id) { if (playerId === Self.id) {
roomScene.promptText = Backend.translate("#PlayCard"); roomScene.setPrompt(Backend.translate("#PlayCard"), true);
roomScene.state = "playing"; roomScene.state = "playing";
okButton.enabled = false; okButton.enabled = false;
} }
@ -1012,7 +1012,7 @@ callbacks["AskForUseActiveSkill"] = (jsonData) => {
roomScene.promptText = Backend.translate("#AskForUseActiveSkill") roomScene.promptText = Backend.translate("#AskForUseActiveSkill")
.arg(Backend.translate(skill_name)); .arg(Backend.translate(skill_name));
} else { } else {
roomScene.promptText = processPrompt(prompt); roomScene.setPrompt(processPrompt(prompt), true);
} }
roomScene.respond_play = false; roomScene.respond_play = false;
@ -1052,7 +1052,7 @@ callbacks["AskForUseCard"] = (jsonData) => {
roomScene.promptText = Backend.translate("#AskForUseCard") roomScene.promptText = Backend.translate("#AskForUseCard")
.arg(Backend.translate(cardname)); .arg(Backend.translate(cardname));
} else { } else {
roomScene.promptText = processPrompt(prompt); roomScene.setPrompt(processPrompt(prompt), true);
} }
roomScene.responding_card = pattern; roomScene.responding_card = pattern;
roomScene.respond_play = false; roomScene.respond_play = false;
@ -1072,7 +1072,7 @@ callbacks["AskForResponseCard"] = (jsonData) => {
roomScene.promptText = Backend.translate("#AskForResponseCard") roomScene.promptText = Backend.translate("#AskForResponseCard")
.arg(Backend.translate(cardname)); .arg(Backend.translate(cardname));
} else { } else {
roomScene.promptText = processPrompt(prompt); roomScene.setPrompt(processPrompt(prompt), true);
} }
roomScene.responding_card = pattern; roomScene.responding_card = pattern;
roomScene.respond_play = true; roomScene.respond_play = true;
@ -1281,7 +1281,7 @@ callbacks["ChangeSelf"] = (j) => {
callbacks["AskForLuckCard"] = (j) => { callbacks["AskForLuckCard"] = (j) => {
// jsonData: int time // jsonData: int time
const time = parseInt(j); const time = parseInt(j);
roomScene.promptText = Backend.translate("#AskForLuckCard").arg(time); roomScene.setPrompt(Backend.translate("#AskForLuckCard").arg(time), true);
roomScene.state = "replying"; roomScene.state = "replying";
roomScene.extra_data = { roomScene.extra_data = {
luckCard: true, luckCard: true,

View File

@ -251,11 +251,31 @@ RowLayout {
} }
} }
function processPrompt(prompt) {
const data = prompt.split(":");
let raw = Backend.translate(data[0]);
const src = parseInt(data[1]);
const dest = parseInt(data[2]);
if (raw.match("%src")) raw = raw.replace("%src", Backend.translate(getPhoto(src).general));
if (raw.match("%dest")) raw = raw.replace("%dest", Backend.translate(getPhoto(dest).general));
if (raw.match("%arg")) raw = raw.replace("%arg", Backend.translate(data[3]));
if (raw.match("%arg2")) raw = raw.replace("%arg2", Backend.translate(data[4]));
return raw;
}
function updatePending() { function updatePending() {
roomScene.resetPrompt();
if (pending_skill === "") return; if (pending_skill === "") return;
const enabled_cards = []; const enabled_cards = [];
const targets = roomScene.selected_targets; const targets = roomScene.selected_targets;
const prompt = JSON.parse(Backend.callLuaFunction(
"ActiveSkillPrompt",
[pending_skill, pendings, targets]
));
if (prompt !== "") {
roomScene.setPrompt(processPrompt(prompt));
}
handcardAreaItem.cards.forEach((card) => { handcardAreaItem.cards.forEach((card) => {
if (card.selected || JSON.parse(Backend.callLuaFunction( if (card.selected || JSON.parse(Backend.callLuaFunction(
@ -337,6 +357,7 @@ RowLayout {
handcardAreaItem.adjustCards(); handcardAreaItem.adjustCards();
handcardAreaItem.unselectAll(); handcardAreaItem.unselectAll();
cardSelected(-1); cardSelected(-1);
roomScene.resetPrompt();
} }
function addSkill(skill_name, prelight) { function addSkill(skill_name, prelight) {

View File

@ -187,12 +187,25 @@ end
function GetPlayerSkills(id) function GetPlayerSkills(id)
local p = ClientInstance:getPlayerById(id) local p = ClientInstance:getPlayerById(id)
return json.encode(table.map(p.player_skills, function(s) local equip = {}
return s.visible and { local ret = {}
name = s.name, table.forEach(p.player_skills, function(s)
description = Fk:getDescription(s.name), if s:isEquipmentSkill() then
} or nil table.insert(equip, s.attached_equip)
elseif s.visible then
table.insert(ret, {
name = s.name,
description = Fk:getDescription(s.name),
})
end
end)
table.insertTable(ret, table.map(equip, function(e)
return {
name = e,
description = Fk:getDescription(e),
}
end)) end))
return json.encode(ret)
end end
---@param card string | integer ---@param card string | integer
@ -352,6 +365,19 @@ function ActiveCanUse(skill_name)
return json.encode(ret) return json.encode(ret)
end end
function ActiveSkillPrompt(skill_name, selected, selected_targets)
local skill = Fk.skills[skill_name]
local ret = false
if skill then
if type(skill.prompt) == "function" then
ret = skill:prompt(selected, selected_targets)
else
ret = skill.prompt
end
end
return json.encode(ret)
end
function ActiveCardFilter(skill_name, to_select, selected, selected_targets) function ActiveCardFilter(skill_name, to_select, selected, selected_targets)
local skill = Fk.skills[skill_name] local skill = Fk.skills[skill_name]
local ret = false local ret = false

View File

@ -162,4 +162,8 @@ function ActiveSkill:onEffect(room, cardEffectEvent) end
---@param cardEffectEvent CardEffectEvent | SkillEffectEvent ---@param cardEffectEvent CardEffectEvent | SkillEffectEvent
function ActiveSkill:onNullified(room, cardEffectEvent) end function ActiveSkill:onNullified(room, cardEffectEvent) end
---@param selected integer[] @ ids of selected players
---@param selected_cards integer[] @ ids of selected cards
function ActiveSkill:prompt(selected, selected_cards) return "" end
return ActiveSkill return ActiveSkill

View File

@ -39,4 +39,8 @@ end
---@param cardUseStruct CardUseStruct ---@param cardUseStruct CardUseStruct
function ViewAsSkill:beforeUse(player, cardUseStruct) end function ViewAsSkill:beforeUse(player, cardUseStruct) end
---@param selected integer[] @ ids of selected players
---@param selected_cards integer[] @ ids of selected cards
function ActiveSkill:prompt(selected, selected_cards) return "" end
return ViewAsSkill return ViewAsSkill

View File

@ -170,6 +170,7 @@ end
---@field public about_to_effect fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean ---@field public about_to_effect fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean
---@field public on_effect fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean ---@field public on_effect fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean
---@field public on_nullified fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean ---@field public on_nullified fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean
---@field public prompt fun(self: ActiveSkill, selected: integer[], selected_cards: integer[]): string
---@param spec ActiveSkillSpec ---@param spec ActiveSkillSpec
---@return ActiveSkill ---@return ActiveSkill
@ -193,6 +194,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
if spec.prompt then skill.prompt = spec.prompt end
if spec.interaction then if spec.interaction then
skill.interaction = setmetatable({}, { skill.interaction = setmetatable({}, {
@ -215,6 +217,7 @@ end
---@field public enabled_at_play fun(self: ViewAsSkill, player: Player): boolean ---@field public enabled_at_play fun(self: ViewAsSkill, player: Player): boolean
---@field public enabled_at_response fun(self: ViewAsSkill, player: Player): boolean ---@field public enabled_at_response fun(self: ViewAsSkill, player: Player): boolean
---@field public before_use fun(self: ViewAsSkill, player: ServerPlayer) ---@field public before_use fun(self: ViewAsSkill, player: ServerPlayer)
---@field public prompt fun(self: ActiveSkill, selected: integer[], selected_cards: integer[]): string
---@param spec ViewAsSkillSpec ---@param spec ViewAsSkillSpec
---@return ViewAsSkill ---@return ViewAsSkill
@ -242,6 +245,7 @@ function fk.CreateViewAsSkill(spec)
return spec.enabled_at_response(curSkill, player, cardResponsing) and curSkill:isEffectable(player) return spec.enabled_at_response(curSkill, player, cardResponsing) and curSkill:isEffectable(player)
end end
end end
if spec.prompt then skill.prompt = spec.prompt end
if spec.interaction then if spec.interaction then
skill.interaction = setmetatable({}, { skill.interaction = setmetatable({}, {

View File

@ -14,8 +14,9 @@ local UI = {}
-- * default: string默认的选项默认为choices的第一个 -- * default: string默认的选项默认为choices的第一个
-- * detailed: bool为真的话送详细信息 -- * detailed: bool为真的话送详细信息
UI.ComboBox = function(spec) UI.ComboBox = function(spec)
assert(type(spec.choices) == "table", "Choices is not a table") -- assert(type(spec.choices) == "table", "Choices is not a table")
assert(#spec.choices > 0, "Choices is empty") -- assert(#spec.choices > 0, "Choices is empty")
spec.choices = type(spec.choices) == "table" and spec.choices or Util.DummyTable
spec.default = spec.default or spec.choices[1] spec.default = spec.default or spec.choices[1]
spec.detailed = spec.detailed spec.detailed = spec.detailed
spec.type = "combo" spec.type = "combo"

View File

@ -150,6 +150,7 @@ local test_vs = fk.CreateViewAsSkill{
c:addSubcard(cards[1]) c:addSubcard(cards[1])
return c return c
end, end,
prompt = "#test_vs",
} }
local test_trig = fk.CreateTriggerSkill{ local test_trig = fk.CreateTriggerSkill{
name = "test_trig", name = "test_trig",
@ -280,6 +281,7 @@ Fk:loadTranslationTable{
["test_vs"] = "视为", ["test_vs"] = "视为",
[":test_vs"] = "你可以将牌当包含无懈在内的某张锦囊使用。", [":test_vs"] = "你可以将牌当包含无懈在内的某张锦囊使用。",
["#test_vs"] = "视为:你可以学习锦囊牌的用法",
["damage_maker"] = "制伤", ["damage_maker"] = "制伤",
[":damage_maker"] = "出牌阶段,你可以进行一次伤害制造器。", [":damage_maker"] = "出牌阶段,你可以进行一次伤害制造器。",