FreeKill/lua/server/gameevent.lua
YoumuKon 21e4c65204
终结标记与界bugfix (#307)
-
正式移除了作为临时手段的-tmp标记,现在can_use和target_filter支持读取extra_data(card_filter暂时搁置)
-
规范了askForUseCard中card_name和pattern的关系,现在的格式将以pattern为主,若无pattern才会将card_name视为pattern
- 将withinDistanceLimit迁移至ActiveSkill内
- 添加了令卡牌无距离/次数限制的标记判断
- 添加放大了⑨倍的冰伤音效
- 优化了同将判断的逻辑,使其能够准确读取trueName
- 身份场主公选将后其他角色能看见主公技能(只是看见,无实际功能)
- 开局添加不存在的技能时会放出警报
- 修复了findParent在当前事件无parent时报错的bug
- 修复了人工洗牌后不刷新摸牌堆的bug
- 修复了getPile返回牌堆实例的bug
- 修复了getSkillNameList无法过滤主公技的bug
- 修复了死亡后武将牌没有圆角效果的bug
2024-01-25 03:13:57 +08:00

196 lines
5.7 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- SPDX-License-Identifier: GPL-3.0-or-later
---@class GameEvent: Object
---@field public id integer @ 事件的id随着时间推移自动增加并分配给新事件
---@field public end_id integer @ 事件的对应结束id如果整个事件中未插入事件那么end_id就是自己的id
---@field public room Room @ room实例
---@field public event integer @ 该事件对应的EventType
---@field public data any @ 事件的附加数据,视类型而定
---@field public parent GameEvent @ 事件的父事件(栈中的上一层事件)
---@field public prepare_func fun(self: GameEvent) @ 事件即将开始时执行的函数
---@field public main_func fun(self: GameEvent) @ 事件的主函数
---@field public clear_func fun(self: GameEvent) @ 事件结束时执行的函数
---@field public extra_clear_funcs fun(self:GameEvent)[] @ 事件结束时执行的自定义函数列表
---@field public exit_func fun(self: GameEvent) @ 事件结束后执行的函数
---@field public extra_exit_funcs fun(self:GameEvent)[] @ 事件结束后执行的自定义函数
---@field public exec_ret boolean? @ exec函数的返回值可能不存在
---@field public interrupted boolean @ 事件是否是因为被中断而结束的,可能是防止事件或者被杀
---@field public killed boolean @ 事件因为终止一切结算而被中断(所谓的“被杀”)
local GameEvent = class("GameEvent")
---@type (fun(self: GameEvent): bool)[]
GameEvent.prepare_funcs = {}
---@type (fun(self: GameEvent): bool)[]
GameEvent.functions = {}
---@type (fun(self: GameEvent): bool)[]
GameEvent.cleaners = {}
---@type (fun(self: GameEvent): bool)[]
GameEvent.exit_funcs = {}
local function wrapCoFunc(f, ...)
if not f then return nil end
local args = {...}
return function() return f(table.unpack(args)) end
end
local dummyFunc = Util.DummyFunc
function GameEvent:initialize(event, ...)
self.id = -1
self.end_id = -1
self.room = RoomInstance
self.event = event
self.data = { ... }
self.prepare_func = GameEvent.prepare_funcs[event] or dummyFunc
self.main_func = wrapCoFunc(GameEvent.functions[event], self) or dummyFunc
self.clear_func = GameEvent.cleaners[event] or dummyFunc
self.extra_clear_funcs = Util.DummyTable
self.exit_func = GameEvent.exit_funcs[event] or dummyFunc
self.extra_exit_funcs = Util.DummyTable
self.interrupted = false
end
-- 静态函数实际定义在events/init.lua
function GameEvent:translate(id)
error('static')
end
function GameEvent:__tostring()
return string.format("<%s #%d>", GameEvent:translate(self.event), self.id)
end
function GameEvent:addCleaner(f)
if self.extra_clear_funcs == Util.DummyTable then
self.extra_clear_funcs = {}
end
table.insert(self.extra_clear_funcs, f)
end
function GameEvent:addExitFunc(f)
if self.extra_exit_funcs == Util.DummyTable then
self.extra_exit_funcs = {}
end
table.insert(self.extra_exit_funcs, f)
end
function GameEvent:prependExitFunc(f)
if self.extra_exit_funcs == Util.DummyTable then
self.extra_exit_funcs = {}
end
table.insert(self.extra_exit_funcs, 1, f)
end
function GameEvent:findParent(eventType, includeSelf)
if includeSelf and self.event == eventType then return self end
local e = self.parent
while e do
if e.event == eventType then return e end
e = e.parent
end
return nil
end
-- 找n个id介于from和to之间的事件。
local function bin_search(events, from, to, n, func)
local left = 1
local right = #events
local mid
local ret = {}
if from < events[1].id then
mid = 1
elseif from > events[right].id then
return ret
else
while true do
if left > right then return ret end
mid = (left + right) // 2
local id = events[mid].id
local id_left = mid == 1 and -math.huge or events[mid - 1].id
if from < id then
if from >= id_left then
break
end
right = mid - 1
else
left = mid + 1
end
end
end
for i = mid, #events do
local v = events[i]
if v.id <= to and func(v) then
table.insert(ret, v)
end
if #ret >= n then break end
end
return ret
end
-- 从某个区间中找出类型符合且符合func函数检测的至多n个事件。
---@param eventType integer @ 要查找的事件类型
---@param n integer @ 最多找多少个
---@param func fun(e: GameEvent): boolean? @ 过滤用的函数
---@param endEvent? GameEvent @ 区间终止点,默认为本事件结束
---@return GameEvent[] @ 找到的符合条件的所有事件最多n个但不保证有n个
function GameEvent:searchEvents(eventType, n, func, endEvent)
local logic = self.room.logic
local events = logic.event_recorder[eventType] or Util.DummyTable
local from = self.id
local to = endEvent and endEvent.id or self.end_id
if math.abs(to) == 1 then to = #logic.all_game_events end
n = n or 1
func = func or Util.TrueFunc
local ret
if #events < 6 then
ret = {}
for _, v in ipairs(events) do
if v.id >= from and v.id <= to and func(v) then
table.insert(ret, v)
end
if #ret >= n then break end
end
else
ret = bin_search(events, from, to, n, func)
end
return ret
end
function GameEvent:exec()
local room = self.room
local logic = room.logic
self.parent = logic:getCurrentEvent()
if self:prepare_func() then return true end
logic:pushEvent(self)
local co = coroutine.create(self.main_func)
self._co = co
coroutine.yield(self, "__newEvent")
Pcall(self.exit_func, self)
for _, f in ipairs(self.extra_exit_funcs) do
if type(f) == "function" then
Pcall(f, self)
end
end
return self.interrupted, self.exec_ret
end
function GameEvent:shutdown()
-- yield to self and break
coroutine.yield(self, "__breakEvent")
end
return GameEvent