---@class BP_PlayerPawn_C:BP_UGCPlayerPawn_C ---@field BreachWidget UWidgetComponent ---@field ParticleSystem UParticleSystemComponent ---@field CameraSocket USceneComponent ---@field WeaponActorSocket USceneComponent ---@field WeaponParticleArray TMap:TEnumAsByte,UParticleSystem --Edit Below-- UGCGameSystem.UGCRequire('Script.Common.ue_enum_custom') UGCGameSystem.UGCRequire('Script.Common.ue_struct_custom') UGCGameSystem.UGCRequire('Script.Global.Global') local BP_PlayerPawn = { IsRunOnServer = false, WeaponActor = nil, IsInArena = false, --是否在场内 IsInTrueDamage = false, --是否在真实伤害状态 DashDuration = -1, --冲刺持续时间 CachedCharacterMovementGravityScale = 1.5, --缓存玩家重力参数 IsDashTo = false, --冲刺状态开关 LaunchCharacterForce = 10000, --冲刺力度 决定要冲刺多远 LaunchDir = nil, --冲刺方向 EnergyData = { Max = 0, Cur = 0 }, --能量值(为了同一帧同步所以合并) bHasApplyedAttribute = false, --是否已有初始属性 AttributeUpdateInterval = 0, --属性更新计时器 bCanBeControlledByMonsters = true, --可被怪物控制 WeaponParticles = {}, --武器特效 BossAttackCount = 0, --Boss被攻击次数(用作播放特效) bIsAlive = true, --玩家是否活着 SkillSystemComponent = nil, --技能系统 TestTimerHandler = nil; ItemActorClass = nil, }; BP_PlayerPawn.OnReceiveDamageDelegate = Delegate.New() BP_PlayerPawn.OnWeaponSpawnedDelegate = Delegate.New() --设置同步的属性 function BP_PlayerPawn:GetReplicatedProperties() return "WeaponActor", "EnergyData", "BossAttackCount", "IsInArena" end function BP_PlayerPawn:GetAvailableServerRPCs() return -- "DrawDebugSphere", -- "DrawDebugLine", -- "DrawDebugBox", -- "Client_MulticastRPC_PlaySkillEffect", -- "Client_MulticastRPC_PlayEffect", -- "Client_MulticastRPC_PlayDirectionalEffect", -- "Client_MulticastRPC_PlayEffectAtLocation", -- "Client_MulticastRPC_RemoveSkillEffect", -- "Client_MulticastRPC_RemoveAllSkillEffect" end function BP_PlayerPawn:ReceiveBeginPlay() BP_PlayerPawn.SuperClass.ReceiveBeginPlay(self) self.IsRunOnServer = UGCGameSystem.IsServer() --禁止掉落伤害 self.bTemperoryDisableFallingDamage = true --缓存当前重力 self.CachedCharacterMovementGravityScale = self.STCharacterMovement.GravityScale self.ItemActorClass = UE.LoadClass(BPClassPath.PickupItemClass) EventSystem.SetTimer(self, function() --self:TestPawn(); end, 30) if self:HasAuthority() then self:BindServerEvent() if self.SkillSystemComponent == nil then local SkillSystemComponentClass = require("Script.SimpleSkill.SkillSystemComponent") self.SkillSystemComponent = SkillSystemComponentClass.New(self) end else self:BindClientEvent() local CommandManager = require('Script.Manager.CommandQueneManager') CommandManager:AddInitCommand(self, self.Client_Init) end end function BP_PlayerPawn:TestPawn() if self:HasAuthority() == false then end --local PlayerState = self:GetPlayerStateSafety() --PlayerState:AddExp(10000) end function BP_PlayerPawn:ReceiveEndPlay() if self:HasAuthority() then self:UnbindServerEvent() else self:UnbindClientEvent() end BP_PlayerPawn.SuperClass.ReceiveEndPlay(self) end function BP_PlayerPawn:ReceiveTick(DeltaTime) BP_PlayerPawn.SuperClass.ReceiveTick(self, DeltaTime) if self.IsRunOnServer then self:ServerTick(DeltaTime) self.SkillSystemComponent:OnTick(DeltaTime) else if self.bHasInitClient == nil and self.PlayerKey ~= 0 then local CommandManager = require('Script.Manager.CommandQueneManager') CommandManager.bPlayerPawnReady = true self.bHasInitClient = true UE.Log("[BP_PlayerPawn] *** BP_PlayerPawn Tick Init Ready PlayerKey:%s", self.PlayerKey) end self:ClientTick(DeltaTime) end end function BP_PlayerPawn:Client_Init() self:ClientOnHPChanged(UGCPawnAttrSystem.GetHealth(self), UGCPawnAttrSystem.GetHealthMax(self), 0) self:OnRep_EnergyData() end ---@field UGC_PreTakeDamageEvent:fun(Damage:float,EventInstigator:AController,DamageEvent:FDamageEvent,DamageCauser:AActor):float function BP_PlayerPawn:UGC_PreTakeDamageEvent(Damage, EventInstigator, DamageEvent, DamageCauser) UE.Log("[BP_PlayerPawn:UGC_PreTakeDamageEvent] Damage = %d", Damage) return Damage end function BP_PlayerPawn:ServerTick(DeltaTime) --自动回复逻辑 if UGCGameSystem.GameState.bHasApplyedAttribute then self.AttributeUpdateInterval = self.AttributeUpdateInterval + DeltaTime if self.AttributeUpdateInterval >= 1.0 then local PlayerState = self:GetPlayerStateSafety() --成长属性 PlayerState:GrowthAttributes() --每秒增加杀敌点 PlayerState:GrowthKillPoint() --刷新战斗力计算结果 PlayerState:RefreshCombatPoint() --每秒回复 PlayerState:RecoverPlayerPawn() --每秒杀敌点 PlayerState:AttributeAdditionPerSecond() self.AttributeUpdateInterval = 0 end end --冲刺逻辑 if self.DashDuration > 0 then self.DashDuration = self.DashDuration - DeltaTime if self.DashDuration <= 0 then self.DashDuration = -1 self.LaunchDir = nil self:EnableDashTo(false) end if self.LaunchDir then self:LaunchCharacter(VectorHelper.MulNumber(self.LaunchDir, self.LaunchCharacterForce * DeltaTime), true, false) if self.CharacterMovement.MovementMode ~= EMovementMode.MOVE_Falling then self.CharacterMovement:SetMovementMode(EMovementMode.MOVE_Falling) end end end end function BP_PlayerPawn:ClientTick(DeltaTime) end function BP_PlayerPawn:BindServerEvent() self.OnCharacterHpChange:Add(BP_PlayerPawn.ServerOnHPChanged, self) self.OnDeath:Add(BP_PlayerPawn.ServerOnSelfDeath, self) end function BP_PlayerPawn:BindClientEvent() EventSystem:AddListener(EventType.ClientUpdateWeapon, BP_PlayerPawn.OnUpdateWeapon, self) self.OnCharacterHpChange:Add(BP_PlayerPawn.ClientOnHPChanged, self) end function BP_PlayerPawn:UnbindServerEvent() self.OnDeath:Remove(BP_PlayerPawn.ServerOnSelfDeath, self) self.OnCharacterHpChange:Remove(BP_PlayerPawn.ServerOnHPChanged, self) end function BP_PlayerPawn:UnbindClientEvent() EventSystem:RemoveListener(EventType.ClientUpdateWeapon, BP_PlayerPawn.OnUpdateWeapon, self) self.OnCharacterHpChange:Remove(BP_PlayerPawn.ClientOnHPChanged, self) end function BP_PlayerPawn:ServerOnSelfDeath(DeadPawn, KillerController, DamageCauser, KillingHitInfo, KillingHitImpulseDir, KillingHitDamageTypeID, DamageTypeClass, IsHeadShotDamage) if DeadPawn.PlayerKey == self.PlayerKey then if UE.IsValid(KillerController) and UE.IsValid(KillerController.Pawn) then EventSystem:SendEvent(EventType.PlayerPawnDead, self.PlayerKey, KillerController.Pawn) end UE.Log("[BP_PlayerPawn:ServerOnSelfDeath] PlayerKey=%d",self.PlayerKey) local PlayerKey = UGCPawnAttrSystem.GetPlayerKeyInt64(self) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(PlayerKey) local PlayerController = UGCGameSystem.GetPlayerControllerByPlayerKey(PlayerKey) PlayerState.BackupEnergyData = TableHelper.DeepCopyTable(self.EnergyData) self.bIsAlive = false if self.SkillSystemComponent then self.SkillSystemComponent:RemoveAllSkill() UnrealNetwork.CallUnrealRPC_Multicast(self, "Client_MulticastRPC_RemoveAllSkillEffect", self) end if DamageCauser and UE.IsValid(DamageCauser) then local MonsterType = GameDataManager.GetMonsterTypeByID(DamageCauser.ID) if MonsterType == EMonsterType.Boss or MonsterType == EMonsterType.Common then if MonsterType == EMonsterType.Boss then DamageCauser.KilledPlayerNum = DamageCauser.KilledPlayerNum + 1 end PlayerController.IsDeadInArena = true else PlayerController.IsDeadInArena = false end end end end function BP_PlayerPawn:ServerOnHPChanged(CurHP, MaxHP, PrevHP) UE.Log("[BP_PlayerPawn:ServerOnHPChanged] PlayerKey = %d, CurHP = %.1f, MaxHP = %.1f, PrevHP = %.1f", UGCPawnAttrSystem.GetPlayerKeyInt64(self), CurHP, MaxHP, PrevHP) end function BP_PlayerPawn:ClientOnHPChanged(CurHP, MaxHP, PrevHP) local PlayerKey = UGCPawnAttrSystem.GetPlayerKeyInt64(self) EventSystem:SendEvent(EventType.OnPlayerHPChanged, PlayerKey, CurHP, MaxHP, PrevHP) UE.Log("[BP_PlayerPawn:ClientOnHPChanged] PlayerKey = %d, CurHP = %.1f, MaxHP = %.1f, PrevHP = %.1f", PlayerKey, CurHP, MaxHP, PrevHP) end function BP_PlayerPawn:IsSkipSpawnDeadTombBox(EventInstigater) return true end function BP_PlayerPawn:GetPickupCollision() return self.PickupCollision end -- 获取武器组件 function BP_PlayerPawn:GetWeaponComponent() return self.WeaponActor end function BP_PlayerPawn:IsFullHealth() local MaxHP = UGCPawnAttrSystem.GetHealthMax(self) local CurHP = UGCPawnAttrSystem.GetHealth(self) return math.isNearlyEqual(MaxHP, CurHP) and MaxHP > 0 end function BP_PlayerPawn:IsFullEnergy() local MaxEnergy = self.EnergyData.Max local CurEnergy = self.EnergyData.Cur return math.isNearlyEqual(MaxEnergy, CurEnergy) and MaxEnergy > 0 end function BP_PlayerPawn:IsSelfAlive() return self.bIsAlive end function BP_PlayerPawn:OnRep_EnergyData() if EventSystem and EventType then local Cur = self.EnergyData.Cur local Max = self.EnergyData.Max UE.Log("[BP_PlayerPawn:OnRep_Energy] Cur = %2.2f, Max = %2.2f", Cur, Max) EventSystem:SendEvent(EventType.OnPlayerEnergyChanged, self.PlayerKey, Cur, Max) end end function BP_PlayerPawn:OnRep_WeaponActor() UE.Log("[BP_PlayerPawn:OnRep_WeaponActor] PlayerKey=%d, Changed", self.PlayerKey) EventSystem.SetTimer(self, function() if self.WeaponActor ~= nil and UE.IsValid(self.WeaponActor) then self.WeaponActor:OnRep_CurrentWeaponId() end end, 0.2) end function BP_PlayerPawn:OnRep_BossAttackCount() if self.WeaponActor == nil then return end local WeaponId = self.WeaponActor.CurrentWeaponId local WT = self.WeaponActor:GetWeaponTypeByWeaponId(WeaponId) if WT == EWeaponClassType.WT_ShooterRifle or WT == EWeaponClassType.WT_AssaultRifle or WT == EWeaponClassType.WT_ShotGun or WT == EWeaponClassType.WT_MachineGun then self:PlaySingleWeaponEffect(self.PlayerKey, WT) end end function BP_PlayerPawn:DashTo(Dir, Duration, DashForce) self.LaunchCharacterForce = DashForce self.DashDuration = Duration self.LaunchDir = Dir self:EnableDashTo(true) end function BP_PlayerPawn:EnableDashTo(IsOn) if IsOn then self.STCharacterMovement.GravityScale = 0 else self.STCharacterMovement.GravityScale = self.CachedCharacterMovementGravityScale end end --- 玩家处理伤害函数 ---@param DamageAmount float ---@param DamageEvent FDamageEvent ---@param EventInstigator AController ---@param DamageCauser AActor function BP_PlayerPawn:BP_CharacterModifyDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser) self.OnReceiveDamageDelegate(self, DamageAmount, EventInstigator, DamageCauser) local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(UGCPawnAttrSystem.GetPlayerKeyInt64(self)) -- 获取 闪避 if PlayerState:Dodge() > 0 then math.randomseed(KismetSystemLibrary.GetGameTimeInSeconds(self)) local Val = math.random() -- (0, 1) if Val <= PlayerState:Dodge() then -- 此时闪避 UE.Log("[BP_PlayerPawn:BP_CharacterModifyDamage] 闪避了一次") return 0 end end local Val = BP_PlayerPawn.SuperClass:BP_CharacterModifyDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser) -- 处理玩家的 defence DamageAmount = PlayerState:GetDamage(DamageCauser, Val) UE.Log("[BP_PlayerPawn:BP_CharacterModifyDamage] PlayerKey=%d, 当前受到伤害=%.2f", self.PlayerKey, DamageAmount) -- 处理反弹伤害 PlayerState:GetReverseDamage(DamageCauser, DamageAmount) -- 检查是否有护盾 local Amount = PlayerState:DealShield(DamageAmount) return Amount end --玩家进行吸血 function BP_PlayerPawn:VampBlood(InNum) if InNum <= 0 then return end -- 获取玩家吸血效率 local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(UGCPawnAttrSystem.GetPlayerKeyInt64(self)) local Val = PlayerState:SuckBlood(InNum) -- 回复血量 self:RecoverCurHP(Val, 0) UE.Log("[BP_PlayerPawn:VampBlood] Vamp = %.2f", Val) end --传过来一个怪物收到的真实伤害 function BP_PlayerPawn:DealRealDamage(InMonster, InNum) -- 处理吸血 self:VampBlood(InNum) -- 可以处理飘字等 -- 飘字 UGC_GetDamageNumberConfigIndex,可以检查一下 if GameDataManager.GetMonsterTypeByID(InMonster.ID) == EMonsterType.Boss then self.BossAttackCount = self.BossAttackCount + 1 end end -- Server function BP_PlayerPawn:SetMaxHealth(InMaxHealth) UGCPawnAttrSystem.SetHealthMax(self, InMaxHealth) UE.Log("[BP_PlayerPawn:SetMaxHealth] PlayerKey = %d, InMaxHP = %2.2f", self.PlayerKey, InMaxHealth) end -- Server function BP_PlayerPawn:SetMaxEnergy(InMaxEnergy) self.EnergyData.Max = InMaxEnergy self.EnergyData.Cur = InMaxEnergy UE.Log("[BP_PlayerPawn:SetMaxEnergy] PlayerKey = %d, Max = %2.2f, Cur = %2.2f", self.PlayerKey, self.EnergyData.Max, self.EnergyData.Cur) end -- Server & Client function BP_PlayerPawn:GetCurEnergy() return self.EnergyData.Cur end -- Server function BP_PlayerPawn:ConsumeEnergy(InDelta) local CurEnergy = math.clamp(self.EnergyData.Cur - InDelta, 0, self.EnergyData.Cur) self.EnergyData.Cur = CurEnergy end -- Server 回复血量 function BP_PlayerPawn:RecoverCurHP(Value, Percent) local MaxHP = UGCPawnAttrSystem.GetHealthMax(self) local CurHP = UGCPawnAttrSystem.GetHealth(self) if math.isNearlyEqual(MaxHP, CurHP) then UE.Log("[BP_PlayerPawn:RecoverCurHP] Full HP") return end local Delta = Value + MaxHP * Percent local NewCurHP = CurHP + Delta NewCurHP = math.clamp(NewCurHP, 0, MaxHP) UE.Log("[BP_PlayerPawn:RecoverCurHP] PlayerKey = %d, Value = %2.2f, CurHP = %2.2f, Real = %2.2f", self.PlayerKey, Delta, CurHP, MaxHP - NewCurHP) UGCPawnAttrSystem.SetHealth(self, NewCurHP) end -- Server function BP_PlayerPawn:RecoverCurEnergy(Value, Percent) if UE.IsValid(self) == false then print(string.format('[BP_PlayerPawn:RecoverCurEnergy] 本身就有问题')) end if self.EnergyData == nil then print(string.format('[BP_PlayerPawn:RecoverCurEnergy] 莫名其妙 Energy == nil')) end if self.EnergyData.Max == nil then print(string.format('[BP_PlayerPawn:RecoverCurEnergy] 莫名其妙 Max Energy == nil')) end if self.EnergyData.Cur == nil then print(string.format('[BP_PlayerPawn:RecoverCurEnergy] 莫名其妙 Cur Energy == nil')) end local MaxEnergy = self.EnergyData.Max local CurEnergy = self.EnergyData.Cur if math.isNearlyEqual(MaxEnergy, CurEnergy) and MaxEnergy > 0 then UE.Log("[BP_PlayerPawn:RecoverCurEnergy] PlayerKey = %d, Full Energy", self.PlayerKey) return end local Delta = Value + MaxEnergy * Percent local NewCurEnergy = CurEnergy + Delta NewCurEnergy = math.clamp(NewCurEnergy, 0, MaxEnergy) UE.Log("[BP_PlayerPawn:RecoverCurEnergy] PlayerKey = %d, Value = %2.2f, CurHP = %2.2f, Real = %2.2f", self.PlayerKey, Delta, CurEnergy, MaxEnergy - NewCurEnergy) self.EnergyData.Cur = NewCurEnergy end ---玩家重生后初始化数据的逻辑 function BP_PlayerPawn:OnPlayerRespawned(OwnerPlayerState, OwnerPlayerController) if (not UE.IsValid(OwnerPlayerState)) or (not UE.IsValid(OwnerPlayerController)) then UE.LogError("[BP_PlayerPawn:OnPlayerRespawned] invalid PS or PC") return end ---Attribute init print(string.format('[BP_PlayerPawn:OnPlayerRespawned] 设置玩家 Energy 的值')) self:SetMaxEnergy(OwnerPlayerState.BackupEnergyData.Max) OwnerPlayerState:ApplyAttributes() ---SkillSystem init if self.SkillSystemComponent == nil then local SkillSystemComponentClass = require("Script.SimpleSkill.SkillSystemComponent") self.SkillSystemComponent = SkillSystemComponentClass.New(self) end local SkillListCopy = TableHelper.DeepCopyTable(OwnerPlayerController.ActiveSkillNameList) for Slot, SkillInfo in pairs(SkillListCopy) do self:GiveSkill(SkillInfo.SkillName, Slot, SkillInfo.SkillLevel) end ---清空上次死亡上传的备份数据 OwnerPlayerState.BackupEnergyData = {} ---Weapon init local OwnedWeapons = OwnerPlayerState:GetWeapons() local CurWeaponId = -1 if not table.isEmpty(OwnedWeapons) then CurWeaponId = OwnedWeapons[1].WeaponId end if self.WeaponActor == nil then AsyncLoadTools:LoadObject(BPClassPath.WeaponBaseActor, function(WeaponClass) if UE.IsValid(self) and UE.IsValid(WeaponClass) and UE.IsValid(OwnerPlayerState) then local Weapon = UGCGameSystem.SpawnActor(self, WeaponClass, self:K2_GetActorLocation(), self:K2_GetActorRotation(), VectorHelper.ScaleOne(), nil) Weapon:SetWeaponID(CurWeaponId) Weapon:SetOwnerCharacter(self) self.WeaponActor = Weapon self.OnWeaponSpawnedDelegate(self) end end) else self.WeaponActor:SetWeaponID(CurWeaponId) end end --仅切换枪的时候再做操作 function BP_PlayerPawn:OnUpdateWeapon(InWeaponId, InOldId, InPlayerKey) -- 因为不需要重复播放 if InOldId == InWeaponId then return end if InPlayerKey ~= self.PlayerKey then return end local WeaponType = GameDataManager.GetWeaponType(InWeaponId) if WeaponType == nil then UE.Log("[BP_WeaponPawnBase:CheckWeaponByWeaponId] Data is nil") return else self:ClearParticles() self:ShowParticle(false) -- 选择对应的特效,并在玩家身上播放 local WeaponParticle = self.WeaponParticleArray[WeaponType] if WeaponParticle ~= nil then self.ParticleSystem:SetTemplate(WeaponParticle) if WeaponType == EWeaponClassType.WT_SubmachineGun or WeaponType == EWeaponClassType.WT_Sniper then -- 持久显示 local Text = '' if WeaponType == EWeaponClassType.WT_ShooterRifle then Text = 'spine_03' end self.WeaponParticles[WeaponType] = GameplayStatics.SpawnEmitterAttached(WeaponParticle, self.Mesh, Text, Vector.New(0, 0, 0), VectorHelper.RotZero(), VectorHelper.ScaleOne(), EAttachLocation.SnapToTarget, false) else --当攻击的时候显示一次,因此不在这里显示 end UE.Log("[BP_PlayerPawn:OnUpdateWeapon] 播放特效, Type = %d", WeaponType) end self:ShowParticle(true) end end function BP_PlayerPawn:PlaySingleWeaponEffect(InPlayerKey, InWeaponType) UE.Log("[BP_PlayerPawn:PlaySingleWeaponEffect] 开始播放特效") if InPlayerKey ~= self.PlayerKey then return end UE.Log("[BP_PlayerPawn:PlaySingleWeaponEffect] 当前武器类型:%d", InWeaponType) if InWeaponType == nil then UE.Log("[BP_WeaponPawnBase:CheckWeaponByWeaponId] 找不到 WeaponType, 请检查一下") return else local WeaponParticle = self.WeaponParticleArray[InWeaponType] if WeaponParticle ~= nil then UE.Log("[BP_PlayerPawn:PlaySingleWeaponEffect] 有武器特效") local EffectParticle = GameplayStatics.SpawnEmitterAttached(WeaponParticle, self.Mesh, "", Vector.New(0, 0, 0), VectorHelper.RotZero(), VectorHelper.ScaleOne(), EAttachLocation.SnapToTarget, true) EventSystem.SetTimer(self, function() if UE.IsValid(EffectParticle) then EffectParticle:K2_DestroyComponent() end end, 1) else UE.Log("[BP_PlayerPawn:PlaySingleWeaponEffect] 找不到武器特效") end end end -- 清除玩家身上的特效 function BP_PlayerPawn:ShowParticle(InShow) -- 设置隐藏即可 self.ParticleSystem:SetHiddenInGame(InShow, false) end function BP_PlayerPawn:ClearParticles() for _, v in pairs(self.WeaponParticles) do v:K2_DestroyComponent(self) end self.WeaponParticles = {} end function BP_PlayerPawn:IsInMainArea() return self.IsInArena end function BP_PlayerPawn:IsInExerciseRoom() return not self.IsInArena end function BP_PlayerPawn:OnRep_IsInArena() -- 进行 if UE.IsValid(self.WeaponActor) then self.WeaponActor:PlayerInArena(self.IsInArena) end end ------------------------------- **************** 技能激活 **************** ----------------------------------- ---@param SkillNameList ESkillName[] function BP_PlayerPawn:GiveSkillWithSkillNameList(SkillNameList) self.SkillSystemComponent:GiveSkillWithList(SkillNameList) end ---@param SkillName ESkillName ---@param SlotID ESkillSlot ---@param SkillLevel int ---@return number 返回-1则添加技能失败,返回0则代表当前slot无技能,其余正常情况返回技能ID function BP_PlayerPawn:GiveSkill(SkillName, SlotID, SkillLevel) return self.SkillSystemComponent:GiveSkill(SkillName, SlotID, SkillLevel) end function BP_PlayerPawn:TryActiveSkillBySlot(SkillSlot) if self.SkillSystemComponent ~= nil then self.SkillSystemComponent:TryActiveSkillBySlot(SkillSlot) else UE.Log("SkillSystemComponent of PlayerPawn is nil") end end function BP_PlayerPawn:RemoveSkill(SkillName) if self.SkillSystemComponent ~= nil then self.SkillSystemComponent:RemoveSkill(SkillName) end end function BP_PlayerPawn:Client_MulticastRPC_PlayEffect(InstanceId, EffectId, CasterActor, ActorList, Duration, SpawnLocationType, BoneName) if (not UE.IsValid(CasterActor)) then UE.Log("[Client_MulticastRPC_PlayEffect] invalid CasterActor") return end local EffectSystemManager = require('Script.Manager.EffectSystemManager') EffectSystemManager.PlayEffect(InstanceId, EffectId, CasterActor, ActorList, Duration, SpawnLocationType, BoneName) end function BP_PlayerPawn:Client_MulticastRPC_PlayDirectionalEffect(InstanceId, EffectId, CasterActor, DestActor, Duration, Rotation) if (not UE.IsValid(CasterActor)) then UE.Log("[Client_MulticastRPC_PlayDirectionalEffect] invalid CasterActor") return end local EffectSystemManager = require('Script.Manager.EffectSystemManager') EffectSystemManager.PlayDirectionalEffect(InstanceId, EffectId, CasterActor, DestActor, Duration, Rotation) end function BP_PlayerPawn:Client_MulticastRPC_PlayEffectAtLocation(InstanceId, EffectId, CasterActor, Location, Rotation, Duration) if (not UE.IsValid(CasterActor)) then UE.Log("[Client_MulticastRPC_PlayEffectAtLocation] invalid CasterActor") return end local EffectSystemManager = require('Script.Manager.EffectSystemManager') EffectSystemManager.PlayEffectAtLocation(InstanceId, EffectId, CasterActor, Location, Rotation, Duration) end function BP_PlayerPawn:Client_MulticastRPC_RemoveSkillEffect(SkillName, InstanceId, CasterActor) if (not UE.IsValid(CasterActor)) then UE.Log("[Client_MulticastRPC_RemoveSkillEffect] invalid CasterActor") return end local EffectSystemManager = require('Script.Manager.EffectSystemManager') EffectSystemManager.RemoveSkillEffectByInstanceId(SkillName, InstanceId, CasterActor) end function BP_PlayerPawn:Client_MulticastRPC_RemoveAllSkillEffect(CasterActor) if (not UE.IsValid(CasterActor)) then UE.Log("[Client_MulticastRPC_RemoveAllSkillEffect] invalid CasterActor") return end local EffectSystemManager = require('Script.Manager.EffectSystemManager') EffectSystemManager.RemoveAllEffectOfActor(CasterActor) end ------------------------------- **************** Debug **************** ----------------------------------- function BP_PlayerPawn:DrawDebugSphere(Center, Color, Radius) STExtraGameplayStatics.ClientDrawDebugSphere(Center, Radius, 10, Color, 10, 1) end function BP_PlayerPawn:DrawDebugLine(Start, End, Color) STExtraGameplayStatics.ClientDrawDebugLine(Start, End, Color, 10, 1) end function BP_PlayerPawn:DrawDebugBox(Center, Extent, Color, Rotation) STExtraGameplayStatics.ClientDrawDebugBox(Center, Extent, Color, Rotation, 1, 2) end return BP_PlayerPawn;