From 6fbaf9d05512a8f6f70d6379ec28052e6e4194a5 Mon Sep 17 00:00:00 2001 From: YoumuKon <38815081+YoumuKon@users.noreply.github.com> Date: Sat, 17 Feb 2024 09:48:42 +0800 Subject: [PATCH] askForYiji (#318) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从Utility那里搬运了askForYiji和doYiji两个函数,负责分配 虽然暂时没实现单烧条,但先这么用着 - 修复了askForCardAndPlayers的选择中可以选择复数张牌的bug - 为prohibitDiscard添加了输入id选项 --- lua/client/i18n/en_US.lua | 6 +- lua/client/i18n/zh_CN.lua | 2 + lua/core/player.lua | 6 +- lua/core/skill_type/active.lua | 4 +- lua/core/skill_type/view_as.lua | 4 +- lua/server/room.lua | 147 +++++++++++++++++++++++++++++++ packages/standard/aux_skills.lua | 20 ++++- packages/standard/i18n/en_US.lua | 2 + packages/standard/i18n/zh_CN.lua | 2 + packages/test/init.lua | 1 + 10 files changed, 185 insertions(+), 9 deletions(-) diff --git a/lua/client/i18n/en_US.lua b/lua/client/i18n/en_US.lua index 4e9ef76f..6c3e5af1 100644 --- a/lua/client/i18n/en_US.lua +++ b/lua/client/i18n/en_US.lua @@ -205,8 +205,10 @@ Fk:loadTranslationTable({ ["#AskForPeaches"] = "%src is dying, please use %arg Peach(es) to save him", ["#AskForPeachesSelf"] = "You are dying, please use %arg Peach(es)/Alcohol to save yourself", - ["#AskForDiscard"] = "Please discard %arg cards (at least %arg2)", - ["#AskForCard"] = "Please choose %arg cards (at least %arg2)", + ["#AskForDiscard"] = "Please discard %arg cards (%arg2 at least)", + ["#AskForCard"] = "Please choose %arg cards (%arg2 at least)", + ["#AskForDistribution"] = "Please distribute cards (%arg at least , %arg2 total)", + ["@DistributionTo"] = "", ["#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 2e92b714..30734967 100644 --- a/lua/client/i18n/zh_CN.lua +++ b/lua/client/i18n/zh_CN.lua @@ -261,6 +261,8 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下 ["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张", ["#AskForCard"] = "请选择 %arg 张牌,最少 %arg2 张", + ["#AskForDistribution"] = "请分配这些牌,至少 %arg 张,至多 %arg2 张", + ["@DistributionTo"] = "", ["#askForPindian"] = "%arg:请选择一张手牌作为拼点牌", ["#StartPindianReason"] = "%from 由于 %arg 而发起拼点", ["#ShowPindianCard"] = "%from 的拼点牌是 %card", diff --git a/lua/core/player.lua b/lua/core/player.lua index 6adfa938..cf5af40d 100644 --- a/lua/core/player.lua +++ b/lua/core/player.lua @@ -929,8 +929,12 @@ function Player:prohibitResponse(card) end --- 确认玩家是否被禁止弃置特定牌。 ----@param card Card @ 特定的牌 +---@param card Card|integer @ 特定的牌 function Player:prohibitDiscard(card) + if type(card) == "number" then + card = Fk:getCardById(card) + end + local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or Util.DummyTable for _, skill in ipairs(status_skills) do if skill:prohibitDiscard(self, card) then diff --git a/lua/core/skill_type/active.lua b/lua/core/skill_type/active.lua index 4e448c03..a0d6a411 100644 --- a/lua/core/skill_type/active.lua +++ b/lua/core/skill_type/active.lua @@ -208,8 +208,8 @@ function ActiveSkill:onEffect(room, cardEffectEvent) end ---@param cardEffectEvent CardEffectEvent | SkillEffectEvent function ActiveSkill:onNullified(room, cardEffectEvent) end ----@param selected integer[] @ ids of selected players ---@param selected_cards integer[] @ ids of selected cards -function ActiveSkill:prompt(selected, selected_cards) return "" end +---@param selected_targets integer[] @ ids of selected players +function ActiveSkill:prompt(selected_cards, selected_targets) return "" end return ActiveSkill diff --git a/lua/core/skill_type/view_as.lua b/lua/core/skill_type/view_as.lua index b3798753..e87e3b09 100644 --- a/lua/core/skill_type/view_as.lua +++ b/lua/core/skill_type/view_as.lua @@ -43,8 +43,8 @@ function ViewAsSkill:beforeUse(player, cardUseStruct) end ---@param cardUseStruct CardUseStruct function ViewAsSkill:afterUse(player, cardUseStruct) end ----@param selected integer[] @ ids of selected players ---@param selected_cards integer[] @ ids of selected cards -function ViewAsSkill:prompt(selected, selected_cards) return "" end +---@param selected_targets integer[] @ ids of selected players +function ViewAsSkill:prompt(selected_cards, selected_targets) return "" end return ViewAsSkill diff --git a/lua/server/room.lua b/lua/server/room.lua index 7f8bd5f8..ac0e80c1 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -1366,6 +1366,94 @@ function Room:askForChooseCardsAndPlayers(player, minCardNum, maxCardNum, target end end +--- 询问将卡牌分配给任意角色。 +---@param player ServerPlayer @ 要询问的玩家 +---@param cards? integer[] @ 要分配的卡牌。默认拥有的所有牌 +---@param targets? ServerPlayer[] @ 可以获得卡牌的角色。默认所有存活角色 +---@param skillName? string @ 技能名,影响焦点信息。默认为“分配” +---@param minNum? integer @ 最少交出的卡牌数,默认0 +---@param maxNum? integer @ 最多交出的卡牌数,默认所有牌 +---@param prompt? string @ 询问提示信息 +---@param expand_pile? string @ 可选私人牌堆名称,如要分配你武将牌上的牌请填写 +---@param skipMove? boolean @ 是否跳过移动。默认不跳过 +---@param single_max? integer|table @ 限制每人能获得的最大牌数。输入整数或(以角色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") + local _cards = table.simpleClone(cards) + targets = table.map(targets, Util.IdMapper) + self:sortPlayersByAction(targets) + skillName = skillName or "distribution_select_skill" + minNum = minNum or 0 + maxNum = maxNum or #cards + local list = {} + for _, pid in ipairs(targets) do + list[pid] = {} + end + local toStr = function(int) return string.format("%d", int) end + local residueMap = {} + if type(single_max) == "table" then + for pid, v in pairs(single_max) do + residueMap[toStr(pid)] = v + end + end + local residue_sum = 0 + local residue_num = type(single_max) == "number" and single_max or 9999 + for _, pid in ipairs(targets) do + residueMap[toStr(pid)] = residueMap[toStr(pid)] or residue_num + residue_sum = residue_sum + residueMap[toStr(pid)] + end + minNum = math.min(minNum, #_cards, residue_sum) + local data = { + cards = _cards, + max_num = maxNum, + targets = targets, + residued_list = residueMap, + expand_pile = expand_pile + } + p(json.encode(residueMap)) + + while maxNum > 0 and #_cards > 0 do + data.max_num = maxNum + prompt = prompt or ("#AskForDistribution:::"..minNum..":"..maxNum) + local success, dat = self:askForUseActiveSkill(player, "distribution_select_skill", prompt, minNum == 0, data, true) + if success and dat then + local to = dat.targets[1] + local give_cards = dat.cards + for _, id in ipairs(give_cards) do + table.insert(list[to], id) + table.removeOne(_cards, id) + self:setCardMark(Fk:getCardById(id), "@DistributionTo", Fk:translate(self:getPlayerById(to).general)) + end + minNum = math.max(0, minNum - #give_cards) + maxNum = maxNum - #give_cards + residueMap[toStr(to)] = residueMap[toStr(to)] - #give_cards + else + break + end + end + + for _, id in ipairs(cards) do + self:setCardMark(Fk:getCardById(id), "@DistributionTo", 0) + end + for _, pid in ipairs(targets) do + if minNum == 0 or #_cards == 0 then break end + local num = math.min(residueMap[toStr(pid)] or 0, minNum, #_cards) + if num > 0 then + for i = num, 1, -1 do + local c = table.remove(_cards, i) + table.insert(list[pid], c) + minNum = minNum - 1 + end + end + end + if not skipMove then + self:doYiji(self, list, player.id, skillName) + end + + return list +end --- 抽个武将 --- --- 同getNCards,抽出来就没有了,所以记得放回去。 @@ -3009,6 +3097,65 @@ function Room:moveCardTo(card, to_place, target, reason, skill_name, special_nam self:moveCards(table.unpack(movesSplitedByOwner)) end +--- 将一些卡牌同时分配给一些角色。 +---@param room Room @ 房间 +---@param list table @ 分配牌和角色的数据表,键为角色id,值为分配给其的牌id数组 +---@param proposer? integer @ 操作者的id。默认为空 +---@param skillName? string @ 技能名。默认为“分配” +---@return table @ 返回成功分配的卡牌 +function Room:doYiji(room, 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 handcards = toP:getCardIds("h") + cards = table.filter(cards, function (id) return not table.contains(handcards, id) end) + if #cards > 0 then + table.insertTable(move_ids, cards) + local moveMap = {} + local noFrom = {} + for _, id in ipairs(cards) do + local from = room.owner_map[id] + if from then + moveMap[from] = moveMap[from] or {} + table.insert(moveMap[from], id) + else + table.insert(noFrom, id) + end + end + for from, _cards in pairs(moveMap) do + table.insert(moveInfos, { + ids = _cards, + moveInfo = table.map(_cards, function(id) + return {cardId = id, fromArea = room:getCardArea(id), fromSpecialName = room:getPlayerById(from):getPileNameOfId(id)} + end), + from = from, + to = to, + toArea = Card.PlayerHand, + moveReason = fk.ReasonGive, + proposer = proposer, + skillName = skillName, + }) + end + if #noFrom > 0 then + table.insert(moveInfos, { + ids = noFrom, + to = to, + toArea = Card.PlayerHand, + moveReason = fk.ReasonGive, + proposer = proposer, + skillName = skillName, + }) + end + end + end + if #moveInfos > 0 then + room:moveCards(table.unpack(moveInfos)) + end + return move_ids +end + ------------------------------------------------------------------------ -- 其他游戏事件 ------------------------------------------------------------------------ diff --git a/packages/standard/aux_skills.lua b/packages/standard/aux_skills.lua index 9c3d6b40..916c6aa4 100644 --- a/packages/standard/aux_skills.lua +++ b/packages/standard/aux_skills.lua @@ -78,8 +78,8 @@ local chooseCardsSkill = fk.CreateActiveSkill{ local choosePlayersSkill = fk.CreateActiveSkill{ name = "choose_players_skill", - card_filter = function(self, to_select) - return self.pattern ~= "" and Exppattern:Parse(self.pattern):match(Fk:getCardById(to_select)) + card_filter = function(self, to_select, selected) + return self.pattern ~= "" and Exppattern:Parse(self.pattern):match(Fk:getCardById(to_select)) and #selected == 0 end, target_filter = function(self, to_select, selected, cards) if self.pattern ~= "" and #cards == 0 then return end @@ -137,6 +137,21 @@ local maxCardsSkill = fk.CreateMaxCardsSkill{ end, } +local distributionSelectSkill = fk.CreateActiveSkill{ + name = "distribution_select_skill", + mute = true, + min_card_num = 1, + card_filter = function(self, to_select, selected) + return #selected < self.max_num and table.contains(self.cards, to_select) + end, + target_num = 1, + target_filter = function(self, to_select, selected, selected_cards) + return #selected == 0 and #selected_cards > 0 and table.contains(self.targets, to_select) + and #selected_cards <= (self.residued_list[string.format("%d", to_select)] or 0) + end, +} + + local choosePlayersToMoveCardInBoardSkill = fk.CreateActiveSkill{ name = "choose_players_to_move_card_in_board", target_num = 2, @@ -281,6 +296,7 @@ AuxSkills = { chooseCardsSkill, choosePlayersSkill, exChooseSkill, + distributionSelectSkill, maxCardsSkill, choosePlayersToMoveCardInBoardSkill, uncompulsoryInvalidity, diff --git a/packages/standard/i18n/en_US.lua b/packages/standard/i18n/en_US.lua index 948ef599..173de1fb 100644 --- a/packages/standard/i18n/en_US.lua +++ b/packages/standard/i18n/en_US.lua @@ -192,6 +192,8 @@ Fk:loadTranslationTable({ ["discard_skill"] = "Discard", ["choose_cards_skill"] = "Choose card", ["choose_players_skill"] = "Choose players", + ["ex__choose_skill"] = "Choose", + ["distribution_select_skill"] = "Distribute", ["choose_players_to_move_card_in_board"] = "Choose players", ["reveal_skill"] = "Reveal", ["#reveal_skill"] = "Choose a character to reveal", diff --git a/packages/standard/i18n/zh_CN.lua b/packages/standard/i18n/zh_CN.lua index 645350e9..acfd0c31 100644 --- a/packages/standard/i18n/zh_CN.lua +++ b/packages/standard/i18n/zh_CN.lua @@ -519,6 +519,8 @@ Fk:loadTranslationTable{ ["discard_skill"] = "弃牌", ["choose_cards_skill"] = "选牌", ["choose_players_skill"] = "选择角色", + ["ex__choose_skill"] = "选择", + ["distribution_select_skill"] = "分配", ["choose_players_to_move_card_in_board"] = "选择角色", ["reveal_skill"] = "亮将", ["#reveal_skill"] = "选择一个武将亮将(点击左侧选择框展开)", diff --git a/packages/test/init.lua b/packages/test/init.lua index 98b9aa71..802b1535 100644 --- a/packages/test/init.lua +++ b/packages/test/init.lua @@ -80,6 +80,7 @@ local control = fk.CreateActiveSkill{ -- ok = {10, 2}, -- }) -- room:swapSeat(from, to) + -- p(room:askForYiji(from, from:getCardIds(Player.Hand), table.map(effect.tos, Util.Id2PlayerMapper), self.name, 2, 10, nil, false, nil, false, 3, true)) for _, pid in ipairs(effect.tos) do local to = room:getPlayerById(pid) -- p(room:askForPoxi(from, "test", {