askForYiji (#318)

- 从Utility那里搬运了askForYiji和doYiji两个函数,负责分配
  虽然暂时没实现单烧条,但先这么用着
- 修复了askForCardAndPlayers的选择中可以选择复数张牌的bug
- 为prohibitDiscard添加了输入id选项
This commit is contained in:
YoumuKon 2024-02-17 09:48:42 +08:00 committed by GitHub
parent 7779f06411
commit 6fbaf9d055
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 185 additions and 9 deletions

View File

@ -205,8 +205,10 @@ Fk:loadTranslationTable({
["#AskForPeaches"] = "%src is dying, please use %arg Peach(es) to save him", ["#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", ["#AskForPeachesSelf"] = "You are dying, please use %arg Peach(es)/Alcohol to save yourself",
["#AskForDiscard"] = "Please discard %arg cards (at least %arg2)", ["#AskForDiscard"] = "Please discard %arg cards (%arg2 at least)",
["#AskForCard"] = "Please choose %arg cards (at least %arg2)", ["#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", ["#askForPindian"] = "%arg: please choose a hand card for point fight",
["#StartPindianReason"] = "%from started point fight (%arg)", ["#StartPindianReason"] = "%from started point fight (%arg)",
["#ShowPindianCard"] = "The point fight card of %from is %card", ["#ShowPindianCard"] = "The point fight card of %from is %card",

View File

@ -261,6 +261,8 @@ FreeKill使用的是libgit2的C API与此同时使用Git完成拓展包的下
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张", ["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
["#AskForCard"] = "请选择 %arg 张牌,最少 %arg2 张", ["#AskForCard"] = "请选择 %arg 张牌,最少 %arg2 张",
["#AskForDistribution"] = "请分配这些牌,至少 %arg 张,至多 %arg2 张",
["@DistributionTo"] = "",
["#askForPindian"] = "%arg请选择一张手牌作为拼点牌", ["#askForPindian"] = "%arg请选择一张手牌作为拼点牌",
["#StartPindianReason"] = "%from 由于 %arg 而发起拼点", ["#StartPindianReason"] = "%from 由于 %arg 而发起拼点",
["#ShowPindianCard"] = "%from 的拼点牌是 %card", ["#ShowPindianCard"] = "%from 的拼点牌是 %card",

View File

@ -929,8 +929,12 @@ function Player:prohibitResponse(card)
end end
--- 确认玩家是否被禁止弃置特定牌。 --- 确认玩家是否被禁止弃置特定牌。
---@param card Card @ 特定的牌 ---@param card Card|integer @ 特定的牌
function Player:prohibitDiscard(card) 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 local status_skills = Fk:currentRoom().status_skills[ProhibitSkill] or Util.DummyTable
for _, skill in ipairs(status_skills) do for _, skill in ipairs(status_skills) do
if skill:prohibitDiscard(self, card) then if skill:prohibitDiscard(self, card) then

View File

@ -208,8 +208,8 @@ function ActiveSkill:onEffect(room, cardEffectEvent) end
---@param cardEffectEvent CardEffectEvent | SkillEffectEvent ---@param cardEffectEvent CardEffectEvent | SkillEffectEvent
function ActiveSkill:onNullified(room, cardEffectEvent) end function ActiveSkill:onNullified(room, cardEffectEvent) end
---@param selected integer[] @ ids of selected players
---@param selected_cards integer[] @ ids of selected cards ---@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 return ActiveSkill

View File

@ -43,8 +43,8 @@ function ViewAsSkill:beforeUse(player, cardUseStruct) end
---@param cardUseStruct CardUseStruct ---@param cardUseStruct CardUseStruct
function ViewAsSkill:afterUse(player, cardUseStruct) end function ViewAsSkill:afterUse(player, cardUseStruct) end
---@param selected integer[] @ ids of selected players
---@param selected_cards integer[] @ ids of selected cards ---@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 return ViewAsSkill

View File

@ -1366,6 +1366,94 @@ function Room:askForChooseCardsAndPlayers(player, minCardNum, maxCardNum, target
end end
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<integer[]> @ 返回一个表键为角色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抽出来就没有了所以记得放回去。 --- 同getNCards抽出来就没有了所以记得放回去。
@ -3009,6 +3097,65 @@ function Room:moveCardTo(card, to_place, target, reason, skill_name, special_nam
self:moveCards(table.unpack(movesSplitedByOwner)) self:moveCards(table.unpack(movesSplitedByOwner))
end end
--- 将一些卡牌同时分配给一些角色。
---@param room Room @ 房间
---@param list table<integer[]> @ 分配牌和角色的数据表键为角色id值为分配给其的牌id数组
---@param proposer? integer @ 操作者的id。默认为空
---@param skillName? string @ 技能名。默认为“分配”
---@return table<integer[]> @ 返回成功分配的卡牌
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
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- 其他游戏事件 -- 其他游戏事件
------------------------------------------------------------------------ ------------------------------------------------------------------------

View File

@ -78,8 +78,8 @@ local chooseCardsSkill = fk.CreateActiveSkill{
local choosePlayersSkill = fk.CreateActiveSkill{ local choosePlayersSkill = fk.CreateActiveSkill{
name = "choose_players_skill", name = "choose_players_skill",
card_filter = function(self, to_select) card_filter = function(self, to_select, selected)
return self.pattern ~= "" and Exppattern:Parse(self.pattern):match(Fk:getCardById(to_select)) return self.pattern ~= "" and Exppattern:Parse(self.pattern):match(Fk:getCardById(to_select)) and #selected == 0
end, end,
target_filter = function(self, to_select, selected, cards) target_filter = function(self, to_select, selected, cards)
if self.pattern ~= "" and #cards == 0 then return end if self.pattern ~= "" and #cards == 0 then return end
@ -137,6 +137,21 @@ local maxCardsSkill = fk.CreateMaxCardsSkill{
end, 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{ local choosePlayersToMoveCardInBoardSkill = fk.CreateActiveSkill{
name = "choose_players_to_move_card_in_board", name = "choose_players_to_move_card_in_board",
target_num = 2, target_num = 2,
@ -281,6 +296,7 @@ AuxSkills = {
chooseCardsSkill, chooseCardsSkill,
choosePlayersSkill, choosePlayersSkill,
exChooseSkill, exChooseSkill,
distributionSelectSkill,
maxCardsSkill, maxCardsSkill,
choosePlayersToMoveCardInBoardSkill, choosePlayersToMoveCardInBoardSkill,
uncompulsoryInvalidity, uncompulsoryInvalidity,

View File

@ -192,6 +192,8 @@ Fk:loadTranslationTable({
["discard_skill"] = "Discard", ["discard_skill"] = "Discard",
["choose_cards_skill"] = "Choose card", ["choose_cards_skill"] = "Choose card",
["choose_players_skill"] = "Choose players", ["choose_players_skill"] = "Choose players",
["ex__choose_skill"] = "Choose",
["distribution_select_skill"] = "Distribute",
["choose_players_to_move_card_in_board"] = "Choose players", ["choose_players_to_move_card_in_board"] = "Choose players",
["reveal_skill"] = "Reveal", ["reveal_skill"] = "Reveal",
["#reveal_skill"] = "Choose a character to reveal", ["#reveal_skill"] = "Choose a character to reveal",

View File

@ -519,6 +519,8 @@ Fk:loadTranslationTable{
["discard_skill"] = "弃牌", ["discard_skill"] = "弃牌",
["choose_cards_skill"] = "选牌", ["choose_cards_skill"] = "选牌",
["choose_players_skill"] = "选择角色", ["choose_players_skill"] = "选择角色",
["ex__choose_skill"] = "选择",
["distribution_select_skill"] = "分配",
["choose_players_to_move_card_in_board"] = "选择角色", ["choose_players_to_move_card_in_board"] = "选择角色",
["reveal_skill"] = "亮将", ["reveal_skill"] = "亮将",
["#reveal_skill"] = "选择一个武将亮将(点击左侧选择框展开)", ["#reveal_skill"] = "选择一个武将亮将(点击左侧选择框展开)",

View File

@ -80,6 +80,7 @@ local control = fk.CreateActiveSkill{
-- ok = {10, 2}, -- ok = {10, 2},
-- }) -- })
-- room:swapSeat(from, to) -- 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 for _, pid in ipairs(effect.tos) do
local to = room:getPlayerById(pid) local to = room:getPlayerById(pid)
-- p(room:askForPoxi(from, "test", { -- p(room:askForPoxi(from, "test", {