enum ETakedownActionType
{
	GrappleFailed = 0,
	Grapple = 1,
	Takedown = 2,
	TakedownNonLethal = 3,
	TakedownNetrunner = 4,
	TakedownMassiveTarget = 5,
	AerialTakedown = 6,
	LeapToTarget = 7,
	Struggle = 8,
	BreakFree = 9,
	TargetDead = 10,
	KillTarget = 11,
	SpareTarget = 12,
	ForceShove = 13,
	BossTakedown = 14,
	DisposalTakedown = 15,
	DisposalTakedownNonLethal = 16,
	None = 17,
}

enum ETakedownBossName
{
	Smasher = 0,
	Oda = 1,
	Royce = 2,
	Sasquatch = 3,
	None = 4,
}

class TakedownUtils
{

	public static function SetInGrappleAnimFeature( scriptInterface : StateGameScriptInterface, b : Bool )
	{
		var animFeature : AnimFeature_Grapple;
		animFeature = new AnimFeature_Grapple;
		animFeature.inGrapple = b;
		scriptInterface.SetAnimationParameterFeature( 'Grapple', animFeature, scriptInterface.executionOwner );
	}

	public static function SetIgnoreLookAtEntity( scriptInterface : StateGameScriptInterface, target : weak< GameObject >, b : Bool )
	{
		var targetingSystem : TargetingSystem;
		targetingSystem = scriptInterface.GetTargetingSystem();
		if( b == true )
		{
			targetingSystem.AddIgnoredLookAtEntity( scriptInterface.executionOwner, target.GetEntityID() );
		}
		else
		{
			targetingSystem.RemoveIgnoredLookAtEntity( scriptInterface.executionOwner, target.GetEntityID() );
		}
	}

	public static function SetIgnoreLookAtEntity( scriptInterface : StateGameScriptInterface, targetID : EntityID, b : Bool )
	{
		var targetingSystem : TargetingSystem;
		targetingSystem = scriptInterface.GetTargetingSystem();
		if( b == true )
		{
			targetingSystem.AddIgnoredLookAtEntity( scriptInterface.executionOwner, targetID );
		}
		else
		{
			targetingSystem.RemoveIgnoredLookAtEntity( scriptInterface.executionOwner, targetID );
		}
	}

	public static function TakedownActionNameToEnum( actionName : CName ) : ETakedownActionType
	{
		switch( actionName )
		{
			case 'GrappleFailed':
				return ETakedownActionType.GrappleFailed;
			case 'GrappleTarget':
				return ETakedownActionType.Grapple;
			case 'Takedown':
				return ETakedownActionType.Takedown;
			case 'TakedownNonLethal':
				return ETakedownActionType.TakedownNonLethal;
			case 'TakedownNetrunner':
				return ETakedownActionType.TakedownNetrunner;
			case 'TakedownMassiveTarget':
				return ETakedownActionType.TakedownMassiveTarget;
			case 'LeapToTarget':
				return ETakedownActionType.LeapToTarget;
			case 'AerialTakedown':
				return ETakedownActionType.AerialTakedown;
			case 'Struggle':
				return ETakedownActionType.Struggle;
			case 'BreakFree':
				return ETakedownActionType.BreakFree;
			case 'TargetDead':
				return ETakedownActionType.TargetDead;
			case 'KillTarget':
				return ETakedownActionType.KillTarget;
			case 'SpareTarget':
				return ETakedownActionType.SpareTarget;
			case 'ForceShove':
				return ETakedownActionType.ForceShove;
			case 'BossTakedown':
				return ETakedownActionType.BossTakedown;
			default:
				break;
		}
		return ETakedownActionType.None;
	}

	public static function SetTakedownAction( stateContext : StateContext, actionName : ETakedownActionType )
	{
		var enumName : CName;
		enumName = EnumValueToName( 'ETakedownActionType', ( ( Int32 )( actionName ) ) );
		stateContext.SetPermanentCNameParameter( 'ETakedownActionType', enumName, true );
	}

	public static function SetTargetBodyType( executionOwner : weak< GameObject >, target : weak< GameObject >, enable : Bool )
	{
		var bodyTypeVarSetter : AnimWrapperWeightSetter;
		var targetPuppet : gamePuppet;
		var bodyType : CName;
		targetPuppet = ( ( gamePuppet )( target ) );
		if( !( targetPuppet ) )
		{
			return;
		}
		bodyType = targetPuppet.GetBodyType();
		bodyTypeVarSetter = new AnimWrapperWeightSetter;
		bodyTypeVarSetter.key = bodyType;
		bodyTypeVarSetter.value = ( ( enable ) ? ( 1.0 ) : ( 0.0 ) );
		executionOwner.QueueEvent( bodyTypeVarSetter );
	}

	public static function CleanUpGrappleState( caller : DefaultTransition, stateContext : StateContext, scriptInterface : StateGameScriptInterface, target : weak< GameObject > )
	{
		var broadcaster : StimBroadcasterComponent;
		SetInGrappleAnimFeature( scriptInterface, false );
		( ( NPCPuppet )( target ) ).MountingEndEnableComponents();
		StatusEffectHelper.RemoveStatusEffect( scriptInterface.executionOwner, T"BaseStatusEffect.HumanShield" );
		if( target.IsAttached() )
		{
			StatusEffectHelper.RemoveStatusEffect( target, T"BaseStatusEffect.Grappled" );
		}
		StatusEffectHelper.RemoveStatusEffect( target, T"BaseStatusEffect.ForceVisibility" );
		StatusEffectHelper.RemoveStatusEffect( scriptInterface.executionOwner, T"GameplayRestriction.NoRadialMenus" );
		SetIgnoreLookAtEntity( scriptInterface, target, false );
		caller.SetGameplayCameraParameters( scriptInterface, "cameraDefault" );
		SetTakedownAction( stateContext, TakedownActionNameToEnum( '' ) );
		SetTargetBodyType( scriptInterface.executionOwner, target, false );
		broadcaster = scriptInterface.executionOwner.GetStimBroadcasterComponent();
		if( broadcaster )
		{
			broadcaster.RemoveActiveStimuliByName( scriptInterface.executionOwner, gamedataStimType.IllegalInteraction );
		}
		target.QueueEvent( new EnableAimAssist );
	}

	public static function CleanUpGrappleState( caller : DefaultTransition, stateContext : StateContext, scriptInterface : StateGameScriptInterface, targetID : EntityID )
	{
		var broadcaster : StimBroadcasterComponent;
		SetInGrappleAnimFeature( scriptInterface, false );
		StatusEffectHelper.RemoveStatusEffect( scriptInterface.executionOwner, T"BaseStatusEffect.HumanShield" );
		StatusEffectHelper.RemoveStatusEffect( scriptInterface.executionOwner, T"GameplayRestriction.NoRadialMenus" );
		SetIgnoreLookAtEntity( scriptInterface, targetID, false );
		caller.SetGameplayCameraParameters( scriptInterface, "cameraDefault" );
		SetTakedownAction( stateContext, TakedownActionNameToEnum( '' ) );
		broadcaster = scriptInterface.executionOwner.GetStimBroadcasterComponent();
		if( broadcaster )
		{
			broadcaster.RemoveActiveStimuliByName( scriptInterface.executionOwner, gamedataStimType.IllegalInteraction );
		}
	}

	public static function ExitWorkspot( scriptInterface : StateGameScriptInterface, owner : GameObject )
	{
		var workspotSystem : WorkspotGameSystem;
		workspotSystem = scriptInterface.GetWorkspotSystem();
		workspotSystem.SendFastExitSignal( owner );
	}

	public static function ShouldForceTakedown( scriptInterface : StateGameScriptInterface ) : Bool
	{
		var tier : Int32;
		if( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Zones ) == ( ( Int32 )( gamePSMZones.Safe ) ) )
		{
			return true;
		}
		tier = scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.HighLevel );
		if( ( tier > ( ( Int32 )( gamePSMHighLevel.SceneTier1 ) ) ) && ( tier <= ( ( Int32 )( gamePSMHighLevel.SceneTier5 ) ) ) )
		{
			return true;
		}
		return false;
	}

}

