abstract class StatusEffectActions extends AIbehaviortaskScript
{
}

class WeaponJammedAction extends StatusEffectActions
{
	var m_jammedWeaponDuration : Float;
	default m_jammedWeaponDuration = 5;
	var m_jammedWeaponStartTimeStamp : Float;
}

abstract class StatusEffectTasks extends AIbehaviortaskScript
{
}

class ApplyStatusEffectOnOwner extends StatusEffectTasks
{
	[ customEditor = "TweakDBGroupInheritance;StatusEffect" ]
	editable var m_statusEffectID : TweakDBID;

	protected override function Activate( context : ScriptExecutionContext )
	{
		StatusEffectHelper.ApplyStatusEffect( GetPuppet( context ), m_statusEffectID );
	}

}

class RemoveStatusEffectOnOwner extends StatusEffectTasks
{
	[ customEditor = "TweakDBGroupInheritance;StatusEffect" ]
	editable var m_statusEffectID : TweakDBID;

	protected override function Activate( context : ScriptExecutionContext )
	{
		StatusEffectHelper.RemoveStatusEffect( GetPuppet( context ), m_statusEffectID );
	}

}

class MonitorStatusEffectBehavior extends StatusEffectTasks
{
	[ customEditor = "TweakDBGroupInheritance;StatusEffect" ]
	editable var m_statusEffectID : TweakDBID;

	protected override function Activate( context : ScriptExecutionContext ) {}

	protected override function Deactivate( context : ScriptExecutionContext )
	{
		if( TweakDBInterface.GetStatusEffectRecord( m_statusEffectID ).AIData().BehaviorType().Type() == gamedataStatusEffectAIBehaviorType.Stoppable )
		{
			StatusEffectHelper.RemoveStatusEffect( ScriptExecutionContext.GetOwner( context ), m_statusEffectID );
		}
	}

}

class UnconsciousManagerTask extends StatusEffectTasks
{

	protected export override function Activate( context : ScriptExecutionContext )
	{
		if( StatusEffectSystem.ObjectHasStatusEffect( ScriptExecutionContext.GetOwner( context ), T"BaseStatusEffect.Unconscious" ) )
		{
			SetUnconsciousBodyVisibleComponent( ( ( NPCPuppet )( GetPuppet( context ) ) ), true );
		}
	}

	protected virtual function SetUnconsciousBodyVisibleComponent( puppet : NPCPuppet, state : Bool )
	{
		var reactionComponent : ReactionManagerComponent;
		reactionComponent = puppet.GetStimReactionComponent();
		if( reactionComponent )
		{
			reactionComponent.SetDownedBodyVisibleComponent( state, 'Unconscious' );
		}
	}

	protected export override function Deactivate( context : ScriptExecutionContext )
	{
		SetUnconsciousBodyVisibleComponent( ( ( NPCPuppet )( GetPuppet( context ) ) ), false );
	}

}

class SystemCollapseManagerTask extends UnconsciousManagerTask
{

	protected export override function Activate( context : ScriptExecutionContext )
	{
		var owner : NPCPuppet;
		var systemCollapseEffects : array< StatusEffect >;
		owner = ( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		StatusEffectHelper.GetAppliedEffectsWithTag( owner, 'SystemCollapse', systemCollapseEffects );
		if( systemCollapseEffects.Size() != 0 )
		{
			SetUnconsciousBodyVisibleComponent( owner, true );
			owner.SetMyKiller( ( ( GameObject )( GameInstance.FindEntityByID( owner.GetGame(), systemCollapseEffects[ 0 ].GetInstigatorEntityID() ) ) ) );
		}
	}

}

class HeartAttackManagerTask extends StatusEffectTasks
{

	protected override function Activate( context : ScriptExecutionContext )
	{
		SetHeartAttackBodyVisibleComponent( ( ( NPCPuppet )( GetPuppet( context ) ) ), true );
	}

	protected virtual function SetHeartAttackBodyVisibleComponent( puppet : NPCPuppet, state : Bool )
	{
		var reactionComponent : ReactionManagerComponent;
		reactionComponent = puppet.GetStimReactionComponent();
		if( reactionComponent )
		{
			reactionComponent.SetDownedBodyVisibleComponent( state, 'HeartAttack' );
		}
	}

	protected override function Deactivate( context : ScriptExecutionContext )
	{
		SetHeartAttackBodyVisibleComponent( ( ( NPCPuppet )( GetPuppet( context ) ) ), false );
	}

}

class DropWeaponTask extends StatusEffectTasks
{

	protected override function Activate( context : ScriptExecutionContext )
	{
		( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).DropWeapons();
	}

	protected override function Deactivate( context : ScriptExecutionContext ) {}
}

class SetHitStimSourceTask extends StatusEffectTasks
{

	protected override function Activate( context : ScriptExecutionContext )
	{
		var target : weak< GameObject >;
		target = ( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).GetHitReactionComponent().GetHitSource();
		ScriptExecutionContext.SetArgumentVector( context, 'StimSource', target.GetWorldPosition() );
	}

	protected override function Deactivate( context : ScriptExecutionContext ) {}
}

class ToggleVisibleObjectComponent extends StatusEffectTasks
{
	editable var m_componentTargetState : Bool;
	editable var m_visibleObjectDescription : CName;

	protected override function Activate( context : ScriptExecutionContext )
	{
		var reactionComponent : ReactionManagerComponent;
		reactionComponent = GetPuppet( context ).GetStimReactionComponent();
		if( reactionComponent )
		{
			reactionComponent.SetDownedBodyVisibleComponent( m_componentTargetState, m_visibleObjectDescription );
		}
	}

}

class SetPlayerAsKiller extends AIbehaviortaskScript
{

	protected override function Activate( context : ScriptExecutionContext )
	{
		var puppet : NPCPuppet;
		puppet = ( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( puppet )
		{
			puppet.SetMyKiller( GameInstance.GetPlayerSystem( puppet.GetGame() ).GetLocalPlayerControlledGameObject() );
		}
	}

}

class SetPendingReactionBB extends StatusEffectTasks
{

	protected export override function Activate( context : ScriptExecutionContext )
	{
		GetPuppet( context ).GetPuppetStateBlackboard().SetBool( GetAllBlackboardDefs().PuppetState.InPendingBehavior, true );
	}

	protected export override function Deactivate( context : ScriptExecutionContext )
	{
		GetPuppet( context ).GetPuppetStateBlackboard().SetBool( GetAllBlackboardDefs().PuppetState.InPendingBehavior, false );
	}

}

class BlindManagerTask extends StatusEffectTasks
{

	protected override function Activate( context : ScriptExecutionContext )
	{
		var hostileThreats : array< TrackedLocation >;
		var i : Int32;
		hostileThreats = GetPuppet( context ).GetTargetTrackerComponent().GetHostileThreats( false );
		for( i = 0; i < hostileThreats.Size(); i += 1 )
		{
			GetPuppet( context ).GetTargetTrackerComponent().SetThreatBaseMul( hostileThreats[ i ].entity, 0.0 );
		}
	}

	protected override function Deactivate( context : ScriptExecutionContext )
	{
		if( !( StatusEffectSystem.ObjectHasStatusEffectWithTag( GetPuppet( context ), 'ResetSquadSync' ) ) )
		{
			GetPuppet( context ).GetTargetTrackerComponent().PullSquadSync( AISquadType.Combat );
		}
	}

}

class CacheFXOnDefeated extends StatusEffectTasks
{
	var npcPuppet : weak< NPCPuppet >;

	protected export override function Activate( context : ScriptExecutionContext )
	{
		var appliedStatusEffects : array< StatusEffect >;
		var vfxToCache : array< weak< StatusEffectFX_Record > >;
		var sfxToCache : array< weak< StatusEffectFX_Record > >;
		var cacheFXEvent : CacheStatusEffectFXEvent;
		var i : Int32;
		var j : Int32;
		npcPuppet = ( ( NPCPuppet )( GetPuppet( context ) ) );
		appliedStatusEffects = StatusEffectHelper.GetAppliedEffects( npcPuppet );
		for( i = 0; i < appliedStatusEffects.Size(); i += 1 )
		{
			for( j = 0; j < appliedStatusEffects[ i ].GetRecord().GetVFXCount(); j += 1 )
			{
				vfxToCache.PushBack( appliedStatusEffects[ i ].GetRecord().GetVFXItem( j ) );
			}
		}
		for( i = 0; i < appliedStatusEffects.Size(); i += 1 )
		{
			for( j = 0; j < appliedStatusEffects[ i ].GetRecord().GetSFXCount(); j += 1 )
			{
				sfxToCache.PushBack( appliedStatusEffects[ i ].GetRecord().GetSFXItem( j ) );
			}
		}
		cacheFXEvent = new CacheStatusEffectFXEvent;
		cacheFXEvent.vfxToCache = vfxToCache;
		cacheFXEvent.sfxToCache = sfxToCache;
		npcPuppet.QueueEvent( cacheFXEvent );
	}

	protected export override function Deactivate( context : ScriptExecutionContext )
	{
		var removeFXEvent : RemoveCachedStatusEffectFXEvent;
		removeFXEvent = new RemoveCachedStatusEffectFXEvent;
		npcPuppet.QueueEvent( removeFXEvent );
	}

}

class CacheStatusEffectAnimationTask extends StatusEffectTasks
{

	protected export override function Activate( context : ScriptExecutionContext )
	{
		QueueStatusEffectAnimEvent( ( ( NPCPuppet )( GetPuppet( context ) ) ), false );
	}

	protected export override function Deactivate( context : ScriptExecutionContext )
	{
		QueueStatusEffectAnimEvent( ( ( NPCPuppet )( GetPuppet( context ) ) ), true );
	}

	protected virtual function QueueStatusEffectAnimEvent( puppet : NPCPuppet, removeCachedStatusEffect : Bool )
	{
		var cacheStatusEffectAnim : CacheStatusEffectAnimEvent;
		cacheStatusEffectAnim = new CacheStatusEffectAnimEvent;
		cacheStatusEffectAnim.removeCachedStatusEffect = removeCachedStatusEffect;
		puppet.QueueEvent( cacheStatusEffectAnim );
	}

}

class CheckFriendlyNPCAboutToBeHit extends StatusEffectTasks
{
	editable inlined var m_outStatusArgument : AIArgumentMapping;
	editable inlined var m_outPositionStatusArgument : AIArgumentMapping;
	editable inlined var m_outPositionArgument : AIArgumentMapping;

	protected override function Activate( context : ScriptExecutionContext )
	{
		var owner : NPCPuppet;
		var player : weak< GameObject >;
		var vehicle : weak< VehicleObject >;
		var distanceBetweenActors : Float;
		var projectedPosition : Vector4;
		var projectedDistance : Float;
		var navmeshProbeDimensions : array< Float >;
		var navmeshTolerance : Vector4;
		var pointOnNavmesh : Vector4;
		var navmeshProbeDistances : array< Float >;
		var i : Int32;
		var foundPointOnNavmesh : Bool;
		owner = ( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		player = GameInstance.GetPlayerSystem( owner.GetGame() ).GetLocalPlayerControlledGameObject();
		if( owner.GetAttitudeTowards( player ) != EAIAttitude.AIA_Friendly && ( owner.GetRecord().Priority().Type() != gamedataSpawnableObjectPriority.Quest || owner.IsPrevention() ) )
		{
			ScriptExecutionContext.SetMappingValue( context, m_outStatusArgument, false );
			return;
		}
		if( VehicleComponent.GetVehicle( owner.GetGame(), player, vehicle ) )
		{
			distanceBetweenActors = Vector4.Distance( owner.GetWorldPosition(), player.GetWorldPosition() );
			projectedPosition = vehicle.GetWorldPosition() + ( vehicle.GetLinearVelocity() * TweakDBInterface.GetFloat( T"AIGeneralSettings.mountedPlayerHitPredictionTime", 2.0 ) );
			projectedDistance = Vector4.Distance( owner.GetWorldPosition(), projectedPosition );
			if( ( distanceBetweenActors <= TweakDBInterface.GetFloat( T"AIGeneralSettings.mountedPlayerMinDistanceForTeleport", 3.0 ) ) || ( projectedDistance <= TweakDBInterface.GetFloat( T"AIGeneralSettings.mountedPlayerMinDistanceForTeleport", 6.0 ) ) )
			{
				ScriptExecutionContext.SetMappingValue( context, m_outStatusArgument, true );
				navmeshProbeDimensions = TDB.GetFloatArray( T"AIGeneralSettings.ragdollRecoveryInitialNavmeshProbeDimensions" );
				navmeshTolerance = Vector4( navmeshProbeDimensions[ 0 ], navmeshProbeDimensions[ 1 ], navmeshProbeDimensions[ 2 ], navmeshProbeDimensions[ 3 ] );
				navmeshProbeDistances = TDB.GetFloatArray( T"AIGeneralSettings.navmeshProbeDistancesFriendly" );
				for( i = 0; i < navmeshProbeDistances.Size(); i += 1 )
				{
					if( GameInstance.GetAINavigationSystem( owner.GetGame() ).TryToFindNavmeshPointAroundPoint( owner, owner.GetWorldPosition(), owner.GetWorldOrientation(), navmeshTolerance, TDB.GetInt( T"AIGeneralSettings.numberOfProbesPerDistance" ), navmeshProbeDistances[ i ], pointOnNavmesh, false ) && ( Vector4.Distance( pointOnNavmesh, player.GetWorldPosition() ) > TweakDBInterface.GetFloat( T"AIGeneralSettings.mountedPlayerMinDistanceForTeleport", 3.0 ) ) )
					{
						foundPointOnNavmesh = true;
						ScriptExecutionContext.SetMappingValue( context, m_outPositionArgument, pointOnNavmesh );
						break;
					}
				}
			}
		}
		ScriptExecutionContext.SetMappingValue( context, m_outPositionStatusArgument, foundPointOnNavmesh );
	}

	protected override function Deactivate( context : ScriptExecutionContext )
	{
		ScriptExecutionContext.SetMappingValue( context, m_outStatusArgument, false );
		ScriptExecutionContext.SetMappingValue( context, m_outPositionStatusArgument, false );
		ScriptExecutionContext.SetMappingValue( context, m_outPositionArgument, Vector4() );
	}

}

class CheckRagdollOutOfNavmeshTask extends StatusEffectTasks
{
	editable inlined var m_outStatusArgument : AIArgumentMapping;
	editable inlined var m_outPositionStatusArgument : AIArgumentMapping;
	editable inlined var m_outPositionArgument : AIArgumentMapping;

	protected override function Activate( context : ScriptExecutionContext )
	{
		var owner : NPCPuppet;
		var ownerPosition : Vector4;
		var foundPointOnNavmesh : Bool;
		var isFriendlyToPlayer : Bool;
		var pointOnNavmesh : Vector4;
		var lastValidNavmeshPosition : Vector4;
		var navmeshProbeDimensions : array< Float >;
		var navmeshProbeDistances : array< Float >;
		var navmeshTolerance : Vector4;
		var numberOfProbes : Int32;
		var i : Int32;
		owner = ( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( owner )
		{
			ownerPosition = owner.GetWorldPosition();
			navmeshProbeDimensions = TDB.GetFloatArray( T"AIGeneralSettings.ragdollRecoveryInitialNavmeshProbeDimensions" );
			navmeshTolerance = Vector4( navmeshProbeDimensions[ 0 ], navmeshProbeDimensions[ 1 ], navmeshProbeDimensions[ 2 ], navmeshProbeDimensions[ 3 ] );
			if( GameInstance.GetAINavigationSystem( owner.GetGame() ).IsPointOnNavmesh( owner, ownerPosition, navmeshTolerance, pointOnNavmesh ) )
			{
				ScriptExecutionContext.SetMappingValue( context, m_outStatusArgument, false );
			}
			else
			{
				ScriptExecutionContext.SetMappingValue( context, m_outStatusArgument, true );
				lastValidNavmeshPosition = owner.GetLastValidNavmeshPoint();
				if( Vector4.Distance( owner.GetWorldPosition(), lastValidNavmeshPosition ) <= TDB.GetFloat( T"AIGeneralSettings.ragdollRecoveryMinDistanceThreshold" ) )
				{
					foundPointOnNavmesh = true;
					ScriptExecutionContext.SetMappingValue( context, m_outPositionArgument, lastValidNavmeshPosition );
				}
				else
				{
					isFriendlyToPlayer = owner.GetAttitudeTowards( GameInstance.GetPlayerSystem( owner.GetGame() ).GetLocalPlayerControlledGameObject() ) == EAIAttitude.AIA_Friendly;
					navmeshProbeDimensions = TDB.GetFloatArray( T"AIGeneralSettings.ragdollRecoveryNavmeshProbeDimensions" );
					navmeshTolerance = Vector4( navmeshProbeDimensions[ 0 ], navmeshProbeDimensions[ 1 ], navmeshProbeDimensions[ 2 ], navmeshProbeDimensions[ 3 ] );
					numberOfProbes = TDB.GetInt( T"AIGeneralSettings.numberOfProbesPerDistance" );
					GameInstance.GetAINavigationSystem( owner.GetGame() ).IsPointOnNavmesh( owner, owner.GetLastValidNavmeshPoint(), navmeshTolerance, lastValidNavmeshPosition );
					if( isFriendlyToPlayer )
					{
						navmeshProbeDistances = TDB.GetFloatArray( T"AIGeneralSettings.navmeshProbeDistancesFriendly" );
					}
					else
					{
						navmeshProbeDistances = TDB.GetFloatArray( T"AIGeneralSettings.navmeshProbeDistancesNonFriendly" );
					}
					for( i = 0; i < navmeshProbeDistances.Size(); i += 1 )
					{
						if( GameInstance.GetAINavigationSystem( owner.GetGame() ).TryToFindNavmeshPointAroundPoint( owner, ownerPosition, Quaternion.BuildFromDirectionVector( lastValidNavmeshPosition - ownerPosition, owner.GetWorldUp() ), navmeshTolerance, numberOfProbes, navmeshProbeDistances[ i ], pointOnNavmesh, false ) )
						{
							foundPointOnNavmesh = true;
							ScriptExecutionContext.SetMappingValue( context, m_outPositionArgument, pointOnNavmesh );
							break;
						}
					}
					if( ( ( owner.GetNPCRarity() == gamedataNPCRarity.Boss || owner.GetNPCRarity() == gamedataNPCRarity.MaxTac ) || isFriendlyToPlayer ) && !( foundPointOnNavmesh ) )
					{
						navmeshProbeDimensions = TDB.GetFloatArray( T"AIGeneralSettings.lastValidNavmeshPosProbeDimensions" );
						navmeshTolerance = Vector4( navmeshProbeDimensions[ 0 ], navmeshProbeDimensions[ 1 ], navmeshProbeDimensions[ 2 ], navmeshProbeDimensions[ 3 ] );
						if( !( Vector4.IsZero( lastValidNavmeshPosition ) ) && GameInstance.GetAINavigationSystem( owner.GetGame() ).IsPointOnNavmesh( owner, lastValidNavmeshPosition, navmeshTolerance, pointOnNavmesh ) )
						{
							foundPointOnNavmesh = true;
							ScriptExecutionContext.SetMappingValue( context, m_outPositionArgument, pointOnNavmesh );
						}
					}
					if( isFriendlyToPlayer && !( foundPointOnNavmesh ) )
					{
						if( !( foundPointOnNavmesh ) && GameInstance.GetAINavigationSystem( owner.GetGame() ).GetNearestNavmeshPointBehind( GameInstance.GetPlayerSystem( owner.GetGame() ).GetLocalPlayerControlledGameObject(), navmeshTolerance.Z, numberOfProbes, pointOnNavmesh, true ) )
						{
							foundPointOnNavmesh = true;
							ScriptExecutionContext.SetMappingValue( context, m_outPositionArgument, pointOnNavmesh );
						}
					}
				}
				ScriptExecutionContext.SetMappingValue( context, m_outPositionStatusArgument, foundPointOnNavmesh );
			}
		}
	}

}

class AIRagdollDelegate extends ScriptBehaviorDelegate
{
	var ragdollInstigator : weak< GameObject >;
	var closestNavmeshPoint : Vector4;
	var ragdollOutOfNavmesh : Bool;
	var isUnderwater : Bool;
	var poseAllowsRecovery : Bool;

	public function DoGetRagdollInstigator( context : ScriptExecutionContext ) : Bool
	{
		var owner : NPCPuppet;
		owner = ( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( owner )
		{
			if( owner.GetRagdollInstigator( ragdollInstigator ) )
			{
				ScriptExecutionContext.SetArgumentObject( context, 'StimTarget', ragdollInstigator );
				return true;
			}
		}
		return false;
	}

	public function DoCheckWaterLevel( context : ScriptExecutionContext ) : Bool
	{
		var npc : NPCPuppet;
		npc = ( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		return npc && npc.KillIfUnderwater();
	}

	public function DoCheckIfPoseAllowsRecovery( context : ScriptExecutionContext ) : Bool
	{
		var owner : NPCPuppet;
		var chestWorldTransform : WorldTransform;
		var hipsWorldTransform : WorldTransform;
		var legsWorldPosition : Vector4;
		var legRightWorldTransform : WorldTransform;
		var legLeftWorldTransform : WorldTransform;
		var floorAngle : Float;
		owner = ( ( NPCPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( ( owner && owner.GetNPCType() == gamedataNPCType.Human ) && owner.IsIncapacitated() )
		{
			if( owner.GetSlotComponent().GetSlotTransform( 'Hips', hipsWorldTransform ) )
			{
				if( !( HasSpaceToRecover( owner, TDB.GetFloatArray( T"AIGeneralSettings.ragdollRecoveryEnviroProbeDimensions" ), hipsWorldTransform ) ) )
				{
					poseAllowsRecovery = false;
					return false;
				}
				if( ( owner.GetSlotComponent().GetSlotTransform( 'Chest', chestWorldTransform ) && owner.GetSlotComponent().GetSlotTransform( 'LegRight', legRightWorldTransform ) ) && owner.GetSlotComponent().GetSlotTransform( 'LegLeft', legLeftWorldTransform ) )
				{
					legsWorldPosition = ( WorldPosition.ToVector4( WorldTransform.GetWorldPosition( legRightWorldTransform ) ) + WorldPosition.ToVector4( WorldTransform.GetWorldPosition( legLeftWorldTransform ) ) ) / 2.0;
					if( !( TorsoAngleWithinParamters( TDB.GetFloat( T"AIGeneralSettings.ragdollRecoveryMaxAllowedTorsoAngle" ), WorldPosition.ToVector4( WorldTransform.GetWorldPosition( hipsWorldTransform ) ), WorldPosition.ToVector4( WorldTransform.GetWorldPosition( chestWorldTransform ) ), legsWorldPosition ) ) )
					{
						poseAllowsRecovery = false;
						return false;
					}
				}
			}
			if( SpatialQueriesHelper.GetFloorAngle( owner, floorAngle ) && ( floorAngle >= TDB.GetFloat( T"AIGeneralSettings.ragdollRecoveryMaxAllowedFloorAngle" ) ) )
			{
				poseAllowsRecovery = false;
				return false;
			}
		}
		poseAllowsRecovery = true;
		return true;
	}

	private function HasSpaceToRecover( owner : NPCPuppet, const queryDimensions : ref< array< Float > >, originTransform : WorldTransform ) : Bool
	{
		var overlapSuccessStatic : Bool;
		var overlapSuccessDynamic : Bool;
		var overlapSuccessVehicle : Bool;
		var queryExtents : Vector4;
		var queryPosition : Vector4;
		var queryOrientation : EulerAngles;
		var vehicleCheckTrace : TraceResult;
		var queryPositionTrace : TraceResult;
		var fitTestOvelap : TraceResult;
		var sqs : SpatialQueriesSystem;
		queryExtents = Vector4( queryDimensions[ 0 ] * 0.5, queryDimensions[ 1 ] * 0.5, queryDimensions[ 2 ] * 0.5, queryDimensions[ 3 ] );
		sqs = GameInstance.GetSpatialQueriesSystem( owner.GetGame() );
		GameInstance.GetSpatialQueriesSystem( owner.GetGame() ).SyncRaycastByCollisionPreset( WorldPosition.ToVector4( WorldTransform.GetWorldPosition( originTransform ) ) + Vector4( 0.0, 0.0, 0.1, 0.0 ), WorldPosition.ToVector4( WorldTransform.GetWorldPosition( originTransform ) ) + Vector4( 0.0, 0.0, -0.69999999, 0.0 ), 'Vehicle Chassis', vehicleCheckTrace );
		if( TraceResult.IsValid( vehicleCheckTrace ) )
		{
			return false;
		}
		GameInstance.GetSpatialQueriesSystem( owner.GetGame() ).SyncRaycastByCollisionPreset( WorldPosition.ToVector4( WorldTransform.GetWorldPosition( originTransform ) ) + Vector4( 0.0, 0.0, 0.1, 0.0 ), WorldPosition.ToVector4( WorldTransform.GetWorldPosition( originTransform ) ) + Vector4( 0.0, 0.0, -5.0, 0.0 ), 'World Static', queryPositionTrace );
		if( TraceResult.IsValid( queryPositionTrace ) )
		{
			queryPosition = ( ( Vector4 )( queryPositionTrace.position ) );
		}
		else
		{
			queryPosition = WorldPosition.ToVector4( WorldTransform.GetWorldPosition( originTransform ) );
		}
		queryPosition.Z += ( queryExtents.Z + 0.1 );
		queryOrientation = Quaternion.ToEulerAngles( owner.GetWorldOrientation() );
		overlapSuccessStatic = sqs.Overlap( queryExtents, queryPosition, queryOrientation, 'Static', fitTestOvelap );
		overlapSuccessDynamic = sqs.Overlap( queryExtents, queryPosition, queryOrientation, 'Dynamic', fitTestOvelap );
		overlapSuccessVehicle = sqs.Overlap( queryExtents, queryPosition, queryOrientation, 'Vehicle', fitTestOvelap );
		return ( !( overlapSuccessStatic ) && !( overlapSuccessDynamic ) ) && !( overlapSuccessVehicle );
	}

	private function TorsoAngleWithinParamters( maxAllowedAngle : Float, hipsPosition : Vector4, chestPosition : Vector4, legsPosition : Vector4 ) : Bool
	{
		var torsoAngle : Float;
		torsoAngle = 180.0 - Vector4.GetAngleBetween( chestPosition - hipsPosition, legsPosition - hipsPosition );
		if( torsoAngle > maxAllowedAngle )
		{
			return false;
		}
		return true;
	}

	public function DoClearActiveStatusEffect( context : ScriptExecutionContext ) : Bool
	{
		var puppet : ScriptedPuppet;
		var removeStatusEffectEvent : RemoveStatusEffectEvent;
		puppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( ( ScriptedPuppet.IsDefeated( puppet ) || !( ScriptedPuppet.IsAlive( puppet ) ) ) || StatusEffectSystem.ObjectHasStatusEffect( puppet, T"BaseStatusEffect.Unconscious" ) )
		{
			StatusEffectHelper.RemoveStatusEffect( puppet, T"BaseStatusEffect.NonInteractable" );
		}
		else
		{
			removeStatusEffectEvent = new RemoveStatusEffectEvent;
			removeStatusEffectEvent.effectID = T"BaseStatusEffect.NonInteractable";
			GameInstance.GetDelaySystem( puppet.GetGame() ).DelayEvent( puppet, removeStatusEffectEvent, 1.25, true );
		}
		return true;
	}

	public function DoHandleDownedSignals( context : ScriptExecutionContext ) : Bool
	{
		var puppet : ScriptedPuppet;
		var signalHandler : AISignalHandlerComponent;
		var signalID : Uint32;
		puppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		signalHandler = puppet.GetSignalHandlerComponent();
		if( StatusEffectSystem.ObjectHasStatusEffectOfType( puppet, gamedataStatusEffectType.Defeated ) && !( signalHandler.IsHighestPriority( EnumValueToName( 'gamedataStatusEffectType', ( ( Int64 )( gamedataStatusEffectType.Defeated ) ) ), signalID ) ) )
		{
			SendDownedSignal( context, puppet, EnumValueToName( 'gamedataStatusEffectType', ( ( Int64 )( gamedataStatusEffectType.Defeated ) ) ) );
		}
		else if( StatusEffectSystem.ObjectHasStatusEffectOfType( puppet, gamedataStatusEffectType.DefeatedWithRecover ) )
		{
			SendStatusEffectSignal( context, puppet, EnumValueToName( 'gamedataStatusEffectType', ( ( Int64 )( gamedataStatusEffectType.DefeatedWithRecover ) ) ) );
		}
		else if( !( ScriptedPuppet.IsAlive( puppet ) ) && !( signalHandler.IsHighestPriority( 'death', signalID ) ) )
		{
			SendDownedSignal( context, puppet, 'death' );
		}
		ScriptExecutionContext.SetArgumentObject( context, 'StimTarget', NULL );
		return true;
	}

	private function SendStatusEffectSignal( context : ScriptExecutionContext, puppet : ScriptedPuppet, seTypeTag : CName )
	{
		var signal : AIGateSignal;
		signal.priority = 9.0;
		signal.lifeTime = RPGManager.GetStatRecord( gamedataStatType.MaxDuration ).Max();
		AIGateSignal.AddTag( signal, 'reactive' );
		AIGateSignal.AddTag( signal, 'statusEffects' );
		AIGateSignal.AddTag( signal, seTypeTag );
		puppet.GetSignalHandlerComponent().AddSignal( signal, false );
	}

	private function SendDownedSignal( context : ScriptExecutionContext, puppet : ScriptedPuppet, downedTypeTag : CName )
	{
		var signal : AIGateSignal;
		signal.priority = 9.0;
		signal.lifeTime = RPGManager.GetStatRecord( gamedataStatType.MaxDuration ).Max();
		AIGateSignal.AddTag( signal, 'downed' );
		AIGateSignal.AddTag( signal, downedTypeTag );
		puppet.GetSignalHandlerComponent().AddSignal( signal, false );
	}

	public function DoHandleRagdollReaction( context : ScriptExecutionContext ) : Bool
	{
		var puppet : ScriptedPuppet;
		var broadcaster : StimBroadcasterComponent;
		var investigateData : stimInvestigateData;
		puppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( ScriptedPuppet.IsAlive( puppet ) )
		{
			if( ragdollInstigator && ( ragdollInstigator.GetEntityID() != ScriptExecutionContext.GetOwner( context ).GetEntityID() ) )
			{
				broadcaster = ragdollInstigator.GetStimBroadcasterComponent();
			}
			if( broadcaster )
			{
				investigateData.skipReactionDelay = true;
				investigateData.skipInitialAnimation = true;
				broadcaster.SendDrirectStimuliToTarget( ScriptExecutionContext.GetOwner( context ), gamedataStimType.Combat, ScriptExecutionContext.GetOwner( context ), investigateData );
			}
			ragdollInstigator = NULL;
		}
		return true;
	}

}

class RemoveStatusEffectsOnStoryTier extends StatusEffectTasks
{

	protected export override function Activate( context : ScriptExecutionContext )
	{
		var appliedEffects : array< StatusEffect >;
		var i : Int32;
		appliedEffects = StatusEffectHelper.GetAppliedEffects( ScriptExecutionContext.GetOwner( context ) );
		for( i = 0; i < appliedEffects.Size(); i += 1 )
		{
			if( appliedEffects[ i ].GetRecord().RemoveOnStoryTier() )
			{
				StatusEffectHelper.RemoveStatusEffect( ScriptExecutionContext.GetOwner( context ), appliedEffects[ i ] );
			}
		}
	}

}

class ForceAnimationOffScreen extends AIbehaviortaskScript
{

	protected override function Activate( context : ScriptExecutionContext )
	{
		GameObject.ToggleForcedVisibilityInAnimSystemEvent( ScriptExecutionContext.GetOwner( context ), 'AIForceAnimationOffScreenTask', true );
	}

	protected override function Deactivate( context : ScriptExecutionContext )
	{
		GameObject.ToggleForcedVisibilityInAnimSystemEvent( ScriptExecutionContext.GetOwner( context ), 'AIForceAnimationOffScreenTask', false );
	}

}

