import class AIPatrolPathParameters extends IScriptable
{
	import var path : NodeRef;
	import var movementType : moveMovementType;
	import var startFromClosestPoint : Bool;
	import var patrolWithWeapon : Bool;
	[ customEditor = "TweakDBGroupInheritance;PatrolActions.AIPatrolActionComposite" ]
	editable var patrolAction : TweakDBID;
	default patrolAction = T"PatrolActions.DefaultPatrolAction";
	import var isBackAndForth : Bool;
	import var isInfinite : Bool;
	import var numberOfLoops : Uint32;
}

import enum AIPatrolContinuationPolicy
{
	FromNextControlPoint,
	FromClosestPoint,
	FromBeginning,
}

implicit cast ( value : Int64 ) : AIPatrolContinuationPolicy
{
	return ( ( AIPatrolContinuationPolicy )( ( ( Int32 )( value ) ) ) );
}

import class PatrolSplineProgress extends IScriptable
{
	public import function IsControlPointIndexValid() : Bool;
}

class PatrolControllerTask extends AIbehaviortaskScript
{

	protected export override function Activate( context : ScriptExecutionContext )
	{
		SetUpdateInterval( context, RandomizeOffsetForUpdateInterval( 0.2 ) );
	}

	protected export override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome
	{
		var bbDef : AIPatrolDef;
		var bb : IBlackboard;
		var pathOverride : AIPatrolPathParameters;
		var selectedPath : AIPatrolPathParameters;
		var pathVariant : Variant;
		var pathOverrideVariant : Variant;
		bbDef = GetAllBlackboardDefs().AIPatrol;
		bb = GetPuppet( context ).GetAIControllerComponent().GetAIPatrolBlackboard();
		pathVariant = bb.GetVariant( bbDef.selectedPath );
		pathOverrideVariant = bb.GetVariant( bbDef.patrolPathOverride );
		if( pathVariant.IsValid() )
		{
			selectedPath = ( ( AIPatrolPathParameters )pathVariant );
		}
		if( pathOverrideVariant.IsValid() )
		{
			pathOverride = ( ( AIPatrolPathParameters )pathOverrideVariant );
		}
		if( pathOverride && ( selectedPath != pathOverride ) )
		{
			selectedPath = pathOverride;
			bb.SetVariant( bbDef.selectedPath, selectedPath );
		}
		return AIbehaviorUpdateOutcome.IN_PROGRESS;
	}

}

class PatrolCommandHandler extends AIbehaviortaskScript
{
	editable inlined var m_inCommand : AIArgumentMapping;