class LocomotionTakedownDecisions extends LocomotionTransition
{

	protected const function IsTakedownAction( actionName : CName ) : Bool
	{
		return ( actionName == 'Takedown' || actionName == 'TakedownNonLethal' ) || actionName == 'TakedownNetrunner';
	}

	protected const function IsTakedownAndDispose( const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return 5 == scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Takedown );
	}

	protected const function IsPowerLevelDifferentialTooHigh( target : weak< GameObject > ) : Bool
	{
		var powDifference : gameEPowerDifferential;
		powDifference = RPGManager.CalculatePowerDifferential( target );
		if( powDifference == gameEPowerDifferential.IMPOSSIBLE )
		{
			return true;
		}
		return false;
	}

	protected const function ShouldInstantlyBreakFree( target : weak< ScriptedPuppet > ) : Bool
	{
		if( !( target ) )
		{
			return false;
		}
		if( target.IsMassive() )
		{
			return IsPowerLevelDifferentialTooHigh( target );
		}
		return false;
	}

}

class LocomotionTakedownEvents extends LocomotionEventsTransition
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	protected function JumpToIdleAnimation( scriptInterface : StateGameScriptInterface, target : weak< GameObject > )
	{
		JumpToAnimationWithID( scriptInterface, scriptInterface.executionOwner, 36, true );
		JumpToAnimationWithID( scriptInterface, target, 28, true );
	}

	protected function JumpToWalkAnimation( scriptInterface : StateGameScriptInterface, target : weak< GameObject > )
	{
		JumpToAnimationWithID( scriptInterface, scriptInterface.executionOwner, 40, true );
		JumpToAnimationWithID( scriptInterface, target, 32, true );
	}

	protected function JumpToStruggleAnimation( scriptInterface : StateGameScriptInterface, target : weak< GameObject > )
	{
		JumpToAnimationWithID( scriptInterface, scriptInterface.executionOwner, 32, true );
		JumpToAnimationWithID( scriptInterface, target, 19, true );
	}

	protected const function IsTakedownAndDispose( const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return 5 == scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Takedown );
	}

	protected function SetPlayerIsStandingAnimParameter( scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.SetAnimationParameterFloat( 'crouch', 0.0 );
	}

	protected function SetGrappleDuration( stateContext : StateContext, scriptInterface : StateGameScriptInterface, grappleDuration : Float, target : GameObject )
	{
		var statSystem : StatsSystem;
		var targetRarity : Float;
		var grappleTime : Float;
		statSystem = scriptInterface.GetStatsSystem();
		targetRarity = statSystem.GetStatValue( target.GetEntityID(), gamedataStatType.NPCRarity );
		grappleTime = grappleDuration - ( targetRarity * 1.5 );
		stateContext.SetPermanentFloatParameter( 'grappleTime', grappleTime, true );
	}

	protected function ForceTemporaryWeaponUnequip( stateContext : StateContext, scriptInterface : StateGameScriptInterface, value : Bool )
	{
		stateContext.SetPermanentBoolParameter( 'forcedTemporaryUnequip', value, true );
	}

	protected function RequestTimeDilationActivation( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		return stateContext.SetTemporaryBoolParameter( 'requestKerenzikovActivation', true, true );
	}

	protected function InterruptCameraAim( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		stateContext.SetTemporaryBoolParameter( 'InterruptAiming', true, true );
	}

	protected function GetRightHandItemObject( scriptInterface : StateGameScriptInterface ) : ItemObject
	{
		return scriptInterface.GetTransactionSystem().GetItemInSlot( scriptInterface.executionOwner, T"AttachmentSlots.WeaponRight" );
	}

	protected function GetRightHandItemName( scriptInterface : StateGameScriptInterface ) : CName
	{
		return StringToName( TweakDBInterface.GetItemRecord( ItemID.GetTDBID( GetRightHandItemObject( scriptInterface ).GetItemID() ) ).FriendlyName() );
	}

	protected function GetRightHandItemType( scriptInterface : StateGameScriptInterface ) : CName
	{
		return TweakDBInterface.GetItemRecord( ItemID.GetTDBID( GetRightHandItemObject( scriptInterface ).GetItemID() ) ).ItemType().Name();
	}

	protected function IsTakedownWeapon( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		return GetWeaponItemTag( stateContext, scriptInterface, 'TakedownWeapon' );
	}

	protected function FillAnimWrapperInfoBasedOnEquippedItem( scriptInterface : StateGameScriptInterface, clearWrapperInfo : Bool )
	{
		var animWrapperEvent : FillAnimWrapperInfoBasedOnEquippedItem;
		animWrapperEvent = new FillAnimWrapperInfoBasedOnEquippedItem;
		animWrapperEvent.itemID = GetRightHandItemObject( scriptInterface ).GetItemID();
		animWrapperEvent.itemType = GetRightHandItemType( scriptInterface );
		animWrapperEvent.itemName = GetRightHandItemName( scriptInterface );
		animWrapperEvent.clearWrapperInfo = clearWrapperInfo;
		scriptInterface.owner.QueueEventForEntityID( scriptInterface.executionOwnerEntityID, animWrapperEvent );
	}

	protected function PlayExitAnimation( scriptInterface : StateGameScriptInterface, owner : GameObject, target : GameObject, syncedAnimName : CName )
	{
		var workspotSystem : WorkspotGameSystem;
		workspotSystem = scriptInterface.GetWorkspotSystem();
		workspotSystem.SendJumpToAnimEnt( owner, syncedAnimName, true );
	}

	protected function JumpToNextAnimationInSequence( scriptInterface : StateGameScriptInterface, owner : GameObject )
	{
		var workspotSystem : WorkspotGameSystem;
		workspotSystem = scriptInterface.GetWorkspotSystem();
		workspotSystem.SendForwardSignal( owner );
	}

	protected function JumpToAnimationWithID( scriptInterface : StateGameScriptInterface, owner : GameObject, ownerEntryId : Int32, instant : Bool )
	{
		var workspotSystem : WorkspotGameSystem;
		workspotSystem = scriptInterface.GetWorkspotSystem();
		workspotSystem.SendJumpCommandEnt( owner, ownerEntryId, instant );
	}

	protected function SelectRandomSyncedAnimation( stateContext : StateContext ) : CName
	{
		var range : Int32;
		var takedownAction : String;
		var takedownName : CName;
		if( GetStaticIntParameterDefault( "DEBUG_forceSelectTakedownAnimation", -1 ) >= 0 )
		{
			range = GetStaticIntParameterDefault( "DEBUG_forceSelectTakedownAnimation", -1 );
		}
		else
		{
			range = RandRange( 0, 3 );
		}
		if( GetTakedownAction( stateContext ) == ETakedownActionType.Takedown )
		{
			takedownAction = NameToString( 'grapple_sync_kill' );
		}
		else if( GetTakedownAction( stateContext ) == ETakedownActionType.TakedownNonLethal )
		{
			takedownAction = NameToString( 'grapple_sync_nonlethal' );
		}
		switch( range )
		{
			case 0:
				takedownName = StringToName( takedownAction );
			break;
			case 1:
				takedownAction += "_02";
			takedownName = StringToName( takedownAction );
			break;
			case 2:
				takedownAction += "_03";
			takedownName = StringToName( takedownAction );
			break;
			default:
				takedownName = StringToName( takedownAction );
			break;
		}
		return takedownName;
	}

	protected function GetBossNameBasedOnRecord( target : GameObject ) : ETakedownBossName
	{
		var targetPuppet : weak< ScriptedPuppet >;
		targetPuppet = ( ( ScriptedPuppet )( target ) );
		switch( targetPuppet.GetRecordID() )
		{
			case T"Character.main_boss_adam_smasher":
			case T"Character.q113_boss_smasher":
			case T"Character.q116_boss_smasher":
				return ETakedownBossName.Smasher;
			case T"Character.main_boss_oda":
			case T"Character.Cyberninja_Oda":
				return ETakedownBossName.Oda;
			case T"Character.main_boss_royce":
			case T"Character.q003_royce_boss":
			case T"Character.arasaka_exo":
			case T"Character.militech_exo":
			case T"Character.ma_std_rcr_11_cyberpsycho":
			case T"Character.ma_bls_ina_se1_07_cyberpsycho_1":
			case T"Character.we_ep1_01_mini_boss_2nd_phase":
				return ETakedownBossName.Royce;
			case T"Character.main_boss_sasquatch":
			case T"Character.q114_main_boss_sasquatch":
			case T"Character.q110_animals_boss":
				return ETakedownBossName.Sasquatch;
			default:
				break;
		}
		return ETakedownBossName.None;
	}

	protected function GetCurrentBossPhase( target : GameObject, stateContext : StateContext, out phase : Int32 )
	{
		var currentBossPhase : Int32;
		switch( GetBossNameBasedOnRecord( target ) )
		{
			case ETakedownBossName.Smasher:
				if( StatusEffectSystem.ObjectHasStatusEffect( target, T"AdamSmasher.Phase3" ) )
				{
					currentBossPhase = 3;
				}
				else if( StatusEffectSystem.ObjectHasStatusEffect( target, T"AdamSmasher.Phase2" ) )
				{
					currentBossPhase = 2;
				}
				else if( StatusEffectSystem.ObjectHasStatusEffect( target, T"AdamSmasher.Phase1" ) )
				{
					currentBossPhase = 1;
				}
			break;
			case ETakedownBossName.Oda:
				if( StatusEffectSystem.ObjectHasStatusEffect( target, T"Oda.Masked" ) )
				{
					currentBossPhase = 1;
				}
				else
				{
					currentBossPhase = 2;
				}
			break;
			case ETakedownBossName.Royce:
				if( !( StatusEffectSystem.ObjectHasStatusEffect( target, T"Royce.Phase2" ) ) )
				{
					currentBossPhase = 1;
				}
				else
				{
					currentBossPhase = 2;
				}
			break;
			case ETakedownBossName.Sasquatch:
				if( StatusEffectSystem.ObjectHasStatusEffect( target, T"BaseStatusEffect.PainInhibitors" ) )
				{
					currentBossPhase = 1;
				}
				else
				{
					currentBossPhase = 2;
				}
			break;
			default:
				break;
		}
		phase = currentBossPhase;
	}

	protected function SelectSyncedAnimationBasedOnPhase( stateContext : StateContext, target : GameObject ) : CName
	{
		var phase : Int32;
		var bossSyncAnimName : String;
		var takedownName : CName;
		switch( GetBossNameBasedOnRecord( target ) )
		{
			case ETakedownBossName.Smasher:
				bossSyncAnimName = "smasher_takedown_phase";
			break;
			case ETakedownBossName.Oda:
				bossSyncAnimName = "oda_takedown_phase";
			break;
			case ETakedownBossName.Royce:
				bossSyncAnimName = "royce_takedown_phase";
			break;
			case ETakedownBossName.Sasquatch:
				bossSyncAnimName = "sasquatch_takedown_phase";
			break;
			default:
				break;
		}
		GetCurrentBossPhase( target, stateContext, phase );
		if( IsStringValid( bossSyncAnimName ) )
		{
			switch( phase )
			{
				case 1:
					takedownName = StringToName( bossSyncAnimName );
				break;
				case 2:
					bossSyncAnimName += "_02";
				takedownName = StringToName( bossSyncAnimName );
				break;
				case 3:
					bossSyncAnimName += "_03";
				takedownName = StringToName( bossSyncAnimName );
				break;
				case 4:
					bossSyncAnimName += "_04";
				takedownName = StringToName( bossSyncAnimName );
				break;
				default:
					takedownName = StringToName( bossSyncAnimName );
				break;
			}
		}
		stateContext.SetPermanentCNameParameter( 'syncedAnimationBasedOnPhaseName', takedownName, true );
		return takedownName;
	}

	protected function GetSyncedAnimationBasedOnPhase( stateContext : StateContext ) : CName
	{
		var syncedAnimationName : CName;
		var param : StateResultCName;
		param = stateContext.GetPermanentCNameParameter( 'syncedAnimationBasedOnPhaseName' );
		return syncedAnimationName = param.value;
	}

	protected function SetEffectorBasedOnPhase( stateContext : StateContext ) : CName
	{
		var effectorBasedOnPhaseName : CName;
		var syncedAnimationString : String;
		var param : StateResultCName;
		param = stateContext.GetPermanentCNameParameter( 'syncedAnimationBasedOnPhaseName' );
		effectorBasedOnPhaseName = param.value;
		if( IsNameValid( effectorBasedOnPhaseName ) )
		{
			syncedAnimationString = NameToString( effectorBasedOnPhaseName );
			effectorBasedOnPhaseName = StringToName( syncedAnimationString + "_damage" );
		}
		return effectorBasedOnPhaseName;
	}

	protected function SelectAerialTakedownWorkspot( scriptInterface : StateGameScriptInterface, owner : GameObject, target : GameObject, optional back : Bool, optional front : Bool, optional left : Bool, optional right : Bool, action : CName ) : CName
	{
		var angleBetweenOwnerAndTarget : Float;
		var takedownName : CName;
		var takedown : String;
		var result : CName;
		var weaponType : gamedataItemType;
		takedownName = action;
		result = takedownName;
		angleBetweenOwnerAndTarget = Vector4.GetAngleBetween( owner.GetWorldForward(), target.GetWorldForward() );
		if( IsNameValid( takedownName ) )
		{
			if( back && ( AbsF( angleBetweenOwnerAndTarget ) < 90.0 ) )
			{
				takedown = NameToString( takedownName );
				takedown += "_Back";
				takedownName = StringToName( takedown );
				result = takedownName;
			}
			else if( front && ( AbsF( angleBetweenOwnerAndTarget ) >= 90.0 ) )
			{
				result = takedownName;
			}
			weaponType = TDB.GetWeaponItemRecord( ItemID.GetTDBID( ScriptedPuppet.GetWeaponRight( owner ).GetItemID() ) ).ItemType().Type();
			if( weaponType == gamedataItemType.Cyb_MantisBlades )
			{
				takedown = NameToString( takedownName );
				takedown += "_MantisBlades";
				takedownName = StringToName( takedown );
				result = takedownName;
			}
			else if( !( GameInstance.GetAINavigationSystem( scriptInterface.GetGame() ).HasPathForward( stateMachineInitData.target, 1.0 ) ) || !( SpatialQueriesHelper.HasSpaceInFront( scriptInterface.executionOwner, 0.34999999, 0.89999998, GetStaticFloatParameterDefault( "minRequiredSpace", 0.1 ), 1.25 ) ) )
			{
				takedown = NameToString( takedownName );
				takedown += "_Simple";
				takedownName = StringToName( takedown );
				result = takedownName;
			}
		}
		return result;
	}

	protected function SelectSyncedAnimationAndExecuteAction( stateContext : StateContext, scriptInterface : StateGameScriptInterface, owner : GameObject, target : GameObject, action : CName )
	{
		var syncedAnimName : CName;
		var effectTag : CName;
		var gameEffectName : CName;
		var dataTrackingEvent : TakedownActionDataTrackingRequest;
		dataTrackingEvent = new TakedownActionDataTrackingRequest;
		gameEffectName = 'takedowns';
		switch( GetTakedownAction( stateContext ) )
		{
			case ETakedownActionType.GrappleFailed:
				TakedownGameEffectHelper.FillTakedownData( scriptInterface.executionOwner, owner, target, gameEffectName, action, "" );
			break;
			case ETakedownActionType.TargetDead:
				syncedAnimName = 'grapple_sync_death';
			break;
			case ETakedownActionType.BreakFree:
				syncedAnimName = 'grapple_sync_recover';
			break;
			case ETakedownActionType.Takedown:
				syncedAnimName = SelectRandomSyncedAnimation( stateContext );
			effectTag = 'kill';
			( ( NPCPuppet )( target ) ).SetMyKiller( owner );
			break;
			case ETakedownActionType.TakedownNonLethal:
				if( stateContext.GetConditionBool( 'CrouchToggled' ) )
				{
					syncedAnimName = 'grapple_sync_nonlethal_crouch';
				}
				else
				{
					syncedAnimName = SelectRandomSyncedAnimation( stateContext );
				}
			effectTag = 'setUnconscious';
			break;
			case ETakedownActionType.TakedownNetrunner:
				syncedAnimName = 'personal_link_takedown_01';
			effectTag = 'setUnconsciousTakedownNetrunner';
			break;
			case ETakedownActionType.TakedownMassiveTarget:
				TakedownGameEffectHelper.FillTakedownData( scriptInterface.executionOwner, owner, target, gameEffectName, action, "" );
			effectTag = 'setUnconsciousTakedownMassiveTarget';
			break;
			case ETakedownActionType.AerialTakedown:
				TakedownGameEffectHelper.FillTakedownData( scriptInterface.executionOwner, owner, target, gameEffectName, SelectAerialTakedownWorkspot( scriptInterface, owner, target, true, true, false, false, action ) );
			effectTag = 'setUnconsciousAerialTakedown';
			break;
			case ETakedownActionType.BossTakedown:
				TakedownGameEffectHelper.FillTakedownData( scriptInterface.executionOwner, owner, target, gameEffectName, SelectSyncedAnimationBasedOnPhase( stateContext, target ), "" );
			effectTag = SetEffectorBasedOnPhase( stateContext );
			syncedAnimName = GetSyncedAnimationBasedOnPhase( stateContext );
			StatusEffectHelper.ApplyStatusEffect( target, T"BaseStatusEffect.BossTakedownCooldown" );
			target.GetTargetTrackerComponent().AddThreat( owner, true, owner.GetWorldPosition(), 1.0, 10.0, false );
			break;
			case ETakedownActionType.ForceShove:
				syncedAnimName = 'grapple_sync_shove';
			break;
			default:
				syncedAnimName = 'grapple_sync_kill';
			effectTag = 'kill';
			break;
		}
		if( ( IsNameValid( syncedAnimName ) && owner ) && target )
		{
			if( IsTakedownWeapon( stateContext, scriptInterface ) )
			{
				FillAnimWrapperInfoBasedOnEquippedItem( scriptInterface, false );
			}
			PlayExitAnimation( scriptInterface, owner, target, syncedAnimName );
		}
		dataTrackingEvent.eventType = GetTakedownAction( stateContext );
		scriptInterface.GetScriptableSystem( 'DataTrackingSystem' ).QueueRequest( dataTrackingEvent );
		DefeatTarget( stateContext, scriptInterface, owner, target, gameEffectName, effectTag );
	}

	private function DefeatTarget( stateContext : StateContext, scriptInterface : StateGameScriptInterface, activator : weak< GameObject >, target : weak< GameObject >, effectName : CName, effectTag : CName )
	{
		if( ( effectTag == 'setUnconscious' || effectTag == 'setUnconsciousAerialTakedown' ) || effectTag == 'setUnconsciousTakedownMassiveTarget' )
		{
			ScriptedPuppet.SendActionSignal( ( ( NPCPuppet )( target ) ), 'takedown_defeat', -1.0 );
		}
		TakedownGameEffectHelper.FillTakedownData( scriptInterface.executionOwner, activator, target, effectName, effectTag );
		ScriptedPuppet.SetBloodPuddleSettings( ( ( ScriptedPuppet )( target ) ), false );
	}

	public function TestNPCOutsideNavmesh( scriptInterface : StateGameScriptInterface, activator : weak< GameObject >, target : weak< GameObject >, timeToTick : Float, b : Bool )
	{
		var evt : TestNPCOutsideNavmeshEvent;
		if( !( target ) )
		{
			return;
		}
		evt = new TestNPCOutsideNavmeshEvent;
		evt.activator = activator;
		evt.target = target;
		evt.enable = b;
		scriptInterface.GetDelaySystem().DelayEvent( target, evt, timeToTick );
	}

	public export override function OnForcedExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		TakedownUtils.ExitWorkspot( scriptInterface, scriptInterface.executionOwner );
		TakedownUtils.CleanUpGrappleState( this, stateContext, scriptInterface, stateMachineInitData.target );
	}

}

