Card limitation (#111)

禁止使用打出弃置
Fk.currentResponseReason
FilterSkill加player参数
This commit is contained in:
notify 2023-04-10 15:55:06 +08:00 committed by GitHub
parent 9a951fdbfe
commit 533cc1a464
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 140 additions and 36 deletions

View File

@ -22,6 +22,10 @@ function Client:initialize()
end end
self.client.callback = function(_self, command, jsonData) self.client.callback = function(_self, command, jsonData)
local cb = fk.client_callback[command] local cb = fk.client_callback[command]
Fk.currentResponsePattern = nil
Fk.currentResponseReason = nil
if (type(cb) == "function") then if (type(cb) == "function") then
cb(jsonData) cb(jsonData)
else else
@ -525,9 +529,21 @@ fk.client_callback["AskForUseActiveSkill"] = function(jsonData)
for k, v in pairs(extra_data) do for k, v in pairs(extra_data) do
skill[k] = v skill[k] = v
end end
Fk.currentResponseReason = extra_data.skillName
ClientInstance:notifyUI("AskForUseActiveSkill", jsonData) ClientInstance:notifyUI("AskForUseActiveSkill", jsonData)
end end
fk.client_callback["AskForUseCard"] = function(jsonData)
Fk.currentResponsePattern = json.decode(jsonData)[2]
ClientInstance:notifyUI("AskForUseCard", jsonData)
end
fk.client_callback["AskForResponseCard"] = function(jsonData)
Fk.currentResponsePattern = json.decode(jsonData)[2]
ClientInstance:notifyUI("AskForResponseCard", jsonData)
end
fk.client_callback["SetPlayerMark"] = function(jsonData) fk.client_callback["SetPlayerMark"] = function(jsonData)
-- jsonData: [ int id, string mark, int value ] -- jsonData: [ int id, string mark, int value ]
local data = json.decode(jsonData) local data = json.decode(jsonData)

View File

@ -166,7 +166,30 @@ function CanUseCard(card, player)
end end
end end
local ret = c.skill:canUse(ClientInstance:getPlayerById(player), c) player = ClientInstance:getPlayerById(player)
local ret = c.skill:canUse(player, c)
if ret then
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
for _, skill in ipairs(status_skills) do
if skill:prohibitUse(player, c) then
ret = false
break
end
end
end
return json.encode(ret)
end
function CardProhibitedUse(cid)
local c = Fk:getCardById(cid)
local ret = false
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
for _, skill in ipairs(status_skills) do
if skill:prohibitUse(Self, c) then
ret = true
break
end
end
return json.encode(ret) return json.encode(ret)
end end
@ -377,6 +400,19 @@ function SkillFitPattern(skill_name, pattern)
return json.encode(ret) return json.encode(ret)
end end
function CardProhibitedResponse(cid)
local c = Fk:getCardById(cid)
local ret = false
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
for _, skill in ipairs(status_skills) do
if skill:prohibitResponse(Self, c) then
ret = true
break
end
end
return json.encode(ret)
end
function SkillCanResponse(skill_name) function SkillCanResponse(skill_name)
local skill = Fk.skills[skill_name] local skill = Fk.skills[skill_name]
local ret = false local ret = false

View File

@ -20,6 +20,8 @@
---@field public translations table<string, table<string, string>> @ 翻译表 ---@field public translations table<string, table<string, string>> @ 翻译表
---@field public game_modes table<string, GameMode> @ 所有游戏模式 ---@field public game_modes table<string, GameMode> @ 所有游戏模式
---@field public disabled_packs string[] @ 禁用的拓展包列表 ---@field public disabled_packs string[] @ 禁用的拓展包列表
---@field public currentResponsePattern string
---@field public currentResponseReason string
local Engine = class("Engine") local Engine = class("Engine")
--- Engine的构造函数。 --- Engine的构造函数。
@ -376,12 +378,8 @@ function Engine:filterCard(id, player, data)
return return
end end
local skills = player:getAllSkills() local skills = player:getAllSkills()
local filters = {} local filters = self:currentRoom().status_skills[FilterSkill]
for _, s in ipairs(skills) do
if s:isInstanceOf(FilterSkill) then
table.insert(filters, s)
end
end
if #filters == 0 then if #filters == 0 then
filtered_cards[id] = nil filtered_cards[id] = nil
return return
@ -394,8 +392,8 @@ function Engine:filterCard(id, player, data)
end end
for _, f in ipairs(filters) do for _, f in ipairs(filters) do
if f:cardFilter(card) then if f:cardFilter(card, player) then
local _card = f:viewAs(card) local _card = f:viewAs(card, player)
_card.id = id _card.id = id
_card.skillName = f.name _card.skillName = f.name
if modify and RoomInstance then if modify and RoomInstance then

View File

@ -4,13 +4,13 @@
local FilterSkill = StatusSkill:subclass("FilterSkill") local FilterSkill = StatusSkill:subclass("FilterSkill")
---@param card Card ---@param card Card
function FilterSkill:cardFilter(card) function FilterSkill:cardFilter(card, player)
return false return false
end end
---@param card Card ---@param card Card
---@return Card ---@return Card
function FilterSkill:viewAs(card) function FilterSkill:viewAs(card, player)
return nil return nil
end end

View File

@ -309,8 +309,8 @@ function fk.CreateTargetModSkill(spec)
end end
---@class FilterSpec: StatusSkillSpec ---@class FilterSpec: StatusSkillSpec
---@field public card_filter fun(self: FilterSkill, card: Card) ---@field public card_filter fun(self: FilterSkill, card: Card, player: Player)
---@field public view_as fun(self: FilterSkill, card: Card) ---@field public view_as fun(self: FilterSkill, card: Card, player: Player)
---@param spec FilterSpec ---@param spec FilterSpec
---@return FilterSkill ---@return FilterSkill

View File

@ -832,7 +832,10 @@ function Room:askForUseActiveSkill(player, skill_name, prompt, cancelable, extra
local command = "AskForUseActiveSkill" local command = "AskForUseActiveSkill"
self:notifyMoveFocus(player, extra_data.skillName or skill_name) -- for display skill name instead of command name self:notifyMoveFocus(player, extra_data.skillName or skill_name) -- for display skill name instead of command name
local data = {skill_name, prompt, cancelable, json.encode(extra_data)} local data = {skill_name, prompt, cancelable, json.encode(extra_data)}
Fk.currentResponseReason = extra_data.skillName
local result = self:doRequest(player, command, json.encode(data)) local result = self:doRequest(player, command, json.encode(data))
Fk.currentResponseReason = nil
if result == "" then if result == "" then
return false return false
@ -869,35 +872,52 @@ end
---@param prompt string @ 提示信息 ---@param prompt string @ 提示信息
---@return integer[] @ 弃掉的牌的id列表可能是空的 ---@return integer[] @ 弃掉的牌的id列表可能是空的
function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern, prompt) function Room:askForDiscard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern, prompt)
cancelable = cancelable or false
pattern = pattern or ""
local canDiscards = table.filter(
player:getCardIds{ Player.Hand, includeEquip and Player.Equip or nil }, function(id)
local checkpoint = true
local card = Fk:getCardById(id)
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
for _, skill in ipairs(status_skills) do
if skill:prohibitDiscard(player, card) then
return false
end
end
if pattern ~= "" then
checkpoint = checkpoint and (Exppattern:Parse(pattern):match(card))
end
return checkpoint
end
)
maxNum = math.min(#canDiscards, maxNum)
minNum = math.min(#canDiscards, minNum)
if minNum < 1 then if minNum < 1 then
return nil return nil
end end
cancelable = cancelable or false
pattern = pattern or ""
local toDiscard = {} local toDiscard = {}
local data = { local data = {
num = maxNum, num = maxNum,
min_num = minNum, min_num = minNum,
include_equip = includeEquip, include_equip = includeEquip,
reason = skillName, skillName = skillName,
pattern = pattern, pattern = pattern,
} }
local prompt = prompt or ("#AskForDiscard:::" .. maxNum .. ":" .. minNum) local prompt = prompt or ("#AskForDiscard:::" .. maxNum .. ":" .. minNum)
local _, ret = self:askForUseActiveSkill(player, "discard_skill", prompt, cancelable, data) local _, ret = self:askForUseActiveSkill(player, "discard_skill", prompt, cancelable, data)
if ret then if ret then
toDiscard = ret.cards toDiscard = ret.cards
else else
if cancelable then return {} end if cancelable then return {} end
local hands = player:getCardIds(Player.Hand) toDiscard = table.random(canDiscards, minNum)
if includeEquip then
table.insertTable(hands, player:getCardIds(Player.Equip))
end
for i = 1, minNum do
local randomId = hands[math.random(1, #hands)]
table.insert(toDiscard, randomId)
table.removeOne(hands, randomId)
end
end end
self:throwCard(toDiscard, skillName, player, player) self:throwCard(toDiscard, skillName, player, player)
@ -962,7 +982,7 @@ function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancel
num = maxNum, num = maxNum,
min_num = minNum, min_num = minNum,
include_equip = includeEquip, include_equip = includeEquip,
reason = skillName, skillName = skillName,
pattern = pattern, pattern = pattern,
expand_pile = expand_pile, expand_pile = expand_pile,
} }
@ -1302,7 +1322,11 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr
return askForUseCardData.result return askForUseCardData.result
else else
local data = {card_name, pattern, prompt, cancelable, extra_data} local data = {card_name, pattern, prompt, cancelable, extra_data}
Fk.currentResponsePattern = pattern
local result = self:doRequest(player, command, json.encode(data)) local result = self:doRequest(player, command, json.encode(data))
Fk.currentResponsePattern = nil
if result ~= "" then if result ~= "" then
return self:handleUseCardReply(player, result) return self:handleUseCardReply(player, result)
end end
@ -1338,7 +1362,11 @@ function Room:askForResponse(player, card_name, pattern, prompt, cancelable, ext
return eventData.result return eventData.result
else else
local data = {card_name, pattern, prompt, cancelable, extra_data} local data = {card_name, pattern, prompt, cancelable, extra_data}
Fk.currentResponsePattern = pattern
local result = self:doRequest(player, command, json.encode(data)) local result = self:doRequest(player, command, json.encode(data))
Fk.currentResponsePattern = nil
if result ~= "" then if result ~= "" then
local use = self:handleUseCardReply(player, result) local use = self:handleUseCardReply(player, result)
if use then if use then
@ -1375,7 +1403,11 @@ function Room:askForNullification(players, card_name, pattern, prompt, cancelabl
self:doBroadcastNotify("WaitForNullification", "") self:doBroadcastNotify("WaitForNullification", "")
local data = {card_name, pattern, prompt, cancelable, extra_data} local data = {card_name, pattern, prompt, cancelable, extra_data}
Fk.currentResponsePattern = pattern
local winner = self:doRaceRequest(command, players, json.encode(data)) local winner = self:doRaceRequest(command, players, json.encode(data))
Fk.currentResponsePattern = nil
if winner then if winner then
local result = winner.client_reply local result = winner.client_reply
return self:handleUseCardReply(winner, result) return self:handleUseCardReply(winner, result)

View File

@ -8,12 +8,21 @@ local discardSkill = fk.CreateActiveSkill{
end end
local checkpoint = true local checkpoint = true
local card = Fk:getCardById(to_select)
local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or {}
for _, skill in ipairs(status_skills) do
if skill:prohibitDiscard(Self, card) then
return false
end
end
if not self.include_equip then if not self.include_equip then
checkpoint = checkpoint and (Fk:currentRoom():getCardArea(to_select) ~= Player.Equip) checkpoint = checkpoint and (Fk:currentRoom():getCardArea(to_select) ~= Player.Equip)
end end
if self.pattern ~= "" then if self.pattern ~= "" then
checkpoint = checkpoint and (Exppattern:Parse(self.pattern):match(Fk:getCardById(to_select))) checkpoint = checkpoint and (Exppattern:Parse(self.pattern):match(card))
end end
return checkpoint return checkpoint
end, end,

View File

@ -311,4 +311,6 @@ Fk:loadTranslationTable{
["discard_skill"] = "弃牌", ["discard_skill"] = "弃牌",
["choose_cards_skill"] = "选牌", ["choose_cards_skill"] = "选牌",
["choose_players_skill"] = "选择角色", ["choose_players_skill"] = "选择角色",
["game_rule"] = "弃牌阶段",
} }

View File

@ -143,18 +143,32 @@ RowLayout {
// If cname is set, we are responding card. // If cname is set, we are responding card.
function enableCards(cname) { function enableCards(cname) {
const cardValid = (cid, cname) => {
let ret = JSON.parse(Backend.callLuaFunction(
"CardFitPattern", [cid, cname]));
if (ret) {
if (roomScene.respond_play) {
ret = ret && !JSON.parse(Backend.callLuaFunction(
"CardProhibitedResponse", [cid]));
} else {
ret = ret && !JSON.parse(Backend.callLuaFunction(
"CardProhibitedUse", [cid]));
}
}
return ret;
}
if (cname) { if (cname) {
let ids = [], cards = handcardAreaItem.cards; let ids = [], cards = handcardAreaItem.cards;
for (let i = 0; i < cards.length; i++) { for (let i = 0; i < cards.length; i++) {
if (JSON.parse(Backend.callLuaFunction("CardFitPattern", [cards[i].cid, cname]))) if (cardValid(cards[i].cid, cname)) {
ids.push(cards[i].cid); ids.push(cards[i].cid);
} }
}
cards = selfPhoto.equipArea.getAllCards(); cards = selfPhoto.equipArea.getAllCards();
cards.forEach(c => { cards.forEach(c => {
if (JSON.parse(Backend.callLuaFunction( if (cardValid(c.cid, cname)) {
"CardFitPattern",
[c.cid, cname]
))) {
ids.push(c.cid); ids.push(c.cid);
if (!expanded_piles["_equip"]) { if (!expanded_piles["_equip"]) {
expandPile("_equip"); expandPile("_equip");
@ -169,10 +183,7 @@ RowLayout {
pile_list = pile_list.split(","); pile_list = pile_list.split(",");
for (let pile_name of pile_list) { for (let pile_name of pile_list) {
pile_data[pile_name] && pile_data[pile_name].forEach(cid => { pile_data[pile_name] && pile_data[pile_name].forEach(cid => {
if (JSON.parse(Backend.callLuaFunction( if (cardValid(cid, cname)) {
"CardFitPattern",
[cid, cname]
))) {
ids.push(cid); ids.push(cid);
if (!expanded_piles[pile_name]) { if (!expanded_piles[pile_name]) {
expandPile(pile_name); expandPile(pile_name);