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

862 lines
32 KiB
Lua
Raw Permalink 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.

---@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;