2025-01-04 23:00:19 +08:00

365 lines
12 KiB
Lua
Raw 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.

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;