diff --git a/lua/client/client.lua b/lua/client/client.lua index 17d2340c..282ce2fd 100644 --- a/lua/client/client.lua +++ b/lua/client/client.lua @@ -243,7 +243,7 @@ end fk.client_callback["EnterRoom"] = function(_data) Self = ClientPlayer:new(fk.Self) - -- 垃圾bug 怎么把这玩意忘了 + -- FIXME: 需要改Qml local ob = ClientInstance.observing ClientInstance = Client:new() -- clear old client data ClientInstance.observing = ob diff --git a/lua/client/client_util.lua b/lua/client/client_util.lua index a898b173..858a81fd 100644 --- a/lua/client/client_util.lua +++ b/lua/client/client_util.lua @@ -902,8 +902,11 @@ function RevertSelection() local unselectData = { selected = false } local selectData = { selected = true } local to_select = {} + local lastcid + local lastselected = false for cid, cardItem in pairs(h.scene:getAllItems("CardItem")) do if table.contains(h.pendings, cid) then + lastcid = cid h:selectCard(cid, unselectData) else table.insert(to_select, cardItem) @@ -911,9 +914,16 @@ function RevertSelection() end for _, cardItem in ipairs(to_select) do if cardItem.enabled then + lastcid = cardItem.id + lastselected = true h:selectCard(cardItem.id, selectData) end end + -- 最后模拟一次真实点击卡牌以更新目标和按钮状态 + if lastcid then + h:selectCard(lastcid, { selected = not lastselected }) + h:update("CardItem", lastcid, "click", { selected = lastselected }) + end h.scene:notifyUI() end @@ -935,12 +945,11 @@ function FinishRequestUI() end end --- TODO 传参带上cardMoveData... -function CardVisibility(cardId, move) +function CardVisibility(cardId) local player = Self local card = Fk:getCardById(cardId) if not card then return false end - return player:cardVisible(cardId, move) + return player:cardVisible(cardId) end function RoleVisibility(targetId) diff --git a/lua/client/i18n/zh_CN.lua b/lua/client/i18n/zh_CN.lua index 7e55c32c..dfa60269 100644 --- a/lua/client/i18n/zh_CN.lua +++ b/lua/client/i18n/zh_CN.lua @@ -360,9 +360,9 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下 ["Resume"] = "继续", ["Bulletin Info"] = [==[ - ## v0.4.13 + ## v0.4.21 - 优化性能 + UI重构!还有很长一段路要走…… ]==], } diff --git a/lua/core/card.lua b/lua/core/card.lua index 9d6a026b..020a1c52 100644 --- a/lua/core/card.lua +++ b/lua/core/card.lua @@ -90,6 +90,8 @@ function Card:initialize(name, suit, number, color) self.color = Card.Red elseif color ~= nil then self.color = color + elseif suit == Card.Unknown then + self.color = Card.Unknown else self.color = Card.NoColor end @@ -242,7 +244,7 @@ end ---@return string @ 描述花色的字符串 function Card:getSuitString(symbol) local suit = self.suit - local ret + local ret = "unknown" if suit == Card.Spade then ret = "spade" elseif suit == Card.Heart then @@ -251,7 +253,7 @@ function Card:getSuitString(symbol) ret = "club" elseif suit == Card.Diamond then ret = "diamond" - else + elseif suit == Card.NoSuit then ret = "nosuit" end return symbol and "log_" .. ret or ret @@ -265,8 +267,10 @@ function Card:getColorString() return "black" elseif color == Card.Red then return "red" + elseif color == Card.NoColor then + return "nocolor" end - return "nocolor" + return "unknown" end --- 获取卡牌类型并返回类型描述(例如基本牌/锦囊牌/装备牌)。 @@ -426,8 +430,11 @@ end --- 比较两张卡牌的花色是否相同 ---@param anotherCard Card @ 另一张卡牌 ---@param diff? boolean @ 比较二者不同 ----@return boolean 返回比较结果 +---@return boolean @ 返回比较结果 function Card:compareSuitWith(anotherCard, diff) + if table.contains({ self.suit, anotherCard.suit }, Card.Unknown) then + return true + end if self ~= anotherCard and table.contains({ self.suit, anotherCard.suit }, Card.NoSuit) then return false end @@ -444,6 +451,9 @@ end ---@param diff? boolean @ 比较二者不同 ---@return boolean @ 返回比较结果 function Card:compareColorWith(anotherCard, diff) + if table.contains({ self.color, anotherCard.color }, Card.Unknown) then + return true + end if self ~= anotherCard and table.contains({ self.color, anotherCard.color }, Card.NoColor) then return false end diff --git a/lua/core/exppattern.lua b/lua/core/exppattern.lua index 1e73c3f6..f9c53486 100644 --- a/lua/core/exppattern.lua +++ b/lua/core/exppattern.lua @@ -33,6 +33,7 @@ ---@field public id? integer[] -- v0.2.6改动: cardType会被解析为trueName数组和name数组,而不是自己单独成立 +-- core改动: name数组为空时,将根据trueName数组生成对应的name数组 local numbertable = { ["A"] = 1, @@ -48,6 +49,8 @@ local placetable = { local card_type_table = {} +local card_truename_table = {} + local function fillCardTypeTable() local tmp = {} for _, cd in ipairs(Fk.cards) do @@ -66,6 +69,20 @@ local function fillCardTypeTable() end end +local function fillCardTrueNameTable() + local tmp = {} + for _, cd in ipairs(Fk.cards) do + local tn = cd.trueName + local n = cd.name + + if not tmp[n] then + card_truename_table[tn] = card_truename_table[tn] or {} + table.insertIfNeed(card_truename_table[tn], n) + tmp[n] = true + end + end +end + local function matchSingleKey(matcher, card, key) local match = matcher[key] if not match then return true end @@ -302,7 +319,9 @@ local function parseMatcher(str) ret.suit = not table.contains(t[3], ".") and t[3] or nil ret.place = not table.contains(t[4], ".") and t[4] or nil - ret.name = not table.contains(t[5], ".") and t[5] or nil + if table.empty(card_truename_table) then + fillCardTrueNameTable() + end -- ret.cardType = not table.contains(t[6], ".") and t[6] or nil if table.empty(card_type_table) then fillCardTypeTable() @@ -325,6 +344,29 @@ local function parseMatcher(str) table.insert(ret.trueName.neg, temp) end + if table.contains(t[5], ".") then + if ret.trueName then + ret.name = {} + for _, tn in ipairs(ret.trueName) do + table.insertTableIfNeed(ret.name, card_truename_table[tn] or Util.DummyTable) + end + for _, neg in ipairs(ret.trueName.neg or Util.DummyTable) do + if type(neg) ~= "table" then neg = { neg } end + if not ret.name.neg then ret.name.neg = {} end + + local temp = {} + for _, tn in ipairs(neg) do + table.insertTableIfNeed(temp, card_truename_table[tn] or Util.DummyTable) + end + table.insert(ret.name.neg, temp) + end + else + ret.name = nil + end + else + ret.name = t[5] + end + if not table.contains(t[7], ".") then ret.id = parseRawNumTable(t[7]) end diff --git a/lua/core/game_mode.lua b/lua/core/game_mode.lua index b74cf40d..8229cf65 100644 --- a/lua/core/game_mode.lua +++ b/lua/core/game_mode.lua @@ -1,5 +1,21 @@ -- SPDX-License-Identifier: GPL-3.0-or-later +-- 呃 起码要做出以下几种吧: +-- Switch:那个开关组件 [boolean model=nil] +-- RadioButton:那个多选一,圆圈里面打点组件 [string model={ label, value }[]] +-- ComboBox: 那个多选一,下拉一个菜单并选择一个的组件 [string model同上] +-- CheckBox: 那个多选多打钩组件 [string[], model={ choices = {label,value}[], min, max}] +-- Spinner: 选integer的组件吧,带加号减号那个 [integer model={min, max}] + +--- 定义一套配置项,供玩家在创建房间时配置。配置完成后返回一个表保存配置信息, +--- 下面假设这个配置信息是表`cfg = {}` +---@class GameModeConfigEntry +---@field public name string @ 配置项的内部名,cfg的键 +---@field public label? string @ 界面上显示的提示信息 +---@field public delegate string @ 要显示哪种? +---@field public model any @ 这种delegate需要的model:参见注释 +---@field public default? any @ 默认值 cfg的value + --- GameMode用来描述一个游戏模式。 --- --- 可以参考欢乐斗地主。 @@ -12,6 +28,7 @@ ---@field public logic? fun(): GameLogic @ 逻辑(通过function完成,通常用来初始化、分配身份及座次) ---@field public whitelist? string[] @ 白名单 ---@field public blacklist? string[] @ 黑名单 +---@field public config_template? GameModeConfigEntry[] 游戏模式的配置页面,如此一个数组 local GameMode = class("GameMode") --- 构造函数,不可随意调用。 @@ -83,4 +100,14 @@ function GameMode:getAdjustedProperty (player) return list end +--- 向游戏模式中添加拓展包过滤。 +---@param whitelist string[] @ 白名单 +---@param blacklist string[] @ 黑名单 +function GameMode:addPackageFilter(whitelist, blacklist) + assert(type(whitelist) == "table") + assert(type(blacklist) == "table") + table.insertTable(self.whitelist, whitelist) + table.insertTable(self.blacklist, blacklist) +end + return GameMode diff --git a/lua/core/player.lua b/lua/core/player.lua index 40d1cf4d..dd0f50a9 100644 --- a/lua/core/player.lua +++ b/lua/core/player.lua @@ -1254,7 +1254,7 @@ function Player:roleVisible(target) end end - if room.observing == false and target == self then return true end + if not room.observing and target == self then return true end return target.role_shown end diff --git a/lua/core/request_type/play_card.lua b/lua/core/request_type/play_card.lua index 844bb310..629c6c91 100644 --- a/lua/core/request_type/play_card.lua +++ b/lua/core/request_type/play_card.lua @@ -100,10 +100,17 @@ function ReqPlayCard:doEndButton() end function ReqPlayCard:selectCard(cid, data) - ReqUseCard.selectCard(self, cid, data) - if self.skill_name and not self.selected_card then return end + if self.skill_name and not self.selected_card then + return ReqActiveSkill.selectCard(self, cid, data) + end + local scene = self.scene + local selected = data.selected + scene:update("CardItem", cid, data) - if self.selected_card then + if selected then + self.skill_name = nil + self.selected_card = Fk:getCardById(cid) + scene:unselectOtherCards(cid) self:setSkillPrompt(self.selected_card.skill, self.selected_card:getEffectiveId()) local sp_skills = {} if self.selected_card.special_skills then @@ -114,11 +121,17 @@ function ReqPlayCard:selectCard(cid, data) end self.scene:update("SpecialSkills", "1", { skills = sp_skills }) else + self.selected_card = nil self:setPrompt(self.original_prompt) self.scene:update("SpecialSkills", "1", { skills = {} }) end end +function ReqPlayCard:selectSkill(skill, data) + ReqUseCard.selectSkill(self, skill, data) + self.scene:update("SpecialSkills", "1", { skills = {} }) +end + function ReqPlayCard:update(elemType, id, action, data) if elemType == "Button" and id == "End" then self:doEndButton() diff --git a/lua/core/request_type/use_card.lua b/lua/core/request_type/use_card.lua index e65a818c..766f6991 100644 --- a/lua/core/request_type/use_card.lua +++ b/lua/core/request_type/use_card.lua @@ -4,6 +4,12 @@ local ReqResponseCard = require 'core.request_type.response_card' ---@class ReqUseCard: ReqResponseCard local ReqUseCard = ReqResponseCard:subclass("ReqUseCard") +function ReqUseCard:skillButtonValidity(name) + local player = self.player + local skill = Fk.skills[name] + return skill:isInstanceOf(ViewAsSkill) and skill:enabledAtResponse(player, false) +end + function ReqUseCard:cardValidity(cid) if self.skill_name then return ReqActiveSkill.cardValidity(self, cid) end local card = cid @@ -31,6 +37,9 @@ end function ReqUseCard:feasible() local skill = Fk.skills[self.skill_name] local card = self.selected_card + if skill then + card = skill:viewAs(self.pendings) + end local ret = false if card and self:cardFeasible(card) then ret = card.skill:feasible(self.selected_targets, diff --git a/lua/core/room/card_manager.lua b/lua/core/room/card_manager.lua index 3b6e5e9e..4b25e921 100644 --- a/lua/core/room/card_manager.lua +++ b/lua/core/room/card_manager.lua @@ -81,6 +81,7 @@ function CardManager:getCardsByArea(area, player, dup, special_name) assert(player ~= nil) if area == Player.Special then assert(special_name ~= nil) + player.special_cards[special_name] = player.special_cards[special_name] or {} ret = player.special_cards[special_name] else ret = player.player_cards[area] diff --git a/lua/server/event.lua b/lua/server/event.lua index 2abb7bbf..78fe463a 100644 --- a/lua/server/event.lua +++ b/lua/server/event.lua @@ -19,6 +19,7 @@ fk.EventPhaseEnd = 6 fk.AfterPhaseEnd = 86 fk.EventPhaseChanging = 7 fk.EventPhaseSkipping = 8 +fk.EventPhaseSkipped = 101 fk.BeforeCardsMove = 9 fk.AfterCardsMove = 10 @@ -149,4 +150,4 @@ fk.AfterPlayerRevived = 95 -- 99 = AfterAskForCardResponse -- 100 = AfterAskForNullification -fk.NumOfEvents = 101 +fk.NumOfEvents = 102 diff --git a/lua/server/events/movecard.lua b/lua/server/events/movecard.lua index 086bb8e3..b83f6da4 100644 --- a/lua/server/events/movecard.lua +++ b/lua/server/events/movecard.lua @@ -336,17 +336,16 @@ function MoveEventWrappers:recastCard(card_ids, who, skillName) end --- 将一些卡牌同时分配给一些角色。 ----@param room Room @ 房间 ---@param list table @ 分配牌和角色的数据表,键为角色id,值为分配给其的牌id数组 ---@param proposer? integer @ 操作者的id。默认为空 ---@param skillName? string @ 技能名。默认为“分配” ---@return table @ 返回成功分配的卡牌 -function MoveEventWrappers:doYiji(room, list, proposer, skillName) +function MoveEventWrappers:doYiji(list, proposer, skillName) skillName = skillName or "distribution_skill" local moveInfos = {} local move_ids = {} for to, cards in pairs(list) do - local toP = room:getPlayerById(to) + local toP = self:getPlayerById(to) local handcards = toP:getCardIds("h") cards = table.filter(cards, function (id) return not table.contains(handcards, id) end) if #cards > 0 then @@ -354,7 +353,7 @@ function MoveEventWrappers:doYiji(room, list, proposer, skillName) local moveMap = {} local noFrom = {} for _, id in ipairs(cards) do - local from = room.owner_map[id] + local from = self.owner_map[id] if from then moveMap[from] = moveMap[from] or {} table.insert(moveMap[from], id) @@ -366,7 +365,7 @@ function MoveEventWrappers:doYiji(room, list, proposer, skillName) table.insert(moveInfos, { ids = _cards, moveInfo = table.map(_cards, function(id) - return {cardId = id, fromArea = room:getCardArea(id), fromSpecialName = room:getPlayerById(from):getPileNameOfId(id)} + return {cardId = id, fromArea = self:getCardArea(id), fromSpecialName = self:getPlayerById(from):getPileNameOfId(id)} end), from = from, to = to, @@ -389,7 +388,7 @@ function MoveEventWrappers:doYiji(room, list, proposer, skillName) end end if #moveInfos > 0 then - room:moveCards(table.unpack(moveInfos)) + self:moveCards(table.unpack(moveInfos)) end return move_ids end diff --git a/lua/server/gamelogic.lua b/lua/server/gamelogic.lua index b074c441..d6e64e34 100644 --- a/lua/server/gamelogic.lua +++ b/lua/server/gamelogic.lua @@ -491,13 +491,14 @@ end -- 作用是启动新事件 都是结构差不多的函数 ---@param event GameEvent ---@return boolean, GameEvent? -function GameLogic:resumeEvent(event, ...) +function GameLogic:resumeEvent(event) local ret, evt local co = event._co + local resume_reason = "unknown" while true do - local err, yield_result, extra_yield_result = coroutine.resume(co, ...) + local err, yield_result, extra_yield_result = coroutine.resume(co, resume_reason) if err == false then -- handle error, then break @@ -510,7 +511,8 @@ function GameLogic:resumeEvent(event, ...) if yield_result == "__handleRequest" then -- yield to requestLoop - coroutine.yield(yield_result, extra_yield_result) + -- handleRequest类的最后被ResumeRoom唤醒,接收原因 + resume_reason = coroutine.yield(yield_result, extra_yield_result) elseif type(yield_result) == "table" and yield_result.class and yield_result:isInstanceOf(GameEvent) then diff --git a/lua/server/network.lua b/lua/server/network.lua index 19385977..a1a607b8 100644 --- a/lua/server/network.lua +++ b/lua/server/network.lua @@ -176,6 +176,7 @@ function Request:ask() local players = table.simpleClone(self.players) local currentTime = os.time() + local resume_reason = "unknown" -- 1. 向所有人发送询问请求 for _, p in ipairs(players) do @@ -191,7 +192,7 @@ function Request:ask() -- 判断1:若投降则直接结束全部询问,若超时则踢掉所有人类玩家(这样AI还可计算) if room.hasSurrendered then break end local elapsed = os.time() - currentTime - if self.timeout - elapsed <= 0 then + if self.timeout - elapsed <= 0 or resume_reason == "request_timer" then for i = #players, 1, -1 do if self.send_success[players[i].serverplayer] then table.remove(players, i) @@ -246,7 +247,7 @@ function Request:ask() -- 需要等待呢,等待被唤醒吧 if not changed then - coroutine.yield("__handleRequest") + resume_reason = coroutine.yield("__handleRequest") end end diff --git a/lua/server/room.lua b/lua/server/room.lua index bc64f043..fdd90e2a 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -89,7 +89,8 @@ function Room:initialize(_room) end -- 供调度器使用的函数。能让房间开始运行/从挂起状态恢复。 -function Room:resume() +---@param reason string? +function Room:resume(reason) -- 如果还没运行的话就先创建自己的主协程 if not self.main_co then self.main_co = coroutine.create(function() @@ -107,7 +108,7 @@ function Room:resume() if not self.game_finished then self.notify_count = 0 - ret, err_msg, rest_time = coroutine.resume(main_co, err_msg) + ret, err_msg, rest_time = coroutine.resume(main_co, reason) -- handle error if ret == false then @@ -600,45 +601,6 @@ function Room:prepareGeneral(player, general, deputy, broadcast) end end ---- 房间信息摘要,返回房间的大致信息 ---- 用于旁观和重连,但也可用于debug -function Room:getSummary(player, observe) - local printed_cards = {} - for i = -2, -math.huge, -1 do - local c = Fk.printed_cards[i] - if not c then break end - table.insert(printed_cards, { c.name, c.suit, c.number }) - end - - local players = {} - for _, p in ipairs(self.players) do - players[tostring(p.id)] = p:getSummary(player, observe) - end - - local cmarks = {} - for k, v in pairs(self.card_marks) do - cmarks[tostring(k)] = v - end - - return { - you = player.id or player:getId(), - -- data for EnterRoom - d = { - -- #self.players, 留给客户端自己思考 - self.timeout, - self.settings, - }, - pc = printed_cards, - cm = cmarks, - b = self.banners, - - circle = table.map(self.players, Util.IdMapper), - p = players, - rnd = self:getTag("RoundCount") or 0, - dp = #self.draw_pile, - } -end - function Room:toJsonObject(player) local o = AbstractRoom.toJsonObject(self) o.round_count = self:getTag("RoundCount") or 0 @@ -1169,7 +1131,7 @@ end ---@param no_indicate? boolean @ 是否不显示指示线 ---@return integer[] @ 选择的牌的id列表,可能是空的 function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancelable, pattern, prompt, expand_pile, no_indicate) - if minNum < 1 then + if maxNum < 1 then return {} end cancelable = (cancelable == nil) and true or cancelable @@ -1312,7 +1274,7 @@ end ---@param expand_pile? string @ 可选私人牌堆名称,如要分配你武将牌上的牌请填写 ---@param skipMove? boolean @ 是否跳过移动。默认不跳过 ---@param single_max? integer|table @ 限制每人能获得的最大牌数。输入整数或(以角色id为键以整数为值)的表 ----@return table @ 返回一个表,键为角色id,值为分配给其的牌id数组 +---@return table @ 返回一个表,键为角色id转字符串,值为分配给其的牌id数组 function Room:askForYiji(player, cards, targets, skillName, minNum, maxNum, prompt, expand_pile, skipMove, single_max) targets = targets or self.alive_players cards = cards or player:getCardIds("he") @@ -1347,7 +1309,7 @@ function Room:askForYiji(player, cards, targets, skillName, minNum, maxNum, prom residued_list = residueMap, expand_pile = expand_pile } - p(json.encode(residueMap)) + -- p(json.encode(residueMap)) while maxNum > 0 and #_cards > 0 do data.max_num = maxNum @@ -1384,7 +1346,7 @@ function Room:askForYiji(player, cards, targets, skillName, minNum, maxNum, prom end end if not skipMove then - self:doYiji(self, list, player.id, skillName) + self:doYiji(list, player.id, skillName) end return list @@ -2019,18 +1981,20 @@ end --- 询问玩家任意交换几堆牌堆。 --- ---@param player ServerPlayer @ 要询问的玩家 ----@param piles table @ 卡牌id列表的列表,也就是……几堆牌堆的集合 ----@param piles_name string[] @ 牌堆名,必须一一对应,否则统一替换为“牌堆X” +---@param piles (integer[])[] @ 卡牌id列表的列表,也就是……几堆牌堆的集合 +---@param piles_name string[] @ 牌堆名,不足部分替换为“牌堆1、牌堆2...” ---@param customNotify? string @ 自定义读条操作提示 ----@return table +---@return (integer[])[] function Room:askForExchange(player, piles, piles_name, customNotify) local command = "AskForExchange" piles_name = piles_name or Util.DummyTable - if #piles_name ~= #piles then - piles_name = {} - for i, _ in ipairs(piles) do + local x = #piles - #piles_name + if x > 0 then + for i = 1, x, 1 do table.insert(piles_name, Fk:translate("Pile") .. i) end + elseif x < 0 then + piles_name = table.slice(piles_name, 1, #piles + 1) end self:notifyMoveFocus(player, customNotify or command) local data = { @@ -2884,6 +2848,7 @@ function Room:abortPlayerArea(player, playerSlots) from = player.id, toArea = Card.DiscardPile, moveReason = fk.ReasonPutIntoDiscardPile, + skillName = "gamerule_aborted" }) table.insertTable(player.sealedSlots, slotsToSeal) diff --git a/lua/server/scheduler.lua b/lua/server/scheduler.lua index 7ac2398f..8eb70d98 100644 --- a/lua/server/scheduler.lua +++ b/lua/server/scheduler.lua @@ -46,12 +46,12 @@ function HandleRequest(req) return true end -function ResumeRoom(roomId) +function ResumeRoom(roomId, reason) local room = requestRoom:getRoom(roomId) if not room then return false end if not room:isReady() then return false end RoomInstance = (room ~= requestRoom and room or nil) - local over = room:resume() + local over = room:resume(reason) RoomInstance = nil if over then diff --git a/lua/server/serverplayer.lua b/lua/server/serverplayer.lua index 4fad62c8..da28bf87 100644 --- a/lua/server/serverplayer.lua +++ b/lua/server/serverplayer.lua @@ -238,7 +238,7 @@ function ServerPlayer:gainAnExtraPhase(phase, delay) local cancel_skip = true if phase ~= Player.NotActive and (skip) then - cancel_skip = logic:trigger(fk.EventPhaseSkipping, self) + cancel_skip = logic:trigger(fk.EventPhaseSkipping, self, phase) end if (not skip) or (cancel_skip) then room:sendLog{ @@ -260,6 +260,7 @@ function ServerPlayer:gainAnExtraPhase(phase, delay) from = self.id, arg = Util.PhaseStrMapper(phase), } + logic:trigger(fk.EventPhaseSkipped, self, phase) end self.phase = current @@ -322,7 +323,7 @@ function ServerPlayer:play(phase_table) local cancel_skip = true if phases[i] ~= Player.NotActive and (skip) then - cancel_skip = logic:trigger(fk.EventPhaseSkipping, self) + cancel_skip = logic:trigger(fk.EventPhaseSkipping, self, self.phase) end if (not skip) or (cancel_skip) then @@ -333,6 +334,7 @@ function ServerPlayer:play(phase_table) from = self.id, arg = Util.PhaseStrMapper(self.phase), } + logic:trigger(fk.EventPhaseSkipped, self, self.phase) end end end diff --git a/packages/standard/game_rule.lua b/packages/standard/game_rule.lua index b5ba5a8e..6e8c57fd 100644 --- a/packages/standard/game_rule.lua +++ b/packages/standard/game_rule.lua @@ -48,6 +48,7 @@ GameRule = fk.CreateTriggerSkill{ end cardNames = table.filter(cardNames, function (cardName) + -- FIXME: 应该印一个“任何情况都适合”的牌,或者说根本不该有这个过滤 local cardCloned = Fk:cloneCard(cardName) return not (player:prohibitUse(cardCloned) or player:isProhibited(dyingPlayer, cardCloned)) end) diff --git a/packages/standard_cards/i18n/en_US.lua b/packages/standard_cards/i18n/en_US.lua index 4a353c52..4ea3df5f 100644 --- a/packages/standard_cards/i18n/en_US.lua +++ b/packages/standard_cards/i18n/en_US.lua @@ -8,7 +8,8 @@ Fk:loadTranslationTable({ ["log_heart"] = '', ["log_club"] = '♣', ["log_diamond"] = '', - ["log_nosuit"] = "No suit", + ["log_nosuit"] = "X", + ["log_unknown"] = "?", -- ["spade"] = "Spade", -- ["heart"] = "Heart", -- ["club"] = "Club", diff --git a/packages/standard_cards/i18n/zh_CN.lua b/packages/standard_cards/i18n/zh_CN.lua index f5a6afa2..39d90453 100644 --- a/packages/standard_cards/i18n/zh_CN.lua +++ b/packages/standard_cards/i18n/zh_CN.lua @@ -8,7 +8,9 @@ Fk:loadTranslationTable{ ["log_heart"] = '', ["log_club"] = '♣', ["log_diamond"] = '', - ["log_nosuit"] = "无花色", + ["log_nosuit"] = "X", + ["log_unknown"] = "?", + ["unknown"] = "未知", ["spade"] = "黑桃", ["heart"] = "红桃", ["club"] = "梅花",