From 533cc1a46426cbe8b7ee4a5ce3e05218d4e73754 Mon Sep 17 00:00:00 2001 From: notify Date: Mon, 10 Apr 2023 15:55:06 +0800 Subject: [PATCH] Card limitation (#111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 禁止使用打出弃置 Fk.currentResponseReason FilterSkill加player参数 --- lua/client/client.lua | 16 ++++++++ lua/client/client_util.lua | 38 ++++++++++++++++++- lua/core/engine.lua | 14 +++---- lua/core/skill_type/filter.lua | 4 +- lua/fk_ex.lua | 4 +- lua/server/room.lua | 58 ++++++++++++++++++++++------- packages/standard/aux_skills.lua | 11 +++++- packages/standard/i18n/zh_CN.lua | 2 + qml/Pages/RoomElement/Dashboard.qml | 29 ++++++++++----- 9 files changed, 140 insertions(+), 36 deletions(-) diff --git a/lua/client/client.lua b/lua/client/client.lua index 3385247e..1dfde8ab 100644 --- a/lua/client/client.lua +++ b/lua/client/client.lua @@ -22,6 +22,10 @@ function Client:initialize() end self.client.callback = function(_self, command, jsonData) local cb = fk.client_callback[command] + + Fk.currentResponsePattern = nil + Fk.currentResponseReason = nil + if (type(cb) == "function") then cb(jsonData) else @@ -525,9 +529,21 @@ fk.client_callback["AskForUseActiveSkill"] = function(jsonData) for k, v in pairs(extra_data) do skill[k] = v end + + Fk.currentResponseReason = extra_data.skillName ClientInstance:notifyUI("AskForUseActiveSkill", jsonData) 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) -- jsonData: [ int id, string mark, int value ] local data = json.decode(jsonData) diff --git a/lua/client/client_util.lua b/lua/client/client_util.lua index b02cb497..b749da6d 100644 --- a/lua/client/client_util.lua +++ b/lua/client/client_util.lua @@ -166,7 +166,30 @@ function CanUseCard(card, player) 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) end @@ -377,6 +400,19 @@ function SkillFitPattern(skill_name, pattern) return json.encode(ret) 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) local skill = Fk.skills[skill_name] local ret = false diff --git a/lua/core/engine.lua b/lua/core/engine.lua index cb1cb595..413ccbb3 100644 --- a/lua/core/engine.lua +++ b/lua/core/engine.lua @@ -20,6 +20,8 @@ ---@field public translations table> @ 翻译表 ---@field public game_modes table @ 所有游戏模式 ---@field public disabled_packs string[] @ 禁用的拓展包列表 +---@field public currentResponsePattern string +---@field public currentResponseReason string local Engine = class("Engine") --- Engine的构造函数。 @@ -376,12 +378,8 @@ function Engine:filterCard(id, player, data) return end local skills = player:getAllSkills() - local filters = {} - for _, s in ipairs(skills) do - if s:isInstanceOf(FilterSkill) then - table.insert(filters, s) - end - end + local filters = self:currentRoom().status_skills[FilterSkill] + if #filters == 0 then filtered_cards[id] = nil return @@ -394,8 +392,8 @@ function Engine:filterCard(id, player, data) end for _, f in ipairs(filters) do - if f:cardFilter(card) then - local _card = f:viewAs(card) + if f:cardFilter(card, player) then + local _card = f:viewAs(card, player) _card.id = id _card.skillName = f.name if modify and RoomInstance then diff --git a/lua/core/skill_type/filter.lua b/lua/core/skill_type/filter.lua index 6996973d..593e57e2 100644 --- a/lua/core/skill_type/filter.lua +++ b/lua/core/skill_type/filter.lua @@ -4,13 +4,13 @@ local FilterSkill = StatusSkill:subclass("FilterSkill") ---@param card Card -function FilterSkill:cardFilter(card) +function FilterSkill:cardFilter(card, player) return false end ---@param card Card ---@return Card -function FilterSkill:viewAs(card) +function FilterSkill:viewAs(card, player) return nil end diff --git a/lua/fk_ex.lua b/lua/fk_ex.lua index 59c6e3dd..e055217d 100644 --- a/lua/fk_ex.lua +++ b/lua/fk_ex.lua @@ -309,8 +309,8 @@ function fk.CreateTargetModSkill(spec) end ---@class FilterSpec: StatusSkillSpec ----@field public card_filter fun(self: FilterSkill, card: Card) ----@field public view_as 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, player: Player) ---@param spec FilterSpec ---@return FilterSkill diff --git a/lua/server/room.lua b/lua/server/room.lua index cacfb225..8c0bf245 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -832,7 +832,10 @@ function Room:askForUseActiveSkill(player, skill_name, prompt, cancelable, extra local command = "AskForUseActiveSkill" 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)} + + Fk.currentResponseReason = extra_data.skillName local result = self:doRequest(player, command, json.encode(data)) + Fk.currentResponseReason = nil if result == "" then return false @@ -869,35 +872,52 @@ end ---@param prompt string @ 提示信息 ---@return integer[] @ 弃掉的牌的id列表,可能是空的 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 return nil end - cancelable = cancelable or false - pattern = pattern or "" local toDiscard = {} local data = { num = maxNum, min_num = minNum, include_equip = includeEquip, - reason = skillName, + skillName = skillName, pattern = pattern, } local prompt = prompt or ("#AskForDiscard:::" .. maxNum .. ":" .. minNum) + local _, ret = self:askForUseActiveSkill(player, "discard_skill", prompt, cancelable, data) + if ret then toDiscard = ret.cards else if cancelable then return {} end - local hands = player:getCardIds(Player.Hand) - 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 + toDiscard = table.random(canDiscards, minNum) end self:throwCard(toDiscard, skillName, player, player) @@ -962,7 +982,7 @@ function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancel num = maxNum, min_num = minNum, include_equip = includeEquip, - reason = skillName, + skillName = skillName, pattern = pattern, expand_pile = expand_pile, } @@ -1302,7 +1322,11 @@ function Room:askForUseCard(player, card_name, pattern, prompt, cancelable, extr return askForUseCardData.result else local data = {card_name, pattern, prompt, cancelable, extra_data} + + Fk.currentResponsePattern = pattern local result = self:doRequest(player, command, json.encode(data)) + Fk.currentResponsePattern = nil + if result ~= "" then return self:handleUseCardReply(player, result) end @@ -1338,7 +1362,11 @@ function Room:askForResponse(player, card_name, pattern, prompt, cancelable, ext return eventData.result else local data = {card_name, pattern, prompt, cancelable, extra_data} + + Fk.currentResponsePattern = pattern local result = self:doRequest(player, command, json.encode(data)) + Fk.currentResponsePattern = nil + if result ~= "" then local use = self:handleUseCardReply(player, result) if use then @@ -1375,7 +1403,11 @@ function Room:askForNullification(players, card_name, pattern, prompt, cancelabl self:doBroadcastNotify("WaitForNullification", "") local data = {card_name, pattern, prompt, cancelable, extra_data} + + Fk.currentResponsePattern = pattern local winner = self:doRaceRequest(command, players, json.encode(data)) + Fk.currentResponsePattern = nil + if winner then local result = winner.client_reply return self:handleUseCardReply(winner, result) diff --git a/packages/standard/aux_skills.lua b/packages/standard/aux_skills.lua index 12b734dc..cda4bbb2 100644 --- a/packages/standard/aux_skills.lua +++ b/packages/standard/aux_skills.lua @@ -8,12 +8,21 @@ local discardSkill = fk.CreateActiveSkill{ end 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 checkpoint = checkpoint and (Fk:currentRoom():getCardArea(to_select) ~= Player.Equip) end 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 return checkpoint end, diff --git a/packages/standard/i18n/zh_CN.lua b/packages/standard/i18n/zh_CN.lua index 9e28bd11..f941d7ff 100644 --- a/packages/standard/i18n/zh_CN.lua +++ b/packages/standard/i18n/zh_CN.lua @@ -311,4 +311,6 @@ Fk:loadTranslationTable{ ["discard_skill"] = "弃牌", ["choose_cards_skill"] = "选牌", ["choose_players_skill"] = "选择角色", + + ["game_rule"] = "弃牌阶段", } diff --git a/qml/Pages/RoomElement/Dashboard.qml b/qml/Pages/RoomElement/Dashboard.qml index 838af9ec..f2a9f9eb 100644 --- a/qml/Pages/RoomElement/Dashboard.qml +++ b/qml/Pages/RoomElement/Dashboard.qml @@ -143,18 +143,32 @@ RowLayout { // If cname is set, we are responding card. 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) { let ids = [], cards = handcardAreaItem.cards; 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); + } } cards = selfPhoto.equipArea.getAllCards(); cards.forEach(c => { - if (JSON.parse(Backend.callLuaFunction( - "CardFitPattern", - [c.cid, cname] - ))) { + if (cardValid(c.cid, cname)) { ids.push(c.cid); if (!expanded_piles["_equip"]) { expandPile("_equip"); @@ -169,10 +183,7 @@ RowLayout { pile_list = pile_list.split(","); for (let pile_name of pile_list) { pile_data[pile_name] && pile_data[pile_name].forEach(cid => { - if (JSON.parse(Backend.callLuaFunction( - "CardFitPattern", - [cid, cname] - ))) { + if (cardValid(cid, cname)) { ids.push(cid); if (!expanded_piles[pile_name]) { expandPile(pile_name);