local BuffAction_RespiratoryRegurgitation = { -- 以下参数信息可以通过manager的 GetBuffDefaultParam(BuffPath, ParamName)来获取 -- -- 默认颜色信息,非必要参数 BuffColor = {R = 0.97, G = 0.88, B = 0.1, A = 1.}; BuffIconPath = "默认Icon路径,非必要参数"; BuffParticlePath = "默认粒子路径,非必要参数"; BuffDesc = "呼吸回复"; -------------------------------------------------------------------------------- bInitBuff = false; LastDetectionTime = 0.; --- Tick 回复频率 DetectionFrequency = 5.; --- {PlayerKey = uint, BuffTag = string, LastHitTime: float, HitDelayExecution = float, RecoveryPerSecond = float}, ... PlayerParams = {}; --- PlayerKey = Time:float PlayerLastHitTime = {} } --- 必须包含ApplyBuff函数 ---@param BuffTag Any Buff的标签 ---@param ValidPawn UGCPlayerPawn* ---@param Args ... Any ---@return ApplySucceed:bool function BuffAction_RespiratoryRegurgitation:ApplyBuff(BuffTag, ValidPawn, InHitDelayExecution, InRecoveryPerSecond) -- Tick逻辑 if not self.bInitBuff then self.LastDetectionTime = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState) self.bInitBuff = true end -- Apply逻辑 if InHitDelayExecution < 0 then return false end ValidPawn.OnPostTakeDamage:Add(self.TargetPlayerTakeDamage, self) table.insert(self.PlayerParams, {PlayerKey = ValidPawn.PlayerKey, BuffTag = BuffTag, HitDelayExecution = InHitDelayExecution, RecoveryPerSecond = InRecoveryPerSecond}) return true end --- 可以包含RemoveBuff,若包含该函数则玩家应用该Buff时会保存Buff信息缓存,作为移除或者获取玩家当前Buff的备份信息 ---@param BuffTag Any Buff的标签 ---@param ValidPawn UGCPlayerPawn_C ---@param Args ... Any Args顺序必须与ApplyBuff顺序一致 function BuffAction_RespiratoryRegurgitation:RemoveBuff(BuffTag, ValidPawn, InHitDelayExecution, InRecoveryPerSecond) -- Remove逻辑 ValidPawn.OnPostTakeDamage:Remove(self.TargetPlayerTakeDamage, self) log_tree("[BuffAction_RespiratoryRegurgitation:RemoveBuff]", self.PlayerParams) for i = #self.PlayerParams, 1, -1 do if self.PlayerParams[i].PlayerKey == ValidPawn.PlayerKey and self.PlayerParams[i].BuffTag == BuffTag then table.remove(self.PlayerParams, i) -- self.PlayerParams[i] = nil end end log_tree("[BuffAction_RespiratoryRegurgitation:RemoveBuff] RemoveFinish", self.PlayerParams) end --- Tick函数 服务器客户端均会调用 function BuffAction_RespiratoryRegurgitation:Tick(DeltaTime) if self.bInitBuff then local NowTime = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState) local DetectionTime = self.LastDetectionTime + (1. / self.DetectionFrequency) --UGCLogSystem.Log("[BuffAction_RespiratoryRegurgitation:Tick] DeltaTime:%f, NowTime:%f, DetectionTime:%f", DeltaTime, NowTime, DetectionTime) if DetectionTime < NowTime then --UGCLogSystem.Log("[BuffAction_RespiratoryRegurgitation:Tick] EXE DetectionTime:%f", DetectionTime) self.LastDetectionTime = DetectionTime local RemovePlayer = {} for i, PlayerParam in pairs(self.PlayerParams) do local TargetPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PlayerParam.PlayerKey) if UE.IsValid(TargetPawn) then if self.PlayerLastHitTime[PlayerParam.PlayerKey] == nil then self.PlayerLastHitTime[PlayerParam.PlayerKey] = 0. end if NowTime - self.PlayerLastHitTime[PlayerParam.PlayerKey] > PlayerParam.HitDelayExecution then UGCPawnAttrSystem.SetHealth(TargetPawn, UGCPawnAttrSystem.GetHealth(TargetPawn) + PlayerParam.RecoveryPerSecond / self.DetectionFrequency) end else RemovePlayer[#RemovePlayer + 1] = PlayerParam.PlayerKey end end for i, v in pairs(RemovePlayer) do self:RemovePlayerKey(v) end end end end --- 当玩家死亡时会触发该函数,作用于以PlayerKey给玩家Buff的BuffAction,以防UGC的Pawn不删除机制所引发的Bug function BuffAction_RespiratoryRegurgitation:PlayerDeathCallBack(PlayerKey) self:RemovePlayerKey(PlayerKey) end function BuffAction_RespiratoryRegurgitation:RemovePlayerKey(PlayerKey) local TargetPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PlayerKey) if UE.IsValid(TargetPawn) then TargetPawn.OnPostTakeDamage:Remove(self.TargetPlayerTakeDamage, self) end for i = #self.PlayerParams, 1, -1 do if self.PlayerParams[i].PlayerKey == PlayerKey then table.remove(self.PlayerParams, i) -- self.PlayerParams[i] = nil end end end --- SelfRef:ASTExtraBaseCharacter,Damage:float,DamageEvent:FDamageEvent,EventInstigator:AController,DamageCauser:AActor) function BuffAction_RespiratoryRegurgitation:TargetPlayerTakeDamage(SelfRef, Damage, DamageEvent, EventInstigator, DamageCauser) UGCLogSystem.Log("[BuffAction_RespiratoryRegurgitation_TargetPlayerTakeDamage] OwnerKey:%d , DamagerKey:%d", SelfRef.PlayerKey, EventInstigator.PlayerKey) local NowTime = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState) self.PlayerLastHitTime[SelfRef.PlayerKey] = NowTime end return BuffAction_RespiratoryRegurgitation