367 lines
12 KiB
Lua
Raw Normal View History

2025-01-04 23:00:19 +08:00
local Dir = "Script.Blueprint.SceneObj.Buff."
local BuffManager1 = {};
---@type table<PlayerKey, table<EBuffType, CustomBuffItem>>
BuffManager1.Buffs = {};
BuffManager1.PreScript = Dir .. "Script.Buff_";
BuffManager1.Inits = {}; -- 初始化脚本存放地点
BuffManager1.BuffTimes = {}; -- 初始化脚本存放地点
--- 初始化函数,
function BuffManager1:Init(InOwner)
-- 检查是否需要初始化操作,如果需要就在此初始化,比如呼吸回血
self.Owner = InOwner;
require('Script.Blueprint.SceneObj.Buff.BuffConfig')
for i, v in pairs(BuffConfig) do
if v.InitScript ~= nil then
local Init = require(Dir .. 'Script.Init.BuffInit_' .. v.InitScript);
self:SetParams(Init, i);
self.Inits[i] = Init;
table.func(Init, "Init", InOwner);
end
end
GlobalTickTool:AddTick(self, self.OnTick);
UGCLogSystem.Log("[BuffManager1:Init] 初始化成功")
return true;
end
function BuffManager1:SetParams(InItem, InBuffType)
if not table.isEmpty(BuffConfig[InBuffType].Params) then
for i, v in pairs(BuffConfig[InBuffType].Params) do
InItem[i] = v; -- 拷贝一份
end
end
InItem.BuffType = InBuffType;
end
--- 添加 BUFF
function BuffManager1:Add(InPlayerKey, InBuffType, ...)
local Params = { ... };
-- 查看里面有什么东西
UGCLogSystem.LogTree(string.format("[BuffManager1:Add] Params ="), Params)
if InBuffType == nil then return ; end
assert(BuffConfig[InBuffType] ~= nil);
local ServerTime = UE.GetServerTime();
-- 服务器需要验证,查看玩家是否包含此 Buff
local BuffItem = self:Get(InPlayerKey, InBuffType);
if IsServer then
if BuffItem then
if BuffItem.State == EBuffState.Cooling then
return false;
elseif BuffItem.State == EBuffState.Using then
return self:AddStack(InPlayerKey, InBuffType, ...);
end
end
end
-- 添加一个
local Item = nil;
if BuffItem then
Item = BuffItem;
else
local ScriptBase = require(self.PreScript .. BuffConfig[InBuffType].Script);
assert(ScriptBase ~= nil)
if table.hasFunc(ScriptBase, 'new') then
Item = table.func(ScriptBase, "new", InPlayerKey, ...)
else
Item = setmetatable({}, { __index = ScriptBase, __metatable = ScriptBase });
end
assert(Item ~= nil);
self:SetParams(Item, InBuffType);
-- 初始化操作
table.func(Item, "Init");
-- 在客户端生成
local Continue = BuffConfig[InBuffType].Continue
if Continue == nil then Continue = 0; end
Item.Continue = Continue;
Item.PlayerKey = InPlayerKey;
local Cooldown = BuffConfig[InBuffType].Cooldown;
if Cooldown == nil then Cooldown = 0; end
Item.Cooldown = Cooldown;
Item.OwnerManager = self;
Item.BuffType = InBuffType;
if not table.hasFunc(Item, "GetInit") then
Item["GetInit"] = function(o) return o.OwnerManager:GetInit(o.BuffType); end
end
if self.Buffs[InPlayerKey] == nil then self.Buffs[InPlayerKey] = {}; end
self.Buffs[InPlayerKey][InBuffType] = Item;
Item.Stack = 0;
Item.BuffStackTime = {};
end
Item.State = EBuffState.None;
-- 同步过去
if IsServer then
self:SendRPC("Add", InPlayerKey, InBuffType, ...); -- 获取服务器时间
if Item.Continue < 0 or BuffConfig[InBuffType].bAuto then self:ApplyOne(InPlayerKey, InBuffType, ...) end
else
Item.Particle = BuffConfig[InBuffType].ClientInfo.Particle;
Item['RemoveParticle'] = function(o)
if type(o.Emitter) == 'table' then
for i, Emitter in pairs(o.Emitter) do
if Emitter and UE.IsValid(Emitter) then
Emitter:SetHiddenInGame(true, true);
Emitter:K2_DestroyComponent(Emitter);
end
end
o.Emitter = {};
elseif type(o.Emitter) ~= 'nil' then
if o.Emitter and UE.IsValid(o.Emitter) then
o.Emitter:SetHiddenInGame(true, true);
o.Emitter:K2_DestroyComponent(o.Emitter);
o.Emitter = nil;
end
end
end
Item['SpawnEmitterAttached'] = function(o, Pawn, Offset)
o:RemoveParticle();
local Emitter = UE.SpawnEmitterAttached(ObjectPath[o.Particle], Pawn, Offset);
return Emitter
end
Item['SpawnEmitterAtLocation'] = function(o, Location)
o:RemoveParticle();
o.Emitter = UE.SpawnEmitterAtLocation(ObjectPath[o.Particle], Location);
end
end
return true;
end
--- 只有正在执行的时候可以添加,否则不可以添加
function BuffManager1:AddStack(InPlayerKey, InBuffType, ...)
return false;
--local BuffItem = self:Get(InPlayerKey, InBuffType);
--if BuffItem.Stack == nil or BuffItem.Stack >= BuffConfig[BuffItem.BuffType].MaxStack then return false, EBuffErrorType.OverStack; end
--BuffItem.Stack = BuffItem.Stack + 1;
--table.insert(BuffItem.BuffStackTime, UE.GetServerTime() + self:GetBuffContinue(InBuffType));
--table.func(BuffItem, "AddStack", ...);-- 可以直接拿到 Stack 进行使用
--if IsServer then
-- self:SendRPC("AddStack", InPlayerKey, InBuffType, ...);
--end
--return true;
end
--- 执行玩家身上所有的 BUFF
function BuffManager1:Apply(InPlayerKey, ...)
-- 查看是否有 Buff
if table.isEmpty(self.Buffs[InPlayerKey]) then return false; end
self:PrintBuff("Apply")
local ServerTime = UE.GetServerTime();
local Ret = false;
for BuffType, BuffItem in pairs(self.Buffs[InPlayerKey]) do
if (self:GetBuffContinue(BuffType) < 0) then
UGCLogSystem.LogError("[BuffManager1:Apply] [WARNING] 在执行一个永久执行的 Buff%s", TableHelper.printEnum(EBuffState, BuffType));
end
-- 只要有一个 true 就是 true
if self:DoApply(InPlayerKey, BuffType, ...) then Ret = true; end
end
if IsServer then
self:SendRPC("Apply", InPlayerKey, ...);
end
return Ret;
end
function BuffManager1:DoApply(InPlayerKey, InBuffType, ...)
local BuffItem = self:Get(InPlayerKey, InBuffType);
if BuffItem == nil then return false; end
local HitType = BuffConfig[InBuffType].HitType;
UGCLogSystem.Log("[BuffManager1:DoApply] State = %s", TableHelper.printEnum(EBuffState, BuffItem.State));
if BuffItem.State ~= EBuffState.Cooling then
local Params = {};
if HitType & EBuffHitType.Self ~= 0 then
local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(InPlayerKey);
if UE.IsValidPawn(Pawn) then
table.insert(Params, Pawn);
end
end
if HitType & EBuffHitType.Location ~= 0 or HitType & EBuffHitType.Pawn ~= 0 then
local Param = { ... };
if not table.isEmpty(Param) then
table.insert(Params, ...);
end
end
if HitType & EBuffHitType.AllEnemy ~= 0 then
UE.ForeachEnemyTeam(InPlayerKey, function(Pawn)
table.insert(Params, Pawn);
end)
end
if HitType & EBuffHitType.AllFriend ~= 0 then
UE.ForeachSelfTeam(InPlayerKey, function(Pawn)
table.insert(Params, Pawn);
end, true);
end
local Success = false;
if BuffItem.State == EBuffState.None then
BuffItem.Params = Params;
Success = BuffItem:AddBuff(table.unpackTable(Params));
if BuffItem.Continue >= 0 then
table.insert(BuffItem.BuffStackTime, UE.GetServerTime() + self:GetBuffContinue(InBuffType));
end
else
Success = self:AddStack(InPlayerKey, InBuffType, table.unpackTable(Params));
end
BuffItem.State = EBuffState.Using;
BuffItem.Stack = BuffItem.Stack + 1;
if IsServer then
else
--if BuffConfig[InBuffType]. then end
end
return Success;
end
return false;
end
function BuffManager1:ApplyOne(InPlayerKey, InBuffType, ...)
self:PrintBuff("ApplyOne")
if IsServer then
self:SendRPC("ApplyOne", InPlayerKey, InBuffType, ...);
end
return self:DoApply(InPlayerKey, InBuffType, ...)
end
function BuffManager1:OnTick(dt, st)
for PlayerKey, PlayerList in pairs(self.Buffs) do
for BuffType, BuffItem in pairs(PlayerList) do
table.func(BuffItem, "Tick", dt, st);
if IsServer then
local StackTime = BuffItem.BuffStackTime
if (not table.isEmpty(StackTime)) then
-- 前多少个移除
local RemoveIndex = 0;
for i = 1, #StackTime do
if StackTime[i] <= st then
RemoveIndex = i;
break ;
end
end
if RemoveIndex > 0 then
UGCLogSystem.LogTree(string.format("[BuffManager1:OnTick] StackTime 111"), StackTime);
for i = 1, RemoveIndex do
table.remove(StackTime, 1);
BuffItem.Stack = BuffItem.Stack - 1;
table.func(BuffItem, "RemoveStack");
end
UGCLogSystem.LogTree(string.format("[BuffManager1:OnTick] StackTime 222"), StackTime);
end
if table.isEmpty(BuffItem.BuffStackTime) and BuffItem.State == EBuffState.Using and (self:GetBuffContinue(BuffType) >= 0) then
-- 执行移除
UGCLogSystem.LogTree(string.format("[BuffManager1:OnTick] StackTime 333"), StackTime);
self:Remove(PlayerKey, BuffType);
end
end
end
end
end
end
function BuffManager1:Has(InPlayerKey, InBuffType)
local BuffItem = self:Get(InPlayerKey, InBuffType);
return BuffItem ~= nil;
end
function BuffManager1:CanAdd(InPlayerKey, InBuffType)
local BuffItem = self:Get(InPlayerKey, InBuffType);
if BuffItem == nil then return true end
return BuffItem.State ~= EBuffState.Cooling;
end
--- 移除 Buff
function BuffManager1:Remove(InPlayerKey, InBuffType, ...)
UGCLogSystem.Log("[BuffManager1:Remove] BuffType = %s", TableHelper.printEnum(EBuffType, InBuffType));
if self.Buffs[InPlayerKey] == nil then return ; end
self:PrintBuff("Remove");
local Params = { ... };
local BuffItem = self.Buffs[InPlayerKey][InBuffType]
if BuffItem then
table.func(BuffItem, "RemoveBuff", table.unpackTable(BuffItem.Params));
BuffItem.State = EBuffState.Cooling; -- 延迟中
end
if IsServer then self:SendRPC("Remove", InPlayerKey, InBuffType, ...); end
local Cooldown = BuffItem.Cooldown;
if Cooldown == nil then Cooldown = 0; end
UGCLogSystem.Log("[BuffManager1:Remove] Cooldown = %f", Cooldown)
if Cooldown >= 0 then
GlobalTickTool:AddTick(self, function() end, 0, nil, Cooldown, function(o)
o:Reset(InPlayerKey, InBuffType, table.unpackTable(Params)); -- 如果完全不想要的话,可以直接 Clear
end);
end
end
function BuffManager1:RemoveAll(InPlayerKey)
end
--- 清除这个
function BuffManager1:Clear(InPlayerKey, InBuffType, ...)
UGCLogSystem.Log("[BuffManager1:Clear] InBuffType = %s", TableHelper.printEnum(EBuffType, InBuffType));
if self.Buffs[InPlayerKey] == nil then return ; end
local BuffItem = self.Buffs[InPlayerKey][InBuffType]
if BuffItem then
table.func(BuffItem, "Clear", InPlayerKey, ...);
BuffItem.State = EBuffState.None; -- 设置为空
end
if IsServer then
self:SendRPC("Clear", InPlayerKey, InBuffType, ...);
end
self.Buffs[InPlayerKey][InBuffType] = nil;
end
function BuffManager1:Reset(InPlayerKey, InBuffType, ...)
self:PrintBuff("Reset")
if self.Buffs[InPlayerKey] == nil then return ; end
local BuffItem = self.Buffs[InPlayerKey][InBuffType];
if BuffItem then
table.func(BuffItem, "Reset", InPlayerKey, ...)
BuffItem.State = EBuffState.None;
end
if IsServer then
self:SendRPC("Reset", InPlayerKey, InBuffType, ...);
end
if BuffConfig[InBuffType].bAutoDestroy then
self.Buffs[InPlayerKey][InBuffType] = nil;
end
end
function BuffManager1:PrintBuff(fmt, ...)
UGCLogSystem.Log("[BuffManager1:PrintBuff] [%0.2f]" .. fmt, UE.GetServerTime(), ...)
end
function BuffManager1:GetInit(InBuffType)
return self.Inits[InBuffType];
end
--- 获取 BuffItem
---@param InPlayerKey PlayerKey
---@param InBuffType EBuffType
function BuffManager1:Get(InPlayerKey, InBuffType)
if self.Buffs[InPlayerKey] == nil then return nil; end
return self.Buffs[InPlayerKey][InBuffType];
end
function BuffManager1:SendRPC(InFuncName, InPlayerKey, InBuffType, ...)
if IsServer then
UnrealNetwork.CallUnrealRPC_Multicast(self.Owner, "SendBuffRPC", InFuncName, InPlayerKey, InBuffType, ...);
else
-- 最好不要使用 客户端 的,一般情况下也用不到
UnrealNetwork.CallUnrealRPC(LocalPlayerController, self.Owner, "SendBuffRPC", InFuncName, InPlayerKey, InBuffType, ...);
end
end
function BuffManager1:GetBuffContinue(InBuffType)
local Continue = BuffConfig[InBuffType].Continue
if Continue == nil then return 0; end
return Continue;
end
function BuffManager1:PrintBuffs()
UGCLogSystem.LogTree(string.format("[BuffManager1:PrintBuffs] Buffs ="), self.Buffs)
end
function BuffManager1:IsBuffActive(InBuffType)
local Config = BuffConfig[InBuffType]
if Config then
return not Config.bAuto
end
return false
end
return BuffManager1;