class CheckReaction extends AIbehaviorconditionScript
{
	editable var m_reactionToCompare : gamedataOutput;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		return GetPuppet( context ).GetStimReactionComponent().GetDesiredReactionName() == m_reactionToCompare;
	}

}

class CheckReactionValueThreshold extends AIbehaviorconditionScript
{
	editable var m_reactionValue : EReactionValue;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var currentStat : Float;
		var threshold : Float;
		switch( m_reactionValue )
		{
			case EReactionValue.Fear:
				currentStat = GetStatPoolValue( context, gamedataStatPoolType.Fear );
			threshold = TweakDBInterface.GetCharacterRecord( GetPuppet( context ).GetRecordID() ).ReactionPreset().FearThreshold();
			break;
			default:
				return false;
		}
		if( threshold == 0.0 )
		{
			return false;
		}
		if( currentStat >= ( threshold - 0.01 ) )
		{
			return true;
		}
		return false;
	}

}

class InvestigateController extends AIbehaviorconditionScript
{
	protected var m_investigateData : stimInvestigateData;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		m_investigateData = GetPuppet( context ).GetStimReactionComponent().GetActiveReactionData().stimInvestigateData;
		return m_investigateData.investigateController;
	}

}

class CheckReactionStimType extends AIbehaviorconditionScript
{
	editable var m_stimToCompare : gamedataStimType;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		return GetPuppet( context ).GetStimReactionComponent().GetActiveReactionData().stimType == m_stimToCompare;
	}

}

class CheckStimTag extends AIbehaviorconditionScript
{
	const editable var m_stimTagToCompare : array< CName >;

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var activeReactionData : AIReactionData;
		var tags : array< CName >;
		var i : Int32;
		activeReactionData = GetPuppet( context ).GetStimReactionComponent().GetActiveReactionData();
		if( !( activeReactionData ) )
		{
			activeReactionData = GetPuppet( context ).GetStimReactionComponent().GetDesiredReactionData();
		}
		tags = activeReactionData.stimRecord.Tags();
		for( i = 0; i < m_stimTagToCompare.Size(); i += 1 )
		{
			if( tags.Contains( m_stimTagToCompare[ i ] ) )
			{
				return true;
			}
		}
		return false;
	}

}

class PlayInitFearAnimation extends AIbehaviorconditionScript
{
	var m_grenadePanic : Bool;
	var m_initialized : Bool;

	protected export override function Activate( context : ScriptExecutionContext )
	{
		var ownerPuppet : weak< ScriptedPuppet >;
		if( m_initialized )
		{
			return;
		}
		m_initialized = true;
		ownerPuppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( ownerPuppet.IsBoss() )
		{
			return;
		}
		if( ownerPuppet.IsElite() )
		{
			return;
		}
		if( AIActionHelper.CheckAbility( ownerPuppet, TweakDBInterface.GetGameplayAbilityRecord( T"Ability.HasSandevistan" ) ) )
		{
			return;
		}
		if( AIActionHelper.CheckAbility( ownerPuppet, TweakDBInterface.GetGameplayAbilityRecord( T"Ability.HasKerenzikov" ) ) )
		{
			return;
		}
		if( AIActionHelper.CheckAbility( ownerPuppet, TweakDBInterface.GetGameplayAbilityRecord( T"Ability.IsTier3Archetype" ) ) )
		{
			return;
		}
		if( AIActionHelper.CheckAbility( ownerPuppet, TweakDBInterface.GetGameplayAbilityRecord( T"Ability.IsAggressive" ) ) )
		{
			return;
		}
		if( AIActionHelper.CheckAbility( ownerPuppet, TweakDBInterface.GetGameplayAbilityRecord( T"Ability.IsReckless" ) ) )
		{
			return;
		}
		if( AIActionHelper.CheckAbility( ownerPuppet, TweakDBInterface.GetGameplayAbilityRecord( T"Ability.IsManMassive" ) ) )
		{
			return;
		}
		m_grenadePanic = true;
	}

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var activeReactionData : AIReactionData;
		var ownerPuppet : weak< ScriptedPuppet >;
		ownerPuppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		activeReactionData = ownerPuppet.GetStimReactionComponent().GetActiveReactionData();
		if( !( activeReactionData ) )
		{
			activeReactionData = ownerPuppet.GetStimReactionComponent().GetDesiredReactionData();
		}
		if( activeReactionData.initAnimInWorkspot && activeReactionData.stimType != gamedataStimType.Scream )
		{
			return false;
		}
		if( activeReactionData.skipInitialAnimation )
		{
			return false;
		}
		if( activeReactionData.stimType == gamedataStimType.GrenadeLanded && !( m_grenadePanic ) )
		{
			return false;
		}
		if( activeReactionData.reactionBehaviorName == gamedataOutput.DodgeToSide )
		{
			return false;
		}
		if( activeReactionData.stimRecord.TagsContains( 'NoInitFearAnimation' ) )
		{
			return false;
		}
		return true;
	}

}

