2023-04-09 05:35:35 +00:00
|
|
|
-- SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2023-02-28 17:43:44 +00:00
|
|
|
local playCardEmotionAndSound = function(room, player, card)
|
|
|
|
if card.type ~= Card.TypeEquip then
|
2023-03-09 04:19:16 +00:00
|
|
|
local anim_path = "./packages/" .. card.package.extensionName .. "/image/anim/" .. card.name
|
|
|
|
if not FileIO.exists(anim_path) then
|
|
|
|
for _, dir in ipairs(FileIO.ls("./packages/")) do
|
|
|
|
anim_path = "./packages/" .. dir .. "/image/anim/" .. card.name
|
|
|
|
if FileIO.exists(anim_path) then break end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if FileIO.exists(anim_path) then room:setEmotion(player, anim_path) end
|
2023-02-28 17:43:44 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
local soundName
|
|
|
|
if card.type == Card.TypeEquip then
|
|
|
|
local subTypeStr
|
|
|
|
if card.sub_type == Card.SubtypeDefensiveRide or card.sub_type == Card.SubtypeOffensiveRide then
|
|
|
|
subTypeStr = "horse"
|
|
|
|
elseif card.sub_type == Card.SubtypeWeapon then
|
|
|
|
subTypeStr = "weapon"
|
|
|
|
else
|
|
|
|
subTypeStr = "armor"
|
|
|
|
end
|
|
|
|
|
|
|
|
soundName = "./audio/card/common/" .. subTypeStr
|
|
|
|
else
|
|
|
|
soundName = "./packages/" .. card.package.extensionName .. "/audio/card/"
|
|
|
|
.. (player.gender == General.Male and "male/" or "female/") .. card.name
|
2023-03-09 04:19:16 +00:00
|
|
|
if not FileIO.exists(soundName .. ".mp3") then
|
2023-12-09 13:57:47 +00:00
|
|
|
local orig = Fk.all_card_types[card.name]
|
|
|
|
soundName = "./packages/" .. orig.package.extensionName .. "/audio/card/"
|
|
|
|
.. (player.gender == General.Male and "male/" or "female/") .. orig.name
|
2023-03-09 04:19:16 +00:00
|
|
|
end
|
2023-02-28 17:43:44 +00:00
|
|
|
end
|
|
|
|
room:broadcastPlaySound(soundName)
|
|
|
|
end
|
|
|
|
|
|
|
|
---@param room Room
|
|
|
|
---@param cardUseEvent CardUseStruct
|
|
|
|
local sendCardEmotionAndLog = function(room, cardUseEvent)
|
|
|
|
local from = cardUseEvent.from
|
|
|
|
local _card = cardUseEvent.card
|
|
|
|
|
|
|
|
-- when this function is called, card is already in PlaceTable and no filter skill is applied.
|
|
|
|
-- So filter this card manually here to get 'real' use.card
|
|
|
|
local card = _card
|
2023-07-01 15:14:30 +00:00
|
|
|
---[[
|
2023-02-28 17:43:44 +00:00
|
|
|
if not _card:isVirtual() then
|
|
|
|
local temp = { card = _card }
|
2024-04-06 16:21:15 +00:00
|
|
|
Fk:filterCard(_card.id, room:getCardOwner(_card), temp)
|
2023-02-28 17:43:44 +00:00
|
|
|
card = temp.card
|
|
|
|
end
|
2023-06-23 14:18:11 +00:00
|
|
|
cardUseEvent.card = card
|
2023-07-01 15:14:30 +00:00
|
|
|
--]]
|
2023-02-28 17:43:44 +00:00
|
|
|
|
|
|
|
playCardEmotionAndSound(room, room:getPlayerById(from), card)
|
2024-04-06 16:21:15 +00:00
|
|
|
|
|
|
|
if not cardUseEvent.noIndicate then
|
|
|
|
room:doAnimate("Indicate", {
|
|
|
|
from = from,
|
|
|
|
to = cardUseEvent.tos or Util.DummyTable,
|
|
|
|
})
|
|
|
|
end
|
2023-02-28 17:43:44 +00:00
|
|
|
|
|
|
|
local useCardIds = card:isVirtual() and card.subcards or { card.id }
|
2024-04-06 16:21:15 +00:00
|
|
|
if cardUseEvent.tos and #cardUseEvent.tos > 0 and not cardUseEvent.noIndicate then
|
2023-02-28 17:43:44 +00:00
|
|
|
local to = {}
|
|
|
|
for _, t in ipairs(cardUseEvent.tos) do
|
|
|
|
table.insert(to, t[1])
|
|
|
|
end
|
|
|
|
|
|
|
|
if card:isVirtual() or (card ~= _card) then
|
|
|
|
if #useCardIds == 0 then
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseV0CardToTargets",
|
|
|
|
from = from,
|
|
|
|
to = to,
|
|
|
|
arg = card:toLogString(),
|
|
|
|
}
|
|
|
|
else
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseVCardToTargets",
|
|
|
|
from = from,
|
|
|
|
to = to,
|
|
|
|
card = useCardIds,
|
|
|
|
arg = card:toLogString(),
|
|
|
|
}
|
|
|
|
end
|
|
|
|
else
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseCardToTargets",
|
|
|
|
from = from,
|
|
|
|
to = to,
|
|
|
|
card = useCardIds
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
for _, t in ipairs(cardUseEvent.tos) do
|
|
|
|
if t[2] then
|
|
|
|
local temp = {table.unpack(t)}
|
|
|
|
table.remove(temp, 1)
|
|
|
|
room:sendLog{
|
|
|
|
type = "#CardUseCollaborator",
|
|
|
|
from = t[1],
|
|
|
|
to = temp,
|
|
|
|
arg = card.name,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
elseif cardUseEvent.toCard then
|
|
|
|
if card:isVirtual() or (card ~= _card) then
|
|
|
|
if #useCardIds == 0 then
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseV0CardToCard",
|
|
|
|
from = from,
|
|
|
|
arg = cardUseEvent.toCard.name,
|
|
|
|
arg2 = card:toLogString(),
|
|
|
|
}
|
|
|
|
else
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseVCardToCard",
|
|
|
|
from = from,
|
|
|
|
card = useCardIds,
|
|
|
|
arg = cardUseEvent.toCard.name,
|
|
|
|
arg2 = card:toLogString(),
|
|
|
|
}
|
|
|
|
end
|
|
|
|
else
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseCardToCard",
|
|
|
|
from = from,
|
|
|
|
card = useCardIds,
|
|
|
|
arg = cardUseEvent.toCard.name,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if card:isVirtual() or (card ~= _card) then
|
|
|
|
if #useCardIds == 0 then
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseV0Card",
|
|
|
|
from = from,
|
|
|
|
arg = card:toLogString(),
|
|
|
|
}
|
|
|
|
else
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseVCard",
|
|
|
|
from = from,
|
|
|
|
card = useCardIds,
|
|
|
|
arg = card:toLogString(),
|
|
|
|
}
|
|
|
|
end
|
|
|
|
else
|
|
|
|
room:sendLog{
|
|
|
|
type = "#UseCard",
|
|
|
|
from = from,
|
|
|
|
card = useCardIds,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
2023-12-12 12:06:07 +00:00
|
|
|
|
|
|
|
return _card
|
2023-12-10 10:55:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
GameEvent.functions[GameEvent.UseCard] = function(self)
|
|
|
|
local cardUseEvent = table.unpack(self.data)
|
|
|
|
local room = self.room
|
|
|
|
local logic = room.logic
|
2023-06-09 18:18:51 +00:00
|
|
|
|
2024-02-04 14:29:54 +00:00
|
|
|
if type(cardUseEvent.attachedSkillAndUser) == "table" then
|
|
|
|
local attachedSkillAndUser = table.simpleClone(cardUseEvent.attachedSkillAndUser)
|
|
|
|
self:addExitFunc(function()
|
|
|
|
if
|
|
|
|
type(attachedSkillAndUser) == "table" and
|
|
|
|
Fk.skills[attachedSkillAndUser.skillName] and
|
|
|
|
Fk.skills[attachedSkillAndUser.skillName].afterUse
|
|
|
|
then
|
|
|
|
Fk.skills[attachedSkillAndUser.skillName]:afterUse(room:getPlayerById(attachedSkillAndUser.user), cardUseEvent)
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
cardUseEvent.attachedSkillAndUser = nil
|
|
|
|
end
|
|
|
|
|
2023-12-10 10:55:16 +00:00
|
|
|
if cardUseEvent.card.skill then
|
|
|
|
cardUseEvent.card.skill:onUse(room, cardUseEvent)
|
|
|
|
end
|
|
|
|
|
2024-01-29 02:19:10 +00:00
|
|
|
if logic:trigger(fk.PreCardUse, room:getPlayerById(cardUseEvent.from), cardUseEvent) then
|
|
|
|
logic:breakEvent()
|
|
|
|
end
|
|
|
|
|
2024-04-06 16:21:15 +00:00
|
|
|
local _card = sendCardEmotionAndLog(room, cardUseEvent)
|
|
|
|
|
2023-12-10 10:55:16 +00:00
|
|
|
room:moveCardTo(cardUseEvent.card, Card.Processing, nil, fk.ReasonUse)
|
|
|
|
|
|
|
|
local card = cardUseEvent.card
|
|
|
|
local useCardIds = card:isVirtual() and card.subcards or { card.id }
|
2023-12-12 12:06:07 +00:00
|
|
|
if #useCardIds > 0 then
|
2024-04-06 16:21:15 +00:00
|
|
|
if cardUseEvent.tos and #cardUseEvent.tos > 0 and #cardUseEvent.tos <= 2 and not cardUseEvent.noIndicate then
|
2023-12-12 12:06:07 +00:00
|
|
|
local tos = table.map(cardUseEvent.tos, function(e) return e[1] end)
|
|
|
|
room:sendFootnote(useCardIds, {
|
|
|
|
type = "##UseCardTo",
|
|
|
|
from = cardUseEvent.from,
|
|
|
|
to = tos,
|
|
|
|
})
|
|
|
|
if card:isVirtual() or card ~= _card then
|
|
|
|
room:sendCardVirtName(useCardIds, card.name)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
room:sendFootnote(useCardIds, {
|
|
|
|
type = "##UseCard",
|
|
|
|
from = cardUseEvent.from,
|
|
|
|
})
|
|
|
|
if card:isVirtual() or card ~= _card then
|
|
|
|
room:sendCardVirtName(useCardIds, card.name)
|
|
|
|
end
|
2023-06-09 18:18:51 +00:00
|
|
|
end
|
|
|
|
end
|
2023-10-27 14:53:25 +00:00
|
|
|
|
2023-02-28 17:43:44 +00:00
|
|
|
if not cardUseEvent.extraUse then
|
2023-08-10 19:19:59 +00:00
|
|
|
room:getPlayerById(cardUseEvent.from):addCardUseHistory(cardUseEvent.card.trueName, 1)
|
2023-02-28 17:43:44 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
if cardUseEvent.responseToEvent then
|
|
|
|
cardUseEvent.responseToEvent.cardsResponded = cardUseEvent.responseToEvent.cardsResponded or {}
|
2023-06-11 04:45:12 +00:00
|
|
|
table.insertIfNeed(cardUseEvent.responseToEvent.cardsResponded, cardUseEvent.card)
|
2023-02-28 17:43:44 +00:00
|
|
|
end
|
|
|
|
|
2023-05-20 08:00:03 +00:00
|
|
|
for _, event in ipairs({ fk.AfterCardUseDeclared, fk.AfterCardTargetDeclared, fk.CardUsing }) do
|
2023-02-28 17:43:44 +00:00
|
|
|
if not cardUseEvent.toCard and #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
|
2023-08-10 19:19:59 +00:00
|
|
|
logic:trigger(event, room:getPlayerById(cardUseEvent.from), cardUseEvent)
|
2023-02-28 17:43:44 +00:00
|
|
|
if event == fk.CardUsing then
|
2023-08-10 19:19:59 +00:00
|
|
|
room:doCardUseEffect(cardUseEvent)
|
2023-02-28 17:43:44 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
GameEvent.cleaners[GameEvent.UseCard] = function(self)
|
|
|
|
local cardUseEvent = table.unpack(self.data)
|
2023-08-10 19:19:59 +00:00
|
|
|
local room = self.room
|
2023-02-28 17:43:44 +00:00
|
|
|
|
2023-08-10 19:19:59 +00:00
|
|
|
room.logic:trigger(fk.CardUseFinished, room:getPlayerById(cardUseEvent.from), cardUseEvent)
|
2023-03-14 12:48:08 +00:00
|
|
|
|
2023-08-10 19:19:59 +00:00
|
|
|
local leftRealCardIds = room:getSubcardsByRule(cardUseEvent.card, { Card.Processing })
|
2023-02-28 17:43:44 +00:00
|
|
|
if #leftRealCardIds > 0 then
|
2023-08-10 19:19:59 +00:00
|
|
|
room:moveCards({
|
2023-02-28 17:43:44 +00:00
|
|
|
ids = leftRealCardIds,
|
|
|
|
toArea = Card.DiscardPile,
|
2023-05-13 06:16:09 +00:00
|
|
|
moveReason = fk.ReasonUse,
|
2023-02-28 17:43:44 +00:00
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
GameEvent.functions[GameEvent.RespondCard] = function(self)
|
|
|
|
local cardResponseEvent = table.unpack(self.data)
|
2023-08-10 19:19:59 +00:00
|
|
|
local room = self.room
|
|
|
|
local logic = room.logic
|
2024-04-06 16:21:15 +00:00
|
|
|
|
|
|
|
if logic:trigger(fk.PreCardRespond, room:getPlayerById(cardResponseEvent.from), cardResponseEvent) then
|
|
|
|
logic:breakEvent()
|
|
|
|
end
|
|
|
|
|
2023-02-28 17:43:44 +00:00
|
|
|
local from = cardResponseEvent.customFrom or cardResponseEvent.from
|
|
|
|
local card = cardResponseEvent.card
|
2023-08-10 19:19:59 +00:00
|
|
|
local cardIds = room:getSubcardsByRule(card)
|
2023-02-28 17:43:44 +00:00
|
|
|
|
|
|
|
if card:isVirtual() then
|
|
|
|
if #cardIds == 0 then
|
2023-08-10 19:19:59 +00:00
|
|
|
room:sendLog{
|
2023-02-28 17:43:44 +00:00
|
|
|
type = "#ResponsePlayV0Card",
|
|
|
|
from = from,
|
|
|
|
arg = card:toLogString(),
|
|
|
|
}
|
|
|
|
else
|
2023-08-10 19:19:59 +00:00
|
|
|
room:sendLog{
|
2023-02-28 17:43:44 +00:00
|
|
|
type = "#ResponsePlayVCard",
|
|
|
|
from = from,
|
|
|
|
card = cardIds,
|
|
|
|
arg = card:toLogString(),
|
|
|
|
}
|
|
|
|
end
|
|
|
|
else
|
2023-08-10 19:19:59 +00:00
|
|
|
room:sendLog{
|
2023-02-28 17:43:44 +00:00
|
|
|
type = "#ResponsePlayCard",
|
|
|
|
from = from,
|
|
|
|
card = cardIds,
|
|
|
|
}
|
|
|
|
end
|
2023-10-18 13:46:11 +00:00
|
|
|
|
|
|
|
playCardEmotionAndSound(room, room:getPlayerById(from), card)
|
|
|
|
|
2023-08-12 18:25:04 +00:00
|
|
|
room:moveCardTo(card, Card.Processing, nil, fk.ReasonResonpse)
|
2023-06-09 18:18:51 +00:00
|
|
|
if #cardIds > 0 then
|
2023-08-10 19:19:59 +00:00
|
|
|
room:sendFootnote(cardIds, {
|
2023-06-09 18:18:51 +00:00
|
|
|
type = "##ResponsePlayCard",
|
|
|
|
from = from,
|
|
|
|
})
|
|
|
|
if card:isVirtual() then
|
2023-08-10 19:19:59 +00:00
|
|
|
room:sendCardVirtName(cardIds, card.name)
|
2023-06-09 18:18:51 +00:00
|
|
|
end
|
|
|
|
end
|
2023-02-28 17:43:44 +00:00
|
|
|
|
2023-08-10 19:19:59 +00:00
|
|
|
logic:trigger(fk.CardResponding, room:getPlayerById(cardResponseEvent.from), cardResponseEvent)
|
2023-04-15 04:06:24 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
GameEvent.cleaners[GameEvent.RespondCard] = function(self)
|
|
|
|
local cardResponseEvent = table.unpack(self.data)
|
2023-08-10 19:19:59 +00:00
|
|
|
local room = self.room
|
2023-04-15 04:06:24 +00:00
|
|
|
|
2023-08-10 19:19:59 +00:00
|
|
|
room.logic:trigger(fk.CardRespondFinished, room:getPlayerById(cardResponseEvent.from), cardResponseEvent)
|
2023-02-28 17:43:44 +00:00
|
|
|
|
2023-08-10 19:19:59 +00:00
|
|
|
local realCardIds = room:getSubcardsByRule(cardResponseEvent.card, { Card.Processing })
|
2023-02-28 17:43:44 +00:00
|
|
|
if #realCardIds > 0 and not cardResponseEvent.skipDrop then
|
2023-08-10 19:19:59 +00:00
|
|
|
room:moveCards({
|
2023-02-28 17:43:44 +00:00
|
|
|
ids = realCardIds,
|
|
|
|
toArea = Card.DiscardPile,
|
2023-05-13 06:16:09 +00:00
|
|
|
moveReason = fk.ReasonResonpse,
|
2023-02-28 17:43:44 +00:00
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
2023-05-28 10:45:54 +00:00
|
|
|
|
|
|
|
GameEvent.functions[GameEvent.CardEffect] = function(self)
|
|
|
|
local cardEffectEvent = table.unpack(self.data)
|
2023-08-10 19:19:59 +00:00
|
|
|
local room = self.room
|
|
|
|
local logic = room.logic
|
2023-05-28 10:45:54 +00:00
|
|
|
|
|
|
|
for _, event in ipairs({ fk.PreCardEffect, fk.BeforeCardEffect, fk.CardEffecting, fk.CardEffectFinished }) do
|
2023-08-10 19:19:59 +00:00
|
|
|
local user = cardEffectEvent.from and room:getPlayerById(cardEffectEvent.from) or nil
|
2023-06-19 13:56:06 +00:00
|
|
|
if cardEffectEvent.isCancellOut then
|
2023-08-10 19:19:59 +00:00
|
|
|
if logic:trigger(fk.CardEffectCancelledOut, user, cardEffectEvent) then
|
2023-06-19 13:56:06 +00:00
|
|
|
cardEffectEvent.isCancellOut = false
|
2023-05-28 10:45:54 +00:00
|
|
|
else
|
2023-08-10 19:19:59 +00:00
|
|
|
logic:breakEvent()
|
2023-05-28 10:45:54 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if
|
|
|
|
not cardEffectEvent.toCard and
|
|
|
|
(
|
2023-08-10 19:19:59 +00:00
|
|
|
not (room:getPlayerById(cardEffectEvent.to):isAlive() and cardEffectEvent.to)
|
|
|
|
or #room:deadPlayerFilter(TargetGroup:getRealTargets(cardEffectEvent.tos)) == 0
|
2023-05-28 10:45:54 +00:00
|
|
|
)
|
|
|
|
then
|
2023-08-10 19:19:59 +00:00
|
|
|
logic:breakEvent()
|
2023-05-28 10:45:54 +00:00
|
|
|
end
|
|
|
|
|
2023-06-11 08:22:11 +00:00
|
|
|
if table.contains((cardEffectEvent.nullifiedTargets or Util.DummyTable), cardEffectEvent.to) then
|
2023-08-10 19:19:59 +00:00
|
|
|
logic:breakEvent()
|
2023-05-28 10:45:54 +00:00
|
|
|
end
|
|
|
|
|
2023-08-02 13:50:47 +00:00
|
|
|
if event == fk.PreCardEffect then
|
2023-08-10 19:19:59 +00:00
|
|
|
if cardEffectEvent.from and logic:trigger(event, room:getPlayerById(cardEffectEvent.from), cardEffectEvent) then
|
2024-02-04 07:29:39 +00:00
|
|
|
if cardEffectEvent.to then
|
|
|
|
cardEffectEvent.nullifiedTargets = cardEffectEvent.nullifiedTargets or {}
|
|
|
|
table.insert(cardEffectEvent.nullifiedTargets, cardEffectEvent.to)
|
|
|
|
end
|
2023-08-10 19:19:59 +00:00
|
|
|
logic:breakEvent()
|
2023-08-02 13:50:47 +00:00
|
|
|
end
|
2023-08-10 19:19:59 +00:00
|
|
|
elseif cardEffectEvent.to and logic:trigger(event, room:getPlayerById(cardEffectEvent.to), cardEffectEvent) then
|
2024-02-04 07:29:39 +00:00
|
|
|
cardEffectEvent.nullifiedTargets = cardEffectEvent.nullifiedTargets or {}
|
|
|
|
table.insert(cardEffectEvent.nullifiedTargets, cardEffectEvent.to)
|
|
|
|
|
2023-08-10 19:19:59 +00:00
|
|
|
logic:breakEvent()
|
2023-05-28 10:45:54 +00:00
|
|
|
end
|
|
|
|
|
2023-08-10 19:19:59 +00:00
|
|
|
room:handleCardEffect(event, cardEffectEvent)
|
2023-05-28 10:45:54 +00:00
|
|
|
end
|
|
|
|
end
|