diff --git a/lua/client/i18n/en_US.lua b/lua/client/i18n/en_US.lua index 6f844dc4..e8790fb5 100644 --- a/lua/client/i18n/en_US.lua +++ b/lua/client/i18n/en_US.lua @@ -81,6 +81,7 @@ Fk:loadTranslationTable({ ["AskForGeneral"] = "Choosing general", ["AskForGuanxing"] = "Stargazing", ["AskForChoice"] = "Making choice", + ["AskForPindian"] = "pindian", ["PlayCard"] = "Playing card", ["AskForCardChosen"] = "Choosing card", @@ -96,6 +97,7 @@ Fk:loadTranslationTable({ ["#AskForNullificationWithoutTo"] = "是否对 %src 使用的 %arg 使用无懈可击?", ["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张", + ["#askForPindian"] = "请选择一张手牌作为拼点牌", -- ["Trust"] = "托管", -- ["Sort Cards"] = "牌序", diff --git a/lua/client/i18n/zh_CN.lua b/lua/client/i18n/zh_CN.lua index 1d659369..a8dff2bc 100644 --- a/lua/client/i18n/zh_CN.lua +++ b/lua/client/i18n/zh_CN.lua @@ -86,6 +86,7 @@ Fk:loadTranslationTable{ ["AskForGeneral"] = "选择武将", ["AskForGuanxing"] = "观星", ["AskForChoice"] = "选择", + ["AskForPindian"] = "拼点", ["PlayCard"] = "出牌", ["AskForCardChosen"] = "选牌", @@ -101,6 +102,7 @@ Fk:loadTranslationTable{ ["#AskForNullificationWithoutTo"] = "是否对 %src 使用的 %arg 使用无懈可击?", ["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张", + ["#askForPindian"] = "请选择一张手牌作为拼点牌", ["Trust"] = "托管", ["Sort Cards"] = "牌序", diff --git a/lua/core/player.lua b/lua/core/player.lua index a58615ae..98f1a887 100644 --- a/lua/core/player.lua +++ b/lua/core/player.lua @@ -68,6 +68,7 @@ function Player:initialize() self.dying = false self.dead = false self.state = "" + self.drank = 0 self.player_skills = {} self.derivative_skills = {} diff --git a/lua/server/event.lua b/lua/server/event.lua index ecb2b189..c6946d08 100644 --- a/lua/server/event.lua +++ b/lua/server/event.lua @@ -33,8 +33,8 @@ fk.AskForRetrial = 25 fk.FinishRetrial = 26 fk.FinishJudge = 27 -fk.PindianVerifying = 28 -fk.Pindian = 29 +fk.Empty28 = 28 +fk.Empty29 = 29 fk.TurnedOver = 30 fk.ChainStateChanged = 31 @@ -53,8 +53,8 @@ fk.AfterDying = 40 fk.PreCardUse = 41 fk.AfterCardUseDeclared = 42 fk.AfterCardTargetDeclared = 43 -fk.BeforeCardUseEffect = 44 -fk.CardUsing = 45 +fk.CardUsing = 44 +fk.BeforeCardUseEffect = 45 fk.TargetSpecifying = 46 fk.TargetConfirming = 47 fk.TargetSpecified = 48 @@ -82,4 +82,9 @@ fk.GameFinished = 65 fk.AskForCardUse = 66 fk.AskForCardResponse = 67 -fk.NumOfEvents = 68 +fk.StartPindian = 68 +fk.PindianCardsDisplayed = 69 +fk.PindianResultConfirmed = 70 +fk.PindianFinished = 71 + +fk.NumOfEvents = 72 diff --git a/lua/server/events/death.lua b/lua/server/events/death.lua index 596adad4..13ed9478 100644 --- a/lua/server/events/death.lua +++ b/lua/server/events/death.lua @@ -53,6 +53,9 @@ GameEvent.functions[GameEvent.Death] = function(self) self:broadcastProperty(victim, "role") self:broadcastProperty(victim, "dead") + victim.drank = 0 + self:broadcastProperty(victim, "drank") + logic:trigger(fk.GameOverJudge, victim, deathStruct) logic:trigger(fk.Death, victim, deathStruct) logic:trigger(fk.BuryVictim, victim, deathStruct) diff --git a/lua/server/events/init.lua b/lua/server/events/init.lua index 79484a8e..bb41ac1a 100644 --- a/lua/server/events/init.lua +++ b/lua/server/events/init.lua @@ -30,6 +30,9 @@ GameEvent.DrawInitial = 15 GameEvent.Turn = 16 dofile "lua/server/events/gameflow.lua" +GameEvent.Pindian = 17 +dofile "lua/server/events/pindian.lua" + -- TODO: fix this GameEvent.BreakEvent = 999 diff --git a/lua/server/events/judge.lua b/lua/server/events/judge.lua index 90062c0d..c9681c46 100644 --- a/lua/server/events/judge.lua +++ b/lua/server/events/judge.lua @@ -3,7 +3,7 @@ GameEvent.functions[GameEvent.Judge] = function(self) local self = self.room local who = data.who self.logic:trigger(fk.StartJudge, who, data) - data.card = Fk:getCardById(self:getNCards(1)[1]) + data.card = data.card or Fk:getCardById(self:getNCards(1)[1]) if data.reason ~= "" then self:sendLog{ @@ -18,7 +18,7 @@ GameEvent.functions[GameEvent.Judge] = function(self) from = who.id, card = {data.card.id}, } - self:moveCardTo(data.card, Card.Processing, nil, fk.ReasonPrey) + self:moveCardTo(data.card, Card.Processing, nil, fk.ReasonPut) self.logic:trigger(fk.AskForRetrial, who, data) self.logic:trigger(fk.FinishRetrial, who, data) diff --git a/lua/server/events/pindian.lua b/lua/server/events/pindian.lua new file mode 100644 index 00000000..83109175 --- /dev/null +++ b/lua/server/events/pindian.lua @@ -0,0 +1,116 @@ +GameEvent.functions[GameEvent.Pindian] = function(self) + local pindianData = table.unpack(self.data) + local self = self.room + self.logic:trigger(fk.StartPindian, pindianData.from, pindianData) + + if pindianData.reason ~= "" then + self:sendLog{ + type = "#StartPindianReason", + from = pindianData.from.id, + arg = pindianData.reason, + } + end + + local extraData = { + num = 1, + min_num = 1, + include_equip = false, + reason = pindianData.reason + } + local prompt = "#askForPindian" + local data = { "choose_cards_skill", prompt, true, json.encode(extraData) } + + local targets = {} + if not pindianData.fromCard then + table.insert(targets, pindianData.from) + pindianData.from.request_data = json.encode(data) + end + for _, to in ipairs(pindianData.tos) do + if not (pindianData.results[to.id] and pindianData.results[to.id].toCard) then + table.insert(targets, to) + to.request_data = json.encode(data) + end + end + + self:notifyMoveFocus(targets, "AskForPindian") + self:doBroadcastRequest("AskForUseActiveSkill", targets) + + local moveInfos = {} + for _, p in ipairs(targets) do + local pindianCard + if p.reply_ready then + local replyCard = json.decode(p.client_reply).card + pindianCard = Fk:getCardById(json.decode(replyCard).subcards[1]) + else + pindianCard = Fk:getCardById(p:getCardIds(Player.Hand)[1]) + end + + if p == pindianData.from then + pindianData.fromCard = pindianCard + else + pindianData.results[p.id] = pindianData.results[p.id] or {} + pindianData.results[p.id].toCard = pindianCard + end + + table.insert(moveInfos, { + ids = { pindianCard.id }, + from = p.id, + toArea = Card.Processing, + moveReason = fk.ReasonPut, + skillName = pindianData.reason, + moveVisible = true, + }) + end + + self:moveCards(table.unpack(moveInfos)) + + self.logic:trigger(fk.PindianCardsDisplayed, nil, pindianData) + + for toId, result in pairs(pindianData.results) do + if pindianData.fromCard.number > result.toCard.number then + pindianData.results[toId].winner = pindianData.from + elseif pindianData.fromCard.number > result.toCard.number then + pindianData.results[toId].winner = Fk:getCardById(toId) + end + + local singlePindianData = { + from = pindianData.from, + to = self:getPlayerById(toId), + fromCard = pindianData.fromCard, + toCard = result.toCard, + winner = pindianData.results[toId].winner, + } + self.logic:trigger(fk.PindianResultConfirmed, nil, singlePindianData) + end + + if self.logic:trigger(fk.PindianFinished, pindianData.from, pindianData) then + self.logic:breakEvent() + end +end + +GameEvent.cleaners[GameEvent.Pindian] = function(self) + local pindianData = table.unpack(self.data) + local self = self.room + + local toProcessingArea = {} + local leftFromCardIds = self:getSubcardsByRule(pindianData.fromCard, { Card.Processing }) + if #leftFromCardIds > 0 then + table.insertTable(toProcessingArea, leftFromCardIds) + end + + for _, result in pairs(pindianData.results) do + local leftToCardIds = self:getSubcardsByRule(result.toCard, { Card.Processing }) + if #leftToCardIds > 0 then + table.insertTable(toProcessingArea, leftToCardIds) + end + end + + if #toProcessingArea > 0 then + self:moveCards({ + ids = toProcessingArea, + toArea = Card.DiscardPile, + moveReason = fk.ReasonPutIntoDiscardPile, + }) + end + if not self.interrupted then return end +end diff --git a/lua/server/events/usecard.lua b/lua/server/events/usecard.lua index 8193b565..fc7f275d 100644 --- a/lua/server/events/usecard.lua +++ b/lua/server/events/usecard.lua @@ -195,14 +195,14 @@ GameEvent.functions[GameEvent.UseCard] = function(self) self:doCardUseEffect(cardUseEvent) end end - - self.logic:trigger(fk.CardUseFinished, self:getPlayerById(cardUseEvent.from), cardUseEvent) end GameEvent.cleaners[GameEvent.UseCard] = function(self) local cardUseEvent = table.unpack(self.data) local self = self.room + self.logic:trigger(fk.CardUseFinished, self:getPlayerById(cardUseEvent.from), cardUseEvent) + local leftRealCardIds = self:getSubcardsByRule(cardUseEvent.card, { Card.Processing }) if #leftRealCardIds > 0 then self:moveCards({ diff --git a/lua/server/gamelogic.lua b/lua/server/gamelogic.lua index a3da424e..83971f73 100644 --- a/lua/server/gamelogic.lua +++ b/lua/server/gamelogic.lua @@ -100,6 +100,7 @@ function GameLogic:chooseGenerals() p.default_reply = arg[1] end + room:notifyMoveFocus(nonlord, "AskForGeneral") room:doBroadcastRequest("AskForGeneral", nonlord) for _, p in ipairs(nonlord) do if p.general == "" and p.reply_ready then diff --git a/lua/server/room.lua b/lua/server/room.lua index 451ab392..f8f844d7 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -378,7 +378,6 @@ end ---@param players ServerPlayer[] function Room:doBroadcastRequest(command, players, jsonData) players = players or self.players - self:notifyMoveFocus(players, command) for _, p in ipairs(players) do self:doRequest(p, command, jsonData or p.request_data, false) end @@ -804,6 +803,45 @@ function Room:askForChoosePlayers(player, targets, minNum, maxNum, prompt, skill end end +---@param player ServerPlayer +---@param minNum integer +---@param maxNum integer +---@param includeEquip boolean +---@param skillName string +---@param cancelable boolean +function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancelable) + if minNum < 1 then + return nil + end + cancelable = cancelable or false + + local chosenCards = {} + local data = { + num = maxNum, + min_num = minNum, + include_equip = includeEquip, + reason = skillName + } + local prompt = "#askForCard:::" .. maxNum .. ":" .. minNum + local _, ret = self:askForUseActiveSkill(player, "choose_cards_skill", prompt, cancelable, data) + if ret then + chosenCards = 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(chosenCards, randomId) + table.removeOne(hands, randomId) + end + end + + return chosenCards +end + ---@param player ServerPlayer ---@param targets integer[] ---@param minNum integer @@ -1255,7 +1293,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators) nullifiedTargets = cardUseEvent.nullifiedTargets or {}, tos = aimGroup, firstTarget = firstTarget, - additionalDamage = cardUseEvent.addtionalDamage + additionalDamage = cardUseEvent.additionalDamage } local index = 1 @@ -1436,8 +1474,9 @@ function Room:doCardUseEffect(cardUseEvent) nullifiedTargets = cardUseEvent.nullifiedTargets, disresponsiveList = cardUseEvent.disresponsiveList, unoffsetableList = cardUseEvent.unoffsetableList, - addtionalDamage = cardUseEvent.addtionalDamage, + additionalDamage = cardUseEvent.additionalDamage, cardIdsResponded = cardUseEvent.nullifiedTargets, + extra_data = cardUseEvent.extra_data, } -- If using card to other card (like jink or nullification), simply effect and return @@ -1456,7 +1495,7 @@ function Room:doCardUseEffect(cardUseEvent) local curAimEvent = aimEventCollaborators[toId][collaboratorsIndex[toId]] cardEffectEvent.subTargets = curAimEvent.subTargets - cardEffectEvent.addtionalDamage = curAimEvent.additionalDamage + cardEffectEvent.additionalDamage = curAimEvent.additionalDamage if curAimEvent.disresponsiveList then for _, disresponsivePlayer in ipairs(curAimEvent.disresponsiveList) do @@ -1890,9 +1929,9 @@ function Room:throwCard(card_ids, skillName, who, thrower) }) end ----@param pindianStruct PindianStruct -function Room:pindian(pindianStruct) - +---@param pindianData PindianStruct +function Room:pindian(pindianData) + return execGameEvent(GameEvent.Pindian, pindianData) end -- other helpers diff --git a/lua/server/serverplayer.lua b/lua/server/serverplayer.lua index 365fc068..1c032bb0 100644 --- a/lua/server/serverplayer.lua +++ b/lua/server/serverplayer.lua @@ -534,4 +534,15 @@ function ServerPlayer:setChainState(chained) } end +---@param from ServerPlayer +---@param tos ServerPlayer[] +---@param skillName string +---@param initialCard Card +---@return PindianStruct +function ServerPlayer:pindian(tos, skillName, initialCard) + local pindianData = { from = self, tos = tos, reson = skillName, fromCard = initialCard, results = {} } + self.room:pindian(pindianData) + return pindianData +end + return ServerPlayer diff --git a/lua/server/system_enum.lua b/lua/server/system_enum.lua index 6cea11bb..34b7c778 100644 --- a/lua/server/system_enum.lua +++ b/lua/server/system_enum.lua @@ -27,6 +27,10 @@ ---@field specialName string|null ---@field specialVisible boolean|null +---@class PindianResult +---@field toCard Card +---@field winner ServerPlayer|null + ---@class HpChangedData ---@field num integer ---@field reason string @@ -76,7 +80,7 @@ fk.FireDamage = 3 ---@field extraUse boolean|null ---@field disresponsiveList integer[]|null ---@field unoffsetableList integer[]|null ----@field addtionalDamage integer|null +---@field additionalDamage integer|null ---@field customFrom integer|null ---@field cardsResponded Card[]|null @@ -107,7 +111,7 @@ fk.FireDamage = 3 ---@field extraUse boolean|null ---@field disresponsiveList integer[]|null ---@field unoffsetableList integer[]|null ----@field addtionalDamage integer|null +---@field additionalDamage integer|null ---@field customFrom integer|null ---@field cardsResponded Card[]|null ---@field disresponsive boolean|null @@ -161,13 +165,10 @@ fk.ReasonResonpse = 10 ---@class PindianStruct ---@field from ServerPlayer ----@field to ServerPlayer ----@field from_card Card ----@field to_card Card ----@field from_number integer ----@field to_number integer +---@field tos ServerPlayer[] +---@field fromCard Card +---@field results table ---@field reason string ----@field winner ServerPlayer|null ---@class LogMessage ---@field type string diff --git a/packages/maneuvering/image/anim/analeptic/0.png b/packages/maneuvering/image/anim/analeptic/0.png new file mode 100644 index 00000000..d8c23a4e Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/0.png differ diff --git a/packages/maneuvering/image/anim/analeptic/1.png b/packages/maneuvering/image/anim/analeptic/1.png new file mode 100644 index 00000000..a99ebe08 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/1.png differ diff --git a/packages/maneuvering/image/anim/analeptic/10.png b/packages/maneuvering/image/anim/analeptic/10.png new file mode 100644 index 00000000..ecc59508 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/10.png differ diff --git a/packages/maneuvering/image/anim/analeptic/11.png b/packages/maneuvering/image/anim/analeptic/11.png new file mode 100644 index 00000000..ac28e788 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/11.png differ diff --git a/packages/maneuvering/image/anim/analeptic/12.png b/packages/maneuvering/image/anim/analeptic/12.png new file mode 100644 index 00000000..37b364c2 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/12.png differ diff --git a/packages/maneuvering/image/anim/analeptic/13.png b/packages/maneuvering/image/anim/analeptic/13.png new file mode 100644 index 00000000..b013d6ef Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/13.png differ diff --git a/packages/maneuvering/image/anim/analeptic/14.png b/packages/maneuvering/image/anim/analeptic/14.png new file mode 100644 index 00000000..1ff43ed2 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/14.png differ diff --git a/packages/maneuvering/image/anim/analeptic/15.png b/packages/maneuvering/image/anim/analeptic/15.png new file mode 100644 index 00000000..7e3acb7b Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/15.png differ diff --git a/packages/maneuvering/image/anim/analeptic/16.png b/packages/maneuvering/image/anim/analeptic/16.png new file mode 100644 index 00000000..bbb9d0fc Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/16.png differ diff --git a/packages/maneuvering/image/anim/analeptic/2.png b/packages/maneuvering/image/anim/analeptic/2.png new file mode 100644 index 00000000..18d9036d Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/2.png differ diff --git a/packages/maneuvering/image/anim/analeptic/3.png b/packages/maneuvering/image/anim/analeptic/3.png new file mode 100644 index 00000000..57b9fe96 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/3.png differ diff --git a/packages/maneuvering/image/anim/analeptic/4.png b/packages/maneuvering/image/anim/analeptic/4.png new file mode 100644 index 00000000..cdc272a4 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/4.png differ diff --git a/packages/maneuvering/image/anim/analeptic/5.png b/packages/maneuvering/image/anim/analeptic/5.png new file mode 100644 index 00000000..3bcbdc27 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/5.png differ diff --git a/packages/maneuvering/image/anim/analeptic/6.png b/packages/maneuvering/image/anim/analeptic/6.png new file mode 100644 index 00000000..bb2c6e70 Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/6.png differ diff --git a/packages/maneuvering/image/anim/analeptic/7.png b/packages/maneuvering/image/anim/analeptic/7.png new file mode 100644 index 00000000..d8cc4cbd Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/7.png differ diff --git a/packages/maneuvering/image/anim/analeptic/8.png b/packages/maneuvering/image/anim/analeptic/8.png new file mode 100644 index 00000000..9e3d29bd Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/8.png differ diff --git a/packages/maneuvering/image/anim/analeptic/9.png b/packages/maneuvering/image/anim/analeptic/9.png new file mode 100644 index 00000000..1d59348e Binary files /dev/null and b/packages/maneuvering/image/anim/analeptic/9.png differ diff --git a/packages/maneuvering/init.lua b/packages/maneuvering/init.lua index b0d7cddd..9a68a3f9 100644 --- a/packages/maneuvering/init.lua +++ b/packages/maneuvering/init.lua @@ -16,7 +16,7 @@ local thunderSlashSkill = fk.CreateActiveSkill{ from = room:getPlayerById(from), to = room:getPlayerById(to), card = effect.card, - damage = 1 + (effect.addtionalDamage or 0), + damage = 1 + (effect.additionalDamage or 0), damageType = fk.ThunderDamage, skillName = self.name }) @@ -53,7 +53,7 @@ local fireSlashSkill = fk.CreateActiveSkill{ from = room:getPlayerById(from), to = room:getPlayerById(to), card = effect.card, - damage = 1 + (effect.addtionalDamage or 0), + damage = 1 + (effect.additionalDamage or 0), damageType = fk.FireDamage, skillName = self.name }) @@ -72,6 +72,87 @@ extension:addCards{ fireSlash:clone(Card.Diamond, 5), } +local analepticSkill = fk.CreateActiveSkill{ + name = "analeptic_skill", + max_turn_use_time = 1, + can_use = function(self, player) + return player:usedCardTimes("analeptic", Player.HistoryTurn) < self:getMaxUseTime(Self, Player.HistoryTurn) + end, + on_use = function(self, room, use) + if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then + use.tos = { { use.from } } + end + + if use.extra_data and use.extra_data.analepticRecover then + use.extraUse = true + end + end, + on_effect = function(self, room, effect) + local to = room:getPlayerById(effect.to) + if effect.extra_data and effect.extra_data.analepticRecover then + room:recover({ + who = to, + num = 1, + recoverBy = room:getPlayerById(effect.from), + card = effect.card, + }) + else + to.drank = to.drank + 1 + room:broadcastProperty(to, "drank") + end + end +} + +local analepticEffect = fk.CreateTriggerSkill{ + name = "analeptic_effect", + global = true, + priority = 0, -- game rule + refresh_events = { fk.PreCardUse, fk.EventPhaseStart }, + can_refresh = function(self, event, target, player, data) + if target ~= player then + return false + end + + if event == fk.PreCardUse then + return data.card.trueName == "slash" and player.drank > 0 + else + return player.phase == Player.NotActive + end + end, + on_refresh = function(self, event, target, player, data) + if event == fk.PreCardUse then + data.additionalDamage = (data.additionalDamage or 0) + player.drank + data.extra_data = data.extra_data or {} + data.extra_data.drankBuff = player.drank + player.drank = 0 + player.room:broadcastProperty(player, "drank") + else + for _, p in ipairs(player.room:getAlivePlayers(true)) do + if p.drank > 0 then + p.drank = 0 + p.room:broadcastProperty(player, "drank") + end + end + end + end, +} +Fk:addSkill(analepticEffect) + +local analeptic = fk.CreateBasicCard{ + name = "analeptic", + suit = Card.Spade, + number = 3, + skill = analepticSkill, +} + +extension:addCards({ + analeptic, + analeptic:clone(Card.Spade, 9), + analeptic:clone(Card.Club, 3), + analeptic:clone(Card.Club, 9), + analeptic:clone(Card.Diamond, 9), +}) + local ironChainEffect = fk.CreateTriggerSkill{ name = "iron_chain_effect", global = true, @@ -307,6 +388,7 @@ Fk:loadTranslationTable{ ["thunder__slash"] = "雷杀", ["fire__slash"] = "火杀", + ["analeptic"] = "酒", ["iron_chain"] = "铁锁连环", ["supply_shortage"] = "兵粮寸断", ["guding_blade"] = "古锭刀", diff --git a/packages/standard/aux_skills.lua b/packages/standard/aux_skills.lua index 4e33383b..29bc9ef5 100644 --- a/packages/standard/aux_skills.lua +++ b/packages/standard/aux_skills.lua @@ -15,6 +15,23 @@ local discardSkill = fk.CreateActiveSkill{ max_card_num = function(self) return self.num end, } +local chooseCardsSkill = fk.CreateActiveSkill{ + name = "choose_cards_skill", + card_filter = function(self, to_select, selected) + if #selected >= self.num then + return false + end + + if not self.include_equip then + return Fk:currentRoom():getCardArea(to_select) ~= Player.Equip + end + + return true + end, + min_card_num = function(self) return self.min_num end, + max_card_num = function(self) return self.num end, +} + local choosePlayersSkill = fk.CreateActiveSkill{ name = "choose_players_skill", card_filter = function(self, to_select) @@ -33,5 +50,6 @@ local choosePlayersSkill = fk.CreateActiveSkill{ AuxSkills = { discardSkill, + chooseCardsSkill, choosePlayersSkill, } diff --git a/packages/standard/game_rule.lua b/packages/standard/game_rule.lua index 8b75b847..fad0a1cf 100644 --- a/packages/standard/game_rule.lua +++ b/packages/standard/game_rule.lua @@ -202,9 +202,18 @@ GameRule = fk.CreateTriggerSkill{ for _, p in ipairs(savers) do if player.hp > 0 or player.dead then break end while player.hp < 1 do - local peach_use = room:askForUseCard(p, "peach") + local pattern = "peach" + if p == player then + pattern = pattern .. ",analeptic" + end + + local peach_use = room:askForUseCard(p, "peach", pattern) if not peach_use then break end peach_use.tos = { {player.id} } + if peach_use.card.trueName == "analeptic" then + peach_use.extra_data = peach_use.extra_data or {} + peach_use.extra_data.analepticRecover = true + end room:useCard(peach_use) end end diff --git a/packages/standard/init.lua b/packages/standard/init.lua index a9e81dc8..f2f26f31 100644 --- a/packages/standard/init.lua +++ b/packages/standard/init.lua @@ -563,9 +563,9 @@ local keji = fk.CreateTriggerSkill{ return false end if event == fk.CardResponding then - return data.card.trueName == "slash" + return player.phase == Player.Play and data.card.trueName == "slash" elseif event == fk.EventPhaseStart then - return player.phase == player.NotActive + return player.phase == Player.NotActive end end, on_refresh = function(self, event, target, player, data) diff --git a/packages/standard_cards/init.lua b/packages/standard_cards/init.lua index 31bea742..0b68c4a7 100644 --- a/packages/standard_cards/init.lua +++ b/packages/standard_cards/init.lua @@ -22,7 +22,7 @@ local slashSkill = fk.CreateActiveSkill{ from = room:getPlayerById(from), to = room:getPlayerById(to), card = effect.card, - damage = 1 + (effect.addtionalDamage or 0), + damage = 1 + (effect.additionalDamage or 0), damageType = fk.NormalDamage, skillName = self.name }) @@ -293,7 +293,7 @@ local duelSkill = fk.CreateActiveSkill{ from = responsers[currentTurn % 2 + 1], to = currentResponser, card = effect.card, - damage = 1 + (effect.addtionalDamage or 0), + damage = 1 + (effect.additionalDamage or 0), damageType = fk.NormalDamage, skillName = self.name, }) @@ -433,7 +433,7 @@ local savageAssaultSkill = fk.CreateActiveSkill{ from = room:getPlayerById(effect.from), to = room:getPlayerById(effect.to), card = effect.card, - damage = 1 + (effect.addtionalDamage or 0), + damage = 1 + (effect.additionalDamage or 0), damageType = fk.NormalDamage, skillName = self.name, }) @@ -480,7 +480,7 @@ local archeryAttackSkill = fk.CreateActiveSkill{ from = room:getPlayerById(effect.from), to = room:getPlayerById(effect.to), card = effect.card, - damage = 1 + (effect.addtionalDamage or 0), + damage = 1 + (effect.additionalDamage or 0), damageType = fk.NormalDamage, skillName = self.name, }) @@ -542,10 +542,73 @@ local amazingGraceSkill = fk.CreateActiveSkill{ end end end, - on_effect = function(self, room, cardEffectEvent) - room:getPlayerById(cardEffectEvent.to):drawCards(1, 'god_salvation') + on_effect = function(self, room, effect) + local to = room:getPlayerById(effect.to) + if not (effect.extra_data and effect.extra_data.AGFilled) then + return + end + + local chosen = room:askForAG(to, effect.extra_data.AGFilled, false, self.name) + room:takeAG(to, chosen, room.players) + room:obtainCard(effect.to, chosen, true, fk.ReasonPrey) + table.removeOne(effect.extra_data.AGFilled, chosen) end } + +local amazingGraceAction = fk.CreateTriggerSkill{ + name = "amazing_grace_action", + global = true, + priority = { [fk.BeforeCardUseEffect] = 0, [fk.CardUseFinished] = 10 }, -- game rule + refresh_events = { fk.BeforeCardUseEffect, fk.CardUseFinished }, + can_refresh = function(self, event, target, player, data) + local frameFilled = data.extra_data and data.extra_data.AGFilled + if event == fk.BeforeCardUseEffect then + return data.card.trueName == 'amazing_grace' and not frameFilled + else + return frameFilled + end + end, + on_refresh = function(self, event, target, player, data) + local room = player.room + if event == fk.BeforeCardUseEffect then + local toDisplay = room:getNCards(#TargetGroup:getRealTargets(data.tos)) + room:moveCards({ + ids = toDisplay, + toArea = Card.Processing, + moveReason = fk.ReasonPut, + }) + + table.forEach(room.players, function(p) + room:fillAG(p, toDisplay) + end) + + data.extra_data = data.extra_data or {} + data.extra_data.AGFilled = toDisplay + else + table.forEach(room.players, function(p) + room:closeAG(p) + end) + + if data.extra_data and data.extra_data.AGFilled then + local toDiscard = table.filter(data.extra_data.AGFilled, function(id) + return room:getCardArea(id) == Card.Processing + end) + + if #toDiscard > 0 then + room:moveCards({ + ids = toDiscard, + toArea = Card.DiscardPile, + moveReason = fk.ReasonPutIntoDiscardPile, + }) + end + end + + data.extra_data.AGFilled = nil + end + end, +} +Fk:addSkill(amazingGraceAction) + local amazingGrace = fk.CreateTrickCard{ name = "amazing_grace", suit = Card.Heart, diff --git a/qml/Pages/Room.qml b/qml/Pages/Room.qml index dd8f298d..3f668e87 100644 --- a/qml/Pages/Room.qml +++ b/qml/Pages/Room.qml @@ -621,7 +621,7 @@ Item { dying: false, faceup: true, chained: false, - drank: false, + drank: 0, isOwner: false } @@ -644,7 +644,7 @@ Item { dying: false, faceup: true, chained: false, - drank: false, + drank: 0, isOwner: false }); } diff --git a/qml/Pages/RoomElement/Photo.qml b/qml/Pages/RoomElement/Photo.qml index cadff7e4..29471abe 100644 --- a/qml/Pages/RoomElement/Photo.qml +++ b/qml/Pages/RoomElement/Photo.qml @@ -23,7 +23,7 @@ Item { property bool dying: false property bool faceup: true property bool chained: false - property bool drank: false + property int drank: 0 property bool isOwner: false property int distance: 0 property string status: "normal" @@ -160,6 +160,7 @@ Item { visible: false fillMode: Image.PreserveAspectCrop source: (general != "") ? SkinBank.getGeneralPicture(general) : "" + } Rectangle { @@ -185,6 +186,18 @@ Item { visible: root.dead } + Rectangle { + x: 31 + y: 5 + width: 138 + height: 222 + radius: 8 + + visible: root.drank > 0 + color: "red" + opacity: 0.4 + Math.log(root.drank) * 0.12 + } + Image { anchors.bottom: parent.bottom anchors.right: parent.right