class PlayStartupLocoFearAnimation extends AIbehaviorconditionScript
{

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var activeReactionData : AIReactionData;
		var ownerPuppet : weak< ScriptedPuppet >;
		var reactionCmp : ReactionManagerComponent;
		ownerPuppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		reactionCmp = ownerPuppet.GetStimReactionComponent();
		activeReactionData = reactionCmp.GetActiveReactionData();
		if( !( activeReactionData ) )
		{
			activeReactionData = reactionCmp.GetDesiredReactionData();
		}
		if( activeReactionData.initAnimInWorkspot && ( reactionCmp.GetPreviousFearPhase() != 2 ) )
		{
			return false;
		}
		return true;
	}

}

class IsWorkspotReaction extends AIbehaviorconditionScript
{

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		return ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).GetStimReactionComponent().GetWorkSpotReactionFlag();
	}

}

class IsValidCombatTarget extends AIbehaviorconditionScript
{
	editable var m_considerSourceAVehicleDriver : Bool;

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var puppet : ScriptedPuppet;
		var stimReactionComp : ReactionManagerComponent;
		var activeReactionData : AIReactionData;
		var investigateData : stimInvestigateData;
		var instigator : ScriptedPuppet;
		var source : ScriptedPuppet;
		var vehicle : VehicleObject;
		var driverInstigator : weak< GameObject >;
		puppet = GetPuppet( context );
		stimReactionComp = puppet.GetStimReactionComponent();
		activeReactionData = stimReactionComp.GetActiveOrDesiredReactionData();
		stimReactionComp.LogStart( EReactLogSource.BehaviorCombatCheck, "IsValidCombatTarget check" );
		if( activeReactionData.stimRecord.TagsContains( 'NoAutoCombatStart' ) )
		{
			stimReactionComp.LogFailure( "this stim can not start combat" );
			return false;
		}
		investigateData = activeReactionData.stimInvestigateData;
		instigator = ( ( ScriptedPuppet )( investigateData.attackInstigator ) );
		source = ( ( ScriptedPuppet )( activeReactionData.stimEventData.source ) );
		vehicle = ( ( VehicleObject )( activeReactionData.stimEventData.source ) );
		if( ( !( source ) && vehicle ) && m_considerSourceAVehicleDriver )
		{
			driverInstigator = VehicleComponent.GetDriver( puppet.GetGame(), vehicle, vehicle.GetEntityID() );
			source = ( ( ScriptedPuppet )( driverInstigator ) );
		}
		if( puppet.IsPrevention() && !( IsValidForPrevention( instigator, source ) ) )
		{
			stimReactionComp.LogFailure( "non-player combat stim can't start prevention combat" );
			return false;
		}
		if( stimReactionComp.ShouldIgnoreCombatStim( activeReactionData.stimType, instigator, source, activeReactionData.stimSource, true ) )
		{
			stimReactionComp.LogFailure( "combat stim explicitely ignored" );
			return false;
		}
		stimReactionComp.LogSuccess( "combat can be started" );
		return true;
	}

	private function IsValidForPrevention( instigator : ScriptedPuppet, source : ScriptedPuppet ) : Bool
	{
		if( source )
		{
			return source.IsPlayer();
		}
		if( instigator )
		{
			return instigator.IsPlayer();
		}
		return false;
	}

}

class IsPlayerAKiller extends AIbehaviorconditionScript
{

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var killer : GameObject;
		var investigateData : stimInvestigateData;
		investigateData = GetPuppet( context ).GetStimReactionComponent().GetActiveReactionData().stimInvestigateData;
		killer = ( ( GameObject )( investigateData.attackInstigator ) );
		if( killer.IsPlayer() )
		{
			return true;
		}
		return false;
	}

}