class TakedownBeginDecisions extends LocomotionTakedownDecisions
{

	protected constexpr const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return true;
	}

	protected constexpr const function ExitCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return true;
	}

}

class TakedownBeginEvents extends LocomotionTakedownEvents
{

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var targetPuppet : gamePuppet;
		var vaultInfo : PlayerClimbInfo;
		vaultInfo = scriptInterface.GetSpatialQueriesSystem().GetPlayerObstacleSystem().GetCurrentClimbInfo( scriptInterface.owner );
		stateContext.SetPermanentBoolParameter( 'PlayerFacingVaultableWall', vaultInfo.vaultValid, true );
		if( vaultInfo.vaultValid )
		{
			stateContext.SetPermanentVectorParameter( 'VaultableWallEndPoint', vaultInfo.obstacleEnd, true );
		}
		targetPuppet = ( ( gamePuppet )( stateMachineInitData.target ) );
		TakedownUtils.SetTakedownAction( stateContext, TakedownUtils.TakedownActionNameToEnum( stateMachineInitData.actionName ) );
		TakedownUtils.SetTargetBodyType( scriptInterface.executionOwner, stateMachineInitData.target, true );
		SetBlackboardIntVariable( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.Takedown, ( ( Int32 )( gamePSMTakedown.EnteringGrapple ) ) );
		SetBlackboardEntityID( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.TakedownTargetID, targetPuppet.GetEntityID() );
		TakedownUtils.SetInGrappleAnimFeature( scriptInterface, true );
		targetPuppet.QueueEvent( new DisableAimAssist );
		StatusEffectHelper.ApplyStatusEffect( scriptInterface.executionOwner, T"GameplayRestriction.NoRadialMenus" );
		( ( ScriptedPuppet )( targetPuppet ) ).GetBumpComponent().Toggle( false );
		UpdateCameraParams( stateContext, scriptInterface );
		SetGameplayCameraParameters( scriptInterface, "cameraTakedowns" );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class TakedownLeapToPreyDecisions extends LocomotionTakedownDecisions
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( stateMachineInitData.actionName == 'LeapToTarget' )
		{
			return true;
		}
		return false;
	}

	protected export const function ToTakedownExecuteTakedown( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return TestTakedownEnterConditions( stateContext, scriptInterface );
	}

	protected const function ToTakedownEnd( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( GetInStateTime() >= GetStaticFloatParameterDefault( "maxDuration", 3.0 ) )
		{
			return true;
		}
		if( CollisionBetweenPlayerAndTarget( stateContext, scriptInterface ) )
		{
			return true;
		}
		return false;
	}

	protected const function TestTakedownEnterConditions( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( CollisionBetweenPlayerAndTarget( stateContext, scriptInterface ) )
		{
			return false;
		}
		return true;
	}

	protected const function CollisionBetweenPlayerAndTarget( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var geometryDescription : GeometryDescriptionQuery;
		var queryFilter : QueryFilter;
		var geometryDescriptionResult : GeometryDescriptionResult;
		var currentPosition : Vector4;
		currentPosition = GetPlayerPosition( scriptInterface );
		QueryFilter.AddGroup( queryFilter, 'Static' );
		geometryDescription = new GeometryDescriptionQuery;
		geometryDescription.AddFlag( worldgeometryDescriptionQueryFlags.DistanceVector );
		geometryDescription.filter = queryFilter;
		geometryDescription.refPosition = currentPosition;
		geometryDescription.refDirection = Vector4( 0.0, 0.0, -1.0, 0.0 );
		geometryDescription.primitiveDimension = Vector4( 0.2, 0.1, 0.1, 0.0 );
		geometryDescription.maxDistance = 0.5;
		geometryDescription.maxExtent = 0.5;
		geometryDescription.probingPrecision = 10.0;
		geometryDescription.probingMaxDistanceDiff = 0.5;
		geometryDescriptionResult = scriptInterface.GetSpatialQueriesSystem().GetGeometryDescriptionSystem().QueryExtents( geometryDescription );
		if( geometryDescriptionResult.queryStatus == worldgeometryDescriptionQueryStatus.NoGeometry )
		{
			return false;
		}
		return true;
	}

}

