|
@ -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"] = "牌序",
|
||||
|
|
|
@ -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"] = "牌序",
|
||||
|
|
|
@ -68,6 +68,7 @@ function Player:initialize()
|
|||
self.dying = false
|
||||
self.dead = false
|
||||
self.state = ""
|
||||
self.drank = 0
|
||||
|
||||
self.player_skills = {}
|
||||
self.derivative_skills = {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
116
lua/server/events/pindian.lua
Normal file
|
@ -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
|
|
@ -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({
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<integer, PindianResult>
|
||||
---@field reason string
|
||||
---@field winner ServerPlayer|null
|
||||
|
||||
---@class LogMessage
|
||||
---@field type string
|
||||
|
|
BIN
packages/maneuvering/image/anim/analeptic/0.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
packages/maneuvering/image/anim/analeptic/1.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
packages/maneuvering/image/anim/analeptic/10.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
packages/maneuvering/image/anim/analeptic/11.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
packages/maneuvering/image/anim/analeptic/12.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
packages/maneuvering/image/anim/analeptic/13.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
packages/maneuvering/image/anim/analeptic/14.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
packages/maneuvering/image/anim/analeptic/15.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
packages/maneuvering/image/anim/analeptic/16.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
packages/maneuvering/image/anim/analeptic/2.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
packages/maneuvering/image/anim/analeptic/3.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
packages/maneuvering/image/anim/analeptic/4.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
packages/maneuvering/image/anim/analeptic/5.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
packages/maneuvering/image/anim/analeptic/6.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
packages/maneuvering/image/anim/analeptic/7.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
packages/maneuvering/image/anim/analeptic/8.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
packages/maneuvering/image/anim/analeptic/9.png
Normal file
After Width: | Height: | Size: 56 KiB |
|
@ -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"] = "古锭刀",
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|