class CheckStimRevealsInstigatorPosition extends AIbehaviorconditionScript
{
	editable var m_checkStimType : Bool;
	editable var m_stimType : gamedataStimType;

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var stimuliCache : array< StimEventTaskData >;
		var investigateData : stimInvestigateData;
		stimuliCache = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).GetStimReactionComponent().GetStimuliCache();
		if( stimuliCache.Size() != 0 )
		{
			investigateData = stimuliCache[ stimuliCache.Size() - 1 ].cachedEvt.stimInvestigateData;
			if( investigateData.revealsInstigatorPosition )
			{
				if( !( m_checkStimType ) || stimuliCache[ ( stimuliCache.Size() - 1 ) ].cachedEvt.GetStimType() == m_stimType )
				{
					return true;
				}
			}
		}
		return false;
	}

}

class CheckLastTriggeredStimuli extends AIbehaviorconditionScript
{

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var stimSourcePos : Vector4;
		var stimuliCache : array< StimEventTaskData >;
		var stimuliEvent : StimuliEvent;
		stimuliCache = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).GetStimReactionComponent().GetStimuliCache();
		if( stimuliCache.Size() != 0 )
		{
			stimuliEvent = stimuliCache[ stimuliCache.Size() - 1 ].cachedEvt;
			if( stimuliEvent.GetStimType() == gamedataStimType.Whistle || stimuliEvent.GetStimType() == gamedataStimType.CombatWhistle )
			{
				return false;
			}
			stimSourcePos = stimuliEvent.sourcePosition;
			if( !( Vector4.IsZero( stimSourcePos ) ) )
			{
				if( stimuliEvent.GetStimType() == gamedataStimType.CrimeWitness )
				{
					if( PreventionSystem.IsChasingPlayer( ScriptExecutionContext.GetOwner( context ).GetGame() ) && ( stimuliEvent.sourceObject.GetEntityID() == PreventionSystem.GetLastKnownPlayerVehicle( ScriptExecutionContext.GetOwner( context ).GetGame() ).GetEntityID() ) )
					{
						PreventionSystem.SetLastKnownPlayerPosition( ScriptExecutionContext.GetOwner( context ).GetGame(), PreventionSystem.GetLastKnownPlayerVehicle( ScriptExecutionContext.GetOwner( context ).GetGame() ).GetWorldPosition() );
						if( !( VehicleComponent.IsMountedToVehicle( ScriptExecutionContext.GetOwner( context ).GetGame(), ScriptExecutionContext.GetOwner( context ) ) ) )
						{
							return false;
						}
					}
				}
				ScriptExecutionContext.SetArgumentVector( context, 'StimSource', stimSourcePos );
				return true;
			}
		}
		return false;
	}

}

class CheckAnimSetTags extends AIbehaviorconditionScript
{
	const editable var m_animsetTagToCompare : array< CName >;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		if( ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) ).HasRuntimeAnimsetTags( m_animsetTagToCompare ) )
		{
			return true;
		}
		return false;
	}

}

class HasPositionFarFromThreat extends AIbehaviorconditionScript
{
	editable var desiredDistance : Float;
	editable var minDistance : Float;
	editable var minPathLength : Float;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var currentPosition : Vector4;
		var destination : Vector4;
		var threatPosition : Vector4;
		var threat : GameObject;
		var pathResult : NavigationPath;
		var pathLength : Float;
		threat = ScriptExecutionContext.GetArgumentObject( context, 'StimTarget' );
		if( threat == NULL )
		{
			return false;
		}
		currentPosition = ScriptExecutionContext.GetOwner( context ).GetWorldPosition();
		threatPosition = threat.GetWorldPosition();
		if( !( GameInstance.GetNavigationSystem( GetGame( context ) ).FindNavmeshPointAwayFromReferencePoint( currentPosition, threatPosition, desiredDistance, NavGenAgentSize.Human, destination, 5.0, 90.0 ) ) )
		{
			return false;
		}
		if( Vector4.LengthSquared( threatPosition - destination ) < ( minDistance * minDistance ) )
		{
			return false;
		}
		pathResult = GameInstance.GetAINavigationSystem( GetGame( context ) ).CalculatePathForCharacter( currentPosition, destination, 1.0, ScriptExecutionContext.GetOwner( context ) );
		if( pathResult )
		{
			pathLength = pathResult.CalculateLength();
		}
		if( pathLength < minPathLength )
		{
			return false;
		}
		ScriptExecutionContext.SetArgumentFloat( context, 'PathLength', pathLength );
		ScriptExecutionContext.SetArgumentVector( context, 'MovementDestination', destination );
		return true;
	}

}

