Modify Use-Event (#314)
- 为使用流程和Aim流程增加属性additionalEffect,用于指定额外结算次数(OL版),顺带移动【五谷丰登】开启和关闭AG的位置; - 为视为技新增after_use方法处理转化牌后的后续操作; - 修复伤害流程时机触发者不变问题; - 修复旁观休整的问题; - 修复可移动场上牌判断函数未判断虚拟牌名的问题。
This commit is contained in:
parent
3b9dd89b10
commit
58e76c1b9c
|
@ -121,9 +121,9 @@ Item {
|
||||||
enabled: !config.observing && !config.replaying
|
enabled: !config.observing && !config.replaying
|
||||||
text: luatr("Surrender")
|
text: luatr("Surrender")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (isStarted && !getPhoto(Self.id).dead) {
|
const photo = getPhoto(Self.id);
|
||||||
const surrenderCheck =
|
if (isStarted && !(photo.dead && photo.rest <= 0)) {
|
||||||
lcall('CheckSurrenderAvailable', miscStatus.playedTime);
|
const surrenderCheck = lcall('CheckSurrenderAvailable', miscStatus.playedTime);
|
||||||
if (!surrenderCheck.length) {
|
if (!surrenderCheck.length) {
|
||||||
surrenderDialog.informativeText =
|
surrenderDialog.informativeText =
|
||||||
luatr('Surrender is disabled in this mode');
|
luatr('Surrender is disabled in this mode');
|
||||||
|
|
|
@ -1006,7 +1006,7 @@ function Player:canMoveCardInBoardTo(to, id)
|
||||||
return
|
return
|
||||||
not (
|
not (
|
||||||
table.find(to:getCardIds(Player.Judge), function(cardId)
|
table.find(to:getCardIds(Player.Judge), function(cardId)
|
||||||
return Fk:getCardById(cardId).name == card.name
|
return (to:getVirualEquip(cardId) or Fk:getCardById(cardId)).name == card.name
|
||||||
end) or
|
end) or
|
||||||
table.contains(to.sealedSlots, Player.JudgeSlot)
|
table.contains(to.sealedSlots, Player.JudgeSlot)
|
||||||
)
|
)
|
||||||
|
|
|
@ -190,6 +190,11 @@ end
|
||||||
---@param cardUseEvent CardUseStruct
|
---@param cardUseEvent CardUseStruct
|
||||||
function ActiveSkill:onUse(room, cardUseEvent) end
|
function ActiveSkill:onUse(room, cardUseEvent) end
|
||||||
|
|
||||||
|
---@param room Room
|
||||||
|
---@param cardUseEvent CardUseStruct
|
||||||
|
---@param isEnding? bool
|
||||||
|
function ActiveSkill:onAction(room, cardUseEvent, finished) end
|
||||||
|
|
||||||
---@param room Room
|
---@param room Room
|
||||||
---@param cardEffectEvent CardEffectEvent | SkillEffectEvent
|
---@param cardEffectEvent CardEffectEvent | SkillEffectEvent
|
||||||
function ActiveSkill:aboutToEffect(room, cardEffectEvent) end
|
function ActiveSkill:aboutToEffect(room, cardEffectEvent) end
|
||||||
|
|
|
@ -39,6 +39,10 @@ end
|
||||||
---@param cardUseStruct CardUseStruct
|
---@param cardUseStruct CardUseStruct
|
||||||
function ViewAsSkill:beforeUse(player, cardUseStruct) end
|
function ViewAsSkill:beforeUse(player, cardUseStruct) end
|
||||||
|
|
||||||
|
---@param player Player
|
||||||
|
---@param cardUseStruct CardUseStruct
|
||||||
|
function ViewAsSkill:afterUse(player, cardUseStruct) end
|
||||||
|
|
||||||
---@param selected integer[] @ ids of selected players
|
---@param selected integer[] @ ids of selected players
|
||||||
---@param selected_cards integer[] @ ids of selected cards
|
---@param selected_cards integer[] @ ids of selected cards
|
||||||
function ViewAsSkill:prompt(selected, selected_cards) return "" end
|
function ViewAsSkill:prompt(selected, selected_cards) return "" end
|
||||||
|
|
|
@ -175,6 +175,7 @@ end
|
||||||
---@field public target_filter? fun(self: ActiveSkill, to_select: integer, selected: integer[], selected_cards: integer[], card: Card, extra_data: any): boolean?
|
---@field public target_filter? fun(self: ActiveSkill, to_select: integer, selected: integer[], selected_cards: integer[], card: Card, extra_data: any): boolean?
|
||||||
---@field public feasible? fun(self: ActiveSkill, selected: integer[], selected_cards: integer[]): boolean?
|
---@field public feasible? fun(self: ActiveSkill, selected: integer[], selected_cards: integer[]): boolean?
|
||||||
---@field public on_use? fun(self: ActiveSkill, room: Room, cardUseEvent: CardUseStruct): boolean?
|
---@field public on_use? fun(self: ActiveSkill, room: Room, cardUseEvent: CardUseStruct): boolean?
|
||||||
|
---@field public on_action? fun(self: ActiveSkill, room: Room, cardUseEvent: CardUseStruct, finished: boolean): boolean?
|
||||||
---@field public about_to_effect? fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean?
|
---@field public about_to_effect? fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean?
|
||||||
---@field public on_effect? fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean?
|
---@field public on_effect? fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean?
|
||||||
---@field public on_nullified? fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean?
|
---@field public on_nullified? fun(self: ActiveSkill, room: Room, cardEffectEvent: CardEffectEvent): boolean?
|
||||||
|
@ -202,6 +203,7 @@ function fk.CreateActiveSkill(spec)
|
||||||
skill.feasible = spec.feasible
|
skill.feasible = spec.feasible
|
||||||
end
|
end
|
||||||
if spec.on_use then skill.onUse = spec.on_use end
|
if spec.on_use then skill.onUse = spec.on_use end
|
||||||
|
if spec.on_action then skill.onAction = spec.on_action end
|
||||||
if spec.about_to_effect then skill.aboutToEffect = spec.about_to_effect end
|
if spec.about_to_effect then skill.aboutToEffect = spec.about_to_effect end
|
||||||
if spec.on_effect then skill.onEffect = spec.on_effect end
|
if spec.on_effect then skill.onEffect = spec.on_effect end
|
||||||
if spec.on_nullified then skill.onNullified = spec.on_nullified end
|
if spec.on_nullified then skill.onNullified = spec.on_nullified end
|
||||||
|
@ -274,6 +276,10 @@ function fk.CreateViewAsSkill(spec)
|
||||||
skill.beforeUse = spec.before_use
|
skill.beforeUse = spec.before_use
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if spec.after_use and type(spec.after_use) == "function" then
|
||||||
|
skill.afterUse = spec.after_use
|
||||||
|
end
|
||||||
|
|
||||||
return skill
|
return skill
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -136,16 +136,16 @@ GameEvent.functions[GameEvent.Damage] = function(self)
|
||||||
assert(damageStruct.to:isInstanceOf(ServerPlayer))
|
assert(damageStruct.to:isInstanceOf(ServerPlayer))
|
||||||
|
|
||||||
local stages = {
|
local stages = {
|
||||||
{fk.PreDamage, damageStruct.from},
|
{fk.PreDamage, "from"},
|
||||||
}
|
}
|
||||||
|
|
||||||
if not damageStruct.isVirtualDMG then
|
if not damageStruct.isVirtualDMG then
|
||||||
table.insertTable(stages, { { fk.DamageCaused, damageStruct.from }, { fk.DamageInflicted, damageStruct.to } })
|
table.insertTable(stages, { { fk.DamageCaused, "from" }, { fk.DamageInflicted, "to" } })
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, struct in ipairs(stages) do
|
for _, struct in ipairs(stages) do
|
||||||
local event, player = table.unpack(struct)
|
local event, player = table.unpack(struct)
|
||||||
if logic:trigger(event, player, damageStruct) or damageStruct.damage < 1 then
|
if logic:trigger(event, damageStruct[player], damageStruct) or damageStruct.damage < 1 then
|
||||||
logic:breakEvent(false)
|
logic:breakEvent(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -184,13 +184,13 @@ GameEvent.functions[GameEvent.Damage] = function(self)
|
||||||
|
|
||||||
|
|
||||||
stages = {
|
stages = {
|
||||||
{fk.Damage, damageStruct.from},
|
{fk.Damage, "from"},
|
||||||
{fk.Damaged, damageStruct.to},
|
{fk.Damaged, "to"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, struct in ipairs(stages) do
|
for _, struct in ipairs(stages) do
|
||||||
local event, player = table.unpack(struct)
|
local event, player = table.unpack(struct)
|
||||||
logic:trigger(event, player, damageStruct)
|
logic:trigger(event, damageStruct[player], damageStruct)
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -335,9 +335,16 @@ GameEvent.functions[GameEvent.CardEffect] = function(self)
|
||||||
|
|
||||||
if event == fk.PreCardEffect then
|
if event == fk.PreCardEffect then
|
||||||
if cardEffectEvent.from and logic:trigger(event, room:getPlayerById(cardEffectEvent.from), cardEffectEvent) then
|
if cardEffectEvent.from and logic:trigger(event, room:getPlayerById(cardEffectEvent.from), cardEffectEvent) then
|
||||||
|
if cardEffectEvent.to then
|
||||||
|
cardEffectEvent.nullifiedTargets = cardEffectEvent.nullifiedTargets or {}
|
||||||
|
table.insert(cardEffectEvent.nullifiedTargets, cardEffectEvent.to)
|
||||||
|
end
|
||||||
logic:breakEvent()
|
logic:breakEvent()
|
||||||
end
|
end
|
||||||
elseif cardEffectEvent.to and logic:trigger(event, room:getPlayerById(cardEffectEvent.to), cardEffectEvent) then
|
elseif cardEffectEvent.to and logic:trigger(event, room:getPlayerById(cardEffectEvent.to), cardEffectEvent) then
|
||||||
|
cardEffectEvent.nullifiedTargets = cardEffectEvent.nullifiedTargets or {}
|
||||||
|
table.insert(cardEffectEvent.nullifiedTargets, cardEffectEvent.to)
|
||||||
|
|
||||||
logic:breakEvent()
|
logic:breakEvent()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ function GameLogic:initialize(room)
|
||||||
self.event_recorder = {}
|
self.event_recorder = {}
|
||||||
self.current_event_id = 0
|
self.current_event_id = 0
|
||||||
self.specific_events_id = {
|
self.specific_events_id = {
|
||||||
[GameEvent.Damage] = 0,
|
[GameEvent.Damage] = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.role_table = {
|
self.role_table = {
|
||||||
|
|
|
@ -1927,6 +1927,7 @@ function Room:handleUseCardReply(player, data)
|
||||||
use.card = c
|
use.card = c
|
||||||
|
|
||||||
self:useSkill(player, skill, Util.DummyFunc)
|
self:useSkill(player, skill, Util.DummyFunc)
|
||||||
|
use.attachedSkillAndUser = { skillName = skill.name, user = player.id }
|
||||||
|
|
||||||
local rejectSkillName = skill:beforeUse(player, use)
|
local rejectSkillName = skill:beforeUse(player, use)
|
||||||
if type(rejectSkillName) == "string" then
|
if type(rejectSkillName) == "string" then
|
||||||
|
@ -2402,7 +2403,23 @@ end
|
||||||
---@param cardUseEvent CardUseStruct @ 使用数据
|
---@param cardUseEvent CardUseStruct @ 使用数据
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function Room:useCard(cardUseEvent)
|
function Room:useCard(cardUseEvent)
|
||||||
return execGameEvent(GameEvent.UseCard, cardUseEvent)
|
local attachedSkillAndUser
|
||||||
|
if type(cardUseEvent.attachedSkillAndUser) == "table" then
|
||||||
|
attachedSkillAndUser = table.simpleClone(cardUseEvent.attachedSkillAndUser)
|
||||||
|
cardUseEvent.attachedSkillAndUser = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local ret = execGameEvent(GameEvent.UseCard, cardUseEvent)
|
||||||
|
|
||||||
|
if
|
||||||
|
type(attachedSkillAndUser) == "table" and
|
||||||
|
Fk.skills[attachedSkillAndUser.skillName] and
|
||||||
|
Fk.skills[attachedSkillAndUser.skillName].afterUse
|
||||||
|
then
|
||||||
|
Fk.skills[attachedSkillAndUser.skillName]:afterUse(self:getPlayerById(attachedSkillAndUser.user), cardUseEvent)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param room Room
|
---@param room Room
|
||||||
|
@ -2439,6 +2456,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
||||||
firstTarget = firstTarget,
|
firstTarget = firstTarget,
|
||||||
additionalDamage = cardUseEvent.additionalDamage,
|
additionalDamage = cardUseEvent.additionalDamage,
|
||||||
additionalRecover = cardUseEvent.additionalRecover,
|
additionalRecover = cardUseEvent.additionalRecover,
|
||||||
|
additionalEffect = cardUseEvent.additionalEffect,
|
||||||
extra_data = cardUseEvent.extra_data,
|
extra_data = cardUseEvent.extra_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2466,6 +2484,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
||||||
aimStruct.targetGroup = cardUseEvent.tos
|
aimStruct.targetGroup = cardUseEvent.tos
|
||||||
aimStruct.nullifiedTargets = cardUseEvent.nullifiedTargets or {}
|
aimStruct.nullifiedTargets = cardUseEvent.nullifiedTargets or {}
|
||||||
aimStruct.firstTarget = firstTarget
|
aimStruct.firstTarget = firstTarget
|
||||||
|
aimStruct.additionalEffect = cardUseEvent.additionalEffect
|
||||||
aimStruct.extra_data = cardUseEvent.extra_data
|
aimStruct.extra_data = cardUseEvent.extra_data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2483,6 +2502,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
||||||
cardUseEvent.from = aimStruct.from
|
cardUseEvent.from = aimStruct.from
|
||||||
cardUseEvent.tos = aimEventTargetGroup
|
cardUseEvent.tos = aimEventTargetGroup
|
||||||
cardUseEvent.nullifiedTargets = aimStruct.nullifiedTargets
|
cardUseEvent.nullifiedTargets = aimStruct.nullifiedTargets
|
||||||
|
cardUseEvent.additionalEffect = aimStruct.additionalEffect
|
||||||
cardUseEvent.extra_data = aimStruct.extra_data
|
cardUseEvent.extra_data = aimStruct.extra_data
|
||||||
|
|
||||||
if #AimGroup:getAllTargets(aimStruct.tos) == 0 then
|
if #AimGroup:getAllTargets(aimStruct.tos) == 0 then
|
||||||
|
@ -2643,6 +2663,11 @@ function Room:doCardUseEffect(cardUseEvent)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for i = 1, (cardUseEvent.additionalEffect or 0) + 1 do
|
||||||
|
if #TargetGroup:getRealTargets(cardUseEvent.tos) > 0 and cardUseEvent.card.skill.onAction then
|
||||||
|
cardUseEvent.card.skill:onAction(self, cardUseEvent)
|
||||||
|
end
|
||||||
|
|
||||||
-- Else: do effect to all targets
|
-- Else: do effect to all targets
|
||||||
local collaboratorsIndex = {}
|
local collaboratorsIndex = {}
|
||||||
for _, toId in ipairs(TargetGroup:getRealTargets(cardUseEvent.tos)) do
|
for _, toId in ipairs(TargetGroup:getRealTargets(cardUseEvent.tos)) do
|
||||||
|
@ -2692,9 +2717,18 @@ function Room:doCardUseEffect(cardUseEvent)
|
||||||
table.insertIfNeed(cardUseEvent.cardsResponded, card)
|
table.insertIfNeed(cardUseEvent.cardsResponded, card)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if type(curCardEffectEvent.nullifiedTargets) == 'table' then
|
||||||
|
table.insertTableIfNeed(cardUseEvent.nullifiedTargets, curCardEffectEvent.nullifiedTargets)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #TargetGroup:getRealTargets(cardUseEvent.tos) > 0 and cardUseEvent.card.skill.onAction then
|
||||||
|
cardUseEvent.card.skill:onAction(self, cardUseEvent, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- 对卡牌效果数据进行生效
|
--- 对卡牌效果数据进行生效
|
||||||
|
|
|
@ -215,7 +215,7 @@ function ServerPlayer:marshal(player, observe)
|
||||||
|
|
||||||
if self.dead then
|
if self.dead then
|
||||||
room:notifyProperty(player, self, "dead")
|
room:notifyProperty(player, self, "dead")
|
||||||
room:notifyProperty(player, self, "role")
|
room:notifyProperty(player, self, self.rest > 0 and "rest" or "role")
|
||||||
else
|
else
|
||||||
room:notifyProperty(player, self, "seat")
|
room:notifyProperty(player, self, "seat")
|
||||||
room:notifyProperty(player, self, "phase")
|
room:notifyProperty(player, self, "phase")
|
||||||
|
|
|
@ -110,6 +110,7 @@ fk.IceDamage = 4
|
||||||
---@field public cardsResponded? Card[]
|
---@field public cardsResponded? Card[]
|
||||||
---@field public prohibitedCardNames? string[]
|
---@field public prohibitedCardNames? string[]
|
||||||
---@field public damageDealt? table<PlayerId, number>
|
---@field public damageDealt? table<PlayerId, number>
|
||||||
|
---@field public additionalEffect? integer
|
||||||
|
|
||||||
---@class AimStruct
|
---@class AimStruct
|
||||||
---@field public from integer
|
---@field public from integer
|
||||||
|
@ -126,6 +127,7 @@ fk.IceDamage = 4
|
||||||
---@field public unoffsetableList? boolean
|
---@field public unoffsetableList? boolean
|
||||||
---@field public additionalResponseTimes? table<string, integer>|integer
|
---@field public additionalResponseTimes? table<string, integer>|integer
|
||||||
---@field public fixedAddTimesResponsors? integer[]
|
---@field public fixedAddTimesResponsors? integer[]
|
||||||
|
---@field public additionalEffect? integer
|
||||||
|
|
||||||
---@class CardEffectEvent
|
---@class CardEffectEvent
|
||||||
---@field public from integer
|
---@field public from integer
|
||||||
|
|
|
@ -608,6 +608,43 @@ local amazingGraceSkill = fk.CreateActiveSkill{
|
||||||
can_use = Util.GlobalCanUse,
|
can_use = Util.GlobalCanUse,
|
||||||
on_use = Util.GlobalOnUse,
|
on_use = Util.GlobalOnUse,
|
||||||
mod_target_filter = Util.TrueFunc,
|
mod_target_filter = Util.TrueFunc,
|
||||||
|
on_action = function(self, room, use, finished)
|
||||||
|
if not finished then
|
||||||
|
local toDisplay = room:getNCards(#TargetGroup:getRealTargets(use.tos))
|
||||||
|
room:moveCards({
|
||||||
|
ids = toDisplay,
|
||||||
|
toArea = Card.Processing,
|
||||||
|
moveReason = fk.ReasonPut,
|
||||||
|
})
|
||||||
|
|
||||||
|
table.forEach(room.players, function(p)
|
||||||
|
room:fillAG(p, toDisplay)
|
||||||
|
end)
|
||||||
|
|
||||||
|
use.extra_data = use.extra_data or {}
|
||||||
|
use.extra_data.AGFilled = toDisplay
|
||||||
|
else
|
||||||
|
if use.extra_data and use.extra_data.AGFilled then
|
||||||
|
table.forEach(room.players, function(p)
|
||||||
|
room:closeAG(p)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local toDiscard = table.filter(use.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
|
||||||
|
|
||||||
|
use.extra_data.AGFilled = nil
|
||||||
|
end
|
||||||
|
end,
|
||||||
on_effect = function(self, room, effect)
|
on_effect = function(self, room, effect)
|
||||||
local to = room:getPlayerById(effect.to)
|
local to = room:getPlayerById(effect.to)
|
||||||
if not (effect.extra_data and effect.extra_data.AGFilled) then
|
if not (effect.extra_data and effect.extra_data.AGFilled) then
|
||||||
|
|
Loading…
Reference in New Issue