|
@ -81,6 +81,7 @@ Fk:loadTranslationTable({
|
||||||
["AskForGeneral"] = "Choosing general",
|
["AskForGeneral"] = "Choosing general",
|
||||||
["AskForGuanxing"] = "Stargazing",
|
["AskForGuanxing"] = "Stargazing",
|
||||||
["AskForChoice"] = "Making choice",
|
["AskForChoice"] = "Making choice",
|
||||||
|
["AskForPindian"] = "pindian",
|
||||||
["PlayCard"] = "Playing card",
|
["PlayCard"] = "Playing card",
|
||||||
|
|
||||||
["AskForCardChosen"] = "Choosing card",
|
["AskForCardChosen"] = "Choosing card",
|
||||||
|
@ -96,6 +97,7 @@ Fk:loadTranslationTable({
|
||||||
["#AskForNullificationWithoutTo"] = "是否对 %src 使用的 %arg 使用无懈可击?",
|
["#AskForNullificationWithoutTo"] = "是否对 %src 使用的 %arg 使用无懈可击?",
|
||||||
|
|
||||||
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
|
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
|
||||||
|
["#askForPindian"] = "请选择一张手牌作为拼点牌",
|
||||||
|
|
||||||
-- ["Trust"] = "托管",
|
-- ["Trust"] = "托管",
|
||||||
-- ["Sort Cards"] = "牌序",
|
-- ["Sort Cards"] = "牌序",
|
||||||
|
|
|
@ -86,6 +86,7 @@ Fk:loadTranslationTable{
|
||||||
["AskForGeneral"] = "选择武将",
|
["AskForGeneral"] = "选择武将",
|
||||||
["AskForGuanxing"] = "观星",
|
["AskForGuanxing"] = "观星",
|
||||||
["AskForChoice"] = "选择",
|
["AskForChoice"] = "选择",
|
||||||
|
["AskForPindian"] = "拼点",
|
||||||
["PlayCard"] = "出牌",
|
["PlayCard"] = "出牌",
|
||||||
|
|
||||||
["AskForCardChosen"] = "选牌",
|
["AskForCardChosen"] = "选牌",
|
||||||
|
@ -101,6 +102,7 @@ Fk:loadTranslationTable{
|
||||||
["#AskForNullificationWithoutTo"] = "是否对 %src 使用的 %arg 使用无懈可击?",
|
["#AskForNullificationWithoutTo"] = "是否对 %src 使用的 %arg 使用无懈可击?",
|
||||||
|
|
||||||
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
|
["#AskForDiscard"] = "请弃置 %arg 张牌,最少 %arg2 张",
|
||||||
|
["#askForPindian"] = "请选择一张手牌作为拼点牌",
|
||||||
|
|
||||||
["Trust"] = "托管",
|
["Trust"] = "托管",
|
||||||
["Sort Cards"] = "牌序",
|
["Sort Cards"] = "牌序",
|
||||||
|
|
|
@ -68,6 +68,7 @@ function Player:initialize()
|
||||||
self.dying = false
|
self.dying = false
|
||||||
self.dead = false
|
self.dead = false
|
||||||
self.state = ""
|
self.state = ""
|
||||||
|
self.drank = 0
|
||||||
|
|
||||||
self.player_skills = {}
|
self.player_skills = {}
|
||||||
self.derivative_skills = {}
|
self.derivative_skills = {}
|
||||||
|
|
|
@ -33,8 +33,8 @@ fk.AskForRetrial = 25
|
||||||
fk.FinishRetrial = 26
|
fk.FinishRetrial = 26
|
||||||
fk.FinishJudge = 27
|
fk.FinishJudge = 27
|
||||||
|
|
||||||
fk.PindianVerifying = 28
|
fk.Empty28 = 28
|
||||||
fk.Pindian = 29
|
fk.Empty29 = 29
|
||||||
|
|
||||||
fk.TurnedOver = 30
|
fk.TurnedOver = 30
|
||||||
fk.ChainStateChanged = 31
|
fk.ChainStateChanged = 31
|
||||||
|
@ -53,8 +53,8 @@ fk.AfterDying = 40
|
||||||
fk.PreCardUse = 41
|
fk.PreCardUse = 41
|
||||||
fk.AfterCardUseDeclared = 42
|
fk.AfterCardUseDeclared = 42
|
||||||
fk.AfterCardTargetDeclared = 43
|
fk.AfterCardTargetDeclared = 43
|
||||||
fk.BeforeCardUseEffect = 44
|
fk.CardUsing = 44
|
||||||
fk.CardUsing = 45
|
fk.BeforeCardUseEffect = 45
|
||||||
fk.TargetSpecifying = 46
|
fk.TargetSpecifying = 46
|
||||||
fk.TargetConfirming = 47
|
fk.TargetConfirming = 47
|
||||||
fk.TargetSpecified = 48
|
fk.TargetSpecified = 48
|
||||||
|
@ -82,4 +82,9 @@ fk.GameFinished = 65
|
||||||
fk.AskForCardUse = 66
|
fk.AskForCardUse = 66
|
||||||
fk.AskForCardResponse = 67
|
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, "role")
|
||||||
self:broadcastProperty(victim, "dead")
|
self:broadcastProperty(victim, "dead")
|
||||||
|
|
||||||
|
victim.drank = 0
|
||||||
|
self:broadcastProperty(victim, "drank")
|
||||||
|
|
||||||
logic:trigger(fk.GameOverJudge, victim, deathStruct)
|
logic:trigger(fk.GameOverJudge, victim, deathStruct)
|
||||||
logic:trigger(fk.Death, victim, deathStruct)
|
logic:trigger(fk.Death, victim, deathStruct)
|
||||||
logic:trigger(fk.BuryVictim, victim, deathStruct)
|
logic:trigger(fk.BuryVictim, victim, deathStruct)
|
||||||
|
|
|
@ -30,6 +30,9 @@ GameEvent.DrawInitial = 15
|
||||||
GameEvent.Turn = 16
|
GameEvent.Turn = 16
|
||||||
dofile "lua/server/events/gameflow.lua"
|
dofile "lua/server/events/gameflow.lua"
|
||||||
|
|
||||||
|
GameEvent.Pindian = 17
|
||||||
|
dofile "lua/server/events/pindian.lua"
|
||||||
|
|
||||||
-- TODO: fix this
|
-- TODO: fix this
|
||||||
GameEvent.BreakEvent = 999
|
GameEvent.BreakEvent = 999
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ GameEvent.functions[GameEvent.Judge] = function(self)
|
||||||
local self = self.room
|
local self = self.room
|
||||||
local who = data.who
|
local who = data.who
|
||||||
self.logic:trigger(fk.StartJudge, who, data)
|
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
|
if data.reason ~= "" then
|
||||||
self:sendLog{
|
self:sendLog{
|
||||||
|
@ -18,7 +18,7 @@ GameEvent.functions[GameEvent.Judge] = function(self)
|
||||||
from = who.id,
|
from = who.id,
|
||||||
card = {data.card.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.AskForRetrial, who, data)
|
||||||
self.logic:trigger(fk.FinishRetrial, who, data)
|
self.logic:trigger(fk.FinishRetrial, who, data)
|
||||||
|
|
|
@ -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)
|
self:doCardUseEffect(cardUseEvent)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self.logic:trigger(fk.CardUseFinished, self:getPlayerById(cardUseEvent.from), cardUseEvent)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
GameEvent.cleaners[GameEvent.UseCard] = function(self)
|
GameEvent.cleaners[GameEvent.UseCard] = function(self)
|
||||||
local cardUseEvent = table.unpack(self.data)
|
local cardUseEvent = table.unpack(self.data)
|
||||||
local self = self.room
|
local self = self.room
|
||||||
|
|
||||||
|
self.logic:trigger(fk.CardUseFinished, self:getPlayerById(cardUseEvent.from), cardUseEvent)
|
||||||
|
|
||||||
local leftRealCardIds = self:getSubcardsByRule(cardUseEvent.card, { Card.Processing })
|
local leftRealCardIds = self:getSubcardsByRule(cardUseEvent.card, { Card.Processing })
|
||||||
if #leftRealCardIds > 0 then
|
if #leftRealCardIds > 0 then
|
||||||
self:moveCards({
|
self:moveCards({
|
||||||
|
|
|
@ -100,6 +100,7 @@ function GameLogic:chooseGenerals()
|
||||||
p.default_reply = arg[1]
|
p.default_reply = arg[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
room:notifyMoveFocus(nonlord, "AskForGeneral")
|
||||||
room:doBroadcastRequest("AskForGeneral", nonlord)
|
room:doBroadcastRequest("AskForGeneral", nonlord)
|
||||||
for _, p in ipairs(nonlord) do
|
for _, p in ipairs(nonlord) do
|
||||||
if p.general == "" and p.reply_ready then
|
if p.general == "" and p.reply_ready then
|
||||||
|
|
|
@ -378,7 +378,6 @@ end
|
||||||
---@param players ServerPlayer[]
|
---@param players ServerPlayer[]
|
||||||
function Room:doBroadcastRequest(command, players, jsonData)
|
function Room:doBroadcastRequest(command, players, jsonData)
|
||||||
players = players or self.players
|
players = players or self.players
|
||||||
self:notifyMoveFocus(players, command)
|
|
||||||
for _, p in ipairs(players) do
|
for _, p in ipairs(players) do
|
||||||
self:doRequest(p, command, jsonData or p.request_data, false)
|
self:doRequest(p, command, jsonData or p.request_data, false)
|
||||||
end
|
end
|
||||||
|
@ -804,6 +803,45 @@ function Room:askForChoosePlayers(player, targets, minNum, maxNum, prompt, skill
|
||||||
end
|
end
|
||||||
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 player ServerPlayer
|
||||||
---@param targets integer[]
|
---@param targets integer[]
|
||||||
---@param minNum integer
|
---@param minNum integer
|
||||||
|
@ -1255,7 +1293,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
||||||
nullifiedTargets = cardUseEvent.nullifiedTargets or {},
|
nullifiedTargets = cardUseEvent.nullifiedTargets or {},
|
||||||
tos = aimGroup,
|
tos = aimGroup,
|
||||||
firstTarget = firstTarget,
|
firstTarget = firstTarget,
|
||||||
additionalDamage = cardUseEvent.addtionalDamage
|
additionalDamage = cardUseEvent.additionalDamage
|
||||||
}
|
}
|
||||||
|
|
||||||
local index = 1
|
local index = 1
|
||||||
|
@ -1436,8 +1474,9 @@ function Room:doCardUseEffect(cardUseEvent)
|
||||||
nullifiedTargets = cardUseEvent.nullifiedTargets,
|
nullifiedTargets = cardUseEvent.nullifiedTargets,
|
||||||
disresponsiveList = cardUseEvent.disresponsiveList,
|
disresponsiveList = cardUseEvent.disresponsiveList,
|
||||||
unoffsetableList = cardUseEvent.unoffsetableList,
|
unoffsetableList = cardUseEvent.unoffsetableList,
|
||||||
addtionalDamage = cardUseEvent.addtionalDamage,
|
additionalDamage = cardUseEvent.additionalDamage,
|
||||||
cardIdsResponded = cardUseEvent.nullifiedTargets,
|
cardIdsResponded = cardUseEvent.nullifiedTargets,
|
||||||
|
extra_data = cardUseEvent.extra_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- If using card to other card (like jink or nullification), simply effect and return
|
-- 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]]
|
local curAimEvent = aimEventCollaborators[toId][collaboratorsIndex[toId]]
|
||||||
|
|
||||||
cardEffectEvent.subTargets = curAimEvent.subTargets
|
cardEffectEvent.subTargets = curAimEvent.subTargets
|
||||||
cardEffectEvent.addtionalDamage = curAimEvent.additionalDamage
|
cardEffectEvent.additionalDamage = curAimEvent.additionalDamage
|
||||||
|
|
||||||
if curAimEvent.disresponsiveList then
|
if curAimEvent.disresponsiveList then
|
||||||
for _, disresponsivePlayer in ipairs(curAimEvent.disresponsiveList) do
|
for _, disresponsivePlayer in ipairs(curAimEvent.disresponsiveList) do
|
||||||
|
@ -1890,9 +1929,9 @@ function Room:throwCard(card_ids, skillName, who, thrower)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param pindianStruct PindianStruct
|
---@param pindianData PindianStruct
|
||||||
function Room:pindian(pindianStruct)
|
function Room:pindian(pindianData)
|
||||||
|
return execGameEvent(GameEvent.Pindian, pindianData)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- other helpers
|
-- other helpers
|
||||||
|
|
|
@ -534,4 +534,15 @@ function ServerPlayer:setChainState(chained)
|
||||||
}
|
}
|
||||||
end
|
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
|
return ServerPlayer
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
---@field specialName string|null
|
---@field specialName string|null
|
||||||
---@field specialVisible boolean|null
|
---@field specialVisible boolean|null
|
||||||
|
|
||||||
|
---@class PindianResult
|
||||||
|
---@field toCard Card
|
||||||
|
---@field winner ServerPlayer|null
|
||||||
|
|
||||||
---@class HpChangedData
|
---@class HpChangedData
|
||||||
---@field num integer
|
---@field num integer
|
||||||
---@field reason string
|
---@field reason string
|
||||||
|
@ -76,7 +80,7 @@ fk.FireDamage = 3
|
||||||
---@field extraUse boolean|null
|
---@field extraUse boolean|null
|
||||||
---@field disresponsiveList integer[]|null
|
---@field disresponsiveList integer[]|null
|
||||||
---@field unoffsetableList integer[]|null
|
---@field unoffsetableList integer[]|null
|
||||||
---@field addtionalDamage integer|null
|
---@field additionalDamage integer|null
|
||||||
---@field customFrom integer|null
|
---@field customFrom integer|null
|
||||||
---@field cardsResponded Card[]|null
|
---@field cardsResponded Card[]|null
|
||||||
|
|
||||||
|
@ -107,7 +111,7 @@ fk.FireDamage = 3
|
||||||
---@field extraUse boolean|null
|
---@field extraUse boolean|null
|
||||||
---@field disresponsiveList integer[]|null
|
---@field disresponsiveList integer[]|null
|
||||||
---@field unoffsetableList integer[]|null
|
---@field unoffsetableList integer[]|null
|
||||||
---@field addtionalDamage integer|null
|
---@field additionalDamage integer|null
|
||||||
---@field customFrom integer|null
|
---@field customFrom integer|null
|
||||||
---@field cardsResponded Card[]|null
|
---@field cardsResponded Card[]|null
|
||||||
---@field disresponsive boolean|null
|
---@field disresponsive boolean|null
|
||||||
|
@ -161,13 +165,10 @@ fk.ReasonResonpse = 10
|
||||||
|
|
||||||
---@class PindianStruct
|
---@class PindianStruct
|
||||||
---@field from ServerPlayer
|
---@field from ServerPlayer
|
||||||
---@field to ServerPlayer
|
---@field tos ServerPlayer[]
|
||||||
---@field from_card Card
|
---@field fromCard Card
|
||||||
---@field to_card Card
|
---@field results table<integer, PindianResult>
|
||||||
---@field from_number integer
|
|
||||||
---@field to_number integer
|
|
||||||
---@field reason string
|
---@field reason string
|
||||||
---@field winner ServerPlayer|null
|
|
||||||
|
|
||||||
---@class LogMessage
|
---@class LogMessage
|
||||||
---@field type string
|
---@field type string
|
||||||
|
|
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 56 KiB |
|
@ -16,7 +16,7 @@ local thunderSlashSkill = fk.CreateActiveSkill{
|
||||||
from = room:getPlayerById(from),
|
from = room:getPlayerById(from),
|
||||||
to = room:getPlayerById(to),
|
to = room:getPlayerById(to),
|
||||||
card = effect.card,
|
card = effect.card,
|
||||||
damage = 1 + (effect.addtionalDamage or 0),
|
damage = 1 + (effect.additionalDamage or 0),
|
||||||
damageType = fk.ThunderDamage,
|
damageType = fk.ThunderDamage,
|
||||||
skillName = self.name
|
skillName = self.name
|
||||||
})
|
})
|
||||||
|
@ -53,7 +53,7 @@ local fireSlashSkill = fk.CreateActiveSkill{
|
||||||
from = room:getPlayerById(from),
|
from = room:getPlayerById(from),
|
||||||
to = room:getPlayerById(to),
|
to = room:getPlayerById(to),
|
||||||
card = effect.card,
|
card = effect.card,
|
||||||
damage = 1 + (effect.addtionalDamage or 0),
|
damage = 1 + (effect.additionalDamage or 0),
|
||||||
damageType = fk.FireDamage,
|
damageType = fk.FireDamage,
|
||||||
skillName = self.name
|
skillName = self.name
|
||||||
})
|
})
|
||||||
|
@ -72,6 +72,87 @@ extension:addCards{
|
||||||
fireSlash:clone(Card.Diamond, 5),
|
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{
|
local ironChainEffect = fk.CreateTriggerSkill{
|
||||||
name = "iron_chain_effect",
|
name = "iron_chain_effect",
|
||||||
global = true,
|
global = true,
|
||||||
|
@ -307,6 +388,7 @@ Fk:loadTranslationTable{
|
||||||
|
|
||||||
["thunder__slash"] = "雷杀",
|
["thunder__slash"] = "雷杀",
|
||||||
["fire__slash"] = "火杀",
|
["fire__slash"] = "火杀",
|
||||||
|
["analeptic"] = "酒",
|
||||||
["iron_chain"] = "铁锁连环",
|
["iron_chain"] = "铁锁连环",
|
||||||
["supply_shortage"] = "兵粮寸断",
|
["supply_shortage"] = "兵粮寸断",
|
||||||
["guding_blade"] = "古锭刀",
|
["guding_blade"] = "古锭刀",
|
||||||
|
|
|
@ -15,6 +15,23 @@ local discardSkill = fk.CreateActiveSkill{
|
||||||
max_card_num = function(self) return self.num end,
|
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{
|
local choosePlayersSkill = fk.CreateActiveSkill{
|
||||||
name = "choose_players_skill",
|
name = "choose_players_skill",
|
||||||
card_filter = function(self, to_select)
|
card_filter = function(self, to_select)
|
||||||
|
@ -33,5 +50,6 @@ local choosePlayersSkill = fk.CreateActiveSkill{
|
||||||
|
|
||||||
AuxSkills = {
|
AuxSkills = {
|
||||||
discardSkill,
|
discardSkill,
|
||||||
|
chooseCardsSkill,
|
||||||
choosePlayersSkill,
|
choosePlayersSkill,
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,9 +202,18 @@ GameRule = fk.CreateTriggerSkill{
|
||||||
for _, p in ipairs(savers) do
|
for _, p in ipairs(savers) do
|
||||||
if player.hp > 0 or player.dead then break end
|
if player.hp > 0 or player.dead then break end
|
||||||
while player.hp < 1 do
|
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
|
if not peach_use then break end
|
||||||
peach_use.tos = { {player.id} }
|
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)
|
room:useCard(peach_use)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -563,9 +563,9 @@ local keji = fk.CreateTriggerSkill{
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if event == fk.CardResponding then
|
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
|
elseif event == fk.EventPhaseStart then
|
||||||
return player.phase == player.NotActive
|
return player.phase == Player.NotActive
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_refresh = function(self, event, target, player, data)
|
on_refresh = function(self, event, target, player, data)
|
||||||
|
|
|
@ -22,7 +22,7 @@ local slashSkill = fk.CreateActiveSkill{
|
||||||
from = room:getPlayerById(from),
|
from = room:getPlayerById(from),
|
||||||
to = room:getPlayerById(to),
|
to = room:getPlayerById(to),
|
||||||
card = effect.card,
|
card = effect.card,
|
||||||
damage = 1 + (effect.addtionalDamage or 0),
|
damage = 1 + (effect.additionalDamage or 0),
|
||||||
damageType = fk.NormalDamage,
|
damageType = fk.NormalDamage,
|
||||||
skillName = self.name
|
skillName = self.name
|
||||||
})
|
})
|
||||||
|
@ -293,7 +293,7 @@ local duelSkill = fk.CreateActiveSkill{
|
||||||
from = responsers[currentTurn % 2 + 1],
|
from = responsers[currentTurn % 2 + 1],
|
||||||
to = currentResponser,
|
to = currentResponser,
|
||||||
card = effect.card,
|
card = effect.card,
|
||||||
damage = 1 + (effect.addtionalDamage or 0),
|
damage = 1 + (effect.additionalDamage or 0),
|
||||||
damageType = fk.NormalDamage,
|
damageType = fk.NormalDamage,
|
||||||
skillName = self.name,
|
skillName = self.name,
|
||||||
})
|
})
|
||||||
|
@ -433,7 +433,7 @@ local savageAssaultSkill = fk.CreateActiveSkill{
|
||||||
from = room:getPlayerById(effect.from),
|
from = room:getPlayerById(effect.from),
|
||||||
to = room:getPlayerById(effect.to),
|
to = room:getPlayerById(effect.to),
|
||||||
card = effect.card,
|
card = effect.card,
|
||||||
damage = 1 + (effect.addtionalDamage or 0),
|
damage = 1 + (effect.additionalDamage or 0),
|
||||||
damageType = fk.NormalDamage,
|
damageType = fk.NormalDamage,
|
||||||
skillName = self.name,
|
skillName = self.name,
|
||||||
})
|
})
|
||||||
|
@ -480,7 +480,7 @@ local archeryAttackSkill = fk.CreateActiveSkill{
|
||||||
from = room:getPlayerById(effect.from),
|
from = room:getPlayerById(effect.from),
|
||||||
to = room:getPlayerById(effect.to),
|
to = room:getPlayerById(effect.to),
|
||||||
card = effect.card,
|
card = effect.card,
|
||||||
damage = 1 + (effect.addtionalDamage or 0),
|
damage = 1 + (effect.additionalDamage or 0),
|
||||||
damageType = fk.NormalDamage,
|
damageType = fk.NormalDamage,
|
||||||
skillName = self.name,
|
skillName = self.name,
|
||||||
})
|
})
|
||||||
|
@ -542,10 +542,73 @@ local amazingGraceSkill = fk.CreateActiveSkill{
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_effect = function(self, room, cardEffectEvent)
|
on_effect = function(self, room, effect)
|
||||||
room:getPlayerById(cardEffectEvent.to):drawCards(1, 'god_salvation')
|
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
|
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{
|
local amazingGrace = fk.CreateTrickCard{
|
||||||
name = "amazing_grace",
|
name = "amazing_grace",
|
||||||
suit = Card.Heart,
|
suit = Card.Heart,
|
||||||
|
|
|
@ -621,7 +621,7 @@ Item {
|
||||||
dying: false,
|
dying: false,
|
||||||
faceup: true,
|
faceup: true,
|
||||||
chained: false,
|
chained: false,
|
||||||
drank: false,
|
drank: 0,
|
||||||
isOwner: false
|
isOwner: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ Item {
|
||||||
dying: false,
|
dying: false,
|
||||||
faceup: true,
|
faceup: true,
|
||||||
chained: false,
|
chained: false,
|
||||||
drank: false,
|
drank: 0,
|
||||||
isOwner: false
|
isOwner: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ Item {
|
||||||
property bool dying: false
|
property bool dying: false
|
||||||
property bool faceup: true
|
property bool faceup: true
|
||||||
property bool chained: false
|
property bool chained: false
|
||||||
property bool drank: false
|
property int drank: 0
|
||||||
property bool isOwner: false
|
property bool isOwner: false
|
||||||
property int distance: 0
|
property int distance: 0
|
||||||
property string status: "normal"
|
property string status: "normal"
|
||||||
|
@ -160,6 +160,7 @@ Item {
|
||||||
visible: false
|
visible: false
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
source: (general != "") ? SkinBank.getGeneralPicture(general) : ""
|
source: (general != "") ? SkinBank.getGeneralPicture(general) : ""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -185,6 +186,18 @@ Item {
|
||||||
visible: root.dead
|
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 {
|
Image {
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|