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
|
||||
text: luatr("Surrender")
|
||||
onClicked: {
|
||||
if (isStarted && !getPhoto(Self.id).dead) {
|
||||
const surrenderCheck =
|
||||
lcall('CheckSurrenderAvailable', miscStatus.playedTime);
|
||||
const photo = getPhoto(Self.id);
|
||||
if (isStarted && !(photo.dead && photo.rest <= 0)) {
|
||||
const surrenderCheck = lcall('CheckSurrenderAvailable', miscStatus.playedTime);
|
||||
if (!surrenderCheck.length) {
|
||||
surrenderDialog.informativeText =
|
||||
luatr('Surrender is disabled in this mode');
|
||||
|
|
|
@ -1006,7 +1006,7 @@ function Player:canMoveCardInBoardTo(to, id)
|
|||
return
|
||||
not (
|
||||
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
|
||||
table.contains(to.sealedSlots, Player.JudgeSlot)
|
||||
)
|
||||
|
|
|
@ -190,6 +190,11 @@ end
|
|||
---@param cardUseEvent CardUseStruct
|
||||
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 cardEffectEvent CardEffectEvent | SkillEffectEvent
|
||||
function ActiveSkill:aboutToEffect(room, cardEffectEvent) end
|
||||
|
|
|
@ -39,6 +39,10 @@ end
|
|||
---@param cardUseStruct CardUseStruct
|
||||
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_cards integer[] @ ids of selected cards
|
||||
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 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_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 on_effect? 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
|
||||
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.on_effect then skill.onEffect = spec.on_effect 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
|
||||
end
|
||||
|
||||
if spec.after_use and type(spec.after_use) == "function" then
|
||||
skill.afterUse = spec.after_use
|
||||
end
|
||||
|
||||
return skill
|
||||
end
|
||||
|
||||
|
|
|
@ -136,16 +136,16 @@ GameEvent.functions[GameEvent.Damage] = function(self)
|
|||
assert(damageStruct.to:isInstanceOf(ServerPlayer))
|
||||
|
||||
local stages = {
|
||||
{fk.PreDamage, damageStruct.from},
|
||||
{fk.PreDamage, "from"},
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
for _, struct in ipairs(stages) do
|
||||
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)
|
||||
end
|
||||
|
||||
|
@ -184,13 +184,13 @@ GameEvent.functions[GameEvent.Damage] = function(self)
|
|||
|
||||
|
||||
stages = {
|
||||
{fk.Damage, damageStruct.from},
|
||||
{fk.Damaged, damageStruct.to},
|
||||
{fk.Damage, "from"},
|
||||
{fk.Damaged, "to"},
|
||||
}
|
||||
|
||||
for _, struct in ipairs(stages) do
|
||||
local event, player = table.unpack(struct)
|
||||
logic:trigger(event, player, damageStruct)
|
||||
logic:trigger(event, damageStruct[player], damageStruct)
|
||||
end
|
||||
|
||||
return true
|
||||
|
|
|
@ -335,9 +335,16 @@ GameEvent.functions[GameEvent.CardEffect] = function(self)
|
|||
|
||||
if event == fk.PreCardEffect 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()
|
||||
end
|
||||
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()
|
||||
end
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ function GameLogic:initialize(room)
|
|||
self.event_recorder = {}
|
||||
self.current_event_id = 0
|
||||
self.specific_events_id = {
|
||||
[GameEvent.Damage] = 0,
|
||||
[GameEvent.Damage] = 1,
|
||||
}
|
||||
|
||||
self.role_table = {
|
||||
|
|
|
@ -1927,6 +1927,7 @@ function Room:handleUseCardReply(player, data)
|
|||
use.card = c
|
||||
|
||||
self:useSkill(player, skill, Util.DummyFunc)
|
||||
use.attachedSkillAndUser = { skillName = skill.name, user = player.id }
|
||||
|
||||
local rejectSkillName = skill:beforeUse(player, use)
|
||||
if type(rejectSkillName) == "string" then
|
||||
|
@ -2402,7 +2403,23 @@ end
|
|||
---@param cardUseEvent CardUseStruct @ 使用数据
|
||||
---@return boolean
|
||||
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
|
||||
|
||||
---@param room Room
|
||||
|
@ -2439,6 +2456,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
|||
firstTarget = firstTarget,
|
||||
additionalDamage = cardUseEvent.additionalDamage,
|
||||
additionalRecover = cardUseEvent.additionalRecover,
|
||||
additionalEffect = cardUseEvent.additionalEffect,
|
||||
extra_data = cardUseEvent.extra_data,
|
||||
}
|
||||
|
||||
|
@ -2466,6 +2484,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
|||
aimStruct.targetGroup = cardUseEvent.tos
|
||||
aimStruct.nullifiedTargets = cardUseEvent.nullifiedTargets or {}
|
||||
aimStruct.firstTarget = firstTarget
|
||||
aimStruct.additionalEffect = cardUseEvent.additionalEffect
|
||||
aimStruct.extra_data = cardUseEvent.extra_data
|
||||
end
|
||||
|
||||
|
@ -2483,6 +2502,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
|||
cardUseEvent.from = aimStruct.from
|
||||
cardUseEvent.tos = aimEventTargetGroup
|
||||
cardUseEvent.nullifiedTargets = aimStruct.nullifiedTargets
|
||||
cardUseEvent.additionalEffect = aimStruct.additionalEffect
|
||||
cardUseEvent.extra_data = aimStruct.extra_data
|
||||
|
||||
if #AimGroup:getAllTargets(aimStruct.tos) == 0 then
|
||||
|
@ -2643,57 +2663,71 @@ function Room:doCardUseEffect(cardUseEvent)
|
|||
return
|
||||
end
|
||||
|
||||
-- Else: do effect to all targets
|
||||
local collaboratorsIndex = {}
|
||||
for _, toId in ipairs(TargetGroup:getRealTargets(cardUseEvent.tos)) do
|
||||
if not table.contains(cardUseEvent.nullifiedTargets, toId) and self:getPlayerById(toId):isAlive() then
|
||||
if aimEventCollaborators[toId] then
|
||||
cardEffectEvent.to = toId
|
||||
collaboratorsIndex[toId] = collaboratorsIndex[toId] or 1
|
||||
local curAimEvent = aimEventCollaborators[toId][collaboratorsIndex[toId]]
|
||||
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
|
||||
|
||||
cardEffectEvent.subTargets = curAimEvent.subTargets
|
||||
cardEffectEvent.additionalDamage = curAimEvent.additionalDamage
|
||||
cardEffectEvent.additionalRecover = curAimEvent.additionalRecover
|
||||
-- Else: do effect to all targets
|
||||
local collaboratorsIndex = {}
|
||||
for _, toId in ipairs(TargetGroup:getRealTargets(cardUseEvent.tos)) do
|
||||
if not table.contains(cardUseEvent.nullifiedTargets, toId) and self:getPlayerById(toId):isAlive() then
|
||||
if aimEventCollaborators[toId] then
|
||||
cardEffectEvent.to = toId
|
||||
collaboratorsIndex[toId] = collaboratorsIndex[toId] or 1
|
||||
local curAimEvent = aimEventCollaborators[toId][collaboratorsIndex[toId]]
|
||||
|
||||
if curAimEvent.disresponsiveList then
|
||||
cardEffectEvent.disresponsiveList = cardEffectEvent.disresponsiveList or {}
|
||||
cardEffectEvent.subTargets = curAimEvent.subTargets
|
||||
cardEffectEvent.additionalDamage = curAimEvent.additionalDamage
|
||||
cardEffectEvent.additionalRecover = curAimEvent.additionalRecover
|
||||
|
||||
for _, disresponsivePlayer in ipairs(curAimEvent.disresponsiveList) do
|
||||
if not table.contains(cardEffectEvent.disresponsiveList, disresponsivePlayer) then
|
||||
table.insert(cardEffectEvent.disresponsiveList, disresponsivePlayer)
|
||||
if curAimEvent.disresponsiveList then
|
||||
cardEffectEvent.disresponsiveList = cardEffectEvent.disresponsiveList or {}
|
||||
|
||||
for _, disresponsivePlayer in ipairs(curAimEvent.disresponsiveList) do
|
||||
if not table.contains(cardEffectEvent.disresponsiveList, disresponsivePlayer) then
|
||||
table.insert(cardEffectEvent.disresponsiveList, disresponsivePlayer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if curAimEvent.unoffsetableList then
|
||||
cardEffectEvent.unoffsetableList = cardEffectEvent.unoffsetableList or {}
|
||||
if curAimEvent.unoffsetableList then
|
||||
cardEffectEvent.unoffsetableList = cardEffectEvent.unoffsetableList or {}
|
||||
|
||||
for _, unoffsetablePlayer in ipairs(curAimEvent.unoffsetableList) do
|
||||
if not table.contains(cardEffectEvent.unoffsetableList, unoffsetablePlayer) then
|
||||
table.insert(cardEffectEvent.unoffsetableList, unoffsetablePlayer)
|
||||
for _, unoffsetablePlayer in ipairs(curAimEvent.unoffsetableList) do
|
||||
if not table.contains(cardEffectEvent.unoffsetableList, unoffsetablePlayer) then
|
||||
table.insert(cardEffectEvent.unoffsetableList, unoffsetablePlayer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cardEffectEvent.disresponsive = curAimEvent.disresponsive
|
||||
cardEffectEvent.unoffsetable = curAimEvent.unoffsetable
|
||||
cardEffectEvent.fixedResponseTimes = curAimEvent.fixedResponseTimes
|
||||
cardEffectEvent.fixedAddTimesResponsors = curAimEvent.fixedAddTimesResponsors
|
||||
cardEffectEvent.disresponsive = curAimEvent.disresponsive
|
||||
cardEffectEvent.unoffsetable = curAimEvent.unoffsetable
|
||||
cardEffectEvent.fixedResponseTimes = curAimEvent.fixedResponseTimes
|
||||
cardEffectEvent.fixedAddTimesResponsors = curAimEvent.fixedAddTimesResponsors
|
||||
|
||||
collaboratorsIndex[toId] = collaboratorsIndex[toId] + 1
|
||||
collaboratorsIndex[toId] = collaboratorsIndex[toId] + 1
|
||||
|
||||
local curCardEffectEvent = table.simpleClone(cardEffectEvent)
|
||||
self:doCardEffect(curCardEffectEvent)
|
||||
local curCardEffectEvent = table.simpleClone(cardEffectEvent)
|
||||
self:doCardEffect(curCardEffectEvent)
|
||||
|
||||
if curCardEffectEvent.cardsResponded then
|
||||
cardUseEvent.cardsResponded = cardUseEvent.cardsResponded or {}
|
||||
for _, card in ipairs(curCardEffectEvent.cardsResponded) do
|
||||
table.insertIfNeed(cardUseEvent.cardsResponded, card)
|
||||
if curCardEffectEvent.cardsResponded then
|
||||
cardUseEvent.cardsResponded = cardUseEvent.cardsResponded or {}
|
||||
for _, card in ipairs(curCardEffectEvent.cardsResponded) do
|
||||
table.insertIfNeed(cardUseEvent.cardsResponded, card)
|
||||
end
|
||||
end
|
||||
|
||||
if type(curCardEffectEvent.nullifiedTargets) == 'table' then
|
||||
table.insertTableIfNeed(cardUseEvent.nullifiedTargets, curCardEffectEvent.nullifiedTargets)
|
||||
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
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ function ServerPlayer:marshal(player, observe)
|
|||
|
||||
if self.dead then
|
||||
room:notifyProperty(player, self, "dead")
|
||||
room:notifyProperty(player, self, "role")
|
||||
room:notifyProperty(player, self, self.rest > 0 and "rest" or "role")
|
||||
else
|
||||
room:notifyProperty(player, self, "seat")
|
||||
room:notifyProperty(player, self, "phase")
|
||||
|
|
|
@ -110,6 +110,7 @@ fk.IceDamage = 4
|
|||
---@field public cardsResponded? Card[]
|
||||
---@field public prohibitedCardNames? string[]
|
||||
---@field public damageDealt? table<PlayerId, number>
|
||||
---@field public additionalEffect? integer
|
||||
|
||||
---@class AimStruct
|
||||
---@field public from integer
|
||||
|
@ -126,6 +127,7 @@ fk.IceDamage = 4
|
|||
---@field public unoffsetableList? boolean
|
||||
---@field public additionalResponseTimes? table<string, integer>|integer
|
||||
---@field public fixedAddTimesResponsors? integer[]
|
||||
---@field public additionalEffect? integer
|
||||
|
||||
---@class CardEffectEvent
|
||||
---@field public from integer
|
||||
|
|
|
@ -608,6 +608,43 @@ local amazingGraceSkill = fk.CreateActiveSkill{
|
|||
can_use = Util.GlobalCanUse,
|
||||
on_use = Util.GlobalOnUse,
|
||||
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)
|
||||
local to = room:getPlayerById(effect.to)
|
||||
if not (effect.extra_data and effect.extra_data.AGFilled) then
|
||||
|
|
Loading…
Reference in New Issue