class CanNPCRun extends AIbehaviorconditionScript
{
	editable var m_maxRunners : Int32;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var reactionSystem : ScriptedReactionSystem;
		var runners : Int32;
		var reactionData : AIReactionData;
		reactionSystem = ( ( ScriptedReactionSystem )( GameInstance.GetScriptableSystemsContainer( ScriptExecutionContext.GetOwner( context ).GetGame() ).Get( 'ScriptedReactionSystem' ) ) );
		runners = reactionSystem.GetFleeingNPCsCount();
		reactionData = GetPuppet( context ).GetStimReactionComponent().GetActiveReactionData();
		if( !( reactionData ) )
		{
			reactionData = GetPuppet( context ).GetStimReactionComponent().GetDesiredReactionData();
		}
		if( ( runners >= m_maxRunners ) && reactionData.stimType != gamedataStimType.HijackVehicle )
		{
			if( reactionSystem.GetRegisterTimeout() > EngineTime.ToFloat( GameInstance.GetSimTime( ScriptExecutionContext.GetOwner( context ).GetGame() ) ) )
			{
				runners = reactionSystem.GetFleeingNPCsCountInDistance( ScriptExecutionContext.GetOwner( context ).GetWorldPosition(), 10.0 );
				if( runners >= m_maxRunners )
				{
					return false;
				}
			}
		}
		return true;
	}

}

class ShouldNPCContinueInAlerted extends AIbehaviorconditionScript
{

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var puppet : ScriptedPuppet;
		var aiComponent : AIHumanComponent;
		var reactionComponent : ReactionManagerComponent;
		var npcIgnoreList : array< EntityID >;
		var alertedWithCorpses : Bool;
		var searchEndTimestamp : Float;
		alertedWithCorpses = false;
		puppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		aiComponent = puppet.GetAIControllerComponent();
		if( ( aiComponent && aiComponent.GetAIRole().GetRoleEnum() == EAIRole.Patrol ) && aiComponent.GetAIPatrolBlackboard().GetBool( GetAllBlackboardDefs().AIPatrol.forceAlerted ) )
		{
			return true;
		}
		if( puppet.IsConnectedToSecuritySystem() )
		{
			if( puppet.GetSecuritySystem().IsReprimandOngoing() )
			{
				return true;
			}
			reactionComponent = puppet.GetStimReactionComponent();
			npcIgnoreList = reactionComponent.GetIgnoreList();
			if( reactionComponent.IsAlertedByDeadBody() || ( npcIgnoreList.Size() > 0 ) )
			{
				alertedWithCorpses = true;
			}
		}
		searchEndTimestamp = ScriptExecutionContext.GetArgumentFloat( context, 'SearchingStarted' );
		if( alertedWithCorpses )
		{
			searchEndTimestamp += TweakDBInterface.GetFloat( T"AIGeneralSettings.alertedSearchDurationWithCorpses", 5.0 );
		}
		else
		{
			searchEndTimestamp += TweakDBInterface.GetFloat( T"AIGeneralSettings.alertedSearchDurationNormal", 5.0 );
		}
		return searchEndTimestamp > EngineTime.ToFloat( GameInstance.GetSimTime( ScriptExecutionContext.GetOwner( context ).GetGame() ) );
	}

}

class IsInTrafficLane extends AIbehaviorconditionScript
{

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		return GetPuppet( context ).GetStimReactionComponent().IsInTrafficLane();
	}

}

class IsBlockedInTraffic extends AIbehaviorconditionScript
{

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		return GetPuppet( context ).GetCrowdMemberComponent().IsBlockedInTraffic();
	}

}

class PreviousFearPhaseCheck extends AIbehaviorconditionScript
{
	editable var m_fearPhase : Int32;

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		return GetPuppet( context ).GetStimReactionComponent().GetPreviousFearPhase() == m_fearPhase;
	}

}