class TakedownLeapToPreyEvents extends LocomotionTakedownEvents
{

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnEnter( stateContext, scriptInterface );
		StopEffect( scriptInterface, 'falling' );
		PlaySound( 'lcm_falling_wind_loop_end', scriptInterface );
		SetLocomotionParameters( stateContext, scriptInterface );
		SetBlackboardIntVariable( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.Takedown, ( ( Int32 )( gamePSMTakedown.Leap ) ) );
	}

	private function RequestPositionAdjustmentWithParabolicMotion( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var adjustPosition : Vector4;
		var distanceFromTarget : Vector4;
		var safetyDisplacement : Vector4;
		var scaledSafetyDisplacement : Vector4;
		var playerPuppetOrientation : Quaternion;
		var horizontalDistanceFromTarget : Float;
		var additionalHorizontalDistance : Float;
		safetyDisplacement.Y = GetStaticFloatParameterDefault( "horizontalDisplacement", 0.0 );
		if( stateMachineInitData.target )
		{
			playerPuppetOrientation = scriptInterface.executionOwner.GetWorldOrientation();
			distanceFromTarget = stateMachineInitData.target.GetWorldPosition() - scriptInterface.executionOwner.GetWorldPosition();
			if( distanceFromTarget.Z > 0.0 )
			{
				safetyDisplacement.Y = safetyDisplacement.Y * GetStaticFloatParameterDefault( "horizontalDisplacementTargetAbovePlayer", 0.0 );
			}
			horizontalDistanceFromTarget = Vector4.Length2D( distanceFromTarget );
			additionalHorizontalDistance = MaxF( safetyDisplacement.Y - horizontalDistanceFromTarget, 0.0 );
			scaledSafetyDisplacement = safetyDisplacement * additionalHorizontalDistance;
			adjustPosition = Quaternion.Transform( playerPuppetOrientation, scaledSafetyDisplacement );
		}
		RequestPlayerPositionAdjustment( stateContext, scriptInterface, stateMachineInitData.target, GetStaticFloatParameterDefault( "slideDuration", 0.0 ), GetStaticFloatParameterDefault( "distanceRadius", 0.0 ), GetStaticFloatParameterDefault( "rotationDuration", 0.0 ), adjustPosition, true );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class TakedownSlideToPreyDecisions extends LocomotionTakedownDecisions
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return stateMachineInitData.actionName == 'GrappleTarget';
	}

}

