class AIActionHelper
{

	public static function ActionDebugHelper( entity : weak< Entity >, const actionName : ref< String > ) : Bool
	{
		var actionNameCheck : String;
		actionNameCheck = ( ( GameObject )( entity ) ).GetTracedActionName();
		if( entity || ( IsStringValid( actionNameCheck ) && IsStringValid( actionName ) ) )
		{
			if( IsStringValid( actionNameCheck ) )
			{
				if( StrContains( actionName, actionNameCheck ) )
				{
					if( ( ( GameObject )( entity ) ) )
					{
						if( ( ( GameObject )( entity ) ).IsSelectedForDebugging() )
						{
							return true;
						}
						return false;
					}
					return true;
				}
				return false;
			}
			if( ( ( GameObject )( entity ) ) )
			{
				if( ( ( GameObject )( entity ) ).IsSelectedForDebugging() )
				{
					return true;
				}
				return false;
			}
		}
		return false;
	}

	public static function ActionDebugHelper( const actionNameCheck : ref< String >, entity : weak< Entity >, const actionName : ref< String > ) : Bool
	{
		if( entity || ( IsStringValid( actionNameCheck ) && IsStringValid( actionName ) ) )
		{
			if( IsStringValid( actionNameCheck ) )
			{
				if( StrContains( actionName, actionNameCheck ) )
				{
					if( ( ( GameObject )( entity ) ) )
					{
						if( ( ( GameObject )( entity ) ).IsSelectedForDebugging() )
						{
							return true;
						}
						return false;
					}
					return true;
				}
				return false;
			}
			if( ( ( GameObject )( entity ) ) )
			{
				if( ( ( GameObject )( entity ) ).IsSelectedForDebugging() )
				{
					return true;
				}
				return false;
			}
		}
		return false;
	}

	public static function ActionDebugHelper( const actionNameCheck : ref< String >, const actionName : ref< String > ) : Bool
	{
		if( IsStringValid( actionNameCheck ) && IsStringValid( actionName ) )
		{
			if( StrContains( actionName, actionNameCheck ) )
			{
				return true;
			}
			return false;
		}
		return false;
	}

	public static function SetActionExclusivity( owner : GameObject, active : Bool )
	{
		var puppet : ScriptedPuppet;
		puppet = ( ( ScriptedPuppet )( owner ) );
		puppet.GetPuppetStateBlackboard().SetBool( GetAllBlackboardDefs().PuppetState.InExclusiveAction, active );
	}

	public static function HasLostTarget( owner : ScriptedPuppet, target : GameObject ) : Bool
	{
		var threat : TrackedLocation;
		var targetTrackerComponent : TargetTrackerComponent;
		if( ( owner && target ) && ( target != owner ) )
		{
			targetTrackerComponent = owner.GetTargetTrackerComponent();
			if( targetTrackerComponent && target.IsPuppet() )
			{
				return !( targetTrackerComponent.ThreatFromEntity( target, threat ) );
			}
		}
		return false;
	}

	public static function HasCombatAICommand( owner : weak< ScriptedPuppet > ) : Bool
	{
		var aiComponent : AIHumanComponent;
		aiComponent = owner.GetAIControllerComponent();
		if( !( aiComponent ) )
		{
			return false;
		}
		return aiComponent.IsCommandActive( 'AICombatRelatedCommand' );
	}

	public static function HasWorkspotAICommand( owner : weak< ScriptedPuppet > ) : Bool
	{
		var aiComponent : AIHumanComponent;
		aiComponent = owner.GetAIControllerComponent();
		if( !( aiComponent ) )
		{
			return false;
		}
		return aiComponent.IsCommandActive( 'AIUseWorkspotCommand' );
	}

	public static function HasFollowerCombatAICommand( owner : weak< ScriptedPuppet > ) : Bool
	{
		var aiComponent : AIHumanComponent;
		aiComponent = owner.GetAIControllerComponent();
		if( !( aiComponent ) )
		{
			return false;
		}
		return aiComponent.IsCommandActive( 'AIFollowerCombatCommand' );
	}

	public static function GetActionBlackboard( owner : ScriptedPuppet ) : IBlackboard
	{
		return owner.GetAIControllerComponent().GetActionBlackboard();
	}

	public static function GetShootingBlackboard( owner : ScriptedPuppet ) : IBlackboard
	{
		return owner.GetAIControllerComponent().GetShootingBlackboard();
	}

	public static function ShouldShootDirectlyAtTarget( weaponOwner : weak< GameObject >, weapon : weak< WeaponObject >, targetPosition : Vector4 ) : Bool
	{
		var coneAngle : Float;
		var absAngleToCombatTarget : Float;
		var vecToTarget : Vector4;
		if( weapon.IsTargetLocked() )
		{
			return true;
		}
		if( Vector4.IsZero( targetPosition ) || !( weaponOwner.GetTargetTrackerComponent().IsPositionValid( targetPosition ) ) )
		{
			return false;
		}
		vecToTarget = targetPosition - weapon.GetWorldPosition();
		coneAngle = MinF( 6.0 * Vector4.Length( vecToTarget ), 30.0 );
		absAngleToCombatTarget = AbsF( Vector4.GetAngleDegAroundAxis( vecToTarget, weapon.GetWorldForward(), weaponOwner.GetWorldUp() ) );
		if( ( ( absAngleToCombatTarget >= 0.0 ) && ( coneAngle > 0.0 ) ) && ( absAngleToCombatTarget <= ( coneAngle * 0.5 ) ) )
		{
			return true;
		}
		return false;
	}

	public static function GetTargetSlotPosition( target : weak< GameObject >, slotName : CName, out slotPosition : Vector4 ) : Bool
	{
		var slotTransform : WorldTransform;
		Vector4.Zero( slotPosition );
		if( !( IsNameValid( slotName ) ) )
		{
			slotName = 'Head';
		}
		if( GetTargetSlotTransform( target, slotName, slotTransform ) )
		{
			slotPosition = WorldPosition.ToVector4( WorldTransform.GetWorldPosition( slotTransform ) );
			return true;
		}
		return false;
	}

	public static function GetTargetPositionFromPast( target : weak< GameObject >, delay : Float, out position : Vector4 ) : Bool
	{
		var targetSP : weak< ScriptedPuppet >;
		targetSP = ( ( ScriptedPuppet )( target ) );
		if( targetSP && targetSP.GetTransformHistoryComponent() )
		{
			position = targetSP.GetTransformHistoryComponent().GetInterpolatedPositionFromHistory( delay );
			return true;
		}
		return false;
	}

	public static function GetTargetSlotTransform( target : weak< GameObject >, slotName : CName, out slotTransform : WorldTransform ) : Bool
	{
		var targetPuppet : ScriptedPuppet;
		var targetMuppet : Muppet;
		var hitRepresentationSlotComponent : SlotComponent;
		var slotComponent : SlotComponent;
		targetPuppet = ( ( ScriptedPuppet )( target ) );
		if( targetPuppet )
		{
			hitRepresentationSlotComponent = targetPuppet.GetHitRepresantationSlotComponent();
			slotComponent = targetPuppet.GetSlotComponent();
		}
		else
		{
			targetMuppet = ( ( Muppet )( target ) );
			if( targetMuppet )
			{
				hitRepresentationSlotComponent = targetMuppet.GetHitRepresantationSlotComponent();
				slotComponent = targetMuppet.GetSlotComponent();
			}
		}
		if( hitRepresentationSlotComponent && hitRepresentationSlotComponent.GetSlotTransform( slotName, slotTransform ) )
		{
			return true;
		}
		if( slotComponent && slotComponent.GetSlotTransform( slotName, slotTransform ) )
		{
			return true;
		}
		return false;
	}

	public static function AnimationsLoadedSignal( ownerPuppet : weak< ScriptedPuppet > )
	{
		var signalId : Uint16;
		signalId = ownerPuppet.GetSignalTable().GetOrCreateSignal( 'AnimationsLoaded' );
		ownerPuppet.GetSignalTable().Set( signalId, false );
		ownerPuppet.GetSignalTable().Set( signalId, true );
	}

	public static function CombatQueriesInit( ownerPuppet : weak< ScriptedPuppet > )
	{
		var signalId : Uint16;
		var signalTable : gameBoolSignalTable;
		signalTable = ownerPuppet.GetSignalTable();
		signalId = signalTable.GetOrCreateSignal( 'CombatQueriesRequest' );
		signalTable.Set( signalId, false );
		signalTable.Set( signalId, true );
	}

	public static function TryChangingAttitudeToHostile( owner : ScriptedPuppet, target : GameObject ) : Bool
	{
		var attitudeOwner : AttitudeAgent;
		var attitudeTarget : AttitudeAgent;
		var currentAttitude : EAIAttitude;
		attitudeOwner = owner.GetAttitudeAgent();
		attitudeTarget = target.GetAttitudeAgent();
		if( !( target.IsPuppet() ) && !( target.IsSensor() ) )
		{
			return false;
		}
		if( !( target.IsActive() ) )
		{
			return false;
		}
		if( attitudeOwner && attitudeTarget )
		{
			currentAttitude = attitudeOwner.GetAttitudeTowards( attitudeTarget );
			switch( currentAttitude )
			{
				case EAIAttitude.AIA_Friendly:
					return false;
				case EAIAttitude.AIA_Hostile:
					return true;
				default:
					if( owner.IsAggressive() )
					{
						attitudeOwner.SetAttitudeTowardsAgentGroup( attitudeTarget, attitudeOwner, EAIAttitude.AIA_Hostile );
						return true;
					}
				return false;
			}
		}
		return false;
	}

