862 lines
32 KiB
Lua
Raw Normal View History

2025-01-04 23:00:19 +08:00
---@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 ValidPawnBP_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;