class HearStimThreshold extends AIbehaviorconditionScript
{
	editable var m_thresholdNumber : Int32;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var stimTime : Float;
		var curThresholdNumber : Int32;
		var puppet : ScriptedPuppet;
		var reactionComponent : ReactionManagerComponent;
		puppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		reactionComponent = puppet.GetStimReactionComponent();
		if( !( reactionComponent ) )
		{
			return false;
		}
		stimTime = reactionComponent.GetCurrentStimTimeStamp();
		curThresholdNumber = reactionComponent.GetCurrentStimThresholdValue();
		if( stimTime >= EngineTime.ToFloat( GameInstance.GetSimTime( ScriptExecutionContext.GetOwner( context ).GetGame() ) ) )
		{
			if( curThresholdNumber >= m_thresholdNumber )
			{
				return true;
			}
		}
		return false;
	}

}

class StealthStimThreshold extends AIbehaviorconditionScript
{
	editable var m_stealthThresholdNumber : Int32;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var stimTime : Float;
		var curThresholdNumber : Int32;
		var puppet : ScriptedPuppet;
		var reactionComponent : ReactionManagerComponent;
		puppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		reactionComponent = puppet.GetStimReactionComponent();
		if( !( reactionComponent ) )
		{
			return false;
		}
		stimTime = reactionComponent.GetCurrentStealthStimTimeStamp();
		curThresholdNumber = reactionComponent.GetCurrentStealthStimThresholdValue();
		if( stimTime >= EngineTime.ToFloat( GameInstance.GetSimTime( ScriptExecutionContext.GetOwner( context ).GetGame() ) ) )
		{
			if( curThresholdNumber >= m_stealthThresholdNumber )
			{
				return true;
			}
		}
		return false;
	}

}

class CanDoReactionAction extends AIbehaviorconditionScript
{
	editable var m_reactionName : CName;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var reactionSystem : ReactionSystem;
		reactionSystem = GameInstance.GetReactionSystem( ScriptExecutionContext.GetOwner( context ).GetGame() );
		if( reactionSystem && reactionSystem.RegisterReaction( m_reactionName ) == AIReactionCountOutcome.Succeded )
		{
			return true;
		}
		return false;
	}

}

class CheckTimestamp extends AIbehaviorconditionScript
{
	editable var m_validationTime : Float;
	editable var m_timestampArgument : CName;

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var timestamp : Float;
		timestamp = ScriptExecutionContext.GetArgumentFloat( context, m_timestampArgument );
		if( ( timestamp + m_validationTime ) > EngineTime.ToFloat( GameInstance.GetSimTime( ScriptExecutionContext.GetOwner( context ).GetGame() ) ) )
		{
			return true;
		}
		return false;
	}

}

class EscalateProvoke extends AIbehaviorconditionScript
{

	protected override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var reactionData : AIReactionData;
		reactionData = GetPuppet( context ).GetStimReactionComponent().GetActiveReactionData();
		if( !( reactionData ) )
		{
			reactionData = GetPuppet( context ).GetStimReactionComponent().GetDesiredReactionData();
		}
		if( reactionData && reactionData.escalateProvoke )
		{
			return true;
		}
		return false;
	}

}

class ReactAfterDodge extends AIbehaviorconditionScript
{

	protected export override function Check( context : ScriptExecutionContext ) : AIbehaviorConditionOutcomes
	{
		var target : GameObject;
		var mountInfo : MountingInfo;
		var ownerPuppet : ScriptedPuppet;
		ownerPuppet = ( ( ScriptedPuppet )( ScriptExecutionContext.GetOwner( context ) ) );
		if( ScriptedPuppet.IsPlayerFollower( ScriptExecutionContext.GetOwner( context ) ) )
		{
			return false;
		}
		if( ownerPuppet.IsCrowd() )
		{
			return true;
		}
		target = ScriptExecutionContext.GetArgumentObject( context, 'StimTarget' );
		if( GameObject.IsVehicle( target ) )
		{
			mountInfo = GameInstance.GetMountingFacility( ownerPuppet.GetGame() ).GetMountingInfoSingleWithObjects( , target );
			target = ( ( GameObject )( GameInstance.FindEntityByID( ownerPuppet.GetGame(), mountInfo.childId ) ) );
		}
		if( target && GameObject.GetAttitudeBetween( ownerPuppet, target ) == EAIAttitude.AIA_Friendly )
		{
			return false;
		}
		return true;
	}

}