	protected override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome
	{
		var rawCommand : IScriptable;
		var typedCommand : AIPatrolCommand;
		var bbDef : AIPatrolDef;
		var bb : IBlackboard;
		var pathParams : AIPatrolPathParameters;
		if( !( m_inCommand ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		rawCommand = ScriptExecutionContext.GetScriptableMappingValue( context, m_inCommand );
		typedCommand = ( ( AIPatrolCommand )( rawCommand ) );
		if( !( typedCommand ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		if( !( typedCommand.pathParams ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		pathParams = typedCommand.pathParams;
		if( !( ScriptExecutionContext.GetArgumentBool( context, 'PatrolInitialized' ) ) && GetPuppet( context ).GetNPCType() == gamedataNPCType.Drone )
		{
			DroneComponent.SetLocomotionWrappers( GetPuppet( context ), EnumValueToName( 'moveMovementType', ( ( Int64 )( pathParams.movementType ) ) ) );
			pathParams.movementType = moveMovementType.Walk;
		}
		bbDef = GetAllBlackboardDefs().AIPatrol;
		bb = GetPuppet( context ).GetAIControllerComponent().GetAIPatrolBlackboard();
		bb.SetVariant( bbDef.patrolPathOverride, pathParams );
		bb.SetBool( bbDef.patrolWithWeapon, pathParams.patrolWithWeapon );
		bb.SetVariant( bbDef.patrolAction, pathParams.patrolAction );
		bb.SetBool( bbDef.sprint, pathParams.movementType == moveMovementType.Sprint );
		ScriptExecutionContext.SetArgumentBool( context, 'PatrolInitialized', true );
		return AIbehaviorUpdateOutcome.SUCCESS;
	}

}

class PatrolRoleHandler extends AIbehaviortaskScript
{

	protected export override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome
	{
		var bbDef : AIPatrolDef;
		var bb : IBlackboard;
		var pathParams : AIPatrolPathParameters;
		var aiComponent : AIHumanComponent;
		var patrolRole : AIPatrolRole;
		aiComponent = GetAIComponent( context );
		if( !( aiComponent ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		patrolRole = ( ( AIPatrolRole )( aiComponent.GetCurrentRole() ) );
		if( !( patrolRole ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		if( !( patrolRole.GetPathParams() ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		pathParams = patrolRole.GetPathParams();
		if( !( ScriptExecutionContext.GetArgumentBool( context, 'PatrolInitialized' ) ) && GetPuppet( context ).GetNPCType() == gamedataNPCType.Drone )
		{
			DroneComponent.SetLocomotionWrappers( GetPuppet( context ), EnumValueToName( 'moveMovementType', ( ( Int64 )( pathParams.movementType ) ) ) );
			pathParams.movementType = moveMovementType.Walk;
		}
		bbDef = GetAllBlackboardDefs().AIPatrol;
		bb = GetPuppet( context ).GetAIControllerComponent().GetAIPatrolBlackboard();
		bb.SetVariant( bbDef.patrolPathOverride, pathParams );
		bb.SetBool( bbDef.patrolWithWeapon, pathParams.patrolWithWeapon );
		bb.SetVariant( bbDef.patrolAction, pathParams.patrolAction );
		bb.SetBool( bbDef.sprint, pathParams.movementType == moveMovementType.Sprint );
		ScriptExecutionContext.SetArgumentBool( context, 'PatrolInitialized', true );
		return AIbehaviorUpdateOutcome.SUCCESS;
	}

}

class PatrolAlertedControllerTask extends AIbehaviortaskScript
{

	protected override function Activate( context : ScriptExecutionContext )
	{
		SetUpdateInterval( context, RandomizeOffsetForUpdateInterval( 0.2 ) );
	}

	protected override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome
	{
		var bbDef : AIAlertedPatrolDef;
		var bb : IBlackboard;
		var pathOverride : AIPatrolPathParameters;
		var selectedPath : AIPatrolPathParameters;
		var tmpVariant : Variant;
		bbDef = GetAllBlackboardDefs().AIAlertedPatrol;
		bb = GetPuppet( context ).GetAIControllerComponent().GetAIAlertedPatrolBlackboard();
		tmpVariant = bb.GetVariant( bbDef.selectedPath );
		if( tmpVariant.IsValid() )
		{
			selectedPath = ( ( AIPatrolPathParameters )tmpVariant );
		}
		tmpVariant = bb.GetVariant( bbDef.patrolPathOverride );
		if( tmpVariant.IsValid() )
		{
			pathOverride = ( ( AIPatrolPathParameters )tmpVariant );
		}
		if( pathOverride && ( selectedPath != pathOverride ) )
		{
			selectedPath = pathOverride;
			bb.SetVariant( bbDef.selectedPath, selectedPath );
		}
		return AIbehaviorUpdateOutcome.IN_PROGRESS;
	}

}

class PatrolAlertedCommandHandler extends AIbehaviortaskScript
{
	editable inlined var m_inCommand : AIArgumentMapping;

	protected override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome
	{
		var rawCommand : IScriptable;
		var typedCommand : AIPatrolCommand;
		var bbDef : AIAlertedPatrolDef;
		var bb : IBlackboard;
		var pathParams : AIPatrolPathParameters;
		if( !( m_inCommand ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		rawCommand = ScriptExecutionContext.GetScriptableMappingValue( context, m_inCommand );
		typedCommand = ( ( AIPatrolCommand )( rawCommand ) );
		if( !( typedCommand ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		if( !( typedCommand.alertedPathParams ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		ScriptExecutionContext.SetArgumentFloat( context, 'InfluenceRadius', typedCommand.alertedRadius );
		pathParams = typedCommand.alertedPathParams;
		if( !( ScriptExecutionContext.GetArgumentBool( context, 'PatrolInitialized' ) ) && GetPuppet( context ).GetNPCType() == gamedataNPCType.Drone )
		{
			DroneComponent.SetLocomotionWrappers( GetPuppet( context ), EnumValueToName( 'moveMovementType', ( ( Int64 )( pathParams.movementType ) ) ) );
			pathParams.movementType = moveMovementType.Walk;
		}
		bbDef = GetAllBlackboardDefs().AIAlertedPatrol;
		bb = GetPuppet( context ).GetAIControllerComponent().GetAIAlertedPatrolBlackboard();
		bb.SetVariant( bbDef.patrolPathOverride, pathParams );
		bb.SetVariant( bbDef.patrolAction, pathParams.patrolAction );
		bb.SetBool( bbDef.sprint, pathParams.movementType == moveMovementType.Sprint );
		ScriptExecutionContext.SetArgumentBool( context, 'PatrolInitialized', true );
		return AIbehaviorUpdateOutcome.SUCCESS;
	}

}

class AlertedRoleHandler extends AIbehaviortaskScript
{
	private var m_pathParamsModified : Bool;

	protected export override function Activate( context : ScriptExecutionContext )
	{
		SetUpdateInterval( context, RandomizeOffsetForUpdateInterval( 0.5 ) );
	}

	protected export override function Update( context : ScriptExecutionContext ) : AIbehaviorUpdateOutcome
	{
		var bbDef : AIAlertedPatrolDef;
		var bb : IBlackboard;
		var pathParams : AIPatrolPathParameters;
		var aiComponent : AIHumanComponent;
		var patrolRole : AIPatrolRole;
		aiComponent = GetAIComponent( context );
		if( !( aiComponent ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		patrolRole = ( ( AIPatrolRole )( aiComponent.GetCurrentRole() ) );
		if( !( patrolRole ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		ScriptExecutionContext.SetArgumentScriptable( context, 'AlertedSpots', patrolRole.GetAlertedSpots() );
		if( !( patrolRole.GetAlertedPathParams() ) && !( patrolRole.GetPathParams() ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		ScriptExecutionContext.SetArgumentFloat( context, 'InfluenceRadius', patrolRole.GetAlertedRadius() );
		pathParams = patrolRole.GetAlertedPathParams();
		if( !( pathParams ) )
		{
			ScriptExecutionContext.SetArgumentBool( context, 'IgnoreWorkspots', true );
			pathParams = patrolRole.GetPathParams();
			if( !( ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).IsBoss() ) )
			{
				if( pathParams.isInfinite )
				{
					pathParams.isInfinite = false;
					pathParams.numberOfLoops = 1;
					m_pathParamsModified = true;
				}
			}
		}
		if( !( ScriptExecutionContext.GetArgumentBool( context, 'PatrolInitialized' ) ) && GetPuppet( context ).GetNPCType() == gamedataNPCType.Drone )
		{
			DroneComponent.SetLocomotionWrappers( GetPuppet( context ), EnumValueToName( 'moveMovementType', ( ( Int64 )( pathParams.movementType ) ) ) );
			pathParams.movementType = moveMovementType.Walk;
		}
		pathParams.startFromClosestPoint = true;
		bbDef = GetAllBlackboardDefs().AIAlertedPatrol;
		bb = GetPuppet( context ).GetAIControllerComponent().GetAIAlertedPatrolBlackboard();
		if( !( bb ) )
		{
			return AIbehaviorUpdateOutcome.FAILURE;
		}
		bb.SetVariant( bbDef.patrolPathOverride, pathParams );
		bb.SetBool( bbDef.forceAlerted, patrolRole.IsForceAlerted() );
		if( pathParams )
		{
			bb.SetVariant( bbDef.patrolAction, pathParams.patrolAction );
			bb.SetBool( bbDef.sprint, pathParams.movementType == moveMovementType.Sprint );
		}
		ScriptExecutionContext.SetArgumentBool( context, 'PatrolInitialized', true );
		return AIbehaviorUpdateOutcome.IN_PROGRESS;
	}

	protected export override function Deactivate( context : ScriptExecutionContext )
	{
		var aiComponent : AIHumanComponent;
		var patrolRole : AIPatrolRole;
		var pathParams : AIPatrolPathParameters;
		if( m_pathParamsModified )
		{
			aiComponent = GetAIComponent( context );
			if( !( aiComponent ) )
			{
				return;
			}
			patrolRole = ( ( AIPatrolRole )( aiComponent.GetCurrentRole() ) );
			if( !( patrolRole ) )
			{
				return;
			}
			pathParams = patrolRole.GetPathParams();
			if( !( pathParams ) )
			{
				return;
			}
			pathParams.isInfinite = true;
			m_pathParamsModified = false;
		}
	}

}

class CheckCurrentWorkspotTag extends AIbehaviorconditionScript
{
	editable inlined var m_tag : AIArgumentMapping;

	protected export override function Activate( context : ScriptExecutionContext )
	{
		SetUpdateInterval( context, RandomizeOffsetForUpdateInterval( 0.5 ) );
	}

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		return ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).HasWorkspotTag( ( ( CName )( ScriptExecutionContext.GetMappingValue( context, m_tag ) ) ) );
	}

}

class GetCurrentPatrolSpotActionPath extends AIbehaviortaskScript
{
	editable inlined var m_outPathArgument : AIArgumentMapping;

	protected override function Activate( context : ScriptExecutionContext )
	{
		var currentWorkspotTags : array< CName >;
		var currentPatrolActionPath : CName;
		currentWorkspotTags = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).GetCurrentWorkspotTags();
		if( currentWorkspotTags.Size() < 2 )
		{
			return;
		}
		currentPatrolActionPath = currentWorkspotTags[ 1 ];
		ScriptExecutionContext.SetMappingValue( context, m_outPathArgument, currentPatrolActionPath );
	}

}

class HasPatrolAction extends AIbehaviorconditionScript
{

	protected export override function Activate( context : ScriptExecutionContext )
	{
		SetUpdateInterval( context, RandomizeOffsetForUpdateInterval( 0.2 ) );
	}

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var patrolAction : TweakDBID;
		patrolAction = ( ( TweakDBID )( GetPuppet( context ).GetAIControllerComponent().GetAIPatrolBlackboard().GetVariant( GetAllBlackboardDefs().AIPatrol.patrolAction ) ) );
		if( TDBID.IsValid( patrolAction ) )
		{
			return true;
		}
		return false;
	}

}

class SendPatrolEndSignal extends AIbehaviortaskScript
{

	protected override function Activate( context : ScriptExecutionContext )
	{
		var puppet : weak< ScriptedPuppet >;
		puppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( !( puppet ) )
		{
			return;
		}
		ScriptedPuppet.SendActionSignal( puppet, 'PatrolEnded', 0.1 );
	}

}

class ShouldContinuePatrolFromNextControlPoint extends AIbehaviorconditionScript
{
	editable inlined var m_patrolContinuationPolicy : AIArgumentMapping;

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var continuationPolicy : AIPatrolContinuationPolicy;
		continuationPolicy = ( ( Int64 )( ScriptExecutionContext.GetMappingValue( context, m_patrolContinuationPolicy ) ) );
		return continuationPolicy == AIPatrolContinuationPolicy.FromNextControlPoint;
	}

}

class ShouldContinuePatrolFromClosestPoint extends AIbehaviorconditionScript
{
	editable inlined var m_patrolContinuationPolicy : AIArgumentMapping;

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var continuationPolicy : AIPatrolContinuationPolicy;
		continuationPolicy = ( ( Int64 )( ScriptExecutionContext.GetMappingValue( context, m_patrolContinuationPolicy ) ) );
		return continuationPolicy == AIPatrolContinuationPolicy.FromClosestPoint;
	}

}

class ShouldContinuePatrolFromBeginning extends AIbehaviorconditionScript
{
	editable inlined var m_patrolContinuationPolicy : AIArgumentMapping;

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var continuationPolicy : AIPatrolContinuationPolicy;
		continuationPolicy = ( ( Int64 )( ScriptExecutionContext.GetMappingValue( context, m_patrolContinuationPolicy ) ) );
		return continuationPolicy == AIPatrolContinuationPolicy.FromBeginning;
	}

}

class IsPatrolProgressValid extends AIbehaviorconditionScript
{
	editable inlined var m_patrolProgress : AIArgumentMapping;

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var patrolProgress : PatrolSplineProgress;
		patrolProgress = ( ( PatrolSplineProgress )( ScriptExecutionContext.GetScriptableMappingValue( context, m_patrolProgress ) ) );
		return patrolProgress && patrolProgress.IsControlPointIndexValid();
	}

}

