Files
BusyRabbit/Script/ManagedBusyRabbit/GameAbilitySystem/Ability/Role/Fox/FoxUltimate.cs
wyatt 8c0623b397 Lua向C#逻辑迁移 一期 #13
狐狸移动,技能迁移和完善
2025-10-26 15:46:04 +08:00

344 lines
11 KiB
C#
Raw 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.

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