diff --git a/Fk/Pages/RoomLogic.js b/Fk/Pages/RoomLogic.js index 025960fe..46fb9508 100644 --- a/Fk/Pages/RoomLogic.js +++ b/Fk/Pages/RoomLogic.js @@ -1107,7 +1107,7 @@ callbacks["AskForCardChosen"] = (jsonData) => { const reason = data._reason; const prompt = data._prompt; if (prompt === "") { - roomScene.promptText = luatr("#AskForChooseCard") + roomScene.promptText = luatr(processPrompt("#AskForChooseCard:" + data._id)) .arg(luatr(reason)); } else { roomScene.setPrompt(processPrompt(prompt), true); @@ -1139,7 +1139,7 @@ callbacks["AskForCardsChosen"] = (jsonData) => { const reason = data._reason; const prompt = data._prompt; if (prompt === "") { - roomScene.promptText = luatr("#AskForChooseCards") + roomScene.promptText = luatr(processPrompt("#AskForChooseCards:" + data._id)) .arg(luatr(reason)).arg(min).arg(max); } else { roomScene.setPrompt(processPrompt(prompt), true); diff --git a/lua/client/client.lua b/lua/client/client.lua index 931f9ff9..33304613 100644 --- a/lua/client/client.lua +++ b/lua/client/client.lua @@ -378,6 +378,7 @@ fk.client_callback["AskForCardChosen"] = function(jsonData) judge = {} end ui_data = { + _id = id, _reason = reason, card_data = {}, _prompt = prompt, @@ -413,6 +414,7 @@ fk.client_callback["AskForCardsChosen"] = function(jsonData) judge = {} end ui_data = { + _id = id, _min = min, _max = max, _reason = reason, diff --git a/lua/client/i18n/en_US.lua b/lua/client/i18n/en_US.lua index 6c3e5af1..ee356e21 100644 --- a/lua/client/i18n/en_US.lua +++ b/lua/client/i18n/en_US.lua @@ -185,12 +185,13 @@ Fk:loadTranslationTable({ ["AskForKingdom"] = "Choosing kingdom", ["AskForPindian"] = "Point fight", ["AskForMoveCardInBoard"] = "Moving cards", + ["replaceEquip"] = "Replacing Equip", ["PlayCard"] = "Playing card", ["AskForCardChosen"] = "Choosing card", ["AskForCardsChosen"] = "Choosing card", - ["#AskForChooseCard"] = "%1: please choose a card", - ["#AskForChooseCards"] = "%1: please choose %2~%3 cards", + ["#AskForChooseCard"] = "%1: please choose a card from %src", + ["#AskForChooseCards"] = "%1: please choose %2~%3 cards from %src", ["$ChooseCard"] = "Choose a card", ["$ChooseCards"] = "Choose %1~%2 cards", ["$Hand"] = "Hand", @@ -209,6 +210,7 @@ Fk:loadTranslationTable({ ["#AskForCard"] = "Please choose %arg cards (%arg2 at least)", ["#AskForDistribution"] = "Please distribute cards (%arg at least , %arg2 total)", ["@DistributionTo"] = "", + ["#replaceEquip"] = "Please Choose a Equip Card to be replaced", ["#askForPindian"] = "%arg: please choose a hand card for point fight", ["#StartPindianReason"] = "%from started point fight (%arg)", ["#ShowPindianCard"] = "The point fight card of %from is %card", diff --git a/lua/client/i18n/zh_CN.lua b/lua/client/i18n/zh_CN.lua index 30734967..59cdc393 100644 --- a/lua/client/i18n/zh_CN.lua +++ b/lua/client/i18n/zh_CN.lua @@ -239,12 +239,13 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下 ["AskForKingdom"] = "选择势力", ["AskForPindian"] = "拼点", ["AskForMoveCardInBoard"] = "移动卡牌", + ["replaceEquip"] = "替换装备", ["PlayCard"] = "出牌", ["AskForCardChosen"] = "选牌", ["AskForCardsChosen"] = "选牌", - ["#AskForChooseCard"] = "%1:请选择其一张卡牌", - ["#AskForChooseCards"] = "%1:请选择其%2至%3张卡牌", + ["#AskForChooseCard"] = "%1:请选择%src的一张卡牌", + ["#AskForChooseCards"] = "%1:请选择%src的%2至%3张卡牌", ["$ChooseCard"] = "请选择一张卡牌", ["$ChooseCards"] = "请选择%1至%2张卡牌", ["$Hand"] = "手牌区", @@ -263,6 +264,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下 ["#AskForCard"] = "请选择 %arg 张牌,最少 %arg2 张", ["#AskForDistribution"] = "请分配这些牌,至少 %arg 张,至多 %arg2 张", ["@DistributionTo"] = "", + ["#replaceEquip"] = "选择一张装备牌替换之", ["#askForPindian"] = "%arg:请选择一张手牌作为拼点牌", ["#StartPindianReason"] = "%from 由于 %arg 而发起拼点", ["#ShowPindianCard"] = "%from 的拼点牌是 %card", diff --git a/lua/core/general.lua b/lua/core/general.lua index 24f4beee..24008eee 100644 --- a/lua/core/general.lua +++ b/lua/core/general.lua @@ -71,7 +71,7 @@ function General:__tostring() end --- 为武将增加技能,需要注意增加其他武将技能时的处理方式。 ----@param skill Skill @ (单个)武将技能 +---@param skill Skill|string @ (单个)武将技能 function General:addSkill(skill) if (type(skill) == "string") then table.insert(self.other_skills, skill) @@ -82,7 +82,7 @@ function General:addSkill(skill) end --- 为武将增加相关技能,需要注意增加其他武将技能时的处理方式。 ----@param skill Skill @ (单个)武将技能 +---@param skill Skill|string @ (单个)武将技能 function General:addRelatedSkill(skill) if (type(skill) == "string") then table.insert(self.related_other_skills, skill) diff --git a/lua/core/player.lua b/lua/core/player.lua index cf5af40d..ceb536b7 100644 --- a/lua/core/player.lua +++ b/lua/core/player.lua @@ -475,9 +475,17 @@ end --- 获取角色是否被移除。 function Player:isRemoved() - return self:getMark(MarkEnum.PlayerRemoved) ~= 0 or table.find(MarkEnum.TempMarkSuffix, function(s) - return self:getMark(MarkEnum.PlayerRemoved .. s) ~= 0 - end) + for mark, _ in pairs(self.mark) do + if mark == MarkEnum.PlayerRemoved then return true end + if mark:startsWith(MarkEnum.PlayerRemoved .. "-") then + for _, suffix in ipairs(MarkEnum.TempMarkSuffix) do + if mark:find(suffix, 1, true) then return true end + end + end + end + -- return self:getMark(MarkEnum.PlayerRemoved) ~= 0 or table.find(MarkEnum.TempMarkSuffix, function(s) + -- return self:getMark(MarkEnum.PlayerRemoved .. s) ~= 0 + -- end) end --- 修改玩家与其他角色的固定距离。 @@ -950,13 +958,21 @@ function Player:prohibitReveal(isDeputy) if type(self:getMark(MarkEnum.RevealProhibited)) == "table" and table.contains(self:getMark(MarkEnum.RevealProhibited), place) then return true end - for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s) - return self:getMark(MarkEnum.RevealProhibited .. s) - end)) do - if type(m) == "table" and table.contains(m, place) then - return true + + for mark, value in pairs(self.mark) do + if mark:startsWith(MarkEnum.RevealProhibited .. "-") and type(value) == "table" then + for _, suffix in ipairs(MarkEnum.TempMarkSuffix) do + if mark:find(suffix, 1, true) then return true end + end end end + -- for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s) + -- return self:getMark(MarkEnum.RevealProhibited .. s) + -- end)) do + -- if type(m) == "table" and table.contains(m, place) then + -- return true + -- end + -- end return false end @@ -981,6 +997,21 @@ function Player:canPindian(to, ignoreFromKong, ignoreToKong) return true end +--- 判断一张牌能否移动至某角色的装备区 +---@param cardId integer @ 移动的牌 +---@param convert? boolean @ 是否可以替换装备(默认可以) +---@return boolean +function Player:canMoveCardIntoEquip(cardId, convert) + convert = (convert == nil) and true or convert + local card = Fk:getCardById(cardId) + if not (card.sub_type >= 3 and card.sub_type <= 7) then return false end + if self.dead or table.contains(self:getCardIds("e"), cardId) then return false end + if self:hasEmptyEquipSlot(card.sub_type) or (#self:getEquipments(card.sub_type) > 0 and convert) then + return true + end + return false +end + --转换技状态阳 fk.SwitchYang = 0 --转换技状态阴 diff --git a/lua/core/skill_type/active.lua b/lua/core/skill_type/active.lua index a0d6a411..7609879c 100644 --- a/lua/core/skill_type/active.lua +++ b/lua/core/skill_type/active.lua @@ -155,21 +155,38 @@ function ActiveSkill:withinDistanceLimit(player, isattack, card, to) local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix) local card_temp_suf = table.simpleClone(MarkEnum.CardTempMarkSuffix) - table.insert(temp_suf, 1, "") - table.insert(temp_suf, "-tmp") - table.insert(card_temp_suf, 1, "") + + ---@param object Card|Player + ---@param markname string + ---@param suffixes string[] + ---@return boolean + local function hasMark(object, markname, suffixes) + if not object then return false end + for mark, _ in pairs(object.mark) do + if mark == markname then return true end + if mark:startsWith(markname .. "-") then + for _, suffix in ipairs(suffixes) do + if mark:find(suffix, 1, true) then return true end + end + end + end + return false + end return (isattack and player:inMyAttackRange(to)) or (player:distanceTo(to) > 0 and player:distanceTo(to) <= self:getDistanceLimit(player, card, to)) or - (card and table.find(card_temp_suf, function(s) - return card:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0 - end)) or - (table.find(temp_suf, function(s) - return player:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0 - end)) or - (to and (table.find(temp_suf, function(s) - return to:getMark(MarkEnum.BypassDistancesLimitTo .. s) ~= 0 - end))) + hasMark(card, MarkEnum.BypassDistancesLimit, card_temp_suf) or + hasMark(player, MarkEnum.BypassDistancesLimit, temp_suf) or + hasMark(to, MarkEnum.BypassDistancesLimitTo, temp_suf) + -- (card and table.find(card_temp_suf, function(s) + -- return card:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0 + -- end)) or + -- (table.find(temp_suf, function(s) + -- return player:getMark(MarkEnum.BypassDistancesLimit .. s) ~= 0 + -- end)) or + -- (to and (table.find(temp_suf, function(s) + -- return to:getMark(MarkEnum.BypassDistancesLimitTo .. s) ~= 0 + -- end))) end --- Determine if selected cards and targets are valid for this skill diff --git a/lua/core/skill_type/usable_skill.lua b/lua/core/skill_type/usable_skill.lua index 34e9d430..7fbbb082 100644 --- a/lua/core/skill_type/usable_skill.lua +++ b/lua/core/skill_type/usable_skill.lua @@ -40,20 +40,37 @@ function UsableSkill:withinTimesLimit(player, scope, card, card_name, to) card_name = card_name or card.trueName local temp_suf = table.simpleClone(MarkEnum.TempMarkSuffix) local card_temp_suf = table.simpleClone(MarkEnum.CardTempMarkSuffix) - table.insert(temp_suf, 1, "") - table.insert(temp_suf, "-tmp") - table.insert(card_temp_suf, 1, "") + + ---@param object Card|Player + ---@param markname string + ---@param suffixes string[] + ---@return boolean + local function hasMark(object, markname, suffixes) + if not object then return false end + for mark, _ in pairs(object.mark) do + if mark == markname then return true end + if mark:startsWith(markname .. "-") then + for _, suffix in ipairs(suffixes) do + if mark:find(suffix, 1, true) then return true end + end + end + end + return false + end return player:usedCardTimes(card_name, scope) < self:getMaxUseTime(player, scope, card, to) or - (card and table.find(card_temp_suf, function(s) - return card:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0 - end)) or - (table.find(temp_suf, function(s) - return player:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0 - end)) or - (to and (table.find(temp_suf, function(s) - return to:getMark(MarkEnum.BypassTimesLimitTo .. s) ~= 0 - end))) + hasMark(card, MarkEnum.BypassTimesLimit, card_temp_suf) or + hasMark(player, MarkEnum.BypassTimesLimit, temp_suf) or + hasMark(to, MarkEnum.BypassTimesLimitTo, temp_suf) + -- (card and table.find(card_temp_suf, function(s) + -- return card:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0 + -- end)) or + -- (table.find(temp_suf, function(s) + -- return player:getMark(MarkEnum.BypassTimesLimit .. s) ~= 0 + -- end)) or + -- (to and (table.find(temp_suf, function(s) + -- return to:getMark(MarkEnum.BypassTimesLimitTo .. s) ~= 0 + -- end))) end return UsableSkill diff --git a/lua/core/util.lua b/lua/core/util.lua index 975c5dd2..77cabc5c 100644 --- a/lua/core/util.lua +++ b/lua/core/util.lua @@ -114,6 +114,73 @@ function fk.sorted_pairs(t, val_func, reverse) return iter, nil, 1 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 + +--- 全局卡牌(包括自己)的canUse +Util.GlobalCanUse = function(self, player, card) + local room = Fk:currentRoom() + for _, p in ipairs(room.alive_players) do + if not (card and player:isProhibited(p, card)) then + return true + end + end +end + +--- AOE卡牌(不包括自己)的canUse +Util.AoeCanUse = function(self, player, card) + local room = Fk:currentRoom() + for _, p in ipairs(room.alive_players) do + if p ~= player and not (card and player:isProhibited(p, card)) then + return true + end + end +end + +--- 全局卡牌(包括自己)的onUse +Util.GlobalOnUse = function(self, room, cardUseEvent) + if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then + cardUseEvent.tos = {} + for _, player in ipairs(room:getAlivePlayers()) do + if not room:getPlayerById(cardUseEvent.from):isProhibited(player, cardUseEvent.card) then + TargetGroup:pushTargets(cardUseEvent.tos, player.id) + end + end + end +end + +--- AOE卡牌(不包括自己)的onUse +Util.AoeOnUse = function(self, room, cardUseEvent) + if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then + cardUseEvent.tos = {} + for _, player in ipairs(room:getOtherPlayers(room:getPlayerById(cardUseEvent.from))) do + if not room:getPlayerById(cardUseEvent.from):isProhibited(player, cardUseEvent.card) then + TargetGroup:pushTargets(cardUseEvent.tos, player.id) + end + end + end +end + +-- Table + ---@param func fun(element, index, array) function table:forEach(func) for i, v in ipairs(self) do @@ -164,66 +231,6 @@ function table:map(func) return ret 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 -Util.GlobalCanUse = function(self, player, card) - local room = Fk:currentRoom() - for _, p in ipairs(room.alive_players) do - if not (card and player:isProhibited(p, card)) then - return true - end - end -end - -Util.AoeCanUse = function(self, player, card) - local room = Fk:currentRoom() - for _, p in ipairs(room.alive_players) do - if p ~= player and not (card and player:isProhibited(p, card)) then - return true - end - end -end - -Util.GlobalOnUse = function(self, room, cardUseEvent) - if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then - cardUseEvent.tos = {} - for _, player in ipairs(room:getAlivePlayers()) do - if not room:getPlayerById(cardUseEvent.from):isProhibited(player, cardUseEvent.card) then - TargetGroup:pushTargets(cardUseEvent.tos, player.id) - end - end - end -end - -Util.AoeOnUse = function(self, room, cardUseEvent) - if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then - cardUseEvent.tos = {} - for _, player in ipairs(room:getOtherPlayers(room:getPlayerById(cardUseEvent.from))) do - if not room:getPlayerById(cardUseEvent.from):isProhibited(player, cardUseEvent.card) then - TargetGroup:pushTargets(cardUseEvent.tos, player.id) - end - end - end -end - ---@generic T ---@param self T[] ---@return T[] diff --git a/lua/server/events/gameflow.lua b/lua/server/events/gameflow.lua index b44f1041..2c8ebea5 100644 --- a/lua/server/events/gameflow.lua +++ b/lua/server/events/gameflow.lua @@ -174,7 +174,7 @@ GameEvent.cleaners[GameEvent.Round] = function(self) p:setCardUseHistory("", 0, Player.HistoryRound) p:setSkillUseHistory("", 0, Player.HistoryRound) for name, _ in pairs(p.mark) do - if name:endsWith("-round") then + if name:find("-round", 1, true) then room:setPlayerMark(p, name, 0) end end @@ -182,7 +182,7 @@ GameEvent.cleaners[GameEvent.Round] = function(self) for cid, cmark in pairs(room.card_marks) do for name, _ in pairs(cmark) do - if name:endsWith("-round") then + if name:find("-round", 1, true) then room:setCardMark(Fk:getCardById(cid), name, 0) end end @@ -249,7 +249,7 @@ GameEvent.cleaners[GameEvent.Turn] = function(self) p:setCardUseHistory("", 0, Player.HistoryTurn) p:setSkillUseHistory("", 0, Player.HistoryTurn) for name, _ in pairs(p.mark) do - if name:endsWith("-turn") then + if name:find("-turn", 1, true) then room:setPlayerMark(p, name, 0) end end @@ -257,7 +257,7 @@ GameEvent.cleaners[GameEvent.Turn] = function(self) for cid, cmark in pairs(room.card_marks) do for name, _ in pairs(cmark) do - if name:endsWith("-turn") then + if name:find("-turn", 1, true) then room:setCardMark(Fk:getCardById(cid), name, 0) end end @@ -372,7 +372,7 @@ GameEvent.cleaners[GameEvent.Phase] = function(self) p:setCardUseHistory("", 0, Player.HistoryPhase) p:setSkillUseHistory("", 0, Player.HistoryPhase) for name, _ in pairs(p.mark) do - if name:endsWith("-phase") then + if name:find("-phase", 1, true) then room:setPlayerMark(p, name, 0) end end @@ -380,7 +380,7 @@ GameEvent.cleaners[GameEvent.Phase] = function(self) for cid, cmark in pairs(room.card_marks) do for name, _ in pairs(cmark) do - if name:endsWith("-phase") then + if name:find("-phase", 1, true) then room:setCardMark(Fk:getCardById(cid), name, 0) end end diff --git a/lua/server/events/movecard.lua b/lua/server/events/movecard.lua index 764a388d..69e7b48b 100644 --- a/lua/server/events/movecard.lua +++ b/lua/server/events/movecard.lua @@ -166,7 +166,7 @@ GameEvent.functions[GameEvent.MoveCards] = function(self) local currentCard = Fk:getCardById(info.cardId) for name, _ in pairs(currentCard.mark) do - if name:endsWith("-inhand") and + if name:find("-inhand", 1, true) and realFromArea == Player.Hand and data.from then diff --git a/lua/server/room.lua b/lua/server/room.lua index ac0e80c1..68491550 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -1501,6 +1501,7 @@ end ---@param name string @ 武将name,如找不到则查找truename,再找不到则返回nil ---@return string? @ 抽出的武将名 function Room:findGeneral(name) + if not Fk.generals[name] then return nil end for i, g in ipairs(self.general_pile) do if g == name or Fk.generals[g].trueName == Fk.generals[name].trueName then return table.remove(self.general_pile, i) @@ -1517,13 +1518,13 @@ function Room:findGenerals(func, n) n = n or 1 local ret = {} local index = 1 - repeat + while #ret < n and index <= #self.general_pile do if func(self.general_pile[index]) then table.insert(ret, table.remove(self.general_pile, index)) else index = index + 1 end - until index >= #self.general_pile or #ret >= n + end return ret end @@ -2993,8 +2994,10 @@ end ---@param proposer? integer @ 移动操作者的id function Room:obtainCard(player, cid, unhide, reason, proposer) if type(cid) ~= "number" then - assert(cid and cid:isInstanceOf(Card)) - cid = cid:isVirtual() and cid.subcards or {cid.id} + assert(cid and type(cid) == "table") + if cid:isInstanceOf(Card) then + cid = cid:isVirtual() and cid.subcards or {cid.id} + end else cid = {cid} end @@ -3156,6 +3159,37 @@ function Room:doYiji(room, list, proposer, skillName) return move_ids end +--- 将一张牌移动至某角色的装备区,若不合法则置入弃牌堆。目前没做相同副类别装备同时置入的适配(甘露神典韦) +---@param target ServerPlayer @ 接受牌的角色 +---@param cards integer|integer[] @ 移动的牌 +---@param skillName? string @ 技能名 +---@param convert? boolean @ 是否可以替换装备(默认可以) +---@param proposer? ServerPlayer @ 操作者 +function Room:moveCardIntoEquip(target, cards, skillName, convert, proposer) + convert = (convert == nil) and true or convert + skillName = skillName or "" + cards = type(cards) == "table" and cards or {cards} + local moves = {} + for _, cardId in ipairs(cards) do + local card = Fk:getCardById(cardId) + local fromId = self.owner_map[cardId] + local proposerId = proposer and proposer.id or nil + if target:canMoveCardIntoEquip(cardId, convert) then + if target:hasEmptyEquipSlot(card.sub_type) then + table.insert(moves,{ids = {cardId}, from = fromId, to = target.id, toArea = Card.PlayerEquip, moveReason = fk.ReasonPut,skillName = skillName,proposer = proposerId}) + else + local existingEquip = target:getEquipments(card.sub_type) + local throw = #existingEquip == 1 and existingEquip[1] or + self:askForCardChosen(proposer or target, target, {card_data = { {Util.convertSubtypeAndEquipSlot(card.sub_type),existingEquip} } }, "replaceEquip","#replaceEquip") + table.insert(moves,{ids = {throw}, from = target.id, toArea = Card.DiscardPile, moveReason = fk.ReasonPutIntoDiscardPile, skillName = skillName,proposer = proposerId}) + table.insert(moves,{ids = {cardId}, from = fromId, to = target.id, toArea = Card.PlayerEquip, moveReason = fk.ReasonPut,skillName = skillName,proposer = proposerId}) + end + else + table.insert(moves,{ids = {cardId}, from = fromId, toArea = Card.DiscardPile, moveReason = fk.ReasonPutIntoDiscardPile,skillName = skillName}) + end + end + self:moveCards(table.unpack(moves)) +end ------------------------------------------------------------------------ -- 其他游戏事件 ------------------------------------------------------------------------ diff --git a/packages/maneuvering/init.lua b/packages/maneuvering/init.lua index 0283fcdc..0a95e07c 100644 --- a/packages/maneuvering/init.lua +++ b/packages/maneuvering/init.lua @@ -366,9 +366,12 @@ local fanSkill = fk.CreateTriggerSkill{ card[k] = v end end - if not data.card:isVirtual() then + if data.card:isVirtual() then + card.subcards = data.card.subcards + else card.id = data.card.id end + card.skillNames = data.card.skillNames card.skillName = "fan" data.card = card end, diff --git a/packages/standard/aux_skills.lua b/packages/standard/aux_skills.lua index 916c6aa4..a3b527ab 100644 --- a/packages/standard/aux_skills.lua +++ b/packages/standard/aux_skills.lua @@ -129,11 +129,25 @@ local maxCardsSkill = fk.CreateMaxCardsSkill{ name = "max_cards_skill", global = true, correct_func = function(self, player) + local function getMark(markname) + local v = 0 + for mark, value in pairs(player.mark) do + if mark == markname then + v = v + value + elseif mark:startsWith(markname .. "-") then + for _, suffix in ipairs(MarkEnum.TempMarkSuffix) do + if mark:find(suffix, 1, true) then + v = v + value + break + end + end + end + end + return v + end return - player:getMark(MarkEnum.AddMaxCards) + - player:getMark(MarkEnum.AddMaxCardsInTurn) - - player:getMark(MarkEnum.MinusMaxCards) - - player:getMark(MarkEnum.MinusMaxCardsInTurn) + getMark(MarkEnum.AddMaxCards) - + getMark(MarkEnum.MinusMaxCards) end, } @@ -181,15 +195,32 @@ local uncompulsoryInvalidity = fk.CreateInvaliditySkill { name = "uncompulsory_invalidity", global = true, invalidity_func = function(self, from, skill) + ---@param object Card|Player + ---@param markname string + ---@param suffixes string[] + ---@return boolean + local function hasMark(object, markname, suffixes) + if not object then return false end + for mark, _ in pairs(object.mark) do + if mark == markname then return true end + if mark:startsWith(markname .. "-") then + for _, suffix in ipairs(suffixes) do + if mark:find(suffix, 1, true) then return true end + end + end + end + return false + end return (skill.frequency ~= Skill.Compulsory and skill.frequency ~= Skill.Wake) and not (skill:isEquipmentSkill() or skill.name:endsWith("&")) and - ( - from:getMark(MarkEnum.UncompulsoryInvalidity) ~= 0 or - table.find(MarkEnum.TempMarkSuffix, function(s) - return from:getMark(MarkEnum.UncompulsoryInvalidity .. s) ~= 0 - end) - ) + hasMark(from, MarkEnum.UncompulsoryInvalidity, MarkEnum.TempMarkSuffix) + -- ( + -- from:getMark(MarkEnum.UncompulsoryInvalidity) ~= 0 or + -- table.find(MarkEnum.TempMarkSuffix, function(s) + -- return from:getMark(MarkEnum.UncompulsoryInvalidity .. s) ~= 0 + -- end) + -- ) end } @@ -201,15 +232,27 @@ local revealProhibited = fk.CreateInvaliditySkill { if type(from:getMark(MarkEnum.RevealProhibited)) == "table" then generals = from:getMark(MarkEnum.RevealProhibited) end - for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s) - return from:getMark(MarkEnum.RevealProhibited .. s) - end)) do - if type(m) == "table" then - for _, g in ipairs(m) do - table.insertIfNeed(generals, g) + + for mark, value in pairs(from.mark) do + if mark:startsWith(MarkEnum.RevealProhibited .. "-") and type(value) == "table" then + for _, suffix in ipairs(MarkEnum.TempMarkSuffix) do + if mark:find(suffix, 1, true) then + for _, g in ipairs(value) do + table.insertIfNeed(generals, g) + end + end end end end + -- for _, m in ipairs(table.map(MarkEnum.TempMarkSuffix, function(s) + -- return from:getMark(MarkEnum.RevealProhibited .. s) + -- end)) do + -- if type(m) == "table" then + -- for _, g in ipairs(m) do + -- table.insertIfNeed(generals, g) + -- end + -- end + -- end if #generals == 0 then return false end local sname = skill.name diff --git a/packages/standard/init.lua b/packages/standard/init.lua index 2d1d5c7e..16670af7 100644 --- a/packages/standard/init.lua +++ b/packages/standard/init.lua @@ -1132,9 +1132,17 @@ local role_getlogic = function() lord_general = lord_generals lord_generals = {lord_general} end - - generals = table.filter(generals, function(g) return not table.contains(lord_generals, g) end) room:returnToGeneralPile(generals) + local index = 1 + while index <= #room.general_pile do + local ret = {} + for _, gname in ipairs(lord_generals) do + if room.general_pile[index] == gname or Fk.generals[room.general_pile[index]].trueName == Fk.generals[gname].trueName then + table.insert(ret, table.remove(room.general_pile, index)) + end + end + if #ret == 0 then index = index + 1 end + end room:setPlayerGeneral(lord, lord_general, true) room:askForChooseKingdom({lord}) @@ -1216,14 +1224,24 @@ local role_getlogic = function() room:setPlayerGeneral(p, general, true, true) room:setDeputyGeneral(p, deputy) else + table.insertTableIfNeed(selected, p.default_reply) room:setPlayerGeneral(p, p.default_reply[1], true, true) room:setDeputyGeneral(p, p.default_reply[2]) end p.default_reply = "" end - generals = table.filter(generals, function(g) return not table.contains(selected, g) end) room:returnToGeneralPile(generals) + local index = 1 + while index <= #room.general_pile do + local ret = {} + for _, gname in ipairs(selected) do + if room.general_pile[index] == gname or Fk.generals[room.general_pile[index]].trueName == Fk.generals[gname].trueName then + table.insert(ret, table.remove(room.general_pile, index)) + end + end + if #ret == 0 then index = index + 1 end + end room:askForChooseKingdom(nonlord) end