local Dir = "Script.Blueprint.SceneObj.Buff." local BuffManager1 = {}; ---@type table> 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;