862 lines
32 KiB
Lua
862 lines
32 KiB
Lua
---@class BP_BuffManager_C:AActor
|
||
---@field DefaultSceneRoot USceneComponent
|
||
--Edit Below--
|
||
---@type BP_BuffManager_C-
|
||
|
||
--require("Script.Blueprint.BUFF.BuffConfig")
|
||
|
||
BP_BuffManager = {
|
||
--- BuffActiveList最后一次获取的ID
|
||
BuffID = 1;
|
||
--- 已require且Check成功后的Buff {BuffType = BuffInst, ...}
|
||
BuffInsts = {};
|
||
--- 已激活的Buff {BuffID = {PlayerKey = uint32, BuffType = BuffConfig.EBuffType, BuffArgs = {...}, ActiveTime = float}}}
|
||
BuffActiveList = {};
|
||
--- 拥有Tick函数的BuffInst {BuffType, ...}
|
||
BuffInstWithTick = {};
|
||
--- 玩家死亡自动清除Buff缓存
|
||
bAutoClearPlayerBuffCache = true;
|
||
--- 已绑定玩家死亡后清除函数的PlayerPawn {PlayerKey = uint32, ... }
|
||
BoundPlayerDeath = {};
|
||
--- 延迟移除Buff的Handle, 用于自动移除及修改Buff存在时间 {BuffID = {Handle = TimeHandle, Duration = float, EnablingTime = float), }
|
||
BuffDurationHandles = {};
|
||
|
||
---缓存的 BuffType 数据
|
||
---@type table<EBuffType, table<int32, AActor>>
|
||
CachedInit = {};
|
||
|
||
-- 当前受到反馈的玩家 Key 的回调
|
||
BenefitCallback = nil;
|
||
};
|
||
|
||
function BP_BuffManager:GetReplicatedProperties()
|
||
return
|
||
"BuffInstWithTick"
|
||
--, { "CachedInit", "Lazy" }
|
||
end
|
||
|
||
--- Buff回调函数枚举
|
||
BP_BuffManager.ECallBack = {
|
||
---@param BuffTag any Buff的标签
|
||
---@param PlayerKey uint32
|
||
---@param BuffType uint32
|
||
---@param BuffID uint32
|
||
AddBuff = "CallBackAddBuff",
|
||
---@param PlayerKey uint32
|
||
---@param BuffType uint32
|
||
---@param BuffID uint32
|
||
RemoveBuff = "CallBackRemoveBuff",
|
||
---@param PlayerKey uint32
|
||
---@param BuffID uint32
|
||
---@param Duration float
|
||
---@param EnablingTime float
|
||
---@param SendTime float
|
||
BuffDurationUpdate = "CallBackBuffDurationUpdate",
|
||
---@param BuffID uint32
|
||
RemoveBuffDuration = "RemoveBuffDuration",
|
||
---@param PlayerKey uint32
|
||
ClearPlayerBuffCache = "ClearPlayerBuffCache",
|
||
}
|
||
|
||
|
||
--- 函数返回值枚举
|
||
BP_BuffManager.EResult = {
|
||
--- 成功
|
||
Succeed = "Succeed";
|
||
--- require 错误
|
||
RequireError = "RequireError";
|
||
--- Pawn无效
|
||
PlayerPawnNotValid = "PlayerPawnNotValid";
|
||
--- BuffID失效
|
||
BuffIDIsNotValid = "BuffIDIsNotValid";
|
||
--- BuffAction的ApplyBuff函数返回false,调用失败
|
||
ApplyBuffFailure = "ApplyBuffFailure";
|
||
--- 没有给Buff设置持续时间
|
||
NotSetBuffDuration = "NotSetBuffDuration";
|
||
--- BuffID与玩家PlayerKey不匹配
|
||
BuffIDMismatch = "BuffIDMismatch";
|
||
}
|
||
|
||
--- Buff检测枚举
|
||
BP_BuffManager.ECheck = {
|
||
--- Warn 应弹出警告
|
||
Warn = 1;
|
||
--- Error Buff无法使用执行
|
||
Error = 2;
|
||
}
|
||
|
||
--- BuffInst 检测表
|
||
BP_BuffManager.CheckBuffInst = {
|
||
--- 使用Buff ApplyBuff:function(ValidPawn:BP_PlayerPawn_C*, ...) --->ApplySucceed:bool
|
||
["ApplyBuff"] = {type = "function", CheckType = BP_BuffManager.ECheck.Error};
|
||
--- 移除Buff RemoveBuff:function(ValidPawn:BP_PlayerPawn_C*, ...)
|
||
["RemoveBuff"] = {type = "function", CheckType = BP_BuffManager.ECheck.Warn};
|
||
--- Tick函数 Tick:function(DeltaTime float)
|
||
["Tick"] = {type = "function", CheckType = BP_BuffManager.ECheck.Warn};
|
||
--- Buff描述 BuffDesc string
|
||
["BuffDesc"] = {type = "string" , CheckType = BP_BuffManager.ECheck.Warn};
|
||
--- Buff默认颜色 BuffColor table
|
||
["BuffColor"] = {type = "table" , CheckType = BP_BuffManager.ECheck.Warn};
|
||
--- Buff默认Icon路径 BuffIconPath string
|
||
["BuffIconPath"] = {type = "string" , CheckType = BP_BuffManager.ECheck.Warn};
|
||
--- Buff默认粒子路径 BuffParticlePath string
|
||
["BuffParticlePath"] = {type = "string" , CheckType = BP_BuffManager.ECheck.Warn};
|
||
--- 玩家死亡,回调,用于清除BuffAction实例中的PlayerKey缓存 PlayerDeathCallBack:function(PlayerKey uint32)
|
||
["PlayerDeathCallBack"] = {type = "function", CheckType = BP_BuffManager.ECheck.Warn}
|
||
}
|
||
--- BuffManager单例
|
||
BP_BuffManager.ManagerInst = nil
|
||
|
||
|
||
|
||
--- 获取单例BP_BuffManager
|
||
--- 若BP_BuffManager为nil则SpawnActor,但是Spawn后需要隔帧调用,否则可能出现无法添加成功的情况
|
||
---@return BP_BuffManager
|
||
function BP_BuffManager.GetBuffManager()
|
||
if BP_BuffManager.ManagerInst == nil then
|
||
local AllBuffManager = GameplayStatics.GetAllActorsOfClass(UGCGameSystem.GameState, BP_BuffManager.GetManagerClass(), {})
|
||
for k, v in pairs(AllBuffManager) do
|
||
BP_BuffManager.ManagerInst = v
|
||
break
|
||
end
|
||
if BP_BuffManager.ManagerInst == nil then
|
||
BP_BuffManager.ManagerInst = UGCGameSystem.SpawnActor(UGCGameSystem.GameState, BP_BuffManager.GetManagerClass(), VectorHelper.VectorZero(), VectorHelper.RotZero(), VectorHelper.ScaleOne())
|
||
--- BP_BuffManager.ManagerInst = ScriptGameplayStatics.SpawnActor(UGCGameSystem.GameState, BP_BuffManager.GetManagerClass(), VectorHelper.VectorZero(), VectorHelper.RotZero(), VectorHelper.ScaleOne());
|
||
end
|
||
end
|
||
return BP_BuffManager.ManagerInst
|
||
end
|
||
|
||
|
||
--- 通过Require路径获取Buff文件名
|
||
---@param requirePath string
|
||
function BP_BuffManager.GetBuffFileNameFromBuffRequirePath(requirePath)
|
||
local segments = {}
|
||
for segment in requirePath:gmatch("[^%.]+") do
|
||
table.insert(segments, segment)
|
||
end
|
||
|
||
local fileName = segments[#segments]
|
||
local fileNameWithoutExtension = fileName:match("(.+)%..+$") or fileName --- 去除后缀
|
||
return fileNameWithoutExtension
|
||
end
|
||
|
||
--- 获取BuffAction文件名(不含后缀),在BuffAction中调用
|
||
function BP_BuffManager.GetBuffFileName()
|
||
local info = debug.getinfo(2, "S")
|
||
local filePath = info.source:sub(2)
|
||
local fileName = filePath:match("^.+/(.+)$") or filePath:match("^.+\\(.+)$") --- 提取文件名部分
|
||
local fileNameWithoutExtension = fileName:match("(.+)%..+$") or fileName --- 去除后缀
|
||
return fileNameWithoutExtension
|
||
end
|
||
|
||
--- 获取BP_BuffManager Class
|
||
function BP_BuffManager.GetManagerClass()
|
||
if BP_BuffManager.ManagerClass == nil then
|
||
BP_BuffManager.ManagerClass = UE.LoadClass(UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/BUFF/BP_BuffManager.BP_BuffManager_C'))
|
||
end
|
||
return BP_BuffManager.ManagerClass
|
||
end
|
||
|
||
function BP_BuffManager.SendBuffEvent(CallBackType, ...)
|
||
UGCEventSystem.SendEvent(CallBackType, ...)
|
||
UGCSendRPCSystem.RPCEvent(nil, CallBackType, ...)
|
||
end
|
||
|
||
|
||
--- 获取唯一BuffID
|
||
---@return number
|
||
function BP_BuffManager:GetNewBuffID()
|
||
if self.BuffActiveList[self.BuffID] == nil then
|
||
return self.BuffID
|
||
end
|
||
while self.BuffActiveList[self.BuffID] ~= nil or self.BuffID == 0 do
|
||
self.BuffID = self.BuffID + 1
|
||
end
|
||
return self.BuffID
|
||
end
|
||
|
||
function BP_BuffManager:ReceiveBeginPlay()
|
||
|
||
end
|
||
|
||
function BP_BuffManager:Init(InCb)
|
||
-- 执行一下
|
||
UGCLogSystem.Log("[BP_BuffManager:Init] 执行")
|
||
for BuffType, Item in pairs(BuffConfig.BuffActionInfo) do
|
||
if Item.EnableInit == true then
|
||
-- 找到对应的 BuffInit
|
||
local InitStr = string.gsub(Item.Path, "Action", "Init")
|
||
local Init = require(InitStr);
|
||
if Init ~= nil then
|
||
UGCLogSystem.Log("[BP_BuffManager.Init] BuffType = %s", tostring(BuffType))
|
||
Init:Init(BuffType);
|
||
end
|
||
end
|
||
end
|
||
|
||
if InCb ~= nil then
|
||
UGCLogSystem.Log("[BP_BuffManager:Init] 开始执行, Callback = %s", tostring(InCb));
|
||
self.BenefitCallback = InCb;
|
||
end
|
||
end
|
||
|
||
-------------------------------------------- Apply Buff --------------------------------------------
|
||
|
||
--- 给玩家施加Buff
|
||
---@param BuffTag any Buff的标签
|
||
---@param PlayerKey uint32
|
||
---@param BuffType EBuffType
|
||
---@tparam ... any Buff所需要的参数
|
||
---@vararg any
|
||
---@return string,int BP_BuffManager.EResult, BuffID
|
||
function BP_BuffManager:AddBuff(BuffTag, PlayerKey, BuffType, ...)
|
||
UGCLogSystem.Log("[BP_BuffManager_AddBuff] BuffType:%s", tostring(BuffType))
|
||
--- 判断PlayerKey
|
||
local TargetPawnIsValid, TargetPawn = self:CheckPlayerKey(PlayerKey)
|
||
if not TargetPawnIsValid then
|
||
return BP_BuffManager.EResult.PlayerPawnNotValid
|
||
end
|
||
|
||
return self:AddBuffFromPlayerPawn(BuffTag, TargetPawn, BuffType, ...)
|
||
end
|
||
|
||
function BP_BuffManager:AddBuffFromPlayerPawn(BuffTag, TargetPawn, BuffType, ...)
|
||
if not UE.IsValid(TargetPawn) then
|
||
return BP_BuffManager.EResult.PlayerPawnNotValid
|
||
end
|
||
local PlayerKey = TargetPawn.PlayerKey
|
||
local BuffID = self:GetNewBuffID()
|
||
local BuffArgs = {...}
|
||
|
||
--- 检测Require Buff
|
||
local BuffInst = self:RequireBuffAction(BuffType)
|
||
if BuffInst == nil then
|
||
return BP_BuffManager.EResult.RequireError
|
||
end
|
||
|
||
if BuffInst['SetBuffType'] ~= nil and type(BuffInst['SetBuffType']) == 'function' then
|
||
BuffInst['SetBuffType'](BuffInst, BuffType);
|
||
end
|
||
|
||
--- Buff使用失败则返回
|
||
local Table = {...};
|
||
if not BuffInst:ApplyBuff(BuffTag, TargetPawn, ...) then
|
||
return BP_BuffManager.EResult.ApplyBuffFailure
|
||
end
|
||
|
||
local Players = BuffInst:GetBenefitPlayer();
|
||
|
||
if self.BenefitCallback ~= nil then
|
||
self.BenefitCallback(TargetPawn.PlayerKey, Players, BuffType);
|
||
end
|
||
|
||
--- 判断Buff是否需要Remove,不需要则不加入缓存列表
|
||
local bBuffHasRemoveFunc, _ = self:CheckBuffInstRemoveBuffFunc(BuffInst)
|
||
if bBuffHasRemoveFunc then
|
||
self.BuffActiveList[BuffID] = {BuffTag = BuffTag, PlayerKey = PlayerKey, BuffType = BuffType, BuffArgs = BuffArgs, ActiveTime = BP_BuffManager.GetNowTime()}
|
||
else
|
||
BuffID = nil
|
||
end
|
||
|
||
self:SpawnParticleToPlayPawn(TargetPawn.PlayerKey, Players, BuffType, true);
|
||
|
||
if not table.hasValue(self.BoundPlayerDeath, PlayerKey) then
|
||
self.BoundPlayerDeath[#self.BoundPlayerDeath + 1] = PlayerKey
|
||
self:BindPlayerDeath(TargetPawn)
|
||
end
|
||
|
||
BP_BuffManager.SendBuffEvent(BP_BuffManager.ECallBack.AddBuff, BuffTag, PlayerKey, BuffType, BuffID)
|
||
return BP_BuffManager.EResult.Succeed, BuffID
|
||
end
|
||
|
||
--- 开启自动清除死亡玩家的Buff缓存
|
||
---@param Enable:bool
|
||
function BP_BuffManager:SetAutoClearPlayerBuffCache(Enable)
|
||
if Enable ~= false or Enable ~= nil then
|
||
self.bAutoClearPlayerBuffCache = true
|
||
end
|
||
self.bAutoClearPlayerBuffCache = false
|
||
end
|
||
|
||
--- 绑定玩家死亡清除函数
|
||
---@param ValidPawn:BP_PlayerPawn_C
|
||
function BP_BuffManager:BindPlayerDeath(ValidPawn)
|
||
if self.bAutoClearPlayerBuffCache then
|
||
ValidPawn.OnDeath:Add(self.PlayerDeath, self)
|
||
end
|
||
end
|
||
|
||
|
||
---@param DeadCharacter:ASTExtraCharacter
|
||
---@param Killer:AController
|
||
---@param DamageCauser:AActor
|
||
---@param KillingHitInfo:FHitResult
|
||
---@param KillingHitImpulseDir:FVector
|
||
---@param KillingHitDamageTypeID int32
|
||
---@param DamageTypeClass:USTExtraDamageType
|
||
---@param IsHeadShotDamage:bool
|
||
function BP_BuffManager:PlayerDeath(DeadCharacter, Killer, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage)
|
||
local DeadPlayerKey = DeadCharacter.PlayerKey
|
||
UGCLogSystem.Log("[BP_BuffManager_PlayerDeath] DeadPlayerKey:%s", tostring(DeadPlayerKey))
|
||
|
||
if table.hasValue(self.BoundPlayerDeath, DeadPlayerKey) then
|
||
-- local OwnedBuffIDs = self:GetPlayerOwnedBuffs(DeadPlayerKey)
|
||
local OwnedBuffIDs = BP_BuffManager.BuffFilter(DeadPlayerKey)
|
||
local InstDoOnceCallBackFunc = {}
|
||
for _, BuffID in pairs(OwnedBuffIDs) do
|
||
local BuffType = self.BuffActiveList[BuffID].BuffType
|
||
local BuffInst = self:RequireBuffAction(BuffType)
|
||
if not table.hasValue(InstDoOnceCallBackFunc, BuffInst) then
|
||
InstDoOnceCallBackFunc[#InstDoOnceCallBackFunc] = BuffInst
|
||
if self:IndividualCheckPlayerDeathCallBackFunc(BuffInst) then
|
||
BuffInst:PlayerDeathCallBack(DeadPlayerKey)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
table.removeValue(self.BoundPlayerDeath, DeadPlayerKey, true)
|
||
self:ClearPlayerBuffCache(DeadPlayerKey)
|
||
UGCLogSystem.Log("[BP_BuffManager_PlayerDeath] Finish")
|
||
end
|
||
|
||
|
||
|
||
|
||
--- 设置Buff持续时间
|
||
---@param BuffID int32
|
||
---@param Duration float Duration <= 0 时,直接移除Buff
|
||
---@return int32 EResult
|
||
function BP_BuffManager:SetBuffDuration(BuffID, Duration)
|
||
if not self:CheckBuffID(BuffID) then
|
||
return BP_BuffManager.EResult.BuffIDIsNotValid
|
||
end
|
||
|
||
self:RemoveBuffDuration(BuffID)
|
||
---
|
||
if Duration <= 0 then
|
||
self:RemoveBuffFromBuffID(BuffID)
|
||
return BP_BuffManager.EResult.Succeed
|
||
end
|
||
|
||
local DurationHandle= UGCEventSystem.SetTimer(self, function ()
|
||
self:RemoveBuffFromBuffID(BuffID)
|
||
end, Duration);
|
||
|
||
local NowTime = BP_BuffManager.GetNowTime()
|
||
self.BuffDurationHandles[BuffID] = {Handle = DurationHandle, Duration = Duration, EnablingTime = NowTime}
|
||
BP_BuffManager.SendBuffEvent(BP_BuffManager.ECallBack.BuffDurationUpdate, BP_BuffManager.GetPlayerKeyOfTheBuffID(BuffID), BuffID, Duration, NowTime, NowTime)
|
||
|
||
return BP_BuffManager.EResult.Succeed
|
||
end
|
||
|
||
|
||
--- 添加Buff持续时间
|
||
---@param BuffID int32
|
||
---@param AddDuration float 可以为负值
|
||
---@return int32 EResult
|
||
function BP_BuffManager:AddBuffDuration(BuffID, AddDuration)
|
||
if not self:CheckBuffID(BuffID) then
|
||
return BP_BuffManager.EResult.BuffIDIsNotValid
|
||
end
|
||
|
||
log_tree("[BP_BuffManager_AddBuffDuration] 1", self.BuffDurationHandles)
|
||
|
||
--- BuffID未添加持续时间,自动为其添加
|
||
if self.BuffDurationHandles[BuffID] == nil then
|
||
return self:SetBuffDuration(BuffID, AddDuration)
|
||
end
|
||
|
||
UGCEventSystem.StopTimer(self.BuffDurationHandles[BuffID].Handle)
|
||
local NewDuration = AddDuration + self.BuffDurationHandles[BuffID].Duration
|
||
local NowTime = BP_BuffManager.GetNowTime()
|
||
local NeedDuration = NewDuration - (NowTime - self.BuffDurationHandles[BuffID].EnablingTime)
|
||
--- 若为减少Buff时间则判断是否达到移除时间
|
||
if NeedDuration <= 0 then
|
||
self:RemoveBuffFromBuffID(BuffID)
|
||
else
|
||
local DurationHandle= UGCEventSystem.SetTimer(
|
||
self,
|
||
function ()
|
||
self:RemoveBuffFromBuffID(BuffID)
|
||
end,
|
||
NeedDuration
|
||
)
|
||
self.BuffDurationHandles[BuffID].Handle = DurationHandle
|
||
self.BuffDurationHandles[BuffID].Duration = NewDuration
|
||
|
||
BP_BuffManager.SendBuffEvent(
|
||
BP_BuffManager.ECallBack.BuffDurationUpdate,
|
||
BP_BuffManager.GetPlayerKeyOfTheBuffID(BuffID),
|
||
BuffID,
|
||
self.BuffDurationHandles[BuffID].Duration,
|
||
self.BuffDurationHandles[BuffID].EnablingTime,
|
||
NowTime
|
||
)
|
||
|
||
end
|
||
|
||
log_tree("[BP_BuffManager_AddBuffDuration] 2", self.BuffDurationHandles)
|
||
|
||
return self.EResult.Succeed
|
||
end
|
||
|
||
--- 获取Buff持续时间
|
||
--- @return int32, float EResult, Duration
|
||
function BP_BuffManager:GetBuffDuration(BuffID)
|
||
if not self:CheckBuffID(BuffID) then
|
||
return BP_BuffManager.EResult.BuffIDIsNotValid, 0.
|
||
end
|
||
if self.BuffDurationHandles[BuffID] == nil then
|
||
return BP_BuffManager.EResult.NotSetBuffDuration, 0.
|
||
end
|
||
return BP_BuffManager.EResult.Succeed, self.BuffDurationHandles[BuffID].Duration
|
||
end
|
||
|
||
--- 获取Buff剩余持续时间
|
||
--- @return int, float EResult, RemainingDuration
|
||
function BP_BuffManager:GetBuffRemainingDuration(BuffID)
|
||
if not self:CheckBuffID(BuffID) then
|
||
return BP_BuffManager.EResult.BuffIDIsNotValid, 0.
|
||
end
|
||
if self.BuffDurationHandles[BuffID] == nil then
|
||
return BP_BuffManager.EResult.NotSetBuffDuration, 0.
|
||
end
|
||
local NowTime = BP_BuffManager.GetNowTime()
|
||
local EnablingTime = self.BuffDurationHandles[BuffID].EnablingTime
|
||
local Duration = self.BuffDurationHandles[BuffID].Duration
|
||
return BP_BuffManager.EResult.Succeed, Duration - (NowTime - EnablingTime)
|
||
end
|
||
|
||
--- 关闭自动移除Buff的延迟句柄及删除信息缓存
|
||
function BP_BuffManager:RemoveBuffDuration(BuffID)
|
||
if self.BuffDurationHandles[BuffID] then
|
||
UGCEventSystem.StopTimer(self.BuffDurationHandles[BuffID].Handle)
|
||
self.BuffDurationHandles[BuffID] = nil
|
||
UGCLogSystem.Log("[BP_BuffManager_RemoveBuffDuration] BuffDurationHandles[%d] Remove Succeed", BuffID)
|
||
BP_BuffManager.SendBuffEvent(BP_BuffManager.ECallBack.RemoveBuffDuration, BuffID)
|
||
|
||
else
|
||
UGCLogSystem.LogError("[BP_BuffManager_RemoveBuffDuration] BuffDurationHandles[%d] is nil", BuffID)
|
||
end
|
||
end
|
||
|
||
------------------------------------------ Apply Buff End ------------------------------------------
|
||
|
||
-------------------------------------------- Remove --------------------------------------------
|
||
|
||
--- 校验BuffID是否与PlayerKey匹配并移除该Buff
|
||
---@param BuffID int32
|
||
---@param PlayerKey uint32
|
||
function BP_BuffManager:CheckRemoveBuffFromBuffID(BuffID, PlayerKey)
|
||
if self:CheckBuffIDMatching(BuffID, PlayerKey) then
|
||
return self:RemoveBuffFromBuffID(BuffID)
|
||
end
|
||
return BP_BuffManager.EResult.BuffIDMismatch
|
||
end
|
||
|
||
--- 通过BuffID移除Buff
|
||
---@param BuffID int32
|
||
function BP_BuffManager:RemoveBuffFromBuffID(BuffID)
|
||
local ActiveBuffInfo = self.BuffActiveList[BuffID]
|
||
if ActiveBuffInfo == nil then
|
||
UGCLogSystem.LogError("[BP_BuffManager_RemoveBuffFromBuffID] ActiveBuffInfo is nil")
|
||
return BP_BuffManager.EResult.BuffIDIsNotValid
|
||
end
|
||
|
||
local PawnIsValid, ValidPlayerPawn = self:CheckPlayerKey(ActiveBuffInfo.PlayerKey)
|
||
if not PawnIsValid then
|
||
return BP_BuffManager.EResult.PlayerPawnNotValid
|
||
end
|
||
|
||
local BuffIsValid, BuffCacheData = self:CheckBuffID(BuffID)
|
||
if not BuffIsValid then
|
||
return BP_BuffManager.EResult.BuffIDIsNotValid
|
||
end
|
||
|
||
local BuffInst = self:RequireBuffAction(BuffCacheData.BuffType)
|
||
local bHasRemoveBuffFunc, RemoveBuffFunc = self:CheckBuffInstRemoveBuffFunc(BuffInst)
|
||
if bHasRemoveBuffFunc then
|
||
RemoveBuffFunc(BuffInst, BuffCacheData.BuffTag, ValidPlayerPawn, table.unpack(BuffCacheData.BuffArgs))
|
||
end
|
||
|
||
self:RemoveBuffDuration(BuffID)
|
||
|
||
self.BuffActiveList[BuffID] = nil
|
||
|
||
BP_BuffManager.SendBuffEvent(BP_BuffManager.ECallBack.RemoveBuff, ActiveBuffInfo.PlayerKey, BuffCacheData.BuffType, BuffID)
|
||
self:SpawnParticleToPlayPawn(ActiveBuffInfo.PlayerKey, nil, BuffCacheData.BuffType, false)
|
||
return BP_BuffManager.EResult.Succeed
|
||
end
|
||
|
||
--- 清除玩家Buff
|
||
---@param ValidPlayerPawn:BP_PlayerPawn_C*
|
||
---@param BuffID int
|
||
function BP_BuffManager:ClearPlayerOwnedBuff(PlayerKey)
|
||
-- local OwnedBuffIDs = self:GetPlayerOwnedBuffs(PlayerKey)
|
||
local OwnedBuffIDs = BP_BuffManager.BuffFilter(PlayerKey)
|
||
for _, BuffID in pairs(OwnedBuffIDs) do
|
||
self:RemoveBuffFromBuffID(BuffID)
|
||
end
|
||
end
|
||
|
||
--- 清除玩家Buff缓存
|
||
---@param PlayerKey uint32
|
||
function BP_BuffManager:ClearPlayerBuffCache(PlayerKey)
|
||
local RemoveBuffIDs = {}
|
||
for BuffID, BuffParam in pairs(self.BuffActiveList) do
|
||
if BuffParam.PlayerKey == PlayerKey then
|
||
RemoveBuffIDs[#RemoveBuffIDs + 1] = BuffID
|
||
end
|
||
end
|
||
|
||
for _, BuffID in pairs(RemoveBuffIDs) do
|
||
self:RemoveBuffDuration(BuffID)
|
||
self.BuffActiveList[BuffID] = nil
|
||
end
|
||
|
||
BP_BuffManager.SendBuffEvent(BP_BuffManager.ECallBack.ClearPlayerBuffCache, PlayerKey)
|
||
end
|
||
|
||
------------------------------------------ Remove End ------------------------------------------
|
||
|
||
function BP_BuffManager:ReceiveTick(DeltaTime)
|
||
self.SuperClass.ReceiveTick(self, DeltaTime);
|
||
|
||
for _, BuffType in pairs(self.BuffInstWithTick) do
|
||
local BuffInst = self:RequireBuffAction(BuffType)
|
||
BuffInst:Tick(DeltaTime)
|
||
end
|
||
end
|
||
|
||
|
||
-------------------------------------------- Get --------------------------------------------
|
||
|
||
--- 获取Buff拥有者
|
||
---@param BuffID int
|
||
---@return PlayerKey uint
|
||
function BP_BuffManager.GetBuffOwner(BuffID)
|
||
local BuffManager = BP_BuffManager.GetBuffManager()
|
||
if BuffManager then
|
||
if BuffManager.BuffActiveList[BuffID] then
|
||
return BuffManager.BuffActiveList[BuffID].PlayerKey
|
||
end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
|
||
|
||
--- Buff 过滤
|
||
---@param PlayerKey uint32
|
||
---@param BuffType EBuffType
|
||
---@param BuffTag any Buff的标签
|
||
---@return table<int> {BuffID int, ...} BuffIDs
|
||
function BP_BuffManager.BuffFilter(PlayerKey, BuffType, BuffTag)
|
||
local BuffManager = BP_BuffManager.GetBuffManager()
|
||
local ResetBuffIDs = {}
|
||
if BuffManager then
|
||
for BuffID, BuffParam in pairs(BuffManager.BuffActiveList) do
|
||
if (BuffParam.PlayerKey == PlayerKey or PlayerKey == nil)
|
||
and (BuffParam.BuffType == BuffType or BuffType == nil)
|
||
and (BuffParam.BuffTag == BuffType or BuffTag == nil)
|
||
then
|
||
ResetBuffIDs[#ResetBuffIDs + 1] = BuffID
|
||
end
|
||
end
|
||
end
|
||
return ResetBuffIDs
|
||
end
|
||
|
||
--- 通过BuffID获取其拥有者
|
||
---@param BuffID int
|
||
---@return PlayerKey uint32
|
||
function BP_BuffManager.GetPlayerKeyOfTheBuffID(BuffID)
|
||
local BuffManager = BP_BuffManager.GetBuffManager()
|
||
if BuffManager then
|
||
return (BuffManager.BuffActiveList[BuffID] ~= nil and BuffManager.BuffActiveList[BuffID].PlayerKey or -1)
|
||
end
|
||
return -1
|
||
end
|
||
|
||
--- 获得BuffPath
|
||
---@param BuffID int
|
||
---@return EBuffType BuffConfig.EBuffType
|
||
function BP_BuffManager.GetBuffTypeFromBuffID(BuffID)
|
||
local BuffManager = BP_BuffManager.GetBuffManager()
|
||
if BuffManager then
|
||
if BuffManager.BuffActiveList[BuffID] then
|
||
return BuffManager.BuffActiveList[BuffID].BuffType
|
||
end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
--- 获取BuffAction默认主题参数
|
||
---@param BuffType EBuffType
|
||
---@param ParamName string
|
||
function BP_BuffManager.GetBuffDefaultParam(BuffType, ParamName)
|
||
local ParamInfo = BP_BuffManager.CheckBuffInst[ParamName]
|
||
local BuffManager = BP_BuffManager.GetBuffManager()
|
||
if BuffManager then
|
||
if ParamInfo then
|
||
local BuffInst = BuffManager:RequireBuffAction(BuffType)
|
||
if BuffInst == nil then
|
||
UGCLogSystem.LogError("[BP_BuffManager_GetBuffDefaultParam] BuffInst is nil. BuffType:%s", tostring(BuffType))
|
||
return nil
|
||
end
|
||
if BuffInst[ParamName] == nil or type(BuffInst[ParamName]) ~= ParamInfo.type then
|
||
UGCLogSystem.LogError("[BP_BuffManager_GetBuffDefaultParam] %s is not %s. BuffType:%s", ParamName, ParamInfo.type, tostring(BuffType))
|
||
return nil
|
||
end
|
||
return BuffInst[ParamName]
|
||
else
|
||
UGCLogSystem.LogError("[BP_BuffManager_GetBuffDefaultParam] ParamInfo not have %s", tostring(ParamName))
|
||
return nil
|
||
end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
--- 获取当前时间
|
||
---@return float NowTime
|
||
function BP_BuffManager.GetNowTime()
|
||
return KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState)
|
||
end
|
||
|
||
--- 通过Manager定义的BuffActionID获取BuffPath
|
||
---@param BuffType EBuffType
|
||
---@return string BuffPath
|
||
function BP_BuffManager.GetBuffPathFromBuffType(BuffType)
|
||
return BuffConfig.BuffActionInfo[BuffType].Path
|
||
end
|
||
|
||
--- 通过BuffPath找BuffType 没有则返回 -1
|
||
---@param BuffPath string
|
||
function BP_BuffManager.GetBuffTypeFromBuffPath(BuffPath)
|
||
for k, v in pairs(BuffConfig.BuffActionInfo) do
|
||
if v.Path == BuffPath then
|
||
return k
|
||
end
|
||
end
|
||
return -1
|
||
end
|
||
|
||
--- 通过BuffName找BuffType 没有则返回 -1
|
||
---@param BuffName string
|
||
function BP_BuffManager.GetBuffTypeFromBuffName(BuffName)
|
||
for k, v in pairs(BuffConfig.BuffActionInfo) do
|
||
if v.Name == BuffName then
|
||
return k
|
||
end
|
||
end
|
||
return -1
|
||
end
|
||
|
||
|
||
|
||
|
||
------------------------------------------ Get End ------------------------------------------
|
||
|
||
-------------------------------------------- Check --------------------------------------------
|
||
|
||
--- 检测并返回Buff的RemoveBuff function
|
||
---@return bool, function
|
||
function BP_BuffManager:CheckBuffInstRemoveBuffFunc(BuffInst)
|
||
return
|
||
(BuffInst["RemoveBuff"] ~= nil and (type(BuffInst["RemoveBuff"]) == "function")),
|
||
BuffInst["RemoveBuff"]
|
||
end
|
||
|
||
--- 检查BuffID
|
||
---@return bool, table<PlayerKey, EBuffType> {PlayerKey = uint32, BuffType = BuffConfig.EBuffType, BuffArgs = {...}} Succeed, BuffActive
|
||
function BP_BuffManager:CheckBuffID(BuffID)
|
||
return (BuffID ~= nil and self.BuffActiveList[BuffID] ~= nil), self.BuffActiveList[BuffID]
|
||
end
|
||
|
||
--- 检查PlayerKey
|
||
---@return bool, BP_PlayerPawn_C*
|
||
function BP_BuffManager:CheckPlayerKey(PlayerKey)
|
||
local TargetPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PlayerKey)
|
||
if not UE.IsValid(TargetPawn) then
|
||
self:ClearPlayerBuffCache(PlayerKey)
|
||
return false, nil
|
||
end
|
||
return true, TargetPawn
|
||
end
|
||
|
||
--- 单独检测BuffInst是否含有Tick函数
|
||
function BP_BuffManager:IndividualCheckTickFunc(BuffInst)
|
||
if BuffInst["Tick"] == nil or type(BuffInst["Tick"]) ~= "function" then
|
||
return false
|
||
end
|
||
return true
|
||
end
|
||
|
||
--- 单独检测BuffInst是否含有PlayerDeathCallBack函数
|
||
function BP_BuffManager:IndividualCheckPlayerDeathCallBackFunc(BuffInst)
|
||
if BuffInst["PlayerDeathCallBack"] == nil or type(BuffInst["PlayerDeathCallBack"]) ~= "function" then
|
||
return false
|
||
end
|
||
return true
|
||
end
|
||
|
||
--- 检测BuffID是否与玩家PlayerKey匹配
|
||
---@param BuffID int32
|
||
---@param PlayerKey uint32
|
||
function BP_BuffManager:CheckBuffIDMatching(BuffID, PlayerKey)
|
||
local BuffIDIsValid, BuffData = self:CheckBuffID(BuffID)
|
||
|
||
if not BuffIDIsValid then
|
||
return false
|
||
end
|
||
|
||
if BuffData.PlayerKey == PlayerKey then
|
||
return true
|
||
end
|
||
|
||
return false
|
||
end
|
||
|
||
------------------------------------------ Check End ------------------------------------------
|
||
|
||
|
||
|
||
--- Require并检测BuffAction
|
||
---@return BuffAction
|
||
function BP_BuffManager:RequireBuffAction(BuffType)
|
||
if self.BuffInsts[BuffType] == nil then
|
||
local BuffPath = BP_BuffManager.GetBuffPathFromBuffType(BuffType)
|
||
if BuffPath == nil then
|
||
return nil
|
||
end
|
||
UGCLogSystem.Log("[BP_BuffManager_RequireBuffAction] RequireBuffPath:%s ", BuffPath)
|
||
local BuffInst = require(BuffPath)
|
||
if BuffInst == nil then
|
||
UGCLogSystem.LogError("[BP_BuffManager_RequireBuffAction] Require Error")
|
||
return nil
|
||
end
|
||
|
||
for PropertyName, CheckTemp in pairs(BP_BuffManager.CheckBuffInst) do
|
||
if BuffInst[PropertyName] == nil then
|
||
if CheckTemp.CheckType == BP_BuffManager.ECheck.Error then
|
||
UGCLogSystem.LogError("[BP_BuffManager_RequireBuffAction] Error BuffInst 没有%s, type:%s", PropertyName, CheckTemp.type)
|
||
return nil
|
||
elseif CheckTemp.CheckType == BP_BuffManager.ECheck.Warn then
|
||
UGCLogSystem.Log("[BP_BuffManager_RequireBuffAction] Warning BuffInst 没有%s, type:%s", PropertyName, CheckTemp.type)
|
||
end
|
||
else
|
||
if type(BuffInst[PropertyName]) ~= CheckTemp.type then
|
||
if CheckTemp.CheckType == BP_BuffManager.ECheck.Error then
|
||
UGCLogSystem.LogError("[BP_BuffManager_RequireBuffAction] Error BuffInst %s类型不匹配, type:%s", PropertyName, CheckTemp.type)
|
||
return nil
|
||
elseif CheckTemp.CheckType == BP_BuffManager.ECheck.Warn then
|
||
UGCLogSystem.Log("[BP_BuffManager_RequireBuffAction] Warning BuffInst %s类型不匹配 type:%s", PropertyName, CheckTemp.type)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
self.BuffInsts[BuffType] = BuffInst
|
||
|
||
if self:IndividualCheckTickFunc(self.BuffInsts[BuffType]) then
|
||
self.BuffInstWithTick[#self.BuffInstWithTick + 1] = BuffType
|
||
DOREPONCE(self, "BuffInstWithTick")
|
||
end
|
||
|
||
end
|
||
|
||
return self.BuffInsts[BuffType]
|
||
end
|
||
|
||
|
||
|
||
--- 服务器客户端均可调,触发BuffAction的TargetFuncName
|
||
---@param TargetPlayerKey:[为uint32则单独发送], [为table{uint32, ...}则多个发送], [为nil则广播发送]. 若客户端调用则无视该参数
|
||
---@param BuffName string Buff文件名,BuffAction代码中可使用BP_BuffManager.GetBuffFileName()获取
|
||
---@param TargetFuncName string 目标BuffAction的函数名
|
||
---@param ...:Args TargetFunc的输入参数
|
||
function BP_BuffManager:BuffNotifyRPC(TargetPlayerKey, BuffName, TargetFuncName, ...)
|
||
|
||
UGCLogSystem.Log("[BP_BuffManager_BuffNotifyRPC] BuffName:%s", BuffName)
|
||
|
||
local BuffType = BP_BuffManager.GetBuffTypeFromBuffName(BuffName)
|
||
if BuffType < 0 then
|
||
UGCLogSystem.LogError("[BP_BuffManager_BuffNotifyRPC] BuffType < 0", tostring(BuffName))
|
||
return
|
||
end
|
||
UGCLogSystem.Log("[BP_BuffManager_BuffNotifyRPC] BuffType:%d, FuncName:%s", BuffType, TargetFuncName)
|
||
|
||
UGCSendRPCSystem.ActorRPCNotify(TargetPlayerKey, self, "BuffRPC", BuffType, TargetFuncName, ...)
|
||
|
||
end
|
||
|
||
|
||
function BP_BuffManager:BuffRPC(BuffType, TargetFuncName, ...)
|
||
UGCLogSystem.Log("[BP_BuffManager_BuffRPC] BuffType:%d, FuncName:%s", BuffType, TargetFuncName)
|
||
local BuffInst = self:RequireBuffAction(BuffType)
|
||
if BuffInst then
|
||
local BuffRPCFunc = BuffInst[TargetFuncName]
|
||
if BuffRPCFunc ~= nil then
|
||
if type(BuffRPCFunc) ~= "function" then
|
||
UGCLogSystem.LogError("[BP_BuffManager_BuffRPC] BuffRPCFunc TypeError:%s", type(BuffRPCFunc))
|
||
else
|
||
BuffRPCFunc(BuffInst, ...)
|
||
end
|
||
else
|
||
UGCLogSystem.LogError("[BP_BuffManager_BuffRPC] BuffRPCFunc is nil")
|
||
end
|
||
else
|
||
UGCLogSystem.LogError("[BP_BuffManager_BuffRPC] BuffInst is nil, BuffType Type:%s, BuffType:%s", type(BuffType), tostring(BuffType))
|
||
end
|
||
end
|
||
|
||
----------------------------- RPC -----------------------------
|
||
|
||
--- 广播到玩家脚下生成粒子
|
||
---@param PlayerKey PlayerKey 目标玩家
|
||
---@param BuffType EBuffType 粒子路径
|
||
function BP_BuffManager:SpawnParticleToPlayPawn(PlayerKey, BenefitPlayers, BuffType, IsShow)
|
||
if UGCGameSystem.IsServer() then
|
||
UGCSendRPCSystem.ActorRPCNotify(nil, self, "MulticastRPC_SpawnParticleAttachPlayer", PlayerKey, BenefitPlayers, BuffType, IsShow);
|
||
else
|
||
self:MulticastRPC_SpawnParticleAttachPlayer(PlayerKey, BenefitPlayers, BuffType, IsShow);
|
||
end
|
||
end
|
||
|
||
---@type table<BuffID, >
|
||
BP_BuffManager.CachedParticle = {}
|
||
|
||
--- 广播到客户端,在玩家脚下生成粒子
|
||
function BP_BuffManager:MulticastRPC_SpawnParticleAttachPlayer(PlayerKey, BenefitPlayers, BuffType, IsShow)
|
||
UGCLogSystem.LogTree(string.format("[BP_BuffManager:MulticastRPC_SpawnParticleAttachPlayer] BenefitPlayers = "), BenefitPlayers);
|
||
if BenefitPlayers == nil then return; end
|
||
local ParticlePath = BuffConfig.BuffInfo[BuffType].ParticlePath;
|
||
if table.isEmpty(self.ParticleTemplateList) then self.ParticleTemplateList = {}; end
|
||
if self.ParticleTemplateList[ParticlePath] then
|
||
for i, v in pairs(BenefitPlayers) do
|
||
local TargetPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(v);
|
||
if TargetPawn and UE.IsValid(TargetPawn) then
|
||
GameplayStatics.SpawnEmitterAttached(self.ParticleTemplateList[ParticlePath], TargetPawn.Mesh, "", VectorHelper.VectorZero(), VectorHelper.RotZero(), VectorHelper.ScaleOne(), EAttachLocation.SnapToTarget, false)
|
||
end
|
||
end
|
||
else
|
||
UE.AsyncLoadObject(ParticlePath, function(TargetObject)
|
||
self.ParticleTemplateList[ParticlePath] = TargetObject;
|
||
for i, v in pairs(BenefitPlayers) do
|
||
local TargetPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(v);
|
||
GameplayStatics.SpawnEmitterAttached(TargetObject, TargetPawn.Mesh, "", VectorHelper.VectorZero(), VectorHelper.RotZero(), VectorHelper.ScaleOne(), EAttachLocation.SnapToTarget, false)
|
||
end
|
||
end)
|
||
end
|
||
end
|
||
|
||
--------------------------- RPC End ---------------------------
|
||
|
||
|
||
function BP_BuffManager:GetAvailableServerRPCs()
|
||
return
|
||
-- "BuffRPC"
|
||
end
|
||
|
||
return BP_BuffManager; |