class TakedownSlideToPreyEvents extends LocomotionTakedownEvents
{

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		SetPlayerIsStandingAnimParameter( scriptInterface );
		stateContext.SetTemporaryBoolParameter( 'requestSandevistanDeactivation', true, true );
		( ( NPCPuppet )( stateMachineInitData.target ) ).MountingStartDisableComponents();
		SetLocomotionParameters( stateContext, scriptInterface );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class TakedownGrapplePreyDecisions extends LocomotionTakedownDecisions
{

	protected constexpr export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return true;
	}

}

class TakedownGrapplePreyEvents extends LocomotionTakedownEvents
{
	var m_isGrappleReactionVOPlayed : Bool;
	default m_isGrappleReactionVOPlayed = false;

	protected export override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var grappleContextName : CName;
		var puppetOwner : weak< ScriptedPuppet >;
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
		if( !( m_isGrappleReactionVOPlayed ) && ( GetInStateTime() >= GetStaticFloatParameterDefault( "delayToPlayNPCReactionVO", 0.40000001 ) ) )
		{
			grappleContextName = 'grapple';
			puppetOwner = ( ( ScriptedPuppet )( scriptInterface.executionOwner ) );
			if( puppetOwner && puppetOwner.GetHighLevelStateFromBlackboard() != gamedataNPCHighLevelState.Combat )
			{
				grappleContextName = 'grapple_grunt';
			}
			GameObject.PlayVoiceOver( stateMachineInitData.target, grappleContextName, 'Scripts:TakedownGrapplePreyEvents' );
			m_isGrappleReactionVOPlayed = true;
		}
	}

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var grappleOverWall : StateResultBool;
		var obstaclePosition : StateResultVector;
		var distanceToObstacle : Float;
		var distanceToTarget : Float;
		var playerPosition : Vector4;
		var targetPosition : Vector4;
		m_isGrappleReactionVOPlayed = false;
		grappleOverWall = stateContext.GetPermanentBoolParameter( 'PlayerFacingVaultableWall' );
		if( grappleOverWall.value )
		{
			obstaclePosition = stateContext.GetPermanentVectorParameter( 'VaultableWallEndPoint' );
			playerPosition = scriptInterface.executionOwner.GetWorldPosition();
			targetPosition = stateMachineInitData.target.GetWorldPosition();
			distanceToObstacle = Vector4.DistanceSquared2D( playerPosition, obstaclePosition.value );
			distanceToTarget = Vector4.DistanceSquared2D( playerPosition, targetPosition );
		}
		ForceTemporaryWeaponUnequip( stateContext, scriptInterface, true );
		SetLocomotionParameters( stateContext, scriptInterface );
		SetGameplayCameraParameters( scriptInterface, "cameraGrapple" );
		InterruptCameraAim( stateContext, scriptInterface );
		TriggerNoiseStim( scriptInterface.executionOwner, ETakedownActionType.Grapple );
		if( grappleOverWall.value && ( distanceToTarget > distanceToObstacle ) )
		{
			TakedownGameEffectHelper.FillTakedownData( scriptInterface.executionOwner, scriptInterface.executionOwner, stateMachineInitData.target, 'takedowns', 'GrappleTargetCover', "" );
		}
		else if( stateMachineInitData.actionName == 'GrappleTarget' && ( stateContext.GetConditionBool( 'CrouchToggled' ) || ( scriptInterface.GetActionValue( 'Crouch' ) > 0.0 ) ) )
		{
			TakedownGameEffectHelper.FillTakedownData( scriptInterface.executionOwner, scriptInterface.executionOwner, stateMachineInitData.target, 'takedowns', 'GrappleTargetPlayerCrouch', "" );
		}
		else
		{
			TakedownGameEffectHelper.FillTakedownData( scriptInterface.executionOwner, scriptInterface.executionOwner, stateMachineInitData.target, 'takedowns', stateMachineInitData.actionName, "" );
		}
	}

	public export override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class TakedownGrappleFailedDecisions extends LocomotionTakedownDecisions
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return ShouldInstantlyBreakFree( ( ( ScriptedPuppet )( stateMachineInitData.target ) ) );
	}

}

class TakedownGrappleFailedEvents extends LocomotionTakedownEvents
{

	public override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		TakedownUtils.SetTakedownAction( stateContext, TakedownUtils.TakedownActionNameToEnum( 'GrappleFailed' ) );
		SetLocomotionParameters( stateContext, scriptInterface );
		TriggerNoiseStim( scriptInterface.executionOwner, ETakedownActionType.GrappleFailed );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class GrappleMountDecisions extends LocomotionTakedownDecisions
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var workSpotInfo : ExtendedWorkspotInfo;
		if( GetInStateTime() >= GetStaticFloatParameterDefault( "transitionTime", 0.60000002 ) )
		{
			workSpotInfo = scriptInterface.GetWorkspotSystem().GetExtendedInfo( scriptInterface.executionOwner );
			if( workSpotInfo.isActive )
			{
				return true;
			}
		}
		return false;
	}

}

class GrappleMountEvents extends LocomotionTakedownEvents
{

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var mountEvent : MountingRequest;
		var mountingInfo : MountingInfo;
		var slotId : MountingSlotId;
		mountEvent = new MountingRequest;
		slotId.id = 'grapple';
		mountingInfo.childId = stateMachineInitData.target.GetEntityID();
		mountingInfo.parentId = scriptInterface.executionOwnerEntityID;
		mountingInfo.slotId = slotId;
		mountEvent.lowLevelMountingInfo = mountingInfo;
		scriptInterface.GetMountingFacility().Mount( mountEvent );
		SetLocomotionParameters( stateContext, scriptInterface );
	}

}

