365 lines
12 KiB
Lua
365 lines
12 KiB
Lua
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] BuffType = %s, Params =", tostring(InBuffType)), Params)
|
||
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 o.Emitter and UE.IsValid(o.Emitter) then
|
||
o.Emitter:SetHiddenInGame(true, true);
|
||
o.Emitter:K2_DestroyComponent(o.Emitter);
|
||
o.Emitter = nil;
|
||
end
|
||
end
|
||
Item['SpawnEmitterAttached'] = function(o, Pawn, Offset)
|
||
o:RemoveParticle();
|
||
o.Emitter = UE.SpawnEmitterAttached(ObjectPath[o.Particle], Pawn, Offset);
|
||
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, ...)
|
||
local BuffItem = self:Get(InPlayerKey, InBuffType);
|
||
if 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)
|
||
if self.Buffs[InPlayerKey] == nil then return; end
|
||
for BuffType, BuffItem in pairs(self.Buffs[InPlayerKey]) do
|
||
self:Remove(InPlayerKey, BuffType);
|
||
self:Clear(InPlayerKey, BuffType);
|
||
end
|
||
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, ...)
|
||
UGCLogSystem.Log("[BuffManager1:SendRPC] 执行")
|
||
if IsServer then
|
||
UGCLogSystem.Log("[BuffManager1:SendRPC] 执行函数:%s", InFuncName);
|
||
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
|
||
|
||
if not UE_SERVER then
|
||
--function BuffManager1:ChangeBuffIcon(InType, Image)
|
||
--
|
||
--end
|
||
end
|
||
|
||
return BuffManager1; |