| 
									
										
										
										
											2025-10-18 04:37:34 +08:00
										 |  |  |  | local GameplayStatics = import("GameplayStatics") | 
					
						
							|  |  |  |  | local AbilitySystemBlueprintLibrary = import("AbilitySystemBlueprintLibrary") | 
					
						
							|  |  |  |  | local BusyGameplayLibrary = import("BusyGameplayLibrary") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | --- @class FoxUltimate | 
					
						
							|  |  |  |  | --- @field RecastWindow number | 
					
						
							|  |  |  |  | local FoxUltimate = {} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:ctor() | 
					
						
							|  |  |  |  |     self.ultimate_phase = 1  -- 大招阶段 | 
					
						
							|  |  |  |  |     self.active_recast_handle = nil | 
					
						
							|  |  |  |  |     self.active_accelerate_handle = nil | 
					
						
							| 
									
										
										
										
											2025-10-18 17:30:58 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-19 03:33:01 +08:00
										 |  |  |  |     self.overlap_delegate_handle = nil | 
					
						
							| 
									
										
										
										
											2025-10-18 17:30:58 +08:00
										 |  |  |  |     self.tag_add_or_remove_delegate = nil | 
					
						
							| 
									
										
										
										
											2025-10-18 04:37:34 +08:00
										 |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:K2_ActivateAbilityFromEvent(EventData) | 
					
						
							|  |  |  |  |     print("FoxUltimate:K2_ActivateAbilityFromEvent", self.ultimate_phase) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-18 17:30:58 +08:00
										 |  |  |  |     if not self:K2_CommitAbilityCost(false) then | 
					
						
							|  |  |  |  |         return self:K2_EndAbility() | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-18 04:37:34 +08:00
										 |  |  |  |     local owner = self:GetOwningActorFromActorInfo() | 
					
						
							|  |  |  |  |     self.movement =  owner.MovementComponent | 
					
						
							|  |  |  |  |     self.animation = owner.SpineAnimationComponent | 
					
						
							|  |  |  |  |     self.asc = AbilitySystemBlueprintLibrary.GetAbilitySystemComponent(owner) | 
					
						
							|  |  |  |  |     self.recast_tag = BusyGameplayLibrary.RequestGameplayTag("Ability.Flags.Recast") | 
					
						
							| 
									
										
										
										
											2025-10-19 03:33:01 +08:00
										 |  |  |  |     self.owner = owner | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-18 04:37:34 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |     local asc = self.asc | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-18 17:30:58 +08:00
										 |  |  |  |     if self.tag_add_or_remove_delegate == nil then | 
					
						
							|  |  |  |  |         self.tag_add_or_remove_delegate = slua.createDelegate(function(tag, is_add) | 
					
						
							|  |  |  |  |             if is_add == 0 and not self.bIsActive then | 
					
						
							|  |  |  |  |                 self.ultimate_phase = 1 | 
					
						
							|  |  |  |  |                 self:K2_CommitAbilityCooldown(false, false) | 
					
						
							|  |  |  |  |             end | 
					
						
							|  |  |  |  |         end) | 
					
						
							|  |  |  |  |         owner:BindGameplayTagAddOrRemove(self.recast_tag, self.tag_add_or_remove_delegate) | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-18 04:37:34 +08:00
										 |  |  |  |     if self.ultimate_phase == 1 or asc:HasMatchingGameplayTag(self.recast_tag) then | 
					
						
							|  |  |  |  |         self:TriggerUltimate(asc) | 
					
						
							|  |  |  |  |     else | 
					
						
							|  |  |  |  |         self:K2_EndAbility() | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:TriggerUltimate(asc) | 
					
						
							|  |  |  |  |     if self.ultimate_phase == 1 then | 
					
						
							|  |  |  |  |         -- 第一次释放大招,添加一个可以再次释放的Tag | 
					
						
							|  |  |  |  |         local _, recast_effect = self:GetAbilityEffectSpecHandle("Recast", asc, 1, nil) | 
					
						
							|  |  |  |  |         self.active_recast_handle = asc:BP_ApplyGameplayEffectSpecToSelf(recast_effect) | 
					
						
							|  |  |  |  |     elseif self.ultimate_phase == 2 then | 
					
						
							|  |  |  |  |         -- 第二次激活,移除可重复释放的tag | 
					
						
							|  |  |  |  |         self.asc:RemoveActiveGameplayEffect(self.active_recast_handle, -1) | 
					
						
							|  |  |  |  |     elseif self.ultimate_phase == 3 then | 
					
						
							|  |  |  |  |         self.asc:RemoveActiveGameplayEffect(self.active_recast_handle, -1) | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     -- 播放动画,并监听动画完成的事件 | 
					
						
							|  |  |  |  |     self:PlayAnimation() | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:GetAnimationName(direction) | 
					
						
							|  |  |  |  |     local animation_name_prefix | 
					
						
							|  |  |  |  |     if direction.X >= 0 then | 
					
						
							|  |  |  |  |         animation_name_prefix = "Ultimate/Right/" | 
					
						
							|  |  |  |  |     else | 
					
						
							|  |  |  |  |         animation_name_prefix = "Ultimate/Left/" | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     if self.ultimate_phase == 1 then | 
					
						
							|  |  |  |  |         return animation_name_prefix .. "UltimateStage1" | 
					
						
							|  |  |  |  |     elseif self.ultimate_phase == 2 then | 
					
						
							|  |  |  |  |         return animation_name_prefix .. "UltimateStage2" | 
					
						
							|  |  |  |  |     elseif self.ultimate_phase == 3 then | 
					
						
							|  |  |  |  |         return animation_name_prefix .. "UltimateStage3" | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  |     return nil | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:K2_OnEndAbility(bWasCancelled) | 
					
						
							|  |  |  |  |     print("FoxUltimate:K2_OnEndAbility") | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:GetSprintSpeedFactor() | 
					
						
							|  |  |  |  |     if self.ultimate_phase == 1 then | 
					
						
							|  |  |  |  |         return 2.5 | 
					
						
							|  |  |  |  |     elseif self.ultimate_phase == 2 then | 
					
						
							|  |  |  |  |         return 2.8 | 
					
						
							|  |  |  |  |     elseif self.ultimate_phase == 3 then | 
					
						
							|  |  |  |  |         return 3.0 | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:PlayAnimation() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     local animation = self.animation | 
					
						
							|  |  |  |  |     local PC = GameplayStatics.GetPlayerController(self, 0) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     local result, ability_direction = PC:GetCursorDirection(nil)  -- 获取技能的朝向 | 
					
						
							|  |  |  |  |     if not result then | 
					
						
							|  |  |  |  |         print("FoxUltimate:TriggerPrimaryPhase can't find direction") | 
					
						
							|  |  |  |  |         return | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  |     local anim_name = self:GetAnimationName(ability_direction)  -- 获取技能动画名称 | 
					
						
							|  |  |  |  |     if not anim_name then | 
					
						
							|  |  |  |  |         print("FoxUltimate:TriggerPrimaryPhase can't get animation", self.ultimate_phase) | 
					
						
							|  |  |  |  |         return | 
					
						
							|  |  |  |  |     end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     local anim_entry = animation:SetAnimation(0, anim_name, false) | 
					
						
							|  |  |  |  |     anim_entry.AnimationComplete:Add(function(entry) self:OnAnimationComplete(entry) end) | 
					
						
							|  |  |  |  |     anim_entry.AnimationEvent:Add(function(entry, event) self:OnAnimationEvent(entry, event) end) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     local anim_total_time = anim_entry:GetAnimationEnd()  -- 获取技能动画时长 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     -- 附加加速buff | 
					
						
							|  |  |  |  |     self:MakeAccelerate(self:GetSprintSpeedFactor(), anim_total_time) | 
					
						
							|  |  |  |  |     self.movement:ActivateSprint(ability_direction, anim_total_time) | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:MakeAccelerate(speed_factor, total_time) | 
					
						
							|  |  |  |  |     local _, accelerate_effect = self:GetAbilityEffectSpecHandle("Accelerate", self.asc, 1, nil) | 
					
						
							|  |  |  |  |     AbilitySystemBlueprintLibrary.AssignTagSetByCallerMagnitude( | 
					
						
							|  |  |  |  |         accelerate_effect, | 
					
						
							|  |  |  |  |         BusyGameplayLibrary.RequestGameplayTag("Effect.Factor"), | 
					
						
							|  |  |  |  |         speed_factor | 
					
						
							|  |  |  |  |     ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     AbilitySystemBlueprintLibrary.AssignTagSetByCallerMagnitude( | 
					
						
							|  |  |  |  |         accelerate_effect, | 
					
						
							|  |  |  |  |         BusyGameplayLibrary.RequestGameplayTag("Effect.Duration"), | 
					
						
							|  |  |  |  |         total_time | 
					
						
							|  |  |  |  |     ) | 
					
						
							|  |  |  |  |     return self.asc:BP_ApplyGameplayEffectSpecToSelf(accelerate_effect) | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:OnAnimationComplete(entry) | 
					
						
							| 
									
										
										
										
											2025-10-18 17:30:58 +08:00
										 |  |  |  |     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 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-18 04:37:34 +08:00
										 |  |  |  |     entry.AnimationComplete:Clear() | 
					
						
							|  |  |  |  |     entry.AnimationEvent:Clear() | 
					
						
							|  |  |  |  |     self:K2_EndAbility() | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function FoxUltimate:OnAnimationEvent(entry, event) | 
					
						
							|  |  |  |  |     if event.Name == "OnSpeedChange" then | 
					
						
							|  |  |  |  |         self.active_accelerate_handle = self:MakeAccelerate(8.0, 0.5) | 
					
						
							|  |  |  |  |     elseif event.Name == "OnSpeedReset" then | 
					
						
							|  |  |  |  |         self.asc:RemoveActiveGameplayEffect(self.active_accelerate_handle, -1) | 
					
						
							| 
									
										
										
										
											2025-10-19 03:33:01 +08:00
										 |  |  |  |     elseif event.Name == "OnDamageBegin" then | 
					
						
							|  |  |  |  |         local collision = self.owner["TailCollision"] | 
					
						
							|  |  |  |  |         collision:SetCollisionEnabled(1) | 
					
						
							|  |  |  |  |         self.overlap_delegate_handle = collision.OnComponentBeginOverlap:Add(function() | 
					
						
							|  |  |  |  |             if not self.asc:HasMatchingGameplayTag(self.recast_tag) then | 
					
						
							|  |  |  |  |                 local _, recast_effect = self:GetAbilityEffectSpecHandle("Recast", self.asc, 1, nil) | 
					
						
							|  |  |  |  |                 self.active_recast_handle = self.asc:BP_ApplyGameplayEffectSpecToSelf(recast_effect) | 
					
						
							|  |  |  |  |             end | 
					
						
							|  |  |  |  |         end) | 
					
						
							|  |  |  |  |     elseif event.Name == "OnDamageEnd" then | 
					
						
							|  |  |  |  |         self.owner["TailCollision"]:SetCollisionEnabled(0) | 
					
						
							|  |  |  |  |         if self.overlap_delegate_handle ~= nil then | 
					
						
							|  |  |  |  |             self.owner["TailCollision"].OnComponentBeginOverlap:Remove(self.overlap_delegate_handle) | 
					
						
							|  |  |  |  |             self.overlap_delegate_handle = nil | 
					
						
							|  |  |  |  |         end | 
					
						
							| 
									
										
										
										
											2025-10-18 04:37:34 +08:00
										 |  |  |  |     end | 
					
						
							|  |  |  |  | end | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | return Class(nil, nil, FoxUltimate) |