class GrappleStandDecisions extends LocomotionTakedownDecisions
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	protected export const function ToTakedownExecuteTakedown( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( IsTakedownAction( stateMachineInitData.actionName ) )
		{
			return true;
		}
		if( TakedownUtils.ShouldForceTakedown( scriptInterface ) )
		{
			return true;
		}
		return false;
	}

	protected export const function ToTakedownExecuteTakedownAndDispose( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( IsTakedownAndDispose( scriptInterface ) )
		{
			return true;
		}
		return false;
	}

	protected export const function ToGrappleStruggle( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( GetInStateTime() >= stateContext.GetFloatParameter( 'grappleTime', true ) )
		{
			return IsBreakingFreeAllowed( stateContext, scriptInterface );
		}
		if( IsDeepEnoughToSwim( scriptInterface ) )
		{
			return true;
		}
		return false;
	}

	protected const function IsBreakingFreeAllowed( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'GrappleNoBreakFree' ) )
		{
			return false;
		}
		return true;
	}

	protected export const function ToGrappleBreakFree( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( ( ( IsPowerLevelDifferentialTooHigh( stateMachineInitData.target ) || NPCManager.HasTag( ( ( NPCPuppet )( stateMachineInitData.target ) ).GetRecordID(), 'MiniBoss' ) ) || NPCManager.HasTag( ( ( NPCPuppet )( stateMachineInitData.target ) ).GetRecordID(), 'q305_maxtac' ) ) || NPCManager.HasTag( ( ( NPCPuppet )( stateMachineInitData.target ) ).GetRecordID(), 'MaxTac_Prevention' ) )
		{
			return IsBreakingFreeAllowed( stateContext, scriptInterface );
		}
		return false;
	}

	protected export const function ToTakedownUnmountPrey( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vitals ) == ( ( Int32 )( gamePSMVitals.Dead ) ) )
		{
			return true;
		}
		return false;
	}

}

class GrappleStandEvents extends LocomotionTakedownEvents
{
	var m_isWalking : Bool;
	default m_isWalking = false;

	protected export override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
		if( !( m_isWalking ) && IsPreferredWalkingSpeed( stateContext, scriptInterface ) )
		{
			JumpToWalkAnimation( scriptInterface, stateMachineInitData.target );
			m_isWalking = true;
		}
		else if( m_isWalking && !( IsPreferredWalkingSpeed( stateContext, scriptInterface ) ) )
		{
			JumpToIdleAnimation( scriptInterface, stateMachineInitData.target );
			m_isWalking = false;
		}
	}

	protected function IsPreferredWalkingSpeed( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		return scriptInterface.GetOwnerStateVectorParameterFloat( physicsStateValue.LinearSpeed ) > 1.0;
	}

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		m_isWalking = false;
		SetLocomotionCameraParameters( stateContext, scriptInterface );
		TakedownUtils.SetIgnoreLookAtEntity( scriptInterface, stateMachineInitData.target, true );
		StatusEffectHelper.ApplyStatusEffect( scriptInterface.executionOwner, T"BaseStatusEffect.HumanShield" );
		SetGrappleDuration( stateContext, scriptInterface, GetStaticFloatParameterDefault( "stateDuration", 11.5 ), stateMachineInitData.target );
		SetLocomotionParameters( stateContext, scriptInterface );
		SetBlackboardIntVariable( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.Takedown, ( ( Int32 )( gamePSMTakedown.Grapple ) ) );
		ScriptedPuppet.EvaluateApplyingStatusEffectsFromMountedObjectToPlayer( stateMachineInitData.target, scriptInterface.executionOwner );
		UpdateCameraParams( stateContext, scriptInterface );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class GrappleStruggleDecisions extends LocomotionTakedownDecisions
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	protected const function ToTakedownExecuteTakedown( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( IsTakedownAction( stateMachineInitData.actionName ) )
		{
			return true;
		}
		if( TakedownUtils.ShouldForceTakedown( scriptInterface ) )
		{
			return true;
		}
		return false;
	}

	protected const function ToTakedownExecuteTakedownAndDispose( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( IsTakedownAndDispose( scriptInterface ) )
		{
			return true;
		}
		return false;
	}

}

class GrappleStruggleEvents extends GrappleStandEvents
{

	public override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		SetLocomotionCameraParameters( stateContext, scriptInterface );
		SetLocomotionParameters( stateContext, scriptInterface );
		JumpToStruggleAnimation( scriptInterface, stateMachineInitData.target );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class GrapplePreyDeadDecisions extends GrappleStandEvents
{

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( !( ScriptedPuppet.IsAlive( stateMachineInitData.target ) ) )
		{
			return true;
		}
		if( ScriptedPuppet.IsDefeated( stateMachineInitData.target ) )
		{
			return true;
		}
		return false;
	}

}

class GrappleFallDecisions extends FallDecisions
{

	protected const function ToGrappleStand( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return ( ToRegularLand( stateContext, scriptInterface ) || ToHardLand( stateContext, scriptInterface ) ) || ToVeryHardLand( stateContext, scriptInterface );
	}

}

class GrappleFallEvents extends FallEvents
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	public override function OnForcedExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		TakedownUtils.ExitWorkspot( scriptInterface, scriptInterface.executionOwner );
		TakedownUtils.CleanUpGrappleState( this, stateContext, scriptInterface, stateMachineInitData.target );
	}

}

class GrapplePreyDeadEvents extends LocomotionTakedownEvents
{

	public override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		SetLocomotionParameters( stateContext, scriptInterface );
		ForceTemporaryWeaponUnequip( stateContext, scriptInterface, true );
		TakedownUtils.SetTakedownAction( stateContext, TakedownUtils.TakedownActionNameToEnum( 'TargetDead' ) );
		SelectSyncedAnimationAndExecuteAction( stateContext, scriptInterface, scriptInterface.executionOwner, stateMachineInitData.target, 'TargetDead' );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class GrappleForceShovePreyDecisions extends GrappleStandDecisions
{

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var scriptedPuppet : ScriptedPuppet;
		scriptedPuppet = ( ( ScriptedPuppet )( stateMachineInitData.target ) );
		if( scriptedPuppet.IsUnderwater() && !( GameInstance.GetAINavigationSystem( scriptedPuppet.GetGame() ).IsPointOnNavmesh( scriptedPuppet, scriptedPuppet.GetWorldPosition(), 2.5 ) ) )
		{
			return true;
		}
		if( stateMachineInitData.actionName == 'ForceShove' )
		{
			return true;
		}
		if( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Fall ) == ( ( Int32 )( gamePSMFallStates.FastFall ) ) )
		{
			return true;
		}
		return false;
	}

}

class GrappleForceShovePreyEvents extends LocomotionTakedownEvents
{
	var m_unmountCalled : Bool;

