344 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			344 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using Level.Role;
 | ||
| using UnrealSharp;
 | ||
| using UnrealSharp.Attributes;
 | ||
| using UnrealSharp.BusyRabbit;
 | ||
| using UnrealSharp.CoreUObject;
 | ||
| using UnrealSharp.Engine;
 | ||
| using UnrealSharp.GameplayAbilities;
 | ||
| using UnrealSharp.GameplayTags;
 | ||
| using UnrealSharp.SpinePlugin;
 | ||
| 
 | ||
| namespace GameAbilitySystem.Ability.Role.Fox;
 | ||
| 
 | ||
| 
 | ||
| [UClass]
 | ||
| public class UFoxUltimate : UBusyGameAbility
 | ||
| {
 | ||
|     protected bool bIsEventBinded = false;
 | ||
|     protected ABusyFoxRole? Owner = null;
 | ||
|     protected UFoxUltimateDataAsset? FoxData = null;
 | ||
|     protected UBusyAbilitySystemComponent? ASC = null;
 | ||
|     protected FActiveGameplayEffectHandle CastStateHandle;
 | ||
|     protected FActiveGameplayEffectHandle SkillStateHandle;
 | ||
| 
 | ||
|     protected FActiveGameplayEffectHandle AccelerateHandle;  // 大招移动速度增加的Effect
 | ||
|     protected FActiveGameplayEffectHandle SprintHandle;      // 大招三阶移速再次增加的Effect
 | ||
| 
 | ||
|     [UFunction()]
 | ||
|     protected void OnGamePlayTagAddOrRemove(FGameplayTag tag, int isAdd)
 | ||
|     {
 | ||
|         if (isAdd == 0 && !IsActive)
 | ||
|         {
 | ||
|             CommitAbilityCooldown();
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /// <summary>
 | ||
|     /// 初始化技能依赖的属性
 | ||
|     /// </summary>
 | ||
|     /// <returns>false->初始化失败</returns>
 | ||
|     protected bool InitAbilityOnce()
 | ||
|     {
 | ||
|         Owner = OwningActorFromActorInfo as ABusyFoxRole;
 | ||
|         if (Owner == null) return false;
 | ||
| 
 | ||
|         FoxData = Data as UFoxUltimateDataAsset;
 | ||
| 
 | ||
|         ASC = AbilitySystemLibrary.GetAbilitySystemComponent(Owner) as UBusyAbilitySystemComponent;
 | ||
|         if (FoxData == null || ASC == null) return false;
 | ||
| 
 | ||
|         PrintString("asdafdasdf");
 | ||
| 
 | ||
| 
 | ||
|         if (bIsEventBinded) return true;
 | ||
|         TDelegate<GameplayTagAddOrRemoveDelegate> Delegate = new TDelegate<GameplayTagAddOrRemoveDelegate>();
 | ||
|         Delegate.BindUFunction(this, "OnGamePlayTagAddOrRemove");
 | ||
|         Owner.BindGameplayTagAddOrRemove(FoxData.SecondStageCastTag, Delegate);
 | ||
|         Owner.BindGameplayTagAddOrRemove(FoxData.LastStageCastTag, Delegate);
 | ||
|         bIsEventBinded = true;
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
|     /// <summary>
 | ||
|     /// 获取当前大招的阶段
 | ||
|     /// </summary>
 | ||
|     /// <returns></returns>
 | ||
|     protected int GetCurrentAbilityStage()
 | ||
|     {
 | ||
|         if (ASC == null || FoxData == null) return 0;
 | ||
|         if (ASC.HasMatchingGameplayTag(FoxData.LastStageCastTag))
 | ||
|         {
 | ||
|             return 3;
 | ||
|         }
 | ||
|         if (ASC.HasMatchingGameplayTag(FoxData.SecondStageCastTag))
 | ||
|         {
 | ||
|             return 2;
 | ||
|         }
 | ||
|         else if (ASC.HasMatchingGameplayTag(FoxData.FirstStageCastTag))
 | ||
|         {
 | ||
|             return 1;
 | ||
|         }
 | ||
|         return 0;
 | ||
|     }
 | ||
| 
 | ||
|     protected override void ActivateAbilityFromEvent(FGameplayEventData eventData)
 | ||
|     {
 | ||
|         base.ActivateAbilityFromEvent(eventData);
 | ||
|         if (!InitAbilityOnce())
 | ||
|         {
 | ||
|             EndAbility();
 | ||
|             return;
 | ||
|         }
 | ||
| 
 | ||
|         if (Owner == null || !CommitAbilityCost(Owner))
 | ||
|         {
 | ||
|             EndAbility();
 | ||
|             return;
 | ||
|         }
 | ||
| 
 | ||
|         int stage = GetCurrentAbilityStage();
 | ||
|         if (stage != 0)
 | ||
|         {
 | ||
|             TriggerAbility(stage);
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             EndAbility();
 | ||
|             return;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /// <summary>
 | ||
|     /// 当被授予技能时,立刻获得可释放第一段大招的常驻Tag
 | ||
|     /// </summary>
 | ||
|     /// <param name="actorInfo"></param>
 | ||
|     /// <param name="spec"></param>
 | ||
|     public override void OnGiveAbility(FGameplayAbilityActorInfo actorInfo, FGameplayAbilitySpec spec)
 | ||
|     {
 | ||
|         base.OnGiveAbility(actorInfo, spec);
 | ||
|         InitAbilityOnce();
 | ||
| 
 | ||
|         if (FoxData == null || ASC == null) return;
 | ||
| 
 | ||
|         UBusyGameplayEffectSubSystem EffectSubSystem = GetGameInstanceSubsystem<UBusyGameplayEffectSubSystem>();
 | ||
|         if (EffectSubSystem == null) return;
 | ||
| 
 | ||
| 
 | ||
|         UGameplayEffect effect = EffectSubSystem.GetTagGrantEffectWithDuration(
 | ||
|             new FGameplayTagContainer(FoxData.FirstStageCastTag),
 | ||
|             new FGameplayTagContainer(), 0
 | ||
|         );
 | ||
| 
 | ||
|         FGameplayEffectSpecHandle handle = UBusyAscLibrary.MakeGameplayEffectSpecHandle(ASC, effect, 1);
 | ||
|         ASC.ApplyGameplayEffectSpecToSelf(handle);
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     protected bool ApplayCastEffect(FGameplayTag CastTag)
 | ||
|     {
 | ||
|         UBusyGameplayEffectSubSystem EffectSubSystem = GetGameInstanceSubsystem<UBusyGameplayEffectSubSystem>();
 | ||
|         if (ASC == null || EffectSubSystem == null || FoxData == null) return false;
 | ||
| 
 | ||
|         ASC.RemoveActiveGameplayEffect(CastStateHandle);
 | ||
| 
 | ||
|         if (CastTag.IsValid)
 | ||
|         {
 | ||
|             UGameplayEffect cast_effect = EffectSubSystem.GetTagGrantEffectWithDuration(
 | ||
|                 new FGameplayTagContainer(CastTag),
 | ||
|                 new FGameplayTagContainer(), FoxData.RecastWindow
 | ||
|             );
 | ||
|             FGameplayEffectSpecHandle CastSpecHandle = UBusyAscLibrary.MakeGameplayEffectSpecHandle(ASC, cast_effect, 1);
 | ||
|             CastStateHandle = ASC.ApplyGameplayEffectSpecToSelf(CastSpecHandle);
 | ||
|         }
 | ||
|         return true;
 | ||
|     }
 | ||
|     protected bool ApplyEffect(FGameplayTag stateTag, FGameplayTag CastTag)
 | ||
|     {
 | ||
|         UBusyGameplayEffectSubSystem EffectSubSystem = GetGameInstanceSubsystem<UBusyGameplayEffectSubSystem>();
 | ||
|         if (ASC == null || EffectSubSystem == null || FoxData == null) return false;
 | ||
|         
 | ||
|         ApplayCastEffect(CastTag);
 | ||
| 
 | ||
|         ASC.RemoveActiveGameplayEffect(SkillStateHandle);
 | ||
|         UGameplayEffect state_effect = EffectSubSystem.GetTagGrantEffectWithDuration(
 | ||
|             new FGameplayTagContainer(stateTag),
 | ||
|             new FGameplayTagContainer(), 0
 | ||
|         );
 | ||
|         FGameplayEffectSpecHandle stateSpecHandle = UBusyAscLibrary.MakeGameplayEffectSpecHandle(ASC, state_effect, 1);
 | ||
|         SkillStateHandle = ASC.ApplyGameplayEffectSpecToSelf(stateSpecHandle);
 | ||
|         return true;
 | ||
|     }
 | ||
|     protected bool TriggerAbility(int stage)
 | ||
|     {
 | ||
|         if (FoxData == null) return false;
 | ||
|         if (stage == 1)
 | ||
|         {
 | ||
|             if (!ApplyEffect(FoxData.FirstStageTag, FoxData.SecondStageCastTag)) return false;
 | ||
|         }
 | ||
|         else if (stage == 2)
 | ||
|         {
 | ||
|             if (!ApplyEffect(FoxData.SecondStageTag, new FGameplayTag())) return false;
 | ||
|         }
 | ||
|         else if(stage == 3)
 | ||
|         {
 | ||
|             if (!ApplyEffect(FoxData.LastStageTag, new FGameplayTag())) return false;
 | ||
|         }
 | ||
| 
 | ||
|         PlayAnimation(stage);
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     protected string GetAnimationName(FVector2D direction, int stage)
 | ||
|     {
 | ||
|         string animation_name_prefix = "";
 | ||
|         if (direction.X >= 0)
 | ||
|         {
 | ||
|             animation_name_prefix = "Ultimate/Right/";
 | ||
|         }
 | ||
|         else
 | ||
|         {
 | ||
|             animation_name_prefix = "Ultimate/Left/";
 | ||
|         }
 | ||
| 
 | ||
|         if (stage == 1)
 | ||
|         {
 | ||
|             return animation_name_prefix + "UltimateStage1";
 | ||
|         }
 | ||
|         else if (stage == 2)
 | ||
|         {
 | ||
|             return animation_name_prefix + "UltimateStage2";
 | ||
|         }
 | ||
|         else if (stage == 3)
 | ||
|         {
 | ||
|             return animation_name_prefix + "UltimateStage3";
 | ||
|         }
 | ||
|         return "";
 | ||
|     }
 | ||
| 
 | ||
|     [UFunction()]
 | ||
|     protected void OnAnimationComplete(UTrackEntry Entry)
 | ||
|     {
 | ||
|         Entry.AnimationComplete.Remove(OnAnimationComplete);
 | ||
|         if (ASC != null)
 | ||
|         {
 | ||
|             if (ASC.HasMatchingGameplayTag(FoxData.LastStageTag))
 | ||
|             {
 | ||
|                 CommitAbilityCooldown();
 | ||
|             }
 | ||
|             ASC.RemoveActiveGameplayEffect(SkillStateHandle);
 | ||
|         }
 | ||
|         EndAbility();
 | ||
|     }
 | ||
| 
 | ||
|     [UFunction()]
 | ||
|     protected void OnTailBeginOverlay(UPrimitiveComponent OverlappedComponent, AActor OtherActor,
 | ||
|         UPrimitiveComponent OtherComp, int OtherBodyIndex, bool bFromSweep, FHitResult SweepResult)
 | ||
|     {
 | ||
|         if (ASC == null || FoxData == null) return;
 | ||
| 
 | ||
|         bool bIsStage2 = ASC.HasMatchingGameplayTag(FoxData.SecondStageTag);
 | ||
| 
 | ||
|         if (bIsStage2 && !ASC.HasMatchingGameplayTag(FoxData.LastStageCastTag))
 | ||
|         {
 | ||
|             ApplayCastEffect(FoxData.LastStageCastTag);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     [UFunction()]
 | ||
|     protected void OnAnimationEvent(UTrackEntry Entry, FSpineEvent Event)
 | ||
|     {
 | ||
|         if (ASC == null || FoxData == null || Owner == null) return;
 | ||
|         if (Event.Name == "OnSpeedChange")
 | ||
|         {
 | ||
|             AccelerateHandle = MakeAccelerate(FoxData.LastStageSprintSpeedFactor, 1);
 | ||
|         }
 | ||
|         else if (Event.Name == "OnSpeedReset")
 | ||
|         {
 | ||
|             ASC.RemoveActiveGameplayEffect(AccelerateHandle);
 | ||
|         }
 | ||
|         else if (Event.Name == "OnDamageBegin")
 | ||
|         {
 | ||
|             Owner.SetTailCollisionEnabled(true);
 | ||
|             Owner.FoxTailCollision.OnComponentBeginOverlap.Add(OnTailBeginOverlay);
 | ||
|         }
 | ||
| 
 | ||
|         else if (Event.Name == "OnDamageEnd")
 | ||
|         {
 | ||
|             Owner.SetTailCollisionEnabled(false);
 | ||
|             Owner.FoxTailCollision.OnComponentBeginOverlap.Remove(OnTailBeginOverlay);
 | ||
|         }
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     protected FActiveGameplayEffectHandle MakeAccelerate(float SpeedFactor, float TotalTime)
 | ||
|     {
 | ||
|         GetAbilityEffectSpecHandle("Accelerate", ASC, 1, out FGameplayEffectSpecHandle handle);
 | ||
|         AbilitySystemLibrary.AssignTagSetByCallerMagnitude(
 | ||
|             handle, UBusyGameplayLibrary.RequestGameplayTag("Effect.Factor"),  SpeedFactor
 | ||
|         );
 | ||
|         AbilitySystemLibrary.AssignTagSetByCallerMagnitude(
 | ||
|             handle, UBusyGameplayLibrary.RequestGameplayTag("Effect.Duration"), TotalTime
 | ||
|         );
 | ||
|         return ApplyGameplayEffectSpecToOwner(handle);
 | ||
|     }
 | ||
|     
 | ||
| 
 | ||
|     protected bool PlayAnimation(int stage)
 | ||
|     {
 | ||
|         FVector2D AbilityDirection = new FVector2D(0, 1);
 | ||
|         if (UGameplayStatics.GetPlayerController(0) is ALevelPlayerController PC)
 | ||
|         {
 | ||
|             PC.GetCursorDirection(out AbilityDirection);
 | ||
|         }
 | ||
|         string AnimationName = GetAnimationName(AbilityDirection, stage);
 | ||
|         if (AnimationName == "") return false;
 | ||
| 
 | ||
|         USpineSkeletonAnimationComponent Animation = Owner.SpineAnimationComponent;
 | ||
|         UTrackEntry AnimEntry = Animation.SetAnimation(0, AnimationName, false);
 | ||
|         AnimEntry.AnimationEvent.Add(OnAnimationEvent);
 | ||
|         AnimEntry.AnimationComplete.Add(OnAnimationComplete);
 | ||
| 
 | ||
|         float TotalTime = AnimEntry.GetAnimationEnd();
 | ||
| 
 | ||
|         if (stage == 1) MakeAccelerate(FoxData.FirstStageSpeedFactor, TotalTime);
 | ||
|         else if (stage == 2) MakeAccelerate(FoxData.SecondStageSpeedFactor, TotalTime);
 | ||
|         else if (stage == 3) MakeAccelerate(FoxData.LastStageNormalSpeedFactor, TotalTime);
 | ||
|         Owner.MovementComponent.ActivateSprint(AbilityDirection, TotalTime);
 | ||
|         return true;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| // function FoxUltimate:ctor()
 | ||
| //     self.ultimate_phase = 1  -- 大招阶段
 | ||
| //     self.active_recast_handle = nil
 | ||
| //     self.active_accelerate_handle = nil
 | ||
| 
 | ||
| //     self.overlap_delegate_handle = nil
 | ||
| //     self.tag_add_or_remove_delegate = nil
 | ||
| // end
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // function FoxUltimate:OnAnimationComplete(entry)
 | ||
| //     local new_phase = self.ultimate_phase + 1
 | ||
| //     if new_phase > 3 then
 | ||
| //         self.ultimate_phase = 1
 | ||
| //     else
 | ||
| //         self.ultimate_phase = new_phase
 | ||
| //     end
 | ||
| //     print("FoxUltimate:OnAnimationComplete", self.ultimate_phase)
 | ||
| 
 | ||
| //     if not self.asc:HasMatchingGameplayTag(self.recast_tag) then
 | ||
| //         self.ultimate_phase = 1
 | ||
| //         self:K2_CommitAbilityCooldown(false, false)
 | ||
| //     end
 | ||
| 
 | ||
| //     entry.AnimationComplete:Clear()
 | ||
| //     entry.AnimationEvent:Clear()
 | ||
| //     self:K2_EndAbility()
 | ||
| // end
 | ||
| 
 | ||
| 
 |