-- 技能任务脚本,实际技能效果实现在此 local SimpleSkillTask = LuaClass("SimpleSkillTask") SimpleSkillTask.OwnerSkill = nil SimpleSkillTask.SkillName = ESkillName.Default SimpleSkillTask.TaskName = "" SimpleSkillTask.SkillLevel = 1 SimpleSkillTask.CasterPawn = nil SimpleSkillTask.DurationPolicy = ETaskDurationPolicy.Instant SimpleSkillTask.Duration = 0 SimpleSkillTask.DurationTimer = 0 SimpleSkillTask.Period = 0 SimpleSkillTask.ExecuteOnApply = true SimpleSkillTask.IsActivated = false SimpleSkillTask.EffectId = 0 SimpleSkillTask.TaskTimer = nil SimpleSkillTask.Selector = nil SimpleSkillTask.SkillEffects = {} SimpleSkillTask.TargetPawns = {} function SimpleSkillTask:ctor(OwnerSkill) self.OwnerSkill = OwnerSkill self.SkillName = OwnerSkill.SkillName self.SkillLevel = OwnerSkill.SkillLevel end function SimpleSkillTask:UpdateSkillLevel(NewSkillLevel) self.SkillLevel = NewSkillLevel end function SimpleSkillTask:InitTaskFromData(TaskData, CasterPawn) self.CasterPawn = CasterPawn self.DurationPolicy = TaskData.DurationPolicy self.Duration = TaskData.Duration self.Period = TaskData.Period self.ExecuteOnApply = TaskData.ExecuteOnApply self.EffectId = TaskData.EffectId self.IsActivated = false end --子类实现 function SimpleSkillTask:ActivateTask() if self.IsActivated then return end UE.Log("[SimpleSkillTask] [%s][%s] Task Activated", KismetSystemLibrary.GetObjectName(self.CasterPawn), self.TaskName) if self.DurationPolicy == ETaskDurationPolicy.HasDuration and self.Duration > 0 then self.IsActivated = true if self.Period > 0 then if self.ExecuteOnApply then self:ActivateTaskInTimer() self:PlaySkillSound(self.CasterPawn) end self.TaskTimer = EventSystem.SetTimerLoop(self.CasterPawn, function() self:ActivateTaskInTimer() self:PlaySkillSound(self.CasterPawn) self.DurationTimer = self.DurationTimer + self.Period UE.Log("[SimpleSkillTask] [%s][%s] DurationTimer = %.2f", KismetSystemLibrary.GetObjectName(self.CasterPawn), self.TaskName, self.DurationTimer) if self.DurationTimer >= self.Duration then self:EndTask() end end, self.Period) else --- 如果Period小于等于0,则直接执行一次任务,在Duration后进行移除 self:ActivateTaskInTimer() self:PlaySkillSound(self.CasterPawn) self.TaskTimer = EventSystem.SetTimer(self.CasterPawn, function() self:EndTask() end, self.Duration) end else self:PlaySkillSound(self.CasterPawn) end end function SimpleSkillTask:EndTask() UE.Log("[SimpleSkillTask] [%s][%s] Task End", KismetSystemLibrary.GetObjectName(self.CasterPawn), self.TaskName) if self.TaskTimer ~= nil then EventSystem.StopTimer(self.TaskTimer) end self:DeactivateTask() self.IsActivated = false end -- 子类实现,非瞬时的技能任务结束时执行 function SimpleSkillTask:DeactivateTask() end -- 如果Task需要周期性执行,则子类需将Task执行逻辑实现 function SimpleSkillTask:ActivateTaskInTimer() end ---播放技能特效: 默认SpawnLocationType为Attach ---@param Pawn APawn 玩家 ---@param ActorList BP_MonsterBase_C[] 目标怪物 ---@param SpawnLocationType EEffectSpawnLocationType 位置类型 ---@param BoneName string 绑定骨骼名称 function SimpleSkillTask:EnableSkillEffect(Pawn, ActorList, SpawnLocationType, BoneName) UE.Log("[SimpleSkillTask:EnableSkillEffect] SkillName: %d", self.SkillName) if SpawnLocationType == nil then SpawnLocationType = EEffectSpawnLocationType.Attach end local Duration = 0 if self.DurationPolicy == ETaskDurationPolicy.HasDuration and self.Duration > 0 then Duration = self.Duration end local InstanceId = GameDataManager.GetEffectInstanceId() local EffectId = self.EffectId UnrealNetwork.CallUnrealRPC_Multicast(self.CasterPawn, "Client_MulticastRPC_PlayEffect", InstanceId, EffectId, Pawn, ActorList, Duration, SpawnLocationType, BoneName) end ---@param EffectId number 特效实例ID ---@param Pawn APawn 特效起始 ---@param ActorList APawn[] 特效终点(若为空,则需填入指定旋转) ---@param Duration number 持续时间(默认0,自动销毁) ---@param SpawnLocationType EEffectSpawnLocationType 位置类型(默认为Bottom) ---@param BoneName string 绑定骨骼名称 function SimpleSkillTask:EnableEffectWithId(EffectId, Pawn, ActorList, Duration, SpawnLocationType, BoneName) UE.Log("[SimpleSkillTask:EnableEffectWithId] SkillName: %d", self.SkillName) if SpawnLocationType == nil then SpawnLocationType = EEffectSpawnLocationType.Bottom end if Duration == nil then Duration = 0 end local InstanceId = GameDataManager.GetEffectInstanceId() UnrealNetwork.CallUnrealRPC_Multicast(self.CasterPawn, "Client_MulticastRPC_PlayEffect", InstanceId, EffectId, Pawn, ActorList, Duration, SpawnLocationType, BoneName) end ---播放指向型特效(InstanceId, EffectId, CasterActor, DestActor, Duration, Rotation) ---@param EffectId number 特效实例ID ---@param CasterActor APawn 特效起始 ---@param DestActor APawn 特效终点(若为空,则需填入指定旋转) ---@param Duration number 持续时间(默认0,自动销毁) ---@param Rotation FRotator 指定旋转(DestActor为空时才生效) function SimpleSkillTask:EnableDirectionalEffect(EffectId, CasterActor, DestActor, Duration, Rotation) UE.Log("[SimpleSkillTask:EnableDirectionalEffect] SkillName: %d", self.SkillName) local InstanceId = GameDataManager.GetEffectInstanceId() UnrealNetwork.CallUnrealRPC_Multicast(self.CasterPawn, "Client_MulticastRPC_PlayDirectionalEffect", InstanceId, EffectId, CasterActor, DestActor, Duration, Rotation) end ---生成技能Actor function SimpleSkillTask:SpawnSkillActor(BPClassPath, CasterActor, Location, Rotation) local Class = UE.LoadClass(BPClassPath) local SkillActor = UGCGameSystem.SpawnActor(CasterActor, Class, Location, Rotation, VectorHelper.ScaleOne(), nil) if not SkillActor then return nil end SkillActor:SetOwner(CasterActor) SkillActor:SetCasterPawn(CasterActor) SkillActor:SetLevel(self.SkillLevel) return SkillActor end ---播放技能音效 function SimpleSkillTask:PlaySkillSound(CasterActor) SoundManager.MulticastPlaySoundAtLocation(100 + self.SkillName, CasterActor:K2_GetActorLocation(), CasterActor:K2_GetActorRotation()) end ---获取目标Pawn ---@return TargetPawns[] function SimpleSkillTask:GetTargetPawns() self.OwnerSkill.TargetPawns = self.OwnerSkill:GetTargetPawns() return self.OwnerSkill.TargetPawns end return SimpleSkillTask;