	public override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		SetLocomotionParameters( stateContext, scriptInterface );
		TakedownUtils.SetTakedownAction( stateContext, TakedownUtils.TakedownActionNameToEnum( 'ForceShove' ) );
		SelectSyncedAnimationAndExecuteAction( stateContext, scriptInterface, scriptInterface.executionOwner, stateMachineInitData.target, 'ForceShove' );
		SetBlackboardIntVariable( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.Takedown, ( ( Int32 )( gamePSMTakedown.Takedown ) ) );
		StatusEffectHelper.ApplyStatusEffectForTimeWindow( stateMachineInitData.target, T"BaseStatusEffect.UncontrolledMovement_Default", scriptInterface.executionOwnerEntityID, 0.0, 1.0 );
		m_unmountCalled = false;
		GameObject.PlayVoiceOver( stateMachineInitData.target, 'shove', 'Scripts:GrappleForceShovePreyEvents' );
	}

	protected function UnmountPrey( scriptInterface : StateGameScriptInterface )
	{
		var unmountEvent : UnmountingRequest;
		var mountingInfo : MountingInfo;
		unmountEvent = new UnmountingRequest;
		mountingInfo.childId = stateMachineInitData.target.GetEntityID();
		unmountEvent.lowLevelMountingInfo = mountingInfo;
		scriptInterface.GetMountingFacility().Unmount( unmountEvent );
	}

	protected override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
		if( !( m_unmountCalled ) && ( GetInStateTime() > 0.30000001 ) )
		{
			UnmountPrey( scriptInterface );
			m_unmountCalled = true;
		}
	}

	protected function InitiateForceShoveAttack( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var startPosition : Vector4;
		var endPosition : Vector4;
		var colliderBox : Vector4;
		var attackTime : Float;
		var dir : Vector4;
		startPosition.X = 0.0;
		startPosition.Y = 0.0;
		startPosition.Z = 0.0;
		endPosition.X = 0.0;
		endPosition.Y = GetStaticFloatParameterDefault( "shoveGameEffectRange", 1.0 );
		endPosition.Z = 0.0;
		dir = endPosition - startPosition;
		colliderBox.X = 1.29999995;
		colliderBox.Y = 1.29999995;
		colliderBox.Z = 1.29999995;
		attackTime = GetStaticFloatParameterDefault( "shoveGameEffectDuration", 0.2 );
		if( dir.Y != 0.0 )
		{
			endPosition.Y = GetStaticFloatParameterDefault( "shoveGameEffectRange", 1.0 );
		}
		SpawnShoveAttackGameEffect( stateContext, scriptInterface, startPosition, endPosition, attackTime, colliderBox );
	}

	protected function SpawnShoveAttackGameEffect( stateContext : StateContext, scriptInterface : StateGameScriptInterface, startPosition : Vector4, endPosition : Vector4, attackTime : Float, colliderBox : Vector4 )
	{
		var effect : EffectInstance;
		var attackStartPositionWorld : Vector4;
		var attackEndPositionWorld : Vector4;
		var attackDirectionWorld : Vector4;
		var cameraWorldTransform : Transform;
		var attack : Attack_GameEffect;
		var initContext : AttackInitContext;
		var attackRecord : Attack_Record;
		cameraWorldTransform = scriptInterface.GetCameraWorldTransform();
		attackStartPositionWorld = Transform.TransformPoint( cameraWorldTransform, startPosition );
		attackStartPositionWorld.W = 0.0;
		attackEndPositionWorld = Transform.TransformPoint( cameraWorldTransform, endPosition );
		attackEndPositionWorld.W = 0.0;
		attackDirectionWorld = attackEndPositionWorld - attackStartPositionWorld;
		attackRecord = TweakDBInterface.GetAttackRecord( T"Attacks.ForwardPush" );
		initContext.record = attackRecord;
		initContext.source = scriptInterface.executionOwner;
		initContext.instigator = scriptInterface.executionOwner;
		attack = ( ( Attack_GameEffect )( IAttack.Create( initContext ) ) );
		if( attack )
		{
			effect = attack.PrepareAttack( scriptInterface.executionOwner );
		}
		EffectData.SetVector( effect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.box, colliderBox );
		EffectData.SetFloat( effect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.duration, attackTime );
		EffectData.SetVector( effect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.position, attackStartPositionWorld );
		EffectData.SetQuat( effect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.rotation, Transform.GetOrientation( cameraWorldTransform ) );
		EffectData.SetVector( effect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.forward, Vector4.Normalize( attackDirectionWorld ) );
		EffectData.SetFloat( effect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.range, Vector4.Length( attackDirectionWorld ) );
		EffectData.SetVariant( effect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.attack, ( ( IAttack )( attack ) ) );
		attack.StartAttack();
	}

	protected virtual function OnExitToTakedownReleasePrey( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var broadcaster : StimBroadcasterComponent;
		broadcaster = scriptInterface.executionOwner.GetStimBroadcasterComponent();
		if( broadcaster )
		{
			broadcaster.SendDrirectStimuliToTarget( scriptInterface.executionOwner, gamedataStimType.Combat, stateMachineInitData.target );
		}
		super.OnExit( stateContext, scriptInterface );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class GrappleBreakFreeDecisions extends GrappleStandEvents
{

	protected const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( GetInStateTime() >= GetStaticFloatParameterDefault( "stateDuration", 4.5 ) )
		{
			return true;
		}
		if( GetTakedownAction( stateContext ) == ETakedownActionType.GrappleFailed )
		{
			return true;
		}
		if( IsDeepEnoughToSwim( scriptInterface ) && ( GetInStateTime() >= 0.60000002 ) )
		{
			return true;
		}
		return false;
	}

}

class GrappleBreakFreeEvents extends GrappleStandEvents
{
	var playerPositionVerified : Bool;
	var shouldPushPlayerAway : Bool;

	public override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var takedownEndEvent : EndTakedownEvent;
		var broadcaster : StimBroadcasterComponent;
		playerPositionVerified = false;
		if( stateContext.GetConditionBool( 'CrouchToggled' ) )
		{
			stateContext.SetConditionBoolParameter( 'CrouchToggled', false, true );
		}
		SetLocomotionParameters( stateContext, scriptInterface );
		ForceTemporaryWeaponUnequip( stateContext, scriptInterface, true );
		AIActionHelper.ClearWorkspotCommand( ( ( NPCPuppet )( stateMachineInitData.target ) ), true );
		StatusEffectHelper.RemoveStatusEffect( stateMachineInitData.target, T"BaseStatusEffect.Grappled" );
		TargetTrackingExtension.InjectThreat( ( ( NPCPuppet )( stateMachineInitData.target ) ), scriptInterface.executionOwner );
		StatusEffectHelper.RemoveStatusEffect( stateMachineInitData.target, T"BaseStatusEffect.ForceVisibility" );
		if( GetTakedownAction( stateContext ) == ETakedownActionType.GrappleFailed )
		{
			SelectSyncedAnimationAndExecuteAction( stateContext, scriptInterface, scriptInterface.executionOwner, stateMachineInitData.target, 'GrappleFailed' );
		}
		else
		{
			TakedownUtils.SetTakedownAction( stateContext, TakedownUtils.TakedownActionNameToEnum( 'BreakFree' ) );
			SelectSyncedAnimationAndExecuteAction( stateContext, scriptInterface, scriptInterface.executionOwner, stateMachineInitData.target, 'BreakFree' );
		}
		SetBlackboardIntVariable( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.Takedown, ( ( Int32 )( gamePSMTakedown.Takedown ) ) );
		takedownEndEvent = new EndTakedownEvent;
		scriptInterface.owner.QueueEvent( takedownEndEvent );
		broadcaster = scriptInterface.executionOwner.GetStimBroadcasterComponent();
		if( broadcaster )
		{
			broadcaster.TriggerSingleBroadcast( scriptInterface.executionOwner, gamedataStimType.Combat );
		}
		if( !( GameInstance.GetAINavigationSystem( scriptInterface.GetGame() ).HasPathForward( stateMachineInitData.target, 1.0 ) ) || !( SpatialQueriesHelper.HasSpaceInFront( scriptInterface.executionOwner, 0.34999999, 0.89999998, 1.5, 1.25 ) ) )
		{
			shouldPushPlayerAway = true;
		}
		else
		{
			shouldPushPlayerAway = false;
			StatusEffectHelper.ApplyStatusEffectForTimeWindow( stateMachineInitData.target, T"BaseStatusEffect.UncontrolledMovement_Default", scriptInterface.executionOwnerEntityID, 1.0 - GetStaticFloatParameterDefault( "playerPositionAdjustmentTime", 0.40000001 ), 0.80000001 );
		}
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

	protected override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var pushDistance : Float;
		if( !( playerPositionVerified ) && ( GetInStateTime() >= GetStaticFloatParameterDefault( "playerPositionAdjustmentTime", 0.40000001 ) ) )
		{
			playerPositionVerified = true;
			if( shouldPushPlayerAway )
			{
				pushDistance = GetStaticFloatParameterDefault( "adjustmentDistance", 1.0 );
				RequestPlayerPositionAdjustment( stateContext, scriptInterface, NULL, 0.1, 0.0, 0.0, scriptInterface.executionOwner.GetWorldPosition() - ( pushDistance * scriptInterface.executionOwner.GetWorldForward() ), true );
			}
		}
	}

}

class TakedownExecuteTakedownDecisions extends LocomotionTakedownDecisions
{
}

class TakedownExecuteTakedownEvents extends LocomotionTakedownEvents
{

	protected export override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
	}

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var actionName : CName;
		var weaponType : gamedataItemType;
		if( TakedownUtils.ShouldForceTakedown( scriptInterface ) )
		{
			actionName = 'TakedownNonLethal';
		}
		else
		{
			actionName = stateMachineInitData.actionName;
		}
		if( GetTakedownAction( stateContext ) == ETakedownActionType.LeapToTarget )
		{
			actionName = 'AerialTakedown';
		}
		UpdateCameraParams( stateContext, scriptInterface );
		SetGameplayCameraParameters( scriptInterface, "cameraTakedowns" );
		weaponType = TDB.GetWeaponItemRecord( ItemID.GetTDBID( ScriptedPuppet.GetWeaponRight( scriptInterface.executionOwner ).GetItemID() ) ).ItemType().Type();
		if( weaponType != gamedataItemType.Cyb_MantisBlades )
		{
			ForceTemporaryWeaponUnequip( stateContext, scriptInterface, true );
		}
		TakedownUtils.SetTakedownAction( stateContext, TakedownUtils.TakedownActionNameToEnum( actionName ) );
		SelectSyncedAnimationAndExecuteAction( stateContext, scriptInterface, scriptInterface.executionOwner, stateMachineInitData.target, actionName );
		SetLocomotionParameters( stateContext, scriptInterface );
		SetBlackboardIntVariable( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.Takedown, ( ( Int32 )( gamePSMTakedown.Takedown ) ) );
		if( !( scriptInterface.HasStatFlag( gamedataStatType.CanTakedownSilently ) ) )
		{
			TriggerNoiseStim( scriptInterface.executionOwner, TakedownUtils.TakedownActionNameToEnum( actionName ) );
		}
		if( GetTakedownAction( stateContext ) == ETakedownActionType.TakedownNonLethal && stateContext.GetConditionBool( 'CrouchToggled' ) )
		{
			scriptInterface.SetAnimationParameterFloat( 'crouch', 1.0 );
		}
		GameInstance.GetRazerChromaEffectsSystem( scriptInterface.GetGame() ).PlayAnimation( 'Takedown', false );
		GameInstance.GetTelemetrySystem( scriptInterface.GetGame() ).LogTakedown( actionName, stateMachineInitData.target );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class TakedownExecuteTakedownAndDisposeDecisions extends LocomotionTakedownDecisions
{

	protected const function ExitCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return !( IsInWorkspot( scriptInterface ) );
	}

}

class TakedownExecuteTakedownAndDisposeEvents extends LocomotionTakedownEvents
{
	var m_targetID : EntityID;

	public override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		m_targetID = stateMachineInitData.target.GetEntityID();
		if( GetStaticBoolParameterDefault( "exitToStandState", true ) )
		{
			stateContext.SetConditionBoolParameter( 'CrouchToggled', false, true );
		}
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		if( stateMachineInitData.target )
		{
			TakedownUtils.CleanUpGrappleState( this, stateContext, scriptInterface, stateMachineInitData.target );
		}
		else
		{
			TakedownUtils.CleanUpGrappleState( this, stateContext, scriptInterface, m_targetID );
		}
	}

}

class TakedownReleasePreyDecisions extends LocomotionTakedownDecisions
{
	const var stateMachineInitData : weak< LocomotionTakedownInitData >;

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( ( GetInStateTime() > 0.5 ) && !( IsInWorkspot( scriptInterface ) ) )
		{
			return true;
		}
		if( !( stateMachineInitData.target.IsAttached() ) )
		{
			return true;
		}
		return false;
	}

}

class TakedownReleasePreyEvents extends LocomotionTakedownEvents
{

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		TakedownUtils.ExitWorkspot( scriptInterface, scriptInterface.executionOwner );
		SetGameplayCameraParameters( scriptInterface, "cameraDefault" );
		SetLocomotionParameters( stateContext, scriptInterface );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class TakedownUnmountPreyDecisions extends LocomotionTakedownDecisions
{

	protected constexpr const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return true;
	}

}

class TakedownUnmountPreyEvents extends LocomotionTakedownEvents
{

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var unmountEvent : UnmountingRequest;
		var mountingInfo : MountingInfo;
		unmountEvent = new UnmountingRequest;
		mountingInfo.childId = stateMachineInitData.target.GetEntityID();
		unmountEvent.lowLevelMountingInfo = mountingInfo;
		scriptInterface.GetMountingFacility().Unmount( unmountEvent );
		SetLocomotionParameters( stateContext, scriptInterface );
		if( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vitals ) == ( ( Int32 )( gamePSMVitals.Dead ) ) )
		{
			StatusEffectHelper.ApplyStatusEffect( stateMachineInitData.target, T"BaseStatusEffect.Unconscious" );
			scriptInterface.GetWorkspotSystem().SendFastExitSignal( stateMachineInitData.target );
		}
	}

	public export override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		TakedownUtils.CleanUpGrappleState( this, stateContext, scriptInterface, stateMachineInitData.target );
	}

}

class PickUpBodyAfterTakedownDecisions extends LocomotionTakedownDecisions
{

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( ( scriptInterface.HasStatFlag( gamedataStatType.CanPickUpBodyAfterTakedown ) && ( scriptInterface.GetActionValue( 'PickUpBodyFromTakedown' ) > 0.0 ) ) && ( scriptInterface.GetActionStateTime( 'PickUpBodyFromTakedown' ) >= 0.1 ) )
		{
			return GetTakedownAction( stateContext ) == ETakedownActionType.Takedown || GetTakedownAction( stateContext ) == ETakedownActionType.TakedownNonLethal;
		}
		return false;
	}

}

class PickUpBodyAfterTakedownEvents extends LocomotionTakedownEvents
{

	public override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var emptyEntityID : EntityID;
		var addCarriedObjectSM : PSMAddOnDemandStateMachine;
		var addLocomotionSM : PSMAddOnDemandStateMachine;
		TakedownUtils.SetTakedownAction( stateContext, TakedownUtils.TakedownActionNameToEnum( stateMachineInitData.actionName ) );
		addCarriedObjectSM = new PSMAddOnDemandStateMachine;
		addCarriedObjectSM.owner = stateMachineInitData.target;
		addCarriedObjectSM.stateMachineName = 'CarriedObject';
		scriptInterface.executionOwner.QueueEvent( addCarriedObjectSM );
		addLocomotionSM = new PSMAddOnDemandStateMachine;
		addLocomotionSM.stateMachineName = 'Locomotion';
		scriptInterface.executionOwner.QueueEvent( addLocomotionSM );
		SetLocomotionParameters( stateContext, scriptInterface );
		SetBlackboardIntVariable( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.Takedown, ( ( Int32 )( gamePSMTakedown.Default ) ) );
		SetBlackboardEntityID( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.TakedownTargetID, emptyEntityID );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

class TakedownEndDecisions extends LocomotionTakedownDecisions
{

	protected constexpr const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return true;
	}

}

class TakedownEndEvents extends LocomotionTakedownEvents
{

	public export override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var emptyEntityID : EntityID;
		var swapEvent : PSMAddOnDemandStateMachine;
		swapEvent = new PSMAddOnDemandStateMachine;
		swapEvent.stateMachineName = 'Locomotion';
		scriptInterface.executionOwner.QueueEvent( swapEvent );
		SetLocomotionParameters( stateContext, scriptInterface );
		SetBlackboardIntVariable( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.Takedown, ( ( Int32 )( gamePSMTakedown.Default ) ) );
		SetBlackboardEntityID( scriptInterface, GetAllBlackboardDefs().PlayerStateMachine.TakedownTargetID, emptyEntityID );
		ForceTemporaryWeaponUnequip( stateContext, scriptInterface, false );
		( ( ScriptedPuppet )( stateMachineInitData.target ) ).GetBumpComponent().Toggle( true );
	}

	public override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
	}

}

