mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-16 11:42:45 +08:00
多选、勾选框和bugfix (#284)
- 修复了prompt看不见extra_data的bug - 添加askForChooseBoth用以选择多牌多角色的情况 - 拆分Util以方便开发插件识别 - 大招不再显示武将卡面信息 - 添加勾选框askForCheck,用以提供多选项多选 --------- Co-authored-by: notify <notify-ctrl@qq.com>
This commit is contained in:
parent
379ea06970
commit
513fcf36d7
87
Fk/Pages/MetroToggleButton.qml
Normal file
87
Fk/Pages/MetroToggleButton.qml
Normal file
|
@ -0,0 +1,87 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
property bool enabled: true
|
||||
property bool triggered: false
|
||||
property alias text: title.text
|
||||
property alias textColor: title.color
|
||||
property alias textFont: title.font
|
||||
property alias backgroundColor: bg.color
|
||||
property alias border: bg.border
|
||||
property alias iconSource: icon.source
|
||||
property int padding: 5
|
||||
|
||||
signal clicked
|
||||
|
||||
id: button
|
||||
width: icon.width + title.implicitWidth + padding * 2
|
||||
height: Math.max(icon.height, title.implicitHeight) + padding * 2
|
||||
|
||||
Rectangle {
|
||||
id: bg
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
border.width: 2
|
||||
border.color: "white"
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "hovered_checked"; when: hover.hovered && triggered
|
||||
PropertyChanges { target: bg; color: "gold" }
|
||||
PropertyChanges { target: title; color: "black" }
|
||||
},
|
||||
State {
|
||||
name: "hovered"; when: hover.hovered
|
||||
PropertyChanges { target: bg; color: "white" }
|
||||
PropertyChanges { target: title; color: "black" }
|
||||
},
|
||||
State {
|
||||
name: "checked"; when: triggered
|
||||
PropertyChanges { target: border; color: "gold" }
|
||||
PropertyChanges { target: title; color: "gold" }
|
||||
},
|
||||
State {
|
||||
name: "disabled"; when: !enabled
|
||||
PropertyChanges { target: button; opacity: 0.2 }
|
||||
}
|
||||
]
|
||||
|
||||
TapHandler {
|
||||
id: mouse
|
||||
onTapped: if (parent.enabled) {
|
||||
triggered = !triggered;
|
||||
parent.clicked();
|
||||
}
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: hover
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
|
||||
Row {
|
||||
x: padding
|
||||
y: padding
|
||||
anchors.centerIn: parent
|
||||
spacing: 5
|
||||
|
||||
Image {
|
||||
id: icon
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
Text {
|
||||
id: title
|
||||
font.pixelSize: 18
|
||||
// font.family: "WenQuanYi Micro Hei"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: ""
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1008,6 +1008,48 @@ callbacks["AskForChoice"] = (jsonData) => {
|
|||
});
|
||||
}
|
||||
|
||||
callbacks["AskForCheck"] = (jsonData) => {
|
||||
// jsonData: [ string[] choices, string skill ]
|
||||
// TODO: multiple choices, e.g. benxi_ol
|
||||
const data = JSON.parse(jsonData);
|
||||
const choices = data[0];
|
||||
const all_choices = data[1];
|
||||
const min_num = data[2][0];
|
||||
const max_num = data[2][1];
|
||||
const cancelable = data[3];
|
||||
const skill_name = data[4];
|
||||
const prompt = data[5];
|
||||
const detailed = data[6];
|
||||
if (prompt === "") {
|
||||
roomScene.promptText = Backend.translate("#AskForCheck")
|
||||
.arg(Backend.translate(skill_name));
|
||||
} else {
|
||||
roomScene.setPrompt(processPrompt(prompt), true);
|
||||
}
|
||||
roomScene.state = "replying";
|
||||
let qmlSrc;
|
||||
if (!detailed) {
|
||||
qmlSrc = "../RoomElement/CheckBox.qml";
|
||||
} else {
|
||||
qmlSrc = "../RoomElement/DetailedCheckBox.qml";
|
||||
}
|
||||
roomScene.popupBox.sourceComponent = Qt.createComponent(qmlSrc);
|
||||
const box = roomScene.popupBox.item;
|
||||
box.options = choices;
|
||||
box.skill_name = skill_name;
|
||||
box.all_options = all_choices;
|
||||
box.min_num = min_num;
|
||||
box.max_num = max_num;
|
||||
box.cancelable = cancelable;
|
||||
box.accepted.connect(() => {
|
||||
const ret = [];
|
||||
box.result.forEach(id => {
|
||||
ret.push(all_choices[id]);
|
||||
});
|
||||
replyToServer(JSON.stringify(ret));
|
||||
});
|
||||
}
|
||||
|
||||
callbacks["AskForCardChosen"] = (jsonData) => {
|
||||
// jsonData: [ int[] handcards, int[] equips, int[] delayedtricks,
|
||||
// string reason ]
|
||||
|
|
|
@ -6,6 +6,7 @@ GeneralsOverview 1.0 GeneralsOverview.qml
|
|||
Init 1.0 Init.qml
|
||||
Lobby 1.0 Lobby.qml
|
||||
MetroButton 1.0 MetroButton.qml
|
||||
MetroToggleButton 1.0 MetroToggleButton.qml
|
||||
ModesOverview 1.0 ModesOverview.qml
|
||||
PackageManage 1.0 PackageManage.qml
|
||||
Room 1.0 Room.qml
|
||||
|
|
90
Fk/RoomElement/CheckBox.qml
Normal file
90
Fk/RoomElement/CheckBox.qml
Normal file
|
@ -0,0 +1,90 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Fk.Pages
|
||||
|
||||
GraphicsBox {
|
||||
property var options: []
|
||||
property var all_options: []
|
||||
property bool cancelable: false
|
||||
property int min_num: 0
|
||||
property int max_num: 0
|
||||
property string skill_name: ""
|
||||
property var result: []
|
||||
|
||||
id: root
|
||||
title.text: Backend.translate("$Choice").arg(Backend.translate(skill_name))
|
||||
width: Math.max(140, body.width + 20)
|
||||
height: buttons.height + body.height + title.height + 20
|
||||
|
||||
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/g, Backend.translate(getPhoto(src).general));
|
||||
if (raw.match("%dest")) raw = raw.replace(/%dest/g, Backend.translate(getPhoto(dest).general));
|
||||
if (raw.match("%arg2")) raw = raw.replace(/%arg2/g, Backend.translate(data[4]));
|
||||
if (raw.match("%arg")) raw = raw.replace(/%arg/g, Backend.translate(data[3]));
|
||||
return raw;
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
id: body
|
||||
// x: 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: title.height + 5
|
||||
flow: GridLayout.TopToBottom
|
||||
rows: 8
|
||||
columnSpacing: 10
|
||||
|
||||
Repeater {
|
||||
model: all_options
|
||||
|
||||
MetroToggleButton {
|
||||
// Layout.fillWidth: true
|
||||
text: processPrompt(modelData)
|
||||
enabled: options.indexOf(modelData) !== -1 && (root.result.length < max_num || triggered)
|
||||
|
||||
onClicked: {
|
||||
if (triggered) {
|
||||
root.result.push(index);
|
||||
} else {
|
||||
root.result.splice(root.result.indexOf(index), 1);
|
||||
}
|
||||
root.result = root.result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
anchors.margins: 8
|
||||
anchors.top: body.bottom
|
||||
anchors.horizontalCenter: root.horizontalCenter
|
||||
spacing: 32
|
||||
|
||||
MetroButton {
|
||||
Layout.fillWidth: true
|
||||
text: processPrompt("OK")
|
||||
enabled: root.result.length >= min_num
|
||||
|
||||
onClicked: {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
MetroButton {
|
||||
Layout.fillWidth: true
|
||||
text: processPrompt("Cancel")
|
||||
visible: cancelable
|
||||
|
||||
onClicked: {
|
||||
root.result = [];
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
107
Fk/RoomElement/DetailedCheckBox.qml
Normal file
107
Fk/RoomElement/DetailedCheckBox.qml
Normal file
|
@ -0,0 +1,107 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
import Fk.Pages
|
||||
|
||||
GraphicsBox {
|
||||
property var options: []
|
||||
property var all_options: []
|
||||
property bool cancelable: false
|
||||
property int min_num: 0
|
||||
property int max_num: 0
|
||||
property string skill_name: ""
|
||||
property var result: []
|
||||
|
||||
id: root
|
||||
title.text: Backend.translate("$Choice").arg(Backend.translate(skill_name))
|
||||
width: Math.max(140, body.width + 20)
|
||||
height: buttons.height + body.height + title.height + 20
|
||||
|
||||
ListView {
|
||||
id: body
|
||||
x: 10
|
||||
y: title.height + 5
|
||||
width: Math.min(700, 220 * model.length)
|
||||
height: 300
|
||||
orientation: ListView.Horizontal
|
||||
clip: true
|
||||
spacing: 20
|
||||
|
||||
model: all_options
|
||||
|
||||
delegate: Item {
|
||||
width: 200
|
||||
height: 290
|
||||
|
||||
MetroToggleButton {
|
||||
id: choicetitle
|
||||
width: parent.width
|
||||
text: Backend.translate(modelData)
|
||||
enabled: options.indexOf(modelData) !== -1 && (root.result.length < max_num || triggered)
|
||||
textFont.pixelSize: 24
|
||||
anchors.top: choiceDetail.bottom
|
||||
anchors.topMargin: 8
|
||||
|
||||
onClicked: {
|
||||
if (triggered) {
|
||||
root.result.push(index);
|
||||
} else {
|
||||
root.result.splice(root.result.indexOf(index), 1);
|
||||
}
|
||||
root.result = root.result;
|
||||
}
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: choiceDetail
|
||||
x: 4
|
||||
height: parent.height - choicetitle.height
|
||||
contentHeight: detail.height
|
||||
width: parent.width
|
||||
clip: true
|
||||
Text {
|
||||
id: detail
|
||||
width: parent.width
|
||||
text: Backend.translate(":" + modelData)
|
||||
color: "white"
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: 16
|
||||
textFormat: TextEdit.RichText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: buttons
|
||||
anchors.margins: 8
|
||||
anchors.bottom: root.bottom
|
||||
anchors.horizontalCenter: root.horizontalCenter
|
||||
spacing: 32
|
||||
|
||||
MetroButton {
|
||||
width: 120
|
||||
height: 35
|
||||
text: Backend.translate("OK")
|
||||
enabled: root.result.length >= min_num
|
||||
|
||||
onClicked: {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
MetroButton {
|
||||
width: 120
|
||||
height: 35
|
||||
text: Backend.translate("Cancel")
|
||||
visible: root.cancelable
|
||||
|
||||
onClicked: {
|
||||
result = [];
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import Fk.Pages
|
|||
GraphicsBox {
|
||||
id: root
|
||||
|
||||
title.text: Backend.callLuaFunction("PoxiPrompt", [poxi_type, card_data])
|
||||
title.text: Backend.callLuaFunction("PoxiPrompt", [poxi_type, card_data, extra_data])
|
||||
|
||||
// TODO: Adjust the UI design in case there are more than 7 cards
|
||||
width: 70 + 700
|
||||
|
@ -116,7 +116,7 @@ GraphicsBox {
|
|||
width: 120
|
||||
height: 35
|
||||
text: Backend.translate("Cancel")
|
||||
enabled: root.cancelable
|
||||
visible: root.cancelable
|
||||
onClicked: root.cardsSelected([])
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ Item {
|
|||
x: root.width + 140
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
opacity: 0
|
||||
detailed: false
|
||||
}
|
||||
|
||||
Text {
|
||||
|
|
|
@ -715,11 +715,11 @@ function GetCardProhibitReason(cid, method, pattern)
|
|||
end
|
||||
end
|
||||
|
||||
function PoxiPrompt(poxi_type, data)
|
||||
function PoxiPrompt(poxi_type, data, extra_data)
|
||||
local poxi = Fk.poxi_methods[poxi_type]
|
||||
if not poxi or not poxi.prompt then return "" end
|
||||
if type(poxi.prompt) == "string" then return Fk:translate(poxi.prompt) end
|
||||
return poxi.prompt(data)
|
||||
return poxi.prompt(data, extra_data)
|
||||
end
|
||||
|
||||
function PoxiFilter(poxi_type, to_select, selected, data, extra_data)
|
||||
|
|
|
@ -159,6 +159,7 @@ Fk:loadTranslationTable({
|
|||
["#AskForLuckCard"] = "Do you want to use luck card (%1 times left)?",
|
||||
["AskForLuckCard"] = "Luck card",
|
||||
["#AskForChoice"] = "%1: Please choose",
|
||||
["#AskForCheck"] = "%1: Please choose",
|
||||
["#choose-trigger"] = "Please choose the skill to use",
|
||||
["trigger"] = "Trigger skill",
|
||||
-- ["Please arrange cards"] = "请拖拽移动卡牌",
|
||||
|
@ -169,6 +170,7 @@ Fk:loadTranslationTable({
|
|||
["AskForGuanxing"] = "Stargazing",
|
||||
["AskForExchange"] = "Exchaging",
|
||||
["AskForChoice"] = "Making choice",
|
||||
["AskForCheck"] = "Making choice",
|
||||
["AskForKingdom"] = "Choosing kingdom",
|
||||
["AskForPindian"] = "Point fight",
|
||||
["AskForMoveCardInBoard"] = "Moving cards",
|
||||
|
|
|
@ -205,6 +205,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["#AskForLuckCard"] = "你想使用手气卡吗?还可以使用 %1 次,剩余手气卡∞张",
|
||||
["AskForLuckCard"] = "手气卡",
|
||||
["#AskForChoice"] = "%1:请选择",
|
||||
["#AskForCheck"] = "%1:请选择",
|
||||
["#choose-trigger"] = "请选择一项技能发动",
|
||||
["trigger"] = "选择技能",
|
||||
["Please arrange cards"] = "请拖拽移动卡牌",
|
||||
|
@ -215,6 +216,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
|
|||
["AskForGuanxing"] = "观星",
|
||||
["AskForExchange"] = "换牌",
|
||||
["AskForChoice"] = "选择",
|
||||
["AskForCheck"] = "选择",
|
||||
["AskForKingdom"] = "选择势力",
|
||||
["AskForPindian"] = "拼点",
|
||||
["AskForMoveCardInBoard"] = "移动卡牌",
|
||||
|
|
|
@ -52,6 +52,24 @@ Util.convertSubtypeAndEquipSlot = function(value)
|
|||
end
|
||||
end
|
||||
|
||||
--- 根据花色文字描述(如 黑桃、红桃、梅花、方块)或者符号(如♠♥♣♦,带颜色)返回花色ID。
|
||||
---@param symbol string @ 描述/符号(原文,确保没被翻译过)
|
||||
---@return Suit @ 花色ID
|
||||
Util.getSuitFromString = function(symbol)
|
||||
assert(type(symbol) == "string")
|
||||
if symbol:find("spade") then
|
||||
return Card.Spade
|
||||
elseif symbol:find("heart") then
|
||||
return Card.Heart
|
||||
elseif symbol:find("club") then
|
||||
return Card.Club
|
||||
elseif symbol:find("diamond") then
|
||||
return Card.Diamond
|
||||
else
|
||||
return Card.NoSuit
|
||||
end
|
||||
end
|
||||
|
||||
function printf(fmt, ...)
|
||||
print(string.format(fmt, ...))
|
||||
end
|
||||
|
@ -118,14 +136,22 @@ function table:map(func)
|
|||
end
|
||||
|
||||
-- frequenly used filter & map functions
|
||||
|
||||
--- 返回ID
|
||||
Util.IdMapper = function(e) return e.id end
|
||||
--- 根据卡牌ID返回卡牌
|
||||
Util.Id2CardMapper = function(id) return Fk:getCardById(id) end
|
||||
--- 根据玩家ID返回玩家
|
||||
Util.Id2PlayerMapper = function(id)
|
||||
return Fk:currentRoom():getPlayerById(id)
|
||||
end
|
||||
--- 返回武将名
|
||||
Util.NameMapper = function(e) return e.name end
|
||||
--- 根据武将名返回武将
|
||||
Util.Name2GeneralMapper = function(e) return Fk.generals[e] end
|
||||
--- 根据技能名返回技能
|
||||
Util.Name2SkillMapper = function(e) return Fk.skills[e] end
|
||||
--- 返回译文
|
||||
Util.TranslateMapper = function(str) return Fk:translate(str) end
|
||||
|
||||
-- for card preset
|
||||
|
|
|
@ -179,7 +179,7 @@ end
|
|||
---@field public on_effect nil|fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): bool
|
||||
---@field public on_nullified nil|fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): bool
|
||||
---@field public mod_target_filter nil|fun(self: ActiveSkill, to_select: integer, selected: integer[], user: integer, card: Card, distance_limited: boolean): bool
|
||||
---@field public prompt nil|string|fun(self: ActiveSkill, selected: integer[], selected_cards: integer[]): string
|
||||
---@field public prompt nil|string|fun(self: ActiveSkill, selected_cards: integer[], selected_targets: integer[]): string
|
||||
---@field public interaction any
|
||||
|
||||
---@param spec ActiveSkillSpec
|
||||
|
|
|
@ -18,7 +18,8 @@ math.randomseed(os.time())
|
|||
|
||||
-- 加载实用类,让Lua编写起来更轻松。
|
||||
local Utils = require "core.util"
|
||||
TargetGroup, AimGroup, Util = table.unpack(Utils)
|
||||
-- TargetGroup, AimGroup, Util = table.unpack(Utils)
|
||||
TargetGroup, AimGroup, Util = Utils[1], Utils[2], Utils[3]
|
||||
dofile "lua/core/debug.lua"
|
||||
|
||||
-- 加载游戏核心类
|
||||
|
|
|
@ -1052,7 +1052,7 @@ end
|
|||
---@param cancelable bool @ 是否可以点取消
|
||||
---@param extra_data table|nil @ 额外信息,因技能而异了
|
||||
---@param no_indicate bool @ 是否不显示指示线
|
||||
---@return boolean, table
|
||||
---@return boolean, table|nil
|
||||
function Room:askForUseActiveSkill(player, skill_name, prompt, cancelable, extra_data, no_indicate)
|
||||
prompt = prompt or ""
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
|
@ -1322,6 +1322,55 @@ function Room:askForChooseCardAndPlayers(player, targets, minNum, maxNum, patter
|
|||
end
|
||||
end
|
||||
|
||||
--- 询问玩家选择X张牌和Y名角色。
|
||||
---
|
||||
--- 返回两个值,第一个是选择的目标列表,第二个是选择的那张牌的id
|
||||
---@param player ServerPlayer @ 要询问的玩家
|
||||
---@param minCardNum integer @ 选卡牌最小值
|
||||
---@param maxCardNum integer @ 选卡牌最大值
|
||||
---@param targets integer[] @ 选择目标的id范围
|
||||
---@param minTargetNum integer @ 选目标最小值
|
||||
---@param maxTargetNum integer @ 选目标最大值
|
||||
---@param pattern string|nil @ 选牌规则
|
||||
---@param prompt string|nil @ 提示信息
|
||||
---@param cancelable bool @ 能否点取消
|
||||
---@param no_indicate bool @ 是否不显示指示线
|
||||
---@return integer[], integer[]
|
||||
function Room:askForChooseBoth(player, minCardNum, maxCardNum, targets, minTargetNum, maxTargetNum, pattern, prompt, skillName, cancelable, no_indicate)
|
||||
if minCardNum < 1 or minTargetNum < 1 then
|
||||
return table.unpack({}, {})
|
||||
end
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
no_indicate = no_indicate or false
|
||||
pattern = pattern or "."
|
||||
|
||||
local pcards = table.filter(player:getCardIds({ Player.Hand, Player.Equip }), function(id)
|
||||
local c = Fk:getCardById(id)
|
||||
return c:matchPattern(pattern)
|
||||
end)
|
||||
if #pcards < minCardNum and not cancelable then return table.unpack({}, {}) end
|
||||
|
||||
local data = {
|
||||
targets = targets,
|
||||
max_target_num = maxTargetNum,
|
||||
min_target_num = minTargetNum,
|
||||
max_card_num = maxCardNum,
|
||||
min_card_num = minCardNum,
|
||||
pattern = pattern,
|
||||
skillName = skillName,
|
||||
}
|
||||
local _, ret = self:askForUseActiveSkill(player, "ex__choose_skill", prompt or "", cancelable, data, no_indicate)
|
||||
if ret then
|
||||
return ret.targets, ret.cards
|
||||
else
|
||||
if cancelable then
|
||||
return table.unpack({}, {})
|
||||
else
|
||||
return table.random(targets, minTargetNum), table.random(pcards, minCardNum)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- 抽个武将
|
||||
---
|
||||
--- 同getNCards,抽出来就没有了,所以记得放回去。
|
||||
|
@ -1609,6 +1658,35 @@ function Room:askForChoice(player, choices, skill_name, prompt, detailed, all_ch
|
|||
return result
|
||||
end
|
||||
|
||||
--- 询问一名玩家从众多选项中勾选任意项。
|
||||
---@param player ServerPlayer @ 要询问的玩家
|
||||
---@param choices string[] @ 可选选项列表
|
||||
---@param minNum number @ 最少选择项数
|
||||
---@param maxNum number @ 最多选择项数
|
||||
---@param skill_name string|nil @ 技能名
|
||||
---@param prompt string|nil @ 提示信息
|
||||
---@param cancelable bool|nil @ 是否可取消
|
||||
---@param detailed bool @ 选项详细描述
|
||||
---@param all_choices string[]|nil @ 所有选项(不可选变灰)
|
||||
---@return string[] @ 选择的选项
|
||||
function Room:askForCheck(player, choices, minNum, maxNum, skill_name, prompt, cancelable, detailed, all_choices)
|
||||
cancelable = (cancelable == nil) and true or cancelable
|
||||
if #choices <= minNum and not all_choices then return choices end
|
||||
assert(minNum <= maxNum)
|
||||
assert(not all_choices or table.every(choices, function(c) return table.contains(all_choices, c) end))
|
||||
local command = "AskForCheck"
|
||||
skill_name = skill_name or ""
|
||||
prompt = prompt or ""
|
||||
all_choices = all_choices or choices
|
||||
detailed = detailed or false
|
||||
self:notifyMoveFocus(player, skill_name)
|
||||
local result = self:doRequest(player, command, json.encode{
|
||||
choices, all_choices, {minNum, maxNum}, cancelable, skill_name, prompt, detailed
|
||||
})
|
||||
if result == "" then return {} end
|
||||
return json.decode(result)
|
||||
end
|
||||
|
||||
--- 询问玩家是否发动技能。
|
||||
---@param player ServerPlayer @ 要询问的玩家
|
||||
---@param skill_name string @ 技能名
|
||||
|
|
|
@ -92,6 +92,23 @@ local choosePlayersSkill = fk.CreateActiveSkill{
|
|||
max_target_num = function(self) return self.num end,
|
||||
}
|
||||
|
||||
local exChooseSkill = fk.CreateActiveSkill{
|
||||
name = "ex__choose_skill",
|
||||
card_filter = function(self, to_select, selected)
|
||||
return self.pattern ~= "" and Exppattern:Parse(self.pattern):match(Fk:getCardById(to_select)) and #selected < self.max_card_num
|
||||
end,
|
||||
target_filter = function(self, to_select, selected, cards)
|
||||
if self.pattern ~= "" and #cards < self.min_card_num then return end
|
||||
if #selected < self.max_target_num then
|
||||
return table.contains(self.targets, to_select)
|
||||
end
|
||||
end,
|
||||
min_target_num = function(self) return self.min_target_num end,
|
||||
max_target_num = function(self) return self.max_target_num end,
|
||||
min_card_num = function(self) return self.min_card_num end,
|
||||
max_card_num = function(self) return self.max_card_num end,
|
||||
}
|
||||
|
||||
local maxCardsSkill = fk.CreateMaxCardsSkill{
|
||||
name = "max_cards_skill",
|
||||
global = true,
|
||||
|
@ -222,6 +239,7 @@ AuxSkills = {
|
|||
discardSkill,
|
||||
chooseCardsSkill,
|
||||
choosePlayersSkill,
|
||||
exChooseSkill,
|
||||
maxCardsSkill,
|
||||
choosePlayersToMoveCardInBoardSkill,
|
||||
uncompulsoryInvalidity,
|
||||
|
|
Loading…
Reference in New Issue
Block a user