	public static function TryStartCombatWithTarget( owner : ScriptedPuppet, target : GameObject ) : Bool
	{
		if( AIActionHelper.TryChangingAttitudeToHostile( owner, target ) )
		{
			TargetTrackingExtension.InjectThreat( owner, target );
			return true;
		}
		return false;
	}

	public static function SetCommandCombatTarget( context : ScriptExecutionContext, target : weak< GameObject >, isPersistant : Bool, persistenceSource : Uint32 ) : Bool
	{
		if( !( target ) || ( ScriptExecutionContext.GetOwner( context ) == target ) )
		{
			return false;
		}
		if( target.IsPuppet() )
		{
			if( !( ScriptedPuppet.IsActive( target ) ) )
			{
				return false;
			}
			GameObject.ChangeAttitudeToHostile( ScriptExecutionContext.GetOwner( context ), target );
			TargetTrackingExtension.InjectThreat( ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ), target );
			if( isPersistant )
			{
				TargetTrackingExtension.SetThreatPersistence( ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ), target, true, persistenceSource );
			}
		}
		ScriptExecutionContext.SetArgumentObject( context, 'CommandCombatTarget', target );
		return true;
	}

	public static function ClearCommandCombatTarget( context : ScriptExecutionContext, persistenceSource : Uint32, optional ignoreCombatTargetCommand : Bool )
	{
		var puppet : weak< ScriptedPuppet >;
		var tt : TargetTrackerComponent;
		var target : weak< GameObject >;
		var combatTargetCmdSourceRecord : AIThreatPersistenceSource_Record;
		puppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		tt = puppet.GetTargetTrackerComponent();
		target = ScriptExecutionContext.GetArgumentObject( context, 'CommandCombatTarget' );
		TargetTrackingExtension.SetThreatPersistence( puppet, target, false, persistenceSource );
		if( !( ignoreCombatTargetCommand ) && tt )
		{
			combatTargetCmdSourceRecord = TweakDBInterface.GetAIThreatPersistenceSourceRecord( T"AIThreatPersistenceSource.CommandInjectCombatTarget" );
			if( tt.GetThreatPersistenceBySource( target, ( ( Uint32 )( combatTargetCmdSourceRecord.EnumValue() ) ) ) == AIThreatPersistenceStatus.Persistent )
			{
				return;
			}
		}
		ScriptExecutionContext.SetArgumentObject( context, 'CommandCombatTarget', NULL );
	}

	public static function IsCommandCombatTargetValid( context : ScriptExecutionContext, commandName : CName ) : Bool
	{
		var target : weak< GameObject >;
		target = ScriptExecutionContext.GetArgumentObject( context, 'CommandCombatTarget' );
		if( !( ScriptedPuppet.IsActive( ScriptExecutionContext.GetOwner( context ) ) ) )
		{
			ScriptExecutionContext.DebugLog( context, commandName, "Canceling command, owner is Dead, Defeated or Unconscious" );
			return false;
		}
		if( !( target ) )
		{
			ScriptExecutionContext.DebugLog( context, commandName, "Canceling command, Target no longer exists" );
			return false;
		}
		if( target.IsPuppet() )
		{
			if( !( ScriptedPuppet.IsActive( target ) ) )
			{
				ScriptExecutionContext.DebugLog( context, commandName, "Canceling command, Target no longer active" );
				return false;
			}
			else if( GameObject.GetAttitudeBetween( ScriptExecutionContext.GetOwner( context ), target ) == EAIAttitude.AIA_Friendly )
			{
				ScriptExecutionContext.DebugLog( context, commandName, "Canceling command, Target is Friendly" );
				return false;
			}
			else if( HasLostTarget( ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ), target ) )
			{
				ScriptExecutionContext.DebugLog( context, commandName, "Canceling command, lost track of target" );
				return false;
			}
		}
		return true;
	}

	public static function TargetAllSquadMembers( owner : weak< GameObject > )
	{
		var attitudeOwner : AttitudeAgent;
		var attitudeTarget : AttitudeAgent;
		var squadMembers : array< weak< Entity > >;
		var target : weak< GameObject >;
		var i : Int32;
		var targetTrackerComponent : TargetTrackerComponent;
		attitudeOwner = owner.GetAttitudeAgent();
		attitudeOwner.SetAttitudeGroup( 'HostileToEveryone' );
		targetTrackerComponent = owner.GetTargetTrackerComponent();
		if( !( AISquadHelper.GetSquadmates( ( ( ScriptedPuppet )( owner ) ), squadMembers ) ) )
		{
			return;
		}
		for( i = 0; i < squadMembers.Size(); i += 1 )
		{
			target = ( ( GameObject )( squadMembers[ i ] ) );
			if( ( !( target ) || ( target == owner ) ) || !( ScriptedPuppet.IsActive( target ) ) )
			{
				continue;
			}
			attitudeTarget = target.GetAttitudeAgent();
			attitudeOwner.SetAttitudeTowards( attitudeTarget, EAIAttitude.AIA_Hostile );
			if( targetTrackerComponent )
			{
				targetTrackerComponent.AddThreat( target, true, target.GetWorldPosition(), 1.0, -1.0, false );
			}
		}
		return;
	}

	public static function SetFriendlyTargetAllSquadMembers( owner : weak< GameObject > )
	{
		var attitudeOwner : AttitudeAgent;
		var attitudeTarget : AttitudeAgent;
		var squadMembers : array< weak< Entity > >;
		var target : weak< GameObject >;
		var i : Int32;
		var targetTrackerComponent : TargetTrackerComponent;
		attitudeOwner = owner.GetAttitudeAgent();
		if( !( AISquadHelper.GetSquadmates( ( ( ScriptedPuppet )( owner ) ), squadMembers ) ) )
		{
			return;
		}
		targetTrackerComponent = owner.GetTargetTrackerComponent();
		if( targetTrackerComponent )
		{
			targetTrackerComponent.ClearThreats();
		}
		for( i = 0; i < squadMembers.Size(); i += 1 )
		{
			target = ( ( GameObject )( squadMembers[ i ] ) );
			if( ( !( target ) || ( target == owner ) ) || !( ScriptedPuppet.IsActive( target ) ) )
			{
				continue;
			}
			attitudeTarget = target.GetAttitudeAgent();
			attitudeOwner.SetAttitudeTowards( attitudeTarget, EAIAttitude.AIA_Hostile );
			if( targetTrackerComponent )
			{
				targetTrackerComponent.AddThreat( target, true, target.GetWorldPosition(), 1.0, -1.0, false );
			}
		}
		return;
	}

	public static function ChangeAttitudeToFriendlyAllSquad( owner : weak< GameObject >, const squadMembers : ref< array< EntityID > > )
	{
		var attitudeOwner : AttitudeAgent;
		var attitudeTarget : AttitudeAgent;
		var target : weak< GameObject >;
		var i : Int32;
		attitudeOwner = owner.GetAttitudeAgent();
		for( i = 0; i < squadMembers.Size(); i += 1 )
		{
			target = ( ( GameObject )( GameInstance.FindEntityByID( owner.GetGame(), squadMembers[ i ] ) ) );
			if( !( target ) || ( target == owner ) )
			{
				continue;
			}
			attitudeTarget = target.GetAttitudeAgent();
			attitudeOwner.SetAttitudeTowards( attitudeTarget, EAIAttitude.AIA_Friendly );
		}
		return;
	}

	public static function GetActiveTopHostilePuppetThreat( puppet : ScriptedPuppet, threat : ref< TrackedLocation > ) : Bool
	{
		var targetTrackerComponent : TargetTrackerComponent;
		var currentTopThreat : TrackedLocation;
		var allThreats : array< TrackedLocation >;
		var newTargetPuppet : ScriptedPuppet;
		var i : Int32;
		targetTrackerComponent = puppet.GetTargetTrackerComponent();
		if( targetTrackerComponent.GetTopHostileThreat( false, currentTopThreat ) )
		{
			threat = currentTopThreat;
			newTargetPuppet = ( ( ScriptedPuppet )( currentTopThreat.entity ) );
			if( newTargetPuppet )
			{
				if( ScriptedPuppet.IsActive( newTargetPuppet ) )
				{
					return true;
				}
				else
				{
					allThreats = targetTrackerComponent.GetHostileThreats( false );
					for( i = allThreats.Size() - 1; i >= 0; i -= 1 )
					{
						newTargetPuppet = ( ( ScriptedPuppet )( allThreats[ i ].entity ) );
						if( ScriptedPuppet.IsActive( newTargetPuppet ) )
						{
							threat = allThreats[ i ];
							return true;
						}
					}
				}
			}
		}
		return false;
	}

	public static function GetAnimWrapperNameBasedOnItemID( itemID : ItemID ) : CName
	{
		var animWrapperName : CName;
		animWrapperName = TDB.GetCName( ItemID.GetTDBID( itemID ) + T".NPCAnimWrapperWeightOverride" );
		if( !( IsNameValid( animWrapperName ) ) )
		{
			animWrapperName = TweakDBInterface.GetItemRecord( ItemID.GetTDBID( itemID ) ).ItemType().Name();
		}
		return animWrapperName;
	}

	public static function GetAnimWrapperNameBasedOnItemTag( itemID : ItemID ) : CName
	{
		var itemRecord : Item_Record;
		itemRecord = TweakDBInterface.GetItemRecord( ItemID.GetTDBID( itemID ) );
		if( itemRecord.TagsContains( WeaponObject.GetMeleeWeaponTag() ) )
		{
			return 'MeleeWeapon';
		}
		else if( itemRecord.TagsContains( WeaponObject.GetRangedWeaponTag() ) )
		{
			return 'RangedWeapon';
		}
		return '';
	}

	public static function SendItemHandling( owner : weak< GameObject >, itemRecord : weak< Item_Record >, animFeatureName : CName, equipped : Bool )
	{
		var itemHandling : AnimFeature_EquipUnequipItem;
		itemHandling = new AnimFeature_EquipUnequipItem;
		itemHandling.itemState = ( ( equipped ) ? ( 2 ) : ( 0 ) );
		itemHandling.itemType = itemRecord.ItemType().AnimFeatureIndex();
		AnimationControllerComponent.ApplyFeatureToReplicate( owner, animFeatureName, itemHandling );
	}

	public static function GetReactionPresetGroup( puppet : weak< ScriptedPuppet > ) : String
	{
		var reactionGroup : String;
		var reactionComponent : ReactionManagerComponent;
		if( puppet )
		{
			reactionComponent = puppet.GetStimReactionComponent();
			if( reactionComponent )
			{
				reactionGroup = reactionComponent.GetReactionPreset().ReactionGroup();
			}
		}
		return reactionGroup;
	}

	public static function PlayWeaponEffect( weapon : WeaponObject, effectName : CName )
	{
		var spawnEffectEvent : entSpawnEffectEvent;
		spawnEffectEvent = new entSpawnEffectEvent;
		spawnEffectEvent.effectName = effectName;
		weapon.QueueEventToChildItems( spawnEffectEvent );
	}

	public static function BreakWeaponEffectLoop( weapon : WeaponObject, effectName : CName )
	{
		var evt : entBreakEffectLoopEvent;
		evt = new entBreakEffectLoopEvent;
		evt.effectName = effectName;
		weapon.QueueEventToChildItems( evt );
	}

	public static function KillWeaponEffect( weapon : WeaponObject, effectName : CName )
	{
		var evt : entKillEffectEvent;
		evt = new entKillEffectEvent;
		evt.effectName = effectName;
		weapon.QueueEventToChildItems( evt );
	}

	public static function CheckFlatheadStatPoolRequirements( game : GameInstance, const actionName : ref< String > ) : Bool
	{
		var statPoolsAffected : array< CName >;
		var statPoolsValueChanges : array< Float >;
		var statPoolType : gamedataStatPoolType;
		var actionID : TweakDBID;
		var flathead : weak< GameObject >;
		var currentStatPoolValue : Float;
		var i : Int32;
		actionID = TDBID.Create( "SpiderbotArchetype." + actionName );
		statPoolsAffected = AITweakParams.GetCNameArrayFromTweak( actionID, "statPoolsAffected" );
		statPoolsValueChanges = AITweakParams.GetFloatArrayFromTweak( actionID, "statPoolsValueChanges" );
		flathead = ( ( SubCharacterSystem )( GameInstance.GetScriptableSystemsContainer( game ).Get( 'SubCharacterSystem' ) ) ).GetFlathead();
		for( i = 0; i < statPoolsAffected.Size(); i += 1 )
		{
			statPoolType = ( ( gamedataStatPoolType )( ( ( Int32 )( EnumValueFromName( 'gamedataStatPoolType', statPoolsAffected[ i ] ) ) ) ) );
			currentStatPoolValue = GameInstance.GetStatPoolsSystem( game ).GetStatPoolValue( flathead.GetEntityID(), statPoolType, false );
			if( ( currentStatPoolValue + statPoolsValueChanges[ i ] ) < 0.0 )
			{
				return false;
			}
		}
		return true;
	}

	public static function IsCurrentlyCrouching( puppet : ScriptedPuppet ) : Bool
	{
		if( puppet.GetStanceStateFromBlackboard() == gamedataNPCStanceState.Crouch )
		{
			return true;
		}
		if( !( AICoverHelper.IsCurrentlyInCover( puppet ) ) )
		{
			return false;
		}
		if( AICoverHelper.GetCurrentCoverStance( puppet ) == 'High' )
		{
			return false;
		}
		else
		{
			if( AICoverHelper.GetCoverNPCCurrentlyExposed( puppet ) && AICoverHelper.IsStandingExposureMethod( AICoverHelper.GetCoverExposureMethod( puppet ) ) )
			{
				return false;
			}
		}
		return true;
	}

	public static function IsCurrentlyExposedInCover( puppet : ScriptedPuppet ) : Bool
	{
		if( !( AICoverHelper.IsCurrentlyInCover( puppet ) ) )
		{
			return false;
		}
		if( AICoverHelper.GetCoverNPCCurrentlyExposed( puppet ) && AICoverHelper.IsUnsafeExposureMethod( AICoverHelper.GetCoverExposureMethod( puppet ) ) )
		{
			return true;
		}
		return false;
	}

	public static function IsCurrentlyInCoverAttackAction( puppet : ScriptedPuppet ) : Bool
	{
		if( !( AICoverHelper.IsCurrentlyInCover( puppet ) ) )
		{
			return false;
		}
		if( AICoverHelper.GetCoverNPCCurrentlyExposed( puppet ) )
		{
			return true;
		}
		return false;
	}

	public static function GetItemsFromWeaponSlots( owner : weak< GameObject >, items : ref< array< weak< ItemObject > > > ) : Bool
	{
		var item : weak< ItemObject >;
		item = GameInstance.GetTransactionSystem( owner.GetGame() ).GetItemInSlot( owner, T"AttachmentSlots.WeaponRight" );
		if( item )
		{
			items.PushBack( item );
		}
		item = GameInstance.GetTransactionSystem( owner.GetGame() ).GetItemInSlot( owner, T"AttachmentSlots.WeaponLeft" );
		if( item )
		{
			items.PushBack( item );
		}
		return items.Size() > 0;
	}

	public static function HasEquippedWeaponWithTag( owner : weak< GameObject >, tag : CName ) : Bool
	{
		var item : ItemObject;
		var items : array< ItemObject >;
		var i : Int32;
		item = GameInstance.GetTransactionSystem( owner.GetGame() ).GetItemInSlot( owner, T"AttachmentSlots.WeaponRight" );
		if( item )
		{
			items.PushBack( item );
		}
		item = GameInstance.GetTransactionSystem( owner.GetGame() ).GetItemInSlot( owner, T"AttachmentSlots.WeaponLeft" );
		if( item )
		{
			items.PushBack( item );
		}
		for( i = 0; i < items.Size(); i += 1 )
		{
			if( item.GetItemData().HasTag( tag ) )
			{
				return true;
			}
		}
		return false;
	}

	public static function IsInWorkspot( owner : weak< GameObject > ) : Bool
	{
		var workspotSystem : WorkspotGameSystem;
		var res : Bool;
		workspotSystem = GameInstance.GetWorkspotSystem( owner.GetGame() );
		if( workspotSystem )
		{
			res = workspotSystem.IsActorInWorkspot( owner );
		}
		return res;
	}

	public static function IsPointInRestrictedMovementArea( ownerPuppet : weak< ScriptedPuppet >, point : Vector4 ) : Bool
	{
		if( !( ownerPuppet ) )
		{
			return false;
		}
		return GameInstance.GetRestrictMovementAreaManager( ownerPuppet.GetGame() ).IsPointInRestrictMovementArea( ownerPuppet.GetEntityID(), point );
	}

	public static function IsPointInRMA( ownerPuppet : weak< ScriptedPuppet >, point : Vector4 ) : Bool
	{
		return IsPointInRestrictedMovementArea( ownerPuppet, point );
	}

	public static function GetCurrentStrongArmsTrailEffect( weapon : ItemObject ) : CName
	{
		var cachedThreshold : Float;
		var statSystem : StatsSystem;
		var weaponID : StatsObjectID;
		var damageType : gamedataDamageType;
		statSystem = GameInstance.GetStatsSystem( weapon.GetGame() );
		weaponID = weapon.GetEntityID();
		cachedThreshold = statSystem.GetStatValue( weaponID, gamedataStatType.PhysicalDamage );
		damageType = gamedataDamageType.Physical;
		if( statSystem.GetStatValue( weaponID, gamedataStatType.ThermalDamage ) > cachedThreshold )
		{
			cachedThreshold = statSystem.GetStatValue( weaponID, gamedataStatType.ThermalDamage );
			damageType = gamedataDamageType.Thermal;
		}
		if( statSystem.GetStatValue( weaponID, gamedataStatType.ElectricDamage ) > cachedThreshold )
		{
			cachedThreshold = statSystem.GetStatValue( weaponID, gamedataStatType.ElectricDamage );
			damageType = gamedataDamageType.Electric;
		}
		if( statSystem.GetStatValue( weaponID, gamedataStatType.ChemicalDamage ) > cachedThreshold )
		{
			cachedThreshold = statSystem.GetStatValue( weaponID, gamedataStatType.ChemicalDamage );
			damageType = gamedataDamageType.Chemical;
		}
		switch( damageType )
		{
			case gamedataDamageType.Physical:
				return 'trail_physical';
			case gamedataDamageType.Thermal:
				return 'trail_thermal';
			case gamedataDamageType.Chemical:
				return 'trail_chemical';
			case gamedataDamageType.Electric:
				return 'trail_electric';
			default:
				return 'trail_physical';
		}
		return 'trail_physical';
	}

	public static function StartCooldown( self : GameObject, record : weak< AIActionCooldown_Record > ) : Int32
	{
		var context : ScriptExecutionContext;
		var cdRequest : RegisterNewCooldownRequest;
		var cs : ICooldownSystem;
		var i : Int32;
		var count : Int32;
		var activationCondition : Bool;
		if( !( record ) )
		{
			return -1;
		}
		if( !( AIHumanComponent.GetScriptContext( ( ( ScriptedPuppet )( self ) ), context ) ) )
		{
			return -1;
		}
		if( ( record.Duration() < 0.0 ) || !( IsNameValid( record.Name() ) ) )
		{
			return -1;
		}
		if( record.Duration() == 0.0 )
		{
			GameObject.RemoveCooldown( self, record.Name() );
			return -1;
		}
		count = record.GetActivationConditionCount();
		if( count > 0 )
		{
			activationCondition = false;
			for( i = 0; i < count; i += 1 )
			{
				if( AICondition.CheckActionCondition( context, record.GetActivationConditionItem( i ) ) )
				{
					activationCondition = true;
					break;
				}
			}
		}
		else
		{
			activationCondition = true;
		}
		if( !( activationCondition ) )
		{
			return -1;
		}
		cs = CSH.GetCooldownSystem( self );
		cdRequest.cooldownName = record.Name();
		cdRequest.duration = record.Duration();
		cdRequest.owner = self;
		return cs.Register( cdRequest );
	}

	public static function StartCooldown( self : GameObject, cooldownName : CName, duration : Float ) : Int32
	{
		var cdRequest : RegisterNewCooldownRequest;
		var cs : ICooldownSystem;
		if( ( duration < 0.0 ) || !( IsNameValid( cooldownName ) ) )
		{
			return -1;
		}
		if( duration == 0.0 )
		{
			GameObject.RemoveCooldown( self, cooldownName );
			return -1;
		}
		cs = CSH.GetCooldownSystem( self );
		cdRequest.cooldownName = cooldownName;
		cdRequest.duration = duration;
		cdRequest.owner = self;
		return cs.Register( cdRequest );
	}

	public static function IsCooldownActive( self : GameObject, record : weak< AIActionCooldown_Record > ) : Bool
	{
		var context : ScriptExecutionContext;
		var cooldownName : CName;
		if( !( record ) )
		{
			return false;
		}
		if( !( AIHumanComponent.GetScriptContext( ( ( ScriptedPuppet )( self ) ), context ) ) )
		{
			return false;
		}
		cooldownName = record.Name();
		if( !( IsNameValid( cooldownName ) ) )
		{
			return false;
		}
		return GameObject.IsCooldownActive( self, cooldownName );
	}

	public static function GetBaseShootingPatternPackages( patternPackages : ref< array< weak< AIPatternsPackage_Record > > > ) : Bool
	{
		var packageIDNames : array< String >;
		var tweakID : TweakDBID;
		var i, size : Int32;
		packageIDNames = TDB.GetStringArray( T"AIGeneralSettings.baseShootingPatternPackages" );
		size = packageIDNames.Size();
		patternPackages.Resize( size );
		for( i = 0; i < size; i += 1 )
		{
			tweakID = TDBID.Create( packageIDNames[ i ] );
			patternPackages[ i ] = TweakDBInterface.GetAIPatternsPackageRecord( tweakID );
		}
		return size > 0;
	}

	public static function ClearWorkspotCommand( puppet : weak< ScriptedPuppet >, optional doNotRepeat : Bool ) : Bool
	{
		var aiComponent : AIHumanComponent;
		var workspotCommand : weak< AIBaseUseWorkspotCommand >;
		var commandID : Uint32;
		if( !( puppet ) )
		{
			return false;
		}
		aiComponent = puppet.GetAIControllerComponent();
		if( !( aiComponent ) )
		{
			return false;
		}
		commandID = ( ( Uint32 )( aiComponent.GetActiveCommandID( 'AIUseWorkspotCommand' ) ) );
		if( aiComponent.CancelCommandById( commandID, doNotRepeat ) )
		{
			return true;
		}
		else
		{
			workspotCommand = ( ( weak< weak< AIBaseUseWorkspotCommand > > )( aiComponent.GetBehaviorArgument( '_command' ) ) );
			if( !( workspotCommand ) )
			{
				workspotCommand = ( ( weak< weak< AIBaseUseWorkspotCommand > > )( aiComponent.GetBehaviorArgument( 'UseWorkspotCommand' ) ) );
			}
			if( workspotCommand && workspotCommand.state == AICommandState.Executing )
			{
				aiComponent.StopExecutingCommand( workspotCommand, true );
			}
		}
		return false;
	}

	public static function GetDistanceRangeFromRingType( ringRecord : weak< AIRingType_Record >, out distanceRange : Vector2 ) : Bool
	{
		if( ringRecord.Distance() >= 0.0 )
		{
			distanceRange.X = ringRecord.Distance();
			distanceRange.Y = distanceRange.X;
		}
		else
		{
			return false;
		}
		if( ringRecord.Tolerance() > 0.0 )
		{
			distanceRange.X = ringRecord.Distance() - ringRecord.Tolerance();
			distanceRange.Y = ringRecord.Distance() + ringRecord.Tolerance();
		}
		return distanceRange.Y > 0.0;
	}

	public static function GetDistanceRangeFromRingType( ringRecord : weak< AIRingType_Record >, condition : weak< AIOptimalDistanceCond_Record >, out distanceRange : Vector2 ) : Bool
	{
		var tolerance : Float;
		if( ringRecord.Distance() < 0.0 )
		{
			return false;
		}
		distanceRange.X = ringRecord.Distance();
		if( condition.DistanceMult() >= 0.0 )
		{
			distanceRange.X *= condition.DistanceMult();
		}
		if( condition.DistanceOffset() != 0.0 )
		{
			distanceRange.X += condition.DistanceOffset();
		}
		distanceRange.Y = distanceRange.X;
		if( distanceRange.X < 0.0 )
		{
			return false;
		}
		if( ringRecord.Tolerance() >= 0.0 )
		{
			tolerance = ringRecord.Tolerance();
			if( condition.ToleranceMult() >= 0.0 )
			{
				tolerance *= condition.ToleranceMult();
			}
			if( condition.ToleranceOffset() != 0.0 )
			{
				tolerance += condition.ToleranceOffset();
			}
		}
		if( tolerance > 0.0 )
		{
			distanceRange.X = ringRecord.Distance() - tolerance;
			distanceRange.Y = ringRecord.Distance() + tolerance;
		}
		return distanceRange.Y > 0.0;
	}

	public static function GetDistanceRangeFromRingType( ringRecord : weak< AIRingType_Record >, condition : weak< MovementPolicy_Record >, out distanceRange : Vector2 ) : Bool
	{
		var tolerance : Float;
		if( ringRecord.Distance() < 0.0 )
		{
			return false;
		}
		distanceRange.X = ringRecord.Distance();
		if( condition.RingDistanceMult() >= 0.0 )
		{
			distanceRange.X *= condition.RingDistanceMult();
		}
		if( condition.RingDistanceOffset() != 0.0 )
		{
			distanceRange.X += condition.RingDistanceOffset();
		}
		distanceRange.Y = distanceRange.X;
		if( distanceRange.X < 0.0 )
		{
			return false;
		}
		if( ringRecord.Tolerance() >= 0.0 )
		{
			tolerance = ringRecord.Tolerance();
			if( condition.RingToleranceMult() >= 0.0 )
			{
				tolerance *= condition.RingToleranceMult();
			}
			if( condition.RingToleranceOffset() != 0.0 )
			{
				tolerance += condition.RingToleranceOffset();
			}
		}
		if( tolerance > 0.0 )
		{
			distanceRange.X = ringRecord.Distance() - tolerance;
			distanceRange.Y = ringRecord.Distance() + tolerance;
		}
		return distanceRange.Y > 0.0;
	}

	public static function GetDistanceAndToleranceFromRingType( record : weak< MovementPolicy_Record >, out distance : Float, out tolerance : Float ) : Bool
	{
		if( record.Ring().Distance() < 0.0 )
		{
			return false;
		}
		distance = record.Ring().Distance();
		if( record.RingDistanceMult() >= 0.0 )
		{
			distance *= record.RingDistanceMult();
		}
		if( record.RingDistanceOffset() != 0.0 )
		{
			distance += record.RingDistanceOffset();
		}
		if( distance < 0.0 )
		{
			return false;
		}
		if( record.Ring().Tolerance() >= 0.0 )
		{
			tolerance = record.Ring().Tolerance();
			if( record.RingToleranceMult() >= 0.0 )
			{
				tolerance *= record.RingToleranceMult();
			}
			if( record.RingToleranceOffset() != 0.0 )
			{
				tolerance += record.RingToleranceOffset();
			}
		}
		if( tolerance < 0.0 )
		{
			tolerance = 0.0;
		}
		return true;
	}

	public static function GetAdditionalTraceTypeValueFromTweakEnum( value : gamedataAIAdditionalTraceType ) : AdditionalTraceType
	{
		switch( value )
		{
			case gamedataAIAdditionalTraceType.Chest:
				return AdditionalTraceType.Chest;
			case gamedataAIAdditionalTraceType.Hip:
				return AdditionalTraceType.Hip;
			case gamedataAIAdditionalTraceType.Knee:
				return AdditionalTraceType.Knee;
			default:
				return AdditionalTraceType.Chest;
		}
	}

	public static function GetLatestActiveRingTypeRecord( puppet : weak< ScriptedPuppet > ) : AIRingType_Record
	{
		var currentRing : gamedataAIRingType;
		currentRing = AISquadHelper.GetCurrentSquadRing( puppet );
		switch( currentRing )
		{
			case gamedataAIRingType.Melee:
				return TweakDBInterface.GetAIRingTypeRecord( T"AIRingType.Melee" );
			case gamedataAIRingType.Close:
				return TweakDBInterface.GetAIRingTypeRecord( T"AIRingType.Close" );
			case gamedataAIRingType.Medium:
				return TweakDBInterface.GetAIRingTypeRecord( T"AIRingType.Medium" );
			case gamedataAIRingType.Far:
				return TweakDBInterface.GetAIRingTypeRecord( T"AIRingType.Far" );
			case gamedataAIRingType.Extreme:
				return TweakDBInterface.GetAIRingTypeRecord( T"AIRingType.Extreme" );
			default:
				return TweakDBInterface.GetAIRingTypeRecord( T"AIRingType.Default" );
		}
	}

	public export static function GetLatestActiveRingTypeRecordHelper( object : GameObject ) : AIRingType_Record
	{
		var puppet : ScriptedPuppet;
		puppet = ( ( ScriptedPuppet )( object ) );
		if( puppet == NULL )
		{
			return NULL;
		}
		return GetLatestActiveRingTypeRecord( puppet );
	}

	public static function WeaponHasTriggerModes( weapon : weak< WeaponObject >, weaponRecord : weak< WeaponItem_Record >, const triggerModes : ref< array< weak< TriggerMode_Record > > > ) : Bool
	{
		var triggerModesSize : Int32;
		var i, j : Int32;
		triggerModesSize = triggerModes.Size();
		if( triggerModesSize == 0 )
		{
			return false;
		}
		for( i = 0; i < triggerModesSize; i += 1 )
		{
			if( triggerModes[ i ].Type() == gamedataTriggerMode.Charge )
			{
				if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.ChargeTime ) > 0.0 )
				{
					j += 1;
					continue;
				}
			}
			else if( triggerModes[ i ].Type() == gamedataTriggerMode.Burst )
			{
				if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.CycleTime_Burst ) > 0.0 )
				{
					j += 1;
					continue;
				}
			}
			if( triggerModes[ i ] == weaponRecord.PrimaryTriggerMode() )
			{
				j += 1;
				continue;
			}
		}
		return triggerModesSize == j;
	}

	public static function WeaponHasTriggerMode( weapon : weak< WeaponObject >, weaponRecord : weak< WeaponItem_Record >, triggerMode : weak< TriggerMode_Record > ) : Bool
	{
		if( triggerMode.Type() == gamedataTriggerMode.Charge )
		{
			if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.ChargeTime ) > 0.0 )
			{
				return true;
			}
		}
		else if( triggerMode.Type() == gamedataTriggerMode.Burst )
		{
			if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.CycleTime_Burst ) > 0.0 )
			{
				return true;
			}
		}
		if( triggerMode == weaponRecord.PrimaryTriggerMode() )
		{
			return true;
		}
		return false;
	}

	public static function WeaponHasTriggerMode( weapon : weak< WeaponObject >, weaponRecord : weak< WeaponItem_Record >, triggerMode : gamedataTriggerMode ) : Bool
	{
		if( triggerMode == gamedataTriggerMode.Charge )
		{
			if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.ChargeTime ) > 0.0 )
			{
				return true;
			}
		}
		else if( triggerMode == gamedataTriggerMode.Burst )
		{
			if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.CycleTime_Burst ) > 0.0 )
			{
				return true;
			}
		}
		if( triggerMode == weaponRecord.PrimaryTriggerMode().Type() )
		{
			return true;
		}
		return false;
	}

	public static function WeaponHasTriggerMode( weapon : weak< WeaponObject >, triggerMode : gamedataTriggerMode ) : Bool
	{
		var weaponRecord : weak< WeaponItem_Record >;
		if( triggerMode == gamedataTriggerMode.Charge )
		{
			if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.ChargeTime ) > 0.0 )
			{
				return true;
			}
		}
		else if( triggerMode == gamedataTriggerMode.Burst )
		{
			if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.CycleTime_Burst ) > 0.0 )
			{
				return true;
			}
		}
		weaponRecord = ( ( WeaponItem_Record )( TweakDBInterface.GetItemRecord( ItemID.GetTDBID( weapon.GetItemID() ) ) ) );
		if( triggerMode == weaponRecord.PrimaryTriggerMode().Type() )
		{
			return true;
		}
		return false;
	}

	public static function WeaponHasTriggerMode( weapon : weak< WeaponObject >, triggerMode : weak< TriggerMode_Record > ) : Bool
	{
		var weaponRecord : weak< WeaponItem_Record >;
		if( triggerMode.Type() == gamedataTriggerMode.Charge )
		{
			if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.ChargeTime ) > 0.0 )
			{
				return true;
			}
		}
		else if( triggerMode.Type() == gamedataTriggerMode.Burst )
		{
			if( GameInstance.GetStatsSystem( weapon.GetGame() ).GetStatValue( weapon.GetEntityID(), gamedataStatType.CycleTime_Burst ) > 0.0 )
			{
				return true;
			}
		}
		weaponRecord = ( ( WeaponItem_Record )( TweakDBInterface.GetItemRecord( ItemID.GetTDBID( weapon.GetItemID() ) ) ) );
		if( triggerMode == weaponRecord.PrimaryTriggerMode() )
		{
			return true;
		}
		return false;
	}

	public static function GetLastRequestedTriggerMode( weapon : weak< WeaponObject > ) : gamedataTriggerMode
	{
		return ( ( gamedataTriggerMode )( weapon.GetAIBlackboard().GetInt( GetAllBlackboardDefs().AIShooting.requestedTriggerMode ) ) );
	}

	public static function UpdateLinkedStatusEffects( owner : weak< GameObject >, linkedStatusEffect : ref< LinkedStatusEffect > )
	{
		var overheatT1 : TweakDBID;
		var overheatT2 : TweakDBID;
		var overheatT3 : TweakDBID;
		var hackMalfunctiontT1 : TweakDBID;
		var hackMalfunctionT2 : TweakDBID;
		var hackMalfunctionT3 : TweakDBID;
		var hackLocomotionT1 : TweakDBID;
		var hackLocomotionT2 : TweakDBID;
		var hackLocomotionT3 : TweakDBID;
		var i : Int32;
		if( EntityID.IsDefined( linkedStatusEffect.targetID ) )
		{
			overheatT1 = T"AIQuickHackStatusEffect.HackOverheat";
			overheatT2 = T"AIQuickHackStatusEffect.HackOverheatTier2";
			overheatT3 = T"AIQuickHackStatusEffect.HackOverheatTier3";
			hackMalfunctiontT1 = T"AIQuickHackStatusEffect.HackWeaponMalfunction";
			hackMalfunctionT2 = T"AIQuickHackStatusEffect.HackWeaponMalfunctionTier2";
			hackMalfunctionT3 = T"AIQuickHackStatusEffect.HackWeaponMalfunctionTier3";
			hackLocomotionT1 = T"AIQuickHackStatusEffect.HackLocomotion";
			hackLocomotionT2 = T"AIQuickHackStatusEffect.HackLocomotionTier2";
			hackLocomotionT3 = T"AIQuickHackStatusEffect.HackLocomotionTier3";
		}
		for( i = 0; i < linkedStatusEffect.statusEffectList.Size(); i += 1 )
		{
			if( linkedStatusEffect.netrunnerIDs.Size() > 0 )
			{
				if( ( ( linkedStatusEffect.statusEffectList[ i ] == overheatT1 ) || ( linkedStatusEffect.statusEffectList[ i ] == overheatT2 ) ) || ( linkedStatusEffect.statusEffectList[ i ] == overheatT3 ) )
				{
					StatusEffectHelper.RemoveStatusEffect( owner, linkedStatusEffect.statusEffectList[ i ] );
					switch( linkedStatusEffect.netrunnerIDs.Size() )
					{
						case 1:
							linkedStatusEffect.statusEffectList[ i ] = overheatT1;
						StatusEffectHelper.ApplyStatusEffect( owner, overheatT1, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						case 2:
							linkedStatusEffect.statusEffectList[ i ] = overheatT2;
						StatusEffectHelper.ApplyStatusEffect( owner, overheatT2, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						case 3:
							linkedStatusEffect.statusEffectList[ i ] = overheatT3;
						StatusEffectHelper.ApplyStatusEffect( owner, overheatT3, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						default:
							break;
					}
				}
				if( ( ( linkedStatusEffect.statusEffectList[ i ] == hackMalfunctiontT1 ) || ( linkedStatusEffect.statusEffectList[ i ] == hackMalfunctionT2 ) ) || ( linkedStatusEffect.statusEffectList[ i ] == hackMalfunctionT3 ) )
				{
					StatusEffectHelper.RemoveStatusEffect( owner, linkedStatusEffect.statusEffectList[ i ] );
					switch( linkedStatusEffect.netrunnerIDs.Size() )
					{
						case 1:
							linkedStatusEffect.statusEffectList[ i ] = hackMalfunctiontT1;
						StatusEffectHelper.ApplyStatusEffect( owner, hackMalfunctiontT1, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						case 2:
							linkedStatusEffect.statusEffectList[ i ] = hackMalfunctionT2;
						StatusEffectHelper.ApplyStatusEffect( owner, hackMalfunctionT2, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						case 3:
							linkedStatusEffect.statusEffectList[ i ] = hackMalfunctionT3;
						StatusEffectHelper.ApplyStatusEffect( owner, hackMalfunctionT3, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						default:
							break;
					}
				}
				if( ( ( linkedStatusEffect.statusEffectList[ i ] == hackLocomotionT1 ) || ( linkedStatusEffect.statusEffectList[ i ] == hackLocomotionT2 ) ) || ( linkedStatusEffect.statusEffectList[ i ] == hackLocomotionT3 ) )
				{
					StatusEffectHelper.RemoveStatusEffect( owner, linkedStatusEffect.statusEffectList[ i ] );
					switch( linkedStatusEffect.netrunnerIDs.Size() )
					{
						case 1:
							linkedStatusEffect.statusEffectList[ i ] = hackLocomotionT1;
						StatusEffectHelper.ApplyStatusEffect( owner, hackLocomotionT1, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						case 2:
							linkedStatusEffect.statusEffectList[ i ] = hackLocomotionT2;
						StatusEffectHelper.ApplyStatusEffect( owner, hackLocomotionT2, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						case 3:
							linkedStatusEffect.statusEffectList[ i ] = hackLocomotionT3;
						StatusEffectHelper.ApplyStatusEffect( owner, hackLocomotionT3, linkedStatusEffect.netrunnerIDs[ 0 ] );
						break;
						default:
							break;
					}
				}
			}
			else
			{
				StatusEffectHelper.RemoveStatusEffect( owner, linkedStatusEffect.statusEffectList[ i ] );
			}
		}
	}

	private static function GetCallingAlliesToCombatDelay( postCombatStart : Bool ) : Float
	{
		var delay : Float;
		delay = TweakDBInterface.GetFloat( T"AIGeneralSettings.callingAlliesToCombatDelay", 2.5 );
		if( postCombatStart )
		{
			delay -= TweakDBInterface.GetFloat( T"AIGeneralSettings.avoidCombatBuffer", 1.5 );
		}
		return delay;
	}

	public static function QueuePullSquadSync( owner : weak< GameObject >, optional postCombatStart : Bool ) : DelayID
	{
		var pullSquadSyncRequest : PullSquadSyncRequest;
		pullSquadSyncRequest = new PullSquadSyncRequest;
		pullSquadSyncRequest.squadType = AISquadType.Combat;
		return GameInstance.GetDelaySystem( owner.GetGame() ).DelayEvent( owner, pullSquadSyncRequest, GetCallingAlliesToCombatDelay( postCombatStart ) );
	}

	public static function QueueSecuritySystemCombatNotification( owner : weak< GameObject >, optional postCombatStart : Bool )
	{
		var notificationEvent : NotifySecuritySystemCombatEvent;
		notificationEvent = new NotifySecuritySystemCombatEvent;
		GameInstance.GetDelaySystem( owner.GetGame() ).DelayEvent( owner, notificationEvent, GetCallingAlliesToCombatDelay( postCombatStart ) );
	}

	public static function QueueNearbyCombatNotification( owner : weak< GameObject > ) : DelayID
	{
		var notificationEvent : NotifyNearbyAboutCombatEvent;
		notificationEvent = new NotifyNearbyAboutCombatEvent;
		return GameInstance.GetDelaySystem( owner.GetGame() ).DelayEvent( owner, notificationEvent, TweakDBInterface.GetFloat( T"AIGeneralSettings.avoidCombatBuffer", 1.5 ) );
	}

	public static function PreloadBaseAnimations( puppet : weak< ScriptedPuppet >, optional melee : Bool ) : Bool
	{
		var result1, result2 : Bool;
		if( melee )
		{
			result1 = PreloadAnimations( puppet, 'melee', true );
		}
		else
		{
			result1 = PreloadAnimations( puppet, 'ranged_base', true );
		}
		result2 = PreloadAnimations( puppet, 'hit_reaction_base', true );
		return result1 && result2;
	}

	public static function PreloadCoreAnimations( puppet : weak< ScriptedPuppet >, optional melee : Bool ) : Bool
	{
		var result1, result2 : Bool;
		if( melee )
		{
			result1 = PreloadAnimations( puppet, 'melee', true );
		}
		else
		{
			result1 = PreloadAnimations( puppet, 'ranged_core', true );
		}
		result2 = PreloadAnimations( puppet, 'hit_reaction_core', true );
		return result1 && result2;
	}

	public static function PreloadAllBaseAnimations( puppet : weak< ScriptedPuppet > )
	{
		PreloadAnimations( puppet, 'melee', true );
		PreloadAnimations( puppet, 'ranged_core', true );
		PreloadAnimations( puppet, 'ranged_base', true );
		PreloadAnimations( puppet, 'hit_reaction_core', true );
		PreloadAnimations( puppet, 'hit_reaction_base', true );
	}

	public static function PreloadAnimations( puppet : weak< ScriptedPuppet >, streamingContextName : CName, highPriority : Bool ) : Bool
	{
		var animComponent : AnimationControllerComponent;
		if( !( puppet ) )
		{
			return false;
		}
		animComponent = puppet.GetAnimationControllerComponent();
		if( !( animComponent ) )
		{
			return false;
		}
		if( !( animComponent.PreloadAnimations( streamingContextName, highPriority ) ) )
		{
			return false;
		}
		return true;
	}

	public static function QueuePreloadCoreAnimationsEvent( puppet : weak< ScriptedPuppet > )
	{
		var evt : PreloadAnimationsEvent;
		if( !( puppet ) )
		{
			return;
		}
		evt = new PreloadAnimationsEvent;
		evt.m_streamingContextName = 'ranged_core';
		evt.m_highPriority = true;
		puppet.QueueEvent( evt );
	}

	public static function QueuePreloadBaseAnimationsEvent( puppet : weak< ScriptedPuppet > )
	{
		var evt : PreloadAnimationsEvent;
		if( !( puppet ) )
		{
			return;
		}
		evt = new PreloadAnimationsEvent;
		evt.m_streamingContextName = 'ranged_base';
		evt.m_highPriority = true;
		puppet.QueueEvent( evt );
	}

	public static function CheckAbility( const object : weak< GameObject >, ability : weak< GameplayAbility_Record > ) : Bool
	{
		var i : Int32;
		var count : Int32;
		var record : IPrereq_Record;
		count = ability.GetPrereqsForUseCount();
		for( i = 0; i < count; i += 1 )
		{
			record = ability.GetPrereqsForUseItem( i );
			if( !( IPrereq.CreatePrereq( record.GetID() ).IsFulfilled( object.GetGame(), object ) ) )
			{
				return false;
			}
		}
		return true;
	}

	public static function SetItemsEquipData( puppet : weak< ScriptedPuppet >, itemsToEquip : array< NPCItemToEquip > )
	{
		var BBoard : IBlackboard;
		var itemData : gameItemData;
		var actionDuration : Float;
		var animDuration : Float;
		if( !( puppet ) )
		{
			return;
		}
		BBoard = puppet.GetAIControllerComponent().GetActionBlackboard();
		if( !( BBoard ) )
		{
			return;
		}
		BBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerItemsToEquip, itemsToEquip );
		itemData = GameInstance.GetTransactionSystem( puppet.GetGame() ).GetItemData( puppet, itemsToEquip[ 0 ].itemID );
		if( puppet.IsCharacterGanger() )
		{
			BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipItemTime, itemData.GetStatValueByType( gamedataStatType.EquipItemTime_Gang ) );
			actionDuration = itemData.GetStatValueByType( gamedataStatType.EquipActionDuration_Gang );
			animDuration = itemData.GetStatValueByType( gamedataStatType.EquipAnimationDuration_Gang );
			if( animDuration == 0.0 )
			{
				BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipDuration, actionDuration );
			}
			else
			{
				BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipDuration, animDuration );
			}
		}
		else
		{
			BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipItemTime, itemData.GetStatValueByType( gamedataStatType.EquipItemTime_Corpo ) );
			actionDuration = itemData.GetStatValueByType( gamedataStatType.EquipActionDuration_Corpo );
			animDuration = itemData.GetStatValueByType( gamedataStatType.EquipAnimationDuration_Corpo );
			if( animDuration == 0.0 )
			{
				BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipDuration, actionDuration );
			}
			else
			{
				BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipDuration, animDuration );
			}
		}
	}

	public static function SetItemsUnequipData( puppet : weak< ScriptedPuppet >, itemsToUnequip : array< NPCItemToEquip >, dropItem : Bool )
	{
		var BBoard : IBlackboard;
		var itemData : gameItemData;
		var actionDuration : Float;
		var animDuration : Float;
		if( !( puppet ) )
		{
			return;
		}
		BBoard = puppet.GetAIControllerComponent().GetActionBlackboard();
		if( !( BBoard ) )
		{
			return;
		}
		BBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerItemsToEquip, itemsToUnequip );
		itemData = GameInstance.GetTransactionSystem( puppet.GetGame() ).GetItemData( puppet, itemsToUnequip[ 0 ].itemID );
		if( puppet.IsCharacterGanger() )
		{
			BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipItemTime, itemData.GetStatValueByType( gamedataStatType.UnequipItemTime_Gang ) );
			actionDuration = itemData.GetStatValueByType( gamedataStatType.UnequipDuration_Gang );
			animDuration = itemData.GetStatValueByType( gamedataStatType.UnequipAnimationDuration_Gang );
			if( animDuration == 0.0 )
			{
				BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipDuration, actionDuration );
			}
			else
			{
				BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipDuration, animDuration );
			}
		}
		else
		{
			BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipItemTime, itemData.GetStatValueByType( gamedataStatType.UnequipItemTime_Corpo ) );
			actionDuration = itemData.GetStatValueByType( gamedataStatType.UnequipDuration_Corpo );
			animDuration = itemData.GetStatValueByType( gamedataStatType.UnequipAnimationDuration_Corpo );
			if( animDuration == 0.0 )
			{
				BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipDuration, actionDuration );
			}
			else
			{
				BBoard.SetFloat( GetAllBlackboardDefs().AIAction.ownerEquipDuration, animDuration );
			}
		}
		BBoard.SetBool( GetAllBlackboardDefs().AIAction.dropItemOnUnequip, dropItem );
	}

	public static function ClearItemsToEquip( puppet : weak< ScriptedPuppet > )
	{
		var BBoard : IBlackboard;
		var itemsToEquip : array< NPCItemToEquip >;
		if( !( puppet ) )
		{
			return;
		}
		BBoard = puppet.GetAIControllerComponent().GetActionBlackboard();
		if( !( BBoard ) )
		{
			return;
		}
		BBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerItemsToEquip, itemsToEquip );
	}

	public static function ClearItemsToUnequip( puppet : weak< ScriptedPuppet > )
	{
		var BBoard : IBlackboard;
		var itemsToUnequip : array< NPCItemToEquip >;
		if( !( puppet ) )
		{
			return;
		}
		BBoard = puppet.GetAIControllerComponent().GetActionBlackboard();
		if( !( BBoard ) )
		{
			return;
		}
		BBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerItemsToEquip, itemsToUnequip );
	}

	public static function ClearItemsUnequipped( puppet : weak< ScriptedPuppet > )
	{
		var BBoard : IBlackboard;
		var itemsToUnequipped : array< NPCItemToEquip >;
		if( !( puppet ) )
		{
			return;
		}
		BBoard = puppet.GetAIControllerComponent().GetActionBlackboard();
		if( !( BBoard ) )
		{
			return;
		}
		BBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerItemsUnequipped, itemsToUnequipped );
	}

	public static function ClearItemsForceUnequipped( puppet : weak< ScriptedPuppet > )
	{
		var BBoard : IBlackboard;
		var itemsToUnequipped : array< NPCItemToEquip >;
		if( !( puppet ) )
		{
			return;
		}
		BBoard = puppet.GetAIControllerComponent().GetActionBlackboard();
		if( !( BBoard ) )
		{
			return;
		}
		BBoard.SetVariant( GetAllBlackboardDefs().AIAction.ownerItemsForceUnequipped, itemsToUnequipped );
	}

	public static function IsMoveCommand( commandName : CName ) : Bool
	{
		switch( commandName )
		{
			case 'AIMoveCommand':
				return true;
			case 'AIMoveToCommand':
				return true;
			case 'AICommsCallMoveToCommand':
				return true;
			case 'AIMoveOnSplineCommand':
				return true;
			case 'AIAnimMoveOnSplineCommand':
				return true;
			case 'AIRotateToCommand':
				return true;
			case 'AIJoinCrowdCommand':
				return true;
			case 'AIFollowTargetCommand':
				return true;
			case 'AIRootMotionCommand':
				return true;
			case 'AIHoldPositionCommand':
				return true;
			case 'AIMoveToCoverCommand':
				return true;
			default:
				return false;
		}
	}

}

class AIActionChecks
{

	public static function CheckOwnerState( puppet : ScriptedPuppet, const npcStates : ref< AIActionNPCStates >, checkAll : Bool ) : Bool
	{
		if( !( puppet ) )
		{
			return true;
		}
		if( checkAll )
		{
			return CheckAllNPCStateTypes( puppet, npcStates );
		}
		return CheckNPCState( puppet, npcStates );
	}

	public static function CheckTargetState( target : ScriptedPuppet, const targetStates : ref< AIActionTargetStates >, checkAll : Bool ) : Bool
	{
		if( !( target ) )
		{
			return true;
		}
		if( target.IsPlayer() )
		{
			if( checkAll )
			{
				return CheckAllPlayerStateTypes( target, targetStates.playerStates );
			}
			return CheckPlayerState( target, targetStates.playerStates );
		}
		else if( target.IsNPC() )
		{
			if( checkAll )
			{
				return CheckAllNPCStateTypes( target, targetStates.npcStates );
			}
			return CheckNPCState( target, targetStates.npcStates );
		}
		return true;
	}

	public static function CheckAllNPCStateTypes( puppet : ScriptedPuppet, const npcStates : ref< AIActionNPCStates > ) : Bool
	{
		if( ( ( ( ( ( npcStates.highLevelStates.Size() == 0 ) && ( npcStates.upperBodyStates.Size() == 0 ) ) && ( npcStates.stanceStates.Size() == 0 ) ) && ( npcStates.behaviorStates.Size() == 0 ) ) && ( npcStates.defenseMode.Size() == 0 ) ) && ( npcStates.locomotionMode.Size() == 0 ) )
		{
			return true;
		}
		if( ( npcStates.highLevelStates.Size() > 0 ) && !( CheckHighLevelState( puppet, npcStates.highLevelStates ) ) )
		{
			return false;
		}
		if( ( npcStates.upperBodyStates.Size() > 0 ) && !( CheckUpperBodyState( puppet, npcStates.upperBodyStates ) ) )
		{
			return false;
		}
		if( ( npcStates.stanceStates.Size() > 0 ) && !( CheckStanceState( puppet, npcStates.stanceStates ) ) )
		{
			return false;
		}
		if( ( npcStates.behaviorStates.Size() > 0 ) && !( CheckBehaviorState( puppet, npcStates.behaviorStates ) ) )
		{
			return false;
		}
		if( ( npcStates.locomotionMode.Size() > 0 ) && !( CheckLocomotionMode( puppet, npcStates.locomotionMode ) ) )
		{
			return false;
		}
		if( ( npcStates.defenseMode.Size() > 0 ) && !( CheckDefenseMode( puppet, npcStates.defenseMode ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckNPCState( puppet : ScriptedPuppet, const npcStates : ref< AIActionNPCStates > ) : Bool
	{
		if( ( ( ( ( ( npcStates.highLevelStates.Size() == 0 ) && ( npcStates.upperBodyStates.Size() == 0 ) ) && ( npcStates.stanceStates.Size() == 0 ) ) && ( npcStates.behaviorStates.Size() == 0 ) ) && ( npcStates.defenseMode.Size() == 0 ) ) && ( npcStates.locomotionMode.Size() == 0 ) )
		{
			return true;
		}
		if( ( npcStates.highLevelStates.Size() > 0 ) && CheckHighLevelState( puppet, npcStates.highLevelStates ) )
		{
			return true;
		}
		if( ( npcStates.upperBodyStates.Size() > 0 ) && CheckUpperBodyState( puppet, npcStates.upperBodyStates ) )
		{
			return true;
		}
		if( ( npcStates.stanceStates.Size() > 0 ) && CheckStanceState( puppet, npcStates.stanceStates ) )
		{
			return true;
		}
		if( ( npcStates.behaviorStates.Size() > 0 ) && CheckBehaviorState( puppet, npcStates.behaviorStates ) )
		{
			return true;
		}
		if( ( npcStates.locomotionMode.Size() > 0 ) && CheckLocomotionMode( puppet, npcStates.locomotionMode ) )
		{
			return true;
		}
		if( ( npcStates.defenseMode.Size() > 0 ) && CheckDefenseMode( puppet, npcStates.defenseMode ) )
		{
			return true;
		}
		return false;
	}

	public static function CheckAllPlayerStateTypes( playerPuppet : ScriptedPuppet, const playerStates : ref< AIActionPlayerStates > ) : Bool
	{
		if( ( ( ( ( ( playerStates.locomotionStates.Size() == 0 ) && ( playerStates.upperBodyStates.Size() == 0 ) ) && ( playerStates.meleeStates.Size() == 0 ) ) && ( playerStates.zoneStates.Size() == 0 ) ) && ( playerStates.bodyCarryStates.Size() == 0 ) ) && ( playerStates.combatStates.Size() == 0 ) )
		{
			return true;
		}
		if( ( playerStates.locomotionStates.Size() > 0 ) && !( CheckPSMLocomotionState( playerPuppet, playerStates.locomotionStates ) ) )
		{
			return false;
		}
		if( ( playerStates.upperBodyStates.Size() > 0 ) && !( CheckPSMUpperBodyState( playerPuppet, playerStates.upperBodyStates ) ) )
		{
			return false;
		}
		if( ( playerStates.meleeStates.Size() > 0 ) && !( CheckPSMMeleeState( playerPuppet, playerStates.meleeStates ) ) )
		{
			return false;
		}
		if( ( playerStates.zoneStates.Size() > 0 ) && !( CheckPSMZoneState( playerPuppet, playerStates.zoneStates ) ) )
		{
			return false;
		}
		if( ( playerStates.bodyCarryStates.Size() > 0 ) && !( CheckPSMBodyCarryState( playerPuppet, playerStates.bodyCarryStates ) ) )
		{
			return false;
		}
		if( ( playerStates.combatStates.Size() > 0 ) && !( CheckPSMCombatState( playerPuppet, playerStates.combatStates ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckPlayerState( playerPuppet : ScriptedPuppet, const playerStates : ref< AIActionPlayerStates > ) : Bool
	{
		if( ( ( ( ( ( playerStates.locomotionStates.Size() == 0 ) && ( playerStates.upperBodyStates.Size() == 0 ) ) && ( playerStates.meleeStates.Size() == 0 ) ) && ( playerStates.zoneStates.Size() == 0 ) ) && ( playerStates.bodyCarryStates.Size() == 0 ) ) && ( playerStates.combatStates.Size() == 0 ) )
		{
			return true;
		}
		if( ( playerStates.locomotionStates.Size() > 0 ) && CheckPSMLocomotionState( playerPuppet, playerStates.locomotionStates ) )
		{
			return true;
		}
		if( ( playerStates.upperBodyStates.Size() > 0 ) && CheckPSMUpperBodyState( playerPuppet, playerStates.upperBodyStates ) )
		{
			return true;
		}
		if( ( playerStates.meleeStates.Size() > 0 ) && CheckPSMMeleeState( playerPuppet, playerStates.meleeStates ) )
		{
			return true;
		}
		if( ( playerStates.zoneStates.Size() > 0 ) && CheckPSMZoneState( playerPuppet, playerStates.zoneStates ) )
		{
			return true;
		}
		if( ( playerStates.bodyCarryStates.Size() > 0 ) && CheckPSMBodyCarryState( playerPuppet, playerStates.bodyCarryStates ) )
		{
			return true;
		}
		if( ( playerStates.combatStates.Size() > 0 ) && CheckPSMCombatState( playerPuppet, playerStates.combatStates ) )
		{
			return true;
		}
		return false;
	}

	public static function CheckHighLevelState( puppet : ScriptedPuppet, const highLevelStates : ref< array< gamedataNPCHighLevelState > > ) : Bool
	{
		var currentHighLevelState : gamedataNPCHighLevelState;
		currentHighLevelState = ( ( gamedataNPCHighLevelState )( puppet.GetPuppetStateBlackboard().GetInt( GetAllBlackboardDefs().PuppetState.HighLevel ) ) );
		if( !( highLevelStates.Contains( currentHighLevelState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckUpperBodyState( puppet : ScriptedPuppet, const upperBodyStates : ref< array< gamedataNPCUpperBodyState > > ) : Bool
	{
		var currentUpperBodyState : gamedataNPCUpperBodyState;
		currentUpperBodyState = ( ( gamedataNPCUpperBodyState )( puppet.GetPuppetStateBlackboard().GetInt( GetAllBlackboardDefs().PuppetState.UpperBody ) ) );
		if( !( puppet ) || !( upperBodyStates.Contains( currentUpperBodyState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckStanceState( puppet : ScriptedPuppet, const stanceStates : ref< array< gamedataNPCStanceState > > ) : Bool
	{
		var currentStanceState : gamedataNPCStanceState;
		currentStanceState = ( ( gamedataNPCStanceState )( puppet.GetPuppetStateBlackboard().GetInt( GetAllBlackboardDefs().PuppetState.Stance ) ) );
		if( !( stanceStates.Contains( currentStanceState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckBehaviorState( puppet : ScriptedPuppet, const behaviorStates : ref< array< gamedataNPCBehaviorState > > ) : Bool
	{
		var currentBehaviorState : gamedataNPCBehaviorState;
		currentBehaviorState = ( ( gamedataNPCBehaviorState )( puppet.GetPuppetStateBlackboard().GetInt( GetAllBlackboardDefs().PuppetState.BehaviorState ) ) );
		if( !( behaviorStates.Contains( currentBehaviorState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckDefenseMode( puppet : ScriptedPuppet, const defenseMode : ref< array< gamedataDefenseMode > > ) : Bool
	{
		var currentDefenseMode : gamedataDefenseMode;
		currentDefenseMode = ( ( gamedataDefenseMode )( puppet.GetPuppetStateBlackboard().GetInt( GetAllBlackboardDefs().PuppetState.DefenseMode ) ) );
		if( !( defenseMode.Contains( currentDefenseMode ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckLocomotionMode( puppet : ScriptedPuppet, const locomotionMode : ref< array< gamedataLocomotionMode > > ) : Bool
	{
		var currentlocomotionMode : gamedataLocomotionMode;
		currentlocomotionMode = ( ( gamedataLocomotionMode )( puppet.GetPuppetStateBlackboard().GetInt( GetAllBlackboardDefs().PuppetState.LocomotionMode ) ) );
		if( !( locomotionMode.Contains( currentlocomotionMode ) ) )
		{
			return false;
		}
		return true;
	}

	public static function GetPSMBlackbordInt( playerPuppet : ScriptedPuppet, id : BlackboardID_Int ) : Int32
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		blackboardSystem = GameInstance.GetBlackboardSystem( playerPuppet.GetGame() );
		blackboard = blackboardSystem.GetLocalInstanced( playerPuppet.GetEntityID(), GetAllBlackboardDefs().PlayerStateMachine );
		return blackboard.GetInt( id );
	}

	public static function CheckPSMLocomotionState( playerPuppet : ScriptedPuppet, const locomotionStates : ref< array< gamePSMLocomotionStates > > ) : Bool
	{
		var currentState : gamePSMLocomotionStates;
		currentState = ( ( gamePSMLocomotionStates )( GetPSMBlackbordInt( playerPuppet, GetAllBlackboardDefs().PlayerStateMachine.Locomotion ) ) );
		if( !( locomotionStates.Contains( currentState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckPSMUpperBodyState( playerPuppet : ScriptedPuppet, const upperBodyStates : ref< array< gamePSMUpperBodyStates > > ) : Bool
	{
		var currentState : gamePSMUpperBodyStates;
		currentState = ( ( gamePSMUpperBodyStates )( GetPSMBlackbordInt( playerPuppet, GetAllBlackboardDefs().PlayerStateMachine.UpperBody ) ) );
		if( !( upperBodyStates.Contains( currentState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckPSMMeleeState( playerPuppet : ScriptedPuppet, const meleeStates : ref< array< gamePSMMelee > > ) : Bool
	{
		var currentState : gamePSMMelee;
		currentState = ( ( gamePSMMelee )( GetPSMBlackbordInt( playerPuppet, GetAllBlackboardDefs().PlayerStateMachine.Melee ) ) );
		if( !( meleeStates.Contains( currentState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckPSMZoneState( playerPuppet : ScriptedPuppet, const zoneStates : ref< array< gamePSMZones > > ) : Bool
	{
		var currentState : gamePSMZones;
		currentState = ( ( gamePSMZones )( GetPSMBlackbordInt( playerPuppet, GetAllBlackboardDefs().PlayerStateMachine.Zones ) ) );
		if( !( zoneStates.Contains( currentState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckPSMBodyCarryState( playerPuppet : ScriptedPuppet, const bodyCarryStates : ref< array< gamePSMBodyCarrying > > ) : Bool
	{
		var currentState : gamePSMBodyCarrying;
		currentState = ( ( gamePSMBodyCarrying )( GetPSMBlackbordInt( playerPuppet, GetAllBlackboardDefs().PlayerStateMachine.BodyCarrying ) ) );
		if( !( bodyCarryStates.Contains( currentState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckPSMCombatState( playerPuppet : ScriptedPuppet, const combatStates : ref< array< gamePSMCombat > > ) : Bool
	{
		var currentState : gamePSMCombat;
		currentState = ( ( gamePSMCombat )( GetPSMBlackbordInt( playerPuppet, GetAllBlackboardDefs().PlayerStateMachine.Combat ) ) );
		if( !( combatStates.Contains( currentState ) ) )
		{
			return false;
		}
		return true;
	}

	public static function CheckMountedVehicleDesiredTags( puppet : ScriptedPuppet, const desiredTags : ref< array< CName > > ) : Bool
	{
		var vehicleRecord : Vehicle_Record;
		var tags : array< CName >;
		var i : Int32;
		if( desiredTags.Size() <= 0 )
		{
			return true;
		}
		if( !( VehicleComponent.GetVehicleRecord( puppet.GetGame(), puppet.GetEntityID(), vehicleRecord ) ) )
		{
			return false;
		}
		tags = vehicleRecord.Tags();
		for( i = 0; i < desiredTags.Size(); i += 1 )
		{
			if( tags.Contains( desiredTags[ i ] ) )
			{
				return true;
			}
		}
		return false;
	}

}

