class NPCStateChangeSignal extends TaggedSignalUserData
{
	var m_highLevelState : gamedataNPCHighLevelState;
	var m_highLevelStateValid : Bool;
	var m_upperBodyState : gamedataNPCUpperBodyState;
	var m_upperBodyStateValid : Bool;
	var m_stanceState : gamedataNPCStanceState;
	var m_stanceStateValid : Bool;
	var m_hitReactionModeState : EHitReactionMode;
	var m_hitReactionModeStateValid : Bool;
	var m_defenseMode : gamedataDefenseMode;
	var m_defenseModeValid : Bool;
	var m_locomotionMode : gamedataLocomotionMode;
	var m_locomotionModeValid : Bool;
	var m_behaviorState : gamedataNPCBehaviorState;
	var m_behaviorStateValid : Bool;
	var m_phaseState : ENPCPhaseState;
	var m_phaseStateValid : Bool;
}

class OnUnstoppableStateSignal extends TaggedSignalUserData
{
}

class BleedingEffectDamageUpdate extends Event
{
}

class NPCStatesComponent extends AINetStateComponent
{
	private var m_aimingLookatEvent : LookAtAddEvent;
	private var m_highLevelAnimFeatureName : CName;
	default m_highLevelAnimFeatureName = 'highLevelState';
	private var m_upperBodyAnimFeatureName : CName;
	default m_upperBodyAnimFeatureName = 'upperBodyState';
	private var m_stanceAnimFeatureName : CName;
	default m_stanceAnimFeatureName = 'stanceState';
	var m_statFlagDefensiveState : gameStatModifierData;
	private var m_prevNPCStanceState : gamedataNPCStanceState;
	default m_prevNPCStanceState = gamedataNPCStanceState.Invalid;
	private var m_previousHighLevelState : gamedataNPCHighLevelState;
	default m_previousHighLevelState = gamedataNPCHighLevelState.Invalid;
	private var m_prevHitReactionMode : EHitReactionMode;
	default m_prevHitReactionMode = EHitReactionMode.Invalid;
	private var m_bulkyStaggerMinRecordID : TweakDBID;
	private var m_staggerMinRecordID : TweakDBID;
	private var m_unstoppableRecordID : TweakDBID;
	private var m_unstoppableTwitchMinRecordID : TweakDBID;
	private var m_unstoppableTwitchNoneRecordID : TweakDBID;
	private var m_forceImpactRecordID : TweakDBID;
	private var m_forceStaggerRecordID : TweakDBID;
	private var m_forceKnockdownRecordID : TweakDBID;
	private var m_fragileRecordID : TweakDBID;
	private var m_weakRecordID : TweakDBID;
	private var m_toughRecordID : TweakDBID;
	private var m_bulkyRecordID : TweakDBID;
	private var m_regularRecordID : TweakDBID;
	private var m_keepRecentThreatAfterRelaxedDuration : Float;
	private var m_inCombat : Bool;
	default m_inCombat = false;

	public export function OnGameAttach()
	{
		m_bulkyStaggerMinRecordID = T"HitReactionThresholdModifiers.BulkyStaggerMin";
		m_staggerMinRecordID = T"HitReactionThresholdModifiers.StaggerMin";
		m_unstoppableRecordID = T"HitReactionThresholdModifiers.Unstoppable";
		m_unstoppableTwitchMinRecordID = T"HitReactionThresholdModifiers.Unstoppable";
		m_unstoppableTwitchNoneRecordID = T"HitReactionThresholdModifiers.Unstoppable";
		m_forceImpactRecordID = T"HitReactionThresholdModifiers.ForceImpact";
		m_forceStaggerRecordID = T"HitReactionThresholdModifiers.ForceStagger";
		m_forceKnockdownRecordID = T"HitReactionThresholdModifiers.ForceKnockdown";
		m_fragileRecordID = T"HitReactionThresholdModifiers.Fragile";
		m_weakRecordID = T"HitReactionThresholdModifiers.Weak";
		m_toughRecordID = T"HitReactionThresholdModifiers.Tough";
		m_bulkyRecordID = T"HitReactionThresholdModifiers.Bulky";
		m_regularRecordID = T"HitReactionThresholdModifiers.Regular";
		m_keepRecentThreatAfterRelaxedDuration = TweakDBInterface.GetFloat( T"AIGeneralSettings.keepRecentThreatAfterRelaxedDuration", 0.0 );
		if( GetPuppetStateBlackboard() )
		{
			GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.Stance, ( ( Int32 )( GetCurrentStanceState() ) ) );
			GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.HighLevel, ( ( Int32 )( GetCurrentHighLevelState() ) ) );
		}
	}

	public function GetCurrentHighLevelState() : gamedataNPCHighLevelState
	{
		return ( ( gamedataNPCHighLevelState )( GetReplicatedHighLevelState() ) );
	}

	public function SetCurrentHighLevelState( newState : gamedataNPCHighLevelState ) : Bool
	{
		return SetReplicatedHighLevelState( ( ( Int32 )( newState ) ) );
	}

	public function GetPreviousHighLevelState() : gamedataNPCHighLevelState
	{
		return m_previousHighLevelState;
	}

	public function GetCurrentUpperBodyState() : gamedataNPCUpperBodyState
	{
		return ( ( gamedataNPCUpperBodyState )( GetReplicatedUpperBodyState() ) );
	}

	public function SetCurrentUpperBodyState( newState : gamedataNPCUpperBodyState ) : Bool
	{
		return SetReplicatedUpperBodyState( ( ( Int32 )( newState ) ) );
	}

	public function GetCurrentDefenseMode() : gamedataDefenseMode
	{
		return ( ( gamedataDefenseMode )( GetReplicatedDefenseMode() ) );
	}

	public function SetCurrentDefenseMode( newState : gamedataDefenseMode ) : Bool
	{
		return SetReplicatedDefenseMode( ( ( Int32 )( newState ) ) );
	}

	public function GetCurrentLocomotionMode() : gamedataLocomotionMode
	{
		return ( ( gamedataLocomotionMode )( GetReplicatedLocomotionMode() ) );
	}

	public function SetCurrentLocomotionMode( newState : gamedataLocomotionMode ) : Bool
	{
		return SetReplicatedLocomotionMode( ( ( Int32 )( newState ) ) );
	}

	public function GetCurrentStanceState() : gamedataNPCStanceState
	{
		return ( ( gamedataNPCStanceState )( GetReplicatedStanceState() ) );
	}

	public function SetPreviousStanceState( prevState : gamedataNPCStanceState )
	{
		m_prevNPCStanceState = prevState;
	}

	public function GetPreviousStanceState() : gamedataNPCStanceState
	{
		return m_prevNPCStanceState;
	}

	public function SetCurrentStanceState( newState : gamedataNPCStanceState ) : Bool
	{
		return SetReplicatedStanceState( ( ( Int32 )( newState ) ) );
	}

	public function SetPreviousHitReactionMode( prevState : EHitReactionMode )
	{
		m_prevHitReactionMode = prevState;
	}

	public function GetPreviousHitReactionMode() : EHitReactionMode
	{
		return m_prevHitReactionMode;
	}

	public function GetCurrentHitReactionModeState() : EHitReactionMode
	{
		return ( ( EHitReactionMode )( GetReplicatedHitReactionModeState() ) );
	}

	public function SetCurrentHitReactionModeState( newState : EHitReactionMode ) : Bool
	{
		return SetReplicatedHitReactionModeState( ( ( Int32 )( newState ) ) );
	}

	public function GetCurrentBehaviorState() : gamedataNPCBehaviorState
	{
		return ( ( gamedataNPCBehaviorState )( GetReplicatedBehaviorState() ) );
	}

	public function SetCurrentBehaviorState( newState : gamedataNPCBehaviorState ) : Bool
	{
		return SetReplicatedBehaviorState( ( ( Int32 )( newState ) ) );
	}

	public function GetCurrentPhaseState() : ENPCPhaseState
	{
		return ( ( ENPCPhaseState )( GetReplicatedPhaseState() ) );
	}

	public function SetCurrentPhaseState( newState : ENPCPhaseState ) : Bool
	{
		return SetReplicatedPhaseState( ( ( Int32 )( newState ) ) );
	}

	public static function GetAnimWrapperNameBasedOnHighLevelState( highLevelState : gamedataNPCHighLevelState ) : CName
	{
		switch( highLevelState )
		{
			case gamedataNPCHighLevelState.Alerted:
				return 'alertedLocomotion';
			case gamedataNPCHighLevelState.Combat:
				return 'combatLocomotion';
			case gamedataNPCHighLevelState.Stealth:
				return 'stealthLocomotion';
			case gamedataNPCHighLevelState.Fear:
				return '';
			return '';
		}
		return '';
	}

	public static function GetAnimWrapperNameBasedOnStanceState( stanceState : gamedataNPCStanceState ) : CName
	{
		switch( stanceState )
		{
			case gamedataNPCStanceState.Crouch:
				return 'inCrouch';
			case gamedataNPCStanceState.Cover:
				return 'inCover';
			case gamedataNPCStanceState.Swim:
				return 'inSwim';
			case gamedataNPCStanceState.Vehicle:
				return 'inVehicle';
			case gamedataNPCStanceState.VehicleWindow:
				return 'inVehicle';
			default:
				return '';
		}
		return '';
	}

	public static function AlertPuppet( ownerPuppet : weak< ScriptedPuppet > ) : Bool
	{
		var currentHLS : gamedataNPCHighLevelState;
		var securitySystem : SecuritySystemControllerPS;
		if( ( !( ownerPuppet ) || !( ownerPuppet.IsActive() ) ) || !( ownerPuppet.IsAggressive() ) )
		{
			return false;
		}
		currentHLS = ownerPuppet.GetHighLevelStateFromBlackboard();
		if( currentHLS == gamedataNPCHighLevelState.Relaxed )
		{
			if( ( !( ownerPuppet.IsCharacterCivilian() ) && !( ownerPuppet.IsCrowd() ) ) || ownerPuppet.IsCharacterPolice() )
			{
				NPCPuppet.ChangeHighLevelState( ownerPuppet, gamedataNPCHighLevelState.Alerted );
			}
			if( !( ownerPuppet.IsBoss() ) && ownerPuppet.GetNPCRarity() != gamedataNPCRarity.MaxTac )
			{
				return true;
			}
		}
		if( currentHLS == gamedataNPCHighLevelState.Alerted && !( GameInstance.GetStatusEffectSystem( ownerPuppet.GetGame() ).HasStatusEffectWithTag( ownerPuppet.GetEntityID(), 'CommsNoiseJam' ) ) )
		{
			securitySystem = ownerPuppet.GetSecuritySystem();
			if( securitySystem )
			{
				ownerPuppet.TriggerSecuritySystemNotification( ownerPuppet.GetWorldPosition(), ownerPuppet, ESecurityNotificationType.ALARM );
				return true;
			}
			else
			{
				AISquadHelper.EnterAlerted( ownerPuppet );
				return true;
			}
		}
		return false;
	}

	private function GetPuppet() : ScriptedPuppet
	{
		return ( ( ScriptedPuppet )( GetOwner() ) );
	}

	private function GetPuppetStateBlackboard() : IBlackboard
	{
		if( GetPuppet() )
		{
			return GetPuppet().GetPuppetStateBlackboard();
		}
		return NULL;
	}

	public function OnNPCStateChangeSignalReceived( signal : NPCStateChangeSignal )
	{
		if( signal.m_highLevelStateValid )
		{
			ChangeHighLevelState( signal.m_highLevelState );
		}
		if( signal.m_upperBodyStateValid )
		{
			ChangeUpperBodyState( signal.m_upperBodyState );
		}
		if( signal.m_stanceStateValid )
		{
			ChangeStanceState( signal.m_stanceState );
		}
		if( signal.m_hitReactionModeStateValid )
		{
			ChangeHitReactionModeState( signal.m_hitReactionModeState );
		}
		if( signal.m_behaviorStateValid )
		{
			ChangeBehaviorState( signal.m_behaviorState );
		}
		if( signal.m_defenseModeValid )
		{
			ChangeDefenseMode( signal.m_defenseMode );
		}
		if( signal.m_locomotionModeValid )
		{
			ChangeLocomotionMode( signal.m_locomotionMode );
		}
		if( signal.m_phaseStateValid )
		{
			ChangePhaseState( signal.m_phaseState );
		}
		if( signal.m_highLevelStateValid && signal.m_highLevelState == gamedataNPCHighLevelState.Combat )
		{
			AIActionHelper.CombatQueriesInit( GetPuppet() );
		}
	}

	private function ChangeHighLevelState( newState : gamedataNPCHighLevelState )
	{
		var currentHighLevelStateEvent : gameHighLevelStateDataEvent;
		m_previousHighLevelState = GetCurrentHighLevelState();
		if( m_previousHighLevelState == newState )
		{
			return;
		}
		if( SetCurrentHighLevelState( newState ) )
		{
			currentHighLevelStateEvent = new gameHighLevelStateDataEvent;
			currentHighLevelStateEvent.currentHighLevelState = GetCurrentHighLevelState();
			currentHighLevelStateEvent.currentNPCEntityID = GetOwner().GetEntityID();
			UpdateHighLevelState( GetCurrentHighLevelState(), m_previousHighLevelState );
			GetOwner().QueueEvent( currentHighLevelStateEvent );
			GetPlayer( GetOwner().GetGame() ).QueueEvent( currentHighLevelStateEvent );
			AIComponent.InvokeBehaviorCallback( GetPuppet(), 'OnHighLevelChanged' );
		}
	}

	private function ChangeDefenseMode( newState : gamedataDefenseMode )
	{
		if( GetCurrentDefenseMode() != newState )
		{
			if( SetCurrentDefenseMode( newState ) )
			{
				UpdateDefenseMode();
			}
		}
	}

	private function ChangeLocomotionMode( newState : gamedataLocomotionMode )
	{
		if( GetCurrentLocomotionMode() != newState )
		{
			if( SetCurrentLocomotionMode( newState ) )
			{
				UpdateLocomotionMode();
			}
		}
	}

	private function ChangeUpperBodyState( newState : gamedataNPCUpperBodyState )
	{
		if( GetCurrentUpperBodyState() != newState )
		{
			if( SetCurrentUpperBodyState( newState ) )
			{
				UpdateUpperBodyState();
			}
		}
	}

	private function ChangeStanceState( newState : gamedataNPCStanceState )
	{
		if( GetCurrentStanceState() != newState )
		{
			if( SetCurrentStanceState( newState ) )
			{
				UpdateStanceState();
			}
		}
	}

	private function ChangeHitReactionModeState( newState : EHitReactionMode )
	{
		if( GetCurrentHitReactionModeState() != newState )
		{
			SetPreviousHitReactionMode( GetCurrentHitReactionModeState() );
			if( SetCurrentHitReactionModeState( newState ) )
			{
				UpdateHitReactionsExceptionState();
			}
		}
	}

	private function ChangeBehaviorState( newState : gamedataNPCBehaviorState )
	{
		if( GetCurrentBehaviorState() != newState )
		{
			if( SetCurrentBehaviorState( newState ) )
			{
				UpdateBehaviorState();
			}
		}
	}

	private function ChangePhaseState( newState : ENPCPhaseState )
	{
		if( GetCurrentPhaseState() != newState )
		{
			if( SetCurrentPhaseState( newState ) )
			{
				UpdatePhaseState();
			}
		}
	}

	private function MaxtacSetQuestCammo( newState : gamedataNPCHighLevelState )
	{
		var gameInstance : GameInstance;
		var puppet : ScriptedPuppet;
		puppet = GetPuppet();
		gameInstance = puppet.GetGame();
		if( !( PreventionSystem.IsPreventionMaxTac( gameInstance, puppet ) ) )
		{
			return;
		}
		if( !( VehicleComponent.IsMountedToVehicle( gameInstance, puppet ) ) )
		{
			if( newState == gamedataNPCHighLevelState.Combat || newState == gamedataNPCHighLevelState.Alerted )
			{
				if( StatusEffectSystem.ObjectHasStatusEffect( puppet, T"BaseStatusEffect.Cloaked" ) )
				{
					StatusEffectHelper.RemoveStatusEffect( puppet, T"BaseStatusEffect.Cloaked" );
				}
			}
			else if( newState == gamedataNPCHighLevelState.Relaxed )
			{
				GameObjectEffectHelper.StartEffectEvent( puppet, 'camo_intro_vfx' );
				StatusEffectHelper.ApplyStatusEffectOnSelf( gameInstance, T"BaseStatusEffect.Cloaked", puppet.GetEntityID() );
			}
		}
	}

	private function UpdateHighLevelState( newState : gamedataNPCHighLevelState, previousState : gamedataNPCHighLevelState )
	{
		var stateAnimFeature : AnimFeature_NPCState;
		var aiRole : AIRole;
		var puppet : ScriptedPuppet;
		puppet = GetPuppet();
		aiRole = puppet.GetAIControllerComponent().GetAIRole();
		MaxtacSetQuestCammo( newState );
		OnHighLevelStateExit( previousState, newState );
		if( aiRole )
		{
			aiRole.OnHighLevelStateExit( GetOwner(), previousState, newState );
		}
		stateAnimFeature = new AnimFeature_NPCState;
		stateAnimFeature.state = ( ( Int32 )( newState ) );
		AnimationControllerComponent.ApplyFeature( GetOwner(), m_highLevelAnimFeatureName, stateAnimFeature );
		GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.HighLevel, ( ( Int32 )( newState ) ) );
		GetPuppetStateBlackboard().FireCallbacks();
		OnHighLevelStateEnter( newState, previousState );
		if( aiRole )
		{
			aiRole.OnHighLevelStateEnter( GetOwner(), newState, previousState );
		}
	}

	private function HandleCombatStateAnimHint( newState : gamedataNPCHighLevelState, previousState : gamedataNPCHighLevelState )
	{
		var owner : GameObject;
		owner = GetOwner();
		if( newState == gamedataNPCHighLevelState.Combat && !( m_inCombat ) )
		{
			GameInstance.GetAnimationSystem( owner.GetGame() ).EnterCombatMode( owner.GetEntityID() );
			m_inCombat = true;
		}
		else if( newState == gamedataNPCHighLevelState.Relaxed && m_inCombat )
		{
			m_inCombat = false;
			GameInstance.GetAnimationSystem( owner.GetGame() ).ExitCombatMode( GetOwner().GetEntityID() );
		}
	}

	private function OnHighLevelStateEnter( newState : gamedataNPCHighLevelState, previousState : gamedataNPCHighLevelState )
	{
		AnimationControllerComponent.SetAnimWrapperWeightOnOwnerAndItems( GetOwner(), GetAnimWrapperNameBasedOnHighLevelState( newState ), 1.0 );
		HandleCombatStateAnimHint( newState, previousState );
		switch( newState )
		{
			case gamedataNPCHighLevelState.Relaxed:
				OnRelaxed();
			break;
			case gamedataNPCHighLevelState.Alerted:
				OnAlerted();
			break;
			case gamedataNPCHighLevelState.Combat:
				OnCombat();
			break;
			case gamedataNPCHighLevelState.Stealth:
				break;
			case gamedataNPCHighLevelState.Dead:
				OnDead();
			break;
			case gamedataNPCHighLevelState.Fear:
				break;
			default:
				break;
		}
	}

	private function OnHighLevelStateExit( leftState : gamedataNPCHighLevelState, nextState : gamedataNPCHighLevelState )
	{
		AnimationControllerComponent.SetAnimWrapperWeightOnOwnerAndItems( GetOwner(), GetAnimWrapperNameBasedOnHighLevelState( leftState ), 0.0 );
		switch( leftState )
		{
			case gamedataNPCHighLevelState.Relaxed:
				break;
			case gamedataNPCHighLevelState.Alerted:
				break;
			case gamedataNPCHighLevelState.Combat:
				if( nextState != gamedataNPCHighLevelState.Dead )
				{
					BumpComponent.ToggleComponentOn( ( ( ScriptedPuppet )( GetOwner() ) ) );
				}
			break;
			case gamedataNPCHighLevelState.Stealth:
				break;
			case gamedataNPCHighLevelState.Dead:
				break;
			case gamedataNPCHighLevelState.Fear:
				break;
			default:
				break;
		}
	}

	private function OnRelaxed()
	{
		var targetTracker : weak< TargetTrackingExtension >;
		( ( NPCPuppet )( GetOwner() ) ).GetInfluenceComponent().SetReservationRadius( 0.5 );
		if( ScriptedPuppet.IsPlayerCompanion( GetPuppet() ) )
		{
			SenseComponent.RequestMainPresetChange( GetPuppet(), "Follower" );
		}
		else
		{
			SenseComponent.RequestMainPresetChange( GetPuppet(), GetPuppet().GetStringFromCharacterTweak( "relaxedSensesPreset", "Relaxed" ) );
		}
		if( TargetTrackingExtension.Get( GetPuppet(), targetTracker ) )
		{
			if( GetPuppet().IsPrevention() )
			{
				targetTracker.ResetRecentlyDroppedThreat( 1.0 );
			}
			else
			{
				targetTracker.ResetRecentlyDroppedThreat( m_keepRecentThreatAfterRelaxedDuration );
			}
		}
	}

	private function OnFear()
	{
		( ( NPCPuppet )( GetOwner() ) ).GetInfluenceComponent().SetReservationRadius( 0.2 );
	}

	private function OnAlerted()
	{
		( ( NPCPuppet )( GetOwner() ) ).GetInfluenceComponent().SetReservationRadius( 1.0 );
		if( ScriptedPuppet.IsPlayerCompanion( GetPuppet() ) )
		{
			SenseComponent.RequestMainPresetChange( GetPuppet(), "Follower" );
		}
		else
		{
			SenseComponent.RequestMainPresetChange( GetPuppet(), GetPuppet().GetStringFromCharacterTweak( "alertedSensesPreset", "Alerted" ) );
		}
		GetPuppet().RefreshCachedReactionPresetData();
		GetPuppet().TryRegisterToPrevention();
	}

	private static function GetCombatTarget( npcPuppet : NPCPuppet ) : weak< GameObject >
	{
		var combatTarget : weak< GameObject >;
		combatTarget = ( ( weak< weak< GameObject > > )( npcPuppet.GetAIControllerComponent().GetBehaviorArgument( 'CombatTarget' ) ) );
		return combatTarget;
	}

	private function OnCombat()
	{
		var npcPuppet : NPCPuppet;
		var presetName : String;
		var delayID : DelayID;
		var game : GameInstance;
		var player : PlayerPuppet;
		var evt : DodgeToAvoidCombatEvent;
		var broadcaster : StimBroadcasterComponent;
		var targetTracker : weak< TargetTrackingExtension >;
		var cooldownIsActive : Bool;
		var failureCooldownIsActive : Bool;
		var aiHoldPositionCommand : AIHoldPositionCommand;
		npcPuppet = ( ( NPCPuppet )( GetPuppet() ) );
		npcPuppet.GetInfluenceComponent().SetReservationRadius( 1.0 );
		presetName = ( ( ScriptedPuppet.IsPlayerCompanion( npcPuppet ) ) ? ( "FollowerCombat" ) : ( npcPuppet.GetStringFromCharacterTweak( "combatSensesPreset", "Combat" ) ) );
		SenseComponent.RequestMainPresetChange( npcPuppet, presetName );
		GameObject.StartCooldown( npcPuppet, 'chatter_flank_order', 7.0 );
		if( GameInstance.GetStatsSystem( game ).GetStatValue( npcPuppet.GetEntityID(), gamedataStatType.IsHeavyRangedArchetype ) > 0.0 )
		{
			GameObject.PlayVoiceOver( npcPuppet, 'hmg_charge', 'Scripts:OnCombat' );
		}
		if( GetPuppet().IsCrowd() )
		{
			GameObject.PlayVoiceOver( npcPuppet, 'crowd_combat', 'Scripts:OnCombat' );
		}
		else
		{
			GameObject.PlayVoiceOver( npcPuppet, 'start_combat', 'Scripts:OnCombat', ( ( ScriptedPuppet.IsPlayerCompanion( npcPuppet ) ) ? ( 1.5 ) : ( 0.0 ) ) );
		}
		delayID = AIActionHelper.QueueNearbyCombatNotification( npcPuppet );
		if( GetCombatTarget( npcPuppet ) )
		{
			game = npcPuppet.GetGame();
			player = GetPlayer( game );
			cooldownIsActive = StatusEffectHelper.HasStatusEffectWithTagConst( player, 'DodgeOutOfSightCooldown' );
			failureCooldownIsActive = StatusEffectHelper.HasStatusEffectWithTagConst( player, 'SecondChancePerkCooldown' );
			if( ( ( player.CanAvoidCombatWithDodge() && !( npcPuppet.PuppetIsNotVisible() ) ) && !( cooldownIsActive ) ) && !( failureCooldownIsActive ) )
			{
				StatusEffectHelper.ApplyStatusEffect( player, T"BaseStatusEffect.SecondChancePerkTimeDilation" );
				evt = new DodgeToAvoidCombatEvent;
				evt.delayID = delayID;
				evt.npcID = npcPuppet.GetEntityID();
				GameInstance.GetDelaySystem( game ).DelayEvent( player, evt, 1.0, false );
				GameInstance.GetDelaySystem( game ).DelayEvent( player, evt, 2.0, false );
				GameInstance.GetDelaySystem( game ).DelayEvent( player, evt, 3.0, false );
			}
			if( player.CanAvoidCombatWithGag() )
			{
				StatusEffectHelper.ApplyStatusEffect( npcPuppet, T"BaseStatusEffect.GagOpportunity" );
			}
			broadcaster = npcPuppet.GetStimBroadcasterComponent();
			if( broadcaster )
			{
				broadcaster.TriggerSingleBroadcast( npcPuppet, gamedataStimType.SilentAlarm, 10.0 );
			}
		}
		if( TargetTrackingExtension.Get( npcPuppet, targetTracker ) )
		{
			targetTracker.ResetRecentlyDroppedThreatNoCallbacks();
		}
		AICoverHelper.GetCoverBlackboard( npcPuppet ).SetBool( GetAllBlackboardDefs().AICover.firstCoverEvaluationDone, false );
		AICoverHelper.GetCoverBlackboard( npcPuppet ).SetFloat( GetAllBlackboardDefs().AICover.startCoverEvaluationTimeStamp, -1.0 );
		npcPuppet.GetBumpComponent().Toggle( false );
		npcPuppet.ReevaluatEAIThreatCalculationType();
		if( PreventionSystem.CheckNPCSpawnedType( GetPuppet().GetGame(), GetPuppet().GetEntityID(), DynamicVehicleType.RoadBlockade ) )
		{
			aiHoldPositionCommand = new AIHoldPositionCommand;
			aiHoldPositionCommand.duration = 20.0;
			AIComponent.SendCommand( GetPuppet(), aiHoldPositionCommand );
		}
		GetPuppet().RefreshCachedReactionPresetData();
		GetPuppet().TryRegisterToPrevention();
	}

	protected event OnNotifyNearbyAboutCombatEvent( evt : NotifyNearbyAboutCombatEvent )
	{
		var npcPuppet : NPCPuppet;
		var npcObject : GameObject;
		var targetTracker : weak< TargetTrackingExtension >;
		var broadcaster : StimBroadcasterComponent;
		npcPuppet = ( ( NPCPuppet )( GetPuppet() ) );
		if( !( npcPuppet.IsActive() ) )
		{
			return true;
		}
		npcObject = ( ( GameObject )( GetEntity() ) );
		if( GetCombatTarget( npcPuppet ) )
		{
			if( !( StatusEffectSystem.ObjectHasStatusEffectWithTag( npcObject, 'CommsNoiseJam' ) ) )
			{
				AIActionHelper.QueuePullSquadSync( npcPuppet, true );
				if( npcPuppet.IsConnectedToSecuritySystem() )
				{
					AIActionHelper.QueueSecuritySystemCombatNotification( npcPuppet, true );
				}
			}
			broadcaster = npcPuppet.GetStimBroadcasterComponent();
			if( broadcaster )
			{
				broadcaster.TriggerSingleBroadcast( GetOwner(), gamedataStimType.Alarm, 10.0 );
			}
		}
		if( TargetTrackingExtension.Get( npcPuppet, targetTracker ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( npcObject, 'ResetSquadSync' ) ) )
		{
			targetTracker.PushSquadSync( AISquadType.Combat );
			targetTracker.PullSquadSync( AISquadType.Combat );
		}
	}

	private function OnDead()
	{
		ChangeUpperBodyState( gamedataNPCUpperBodyState.Normal );
		GetPuppet().GetSensesComponent().Toggle( false );
		GetPuppet().GetBumpComponent().Toggle( false );
		PlayDeadVO();
	}

	private function PlayDeadVO()
	{
		var broadcaster : StimBroadcasterComponent;
		if( m_previousHighLevelState != gamedataNPCHighLevelState.Combat || StatusEffectSystem.ObjectHasStatusEffectOfType( ( ( GameObject )( GetEntity() ) ), gamedataStatusEffectType.MuteAudioStims ) )
		{
			GameObject.PlayVoiceOver( GetOwner(), 'stlh_death', 'Scripts:PlayDeadVO' );
		}
		else
		{
			GameObject.PlayVoiceOver( GetOwner(), 'start_dead', 'Scripts:PlayDeadVO' );
			broadcaster = GetOwner().GetStimBroadcasterComponent();
			if( broadcaster )
			{
				broadcaster.TriggerSingleBroadcast( GetOwner(), gamedataStimType.Attention );
			}
		}
	}

	protected event OnNotifySecuritySystemCombatEvent( evt : NotifySecuritySystemCombatEvent )
	{
		if( GetOwner().IsActive() )
		{
			NotifySecuritySystemCombat();
		}
	}

	private function NotifySecuritySystemCombat()
	{
		var puppet : ScriptedPuppet;
		var threat : weak< GameObject >;
		var threatLocation : TrackedLocation;
		var lastKnownPosition : Vector4;
		puppet = ( ( ScriptedPuppet )( GetOwner() ) );
		if( puppet )
		{
			AIActionHelper.GetActiveTopHostilePuppetThreat( puppet, threatLocation );
			threat = ( ( GameObject )( threatLocation.entity ) );
			if( threat )
			{
				lastKnownPosition = threatLocation.sharedLocation.position;
				puppet.TriggerSecuritySystemNotification( lastKnownPosition, threat, ESecurityNotificationType.COMBAT );
			}
		}
	}

	private function UpdateUpperBodyState()
	{
		var stateAnimFeature : AnimFeature_NPCState;
		stateAnimFeature = new AnimFeature_NPCState;
		stateAnimFeature.state = GetUpperBodyStateForAnimGraph();
		AnimationControllerComponent.ApplyFeature( GetOwner(), m_upperBodyAnimFeatureName, stateAnimFeature );
		GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.UpperBody, ( ( Int32 )( GetCurrentUpperBodyState() ) ) );
		OnUpperBodyStateChanged();
		switch( GetCurrentUpperBodyState() )
		{
			case gamedataNPCUpperBodyState.Normal:
				OnNormal();
			break;
			case gamedataNPCUpperBodyState.Shoot:
				OnShoot();
			break;
			case gamedataNPCUpperBodyState.Reload:
				OnReload();
			break;
			case gamedataNPCUpperBodyState.Defend:
				OnDefend();
			break;
			case gamedataNPCUpperBodyState.Parry:
				OnParry();
			break;
			case gamedataNPCUpperBodyState.Attack:
				break;
			OnAttack();
			case gamedataNPCUpperBodyState.ChargedAttack:
				break;
			OnChargeAttack();
			default:
				break;
		}
	}

	private function GetUpperBodyStateForAnimGraph() : Int32
	{
		switch( GetCurrentUpperBodyState() )
		{
			case gamedataNPCUpperBodyState.Aim:
				return 1;
			case gamedataNPCUpperBodyState.Attack:
				return 2;
			case gamedataNPCUpperBodyState.ChargedAttack:
				return 3;
			case gamedataNPCUpperBodyState.Defend:
				return 4;
			case gamedataNPCUpperBodyState.Equip:
				return 5;
			case gamedataNPCUpperBodyState.Normal:
				return 6;
			case gamedataNPCUpperBodyState.Parry:
				return 7;
			case gamedataNPCUpperBodyState.Reload:
				return 8;
			case gamedataNPCUpperBodyState.Shoot:
				return 9;
			case gamedataNPCUpperBodyState.Taunt:
				return 10;
			default:
				return 0;
		}
	}

	private function OnUpperBodyStateChanged()
	{
		UpdateDefensiveState( false );
		TurnOffParryState();
	}

	private function OnNormal() {}

	private function OnShoot() {}

	private function OnReload() {}

	private function OnDefend()
	{
		UpdateDefensiveState( true );
	}

	private function OnParry()
	{
		TurnOnParryState();
	}

	private function OnAttack() {}

	private function OnChargeAttack() {}

	private function UpdateLocomotionMode()
	{
		GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.LocomotionMode, ( ( Int32 )( GetCurrentLocomotionMode() ) ) );
		OnLocomotionModeChanged();
		switch( GetCurrentLocomotionMode() )
		{
			case gamedataLocomotionMode.Static:
				OnStatic();
			break;
			case gamedataLocomotionMode.Moving:
				OnMoving();
			break;
			default:
				break;
		}
	}

	private function OnLocomotionModeChanged() {}

	private function OnStatic() {}

	private function OnMoving() {}

	private function UpdateDefenseMode()
	{
		GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.DefenseMode, ( ( Int32 )( GetCurrentDefenseMode() ) ) );
		OnDefenseModeChanged();
		switch( GetCurrentDefenseMode() )
		{
			case gamedataDefenseMode.NoDefend:
				OnNoDefend();
			break;
			case gamedataDefenseMode.DefendAll:
				OnDefendAll();
			break;
			case gamedataDefenseMode.DefendMelee:
				OnDefendMelee();
			break;
			case gamedataDefenseMode.DefendRanged:
				OnDefendRanged();
			break;
			default:
				break;
		}
	}

	private function OnDefenseModeChanged() {}

	private function OnNoDefend() {}

	private function OnDefendAll() {}

	private function OnDefendMelee() {}

	private function OnDefendRanged() {}

	private function UpdateBehaviorState()
	{
		GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.BehaviorState, ( ( Int32 )( GetCurrentBehaviorState() ) ) );
	}

	private function UpdatePhaseState()
	{
		GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.PhaseState, ( ( Int32 )( GetCurrentPhaseState() ) ) );
	}

	private function UpdateDefensiveState( enable : Bool )
	{
		var puppetID : StatsObjectID;
		var stats : StatsSystem;
		puppetID = GetPuppet().GetEntityID();
		stats = GameInstance.GetStatsSystem( GetPuppet().GetGame() );
		if( enable )
		{
			if( stats.GetStatValue( puppetID, gamedataStatType.IsBlocking ) == 0.0 )
			{
				m_statFlagDefensiveState = RPGManager.CreateStatModifier( gamedataStatType.IsBlocking, gameStatModifierType.Additive, 1.0 );
				stats.AddModifier( puppetID, m_statFlagDefensiveState );
			}
		}
		else
		{
			if( stats.GetStatValue( puppetID, gamedataStatType.IsBlocking ) == 1.0 )
			{
				stats.RemoveModifier( puppetID, m_statFlagDefensiveState );
			}
		}
	}

	private function TurnOnParryState()
	{
		var statFlag : gameStatModifierData;
		var puppetID : StatsObjectID;
		var stats : StatsSystem;
		puppetID = GetPuppet().GetEntityID();
		stats = GameInstance.GetStatsSystem( GetPuppet().GetGame() );
		if( stats.GetStatValue( puppetID, gamedataStatType.IsDeflecting ) == 0.0 )
		{
			statFlag = RPGManager.CreateStatModifier( gamedataStatType.IsDeflecting, gameStatModifierType.Additive, 1.0 );
			stats.AddModifier( puppetID, statFlag );
		}
	}

	private function TurnOffParryState()
	{
		var statFlag : gameStatModifierData;
		var puppetID : StatsObjectID;
		var stats : StatsSystem;
		puppetID = GetPuppet().GetEntityID();
		stats = GameInstance.GetStatsSystem( GetPuppet().GetGame() );
		if( stats.GetStatValue( puppetID, gamedataStatType.IsDeflecting ) == 1.0 )
		{
			statFlag = RPGManager.CreateStatModifier( gamedataStatType.IsDeflecting, gameStatModifierType.Additive, -1.0 );
			stats.AddModifier( puppetID, statFlag );
		}
	}

	private function UpdateHitReactionsExceptionState()
	{
		var statSystem : StatsSystem;
		var entityID : EntityID;
		statSystem = GameInstance.GetStatsSystem( GetOwner().GetGame() );
		entityID = GetOwner().GetEntityID();
		GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.HitReactionMode, ( ( Int32 )( GetCurrentHitReactionModeState() ) ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_bulkyStaggerMinRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_staggerMinRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_unstoppableRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_unstoppableTwitchMinRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_unstoppableTwitchNoneRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_forceImpactRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_forceStaggerRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_forceKnockdownRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_fragileRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_weakRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_toughRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_bulkyRecordID ) );
		statSystem.RemoveModifierGroup( entityID, TDBID.ToNumber( m_regularRecordID ) );
		switch( GetCurrentHitReactionModeState() )
		{
			case EHitReactionMode.BulkyStaggerMin:
				OnBulkyStaggerMin( statSystem, entityID, m_bulkyStaggerMinRecordID );
			break;
			case EHitReactionMode.StaggerMin:
				OnStaggerMin( statSystem, entityID, m_staggerMinRecordID );
			break;
			case EHitReactionMode.Unstoppable:
				OnUnstoppable( statSystem, entityID, m_unstoppableRecordID );
			break;
			case EHitReactionMode.UnstoppableTwitchMin:
				OnUnstoppableTwitchMin( statSystem, entityID, m_unstoppableTwitchMinRecordID );
			break;
			case EHitReactionMode.UnstoppableTwitchNone:
				OnUnstoppableTwitchNone( statSystem, entityID, m_unstoppableTwitchNoneRecordID );
			break;
			case EHitReactionMode.ForceImpact:
				OnForceImpact( statSystem, entityID, m_forceImpactRecordID );
			break;
			case EHitReactionMode.ForceStagger:
				OnForceStagger( statSystem, entityID, m_forceStaggerRecordID );
			break;
			case EHitReactionMode.ForceKnockdown:
				OnForceKnockdown( statSystem, entityID, m_forceKnockdownRecordID );
			break;
			case EHitReactionMode.Fragile:
				OnFragile( statSystem, entityID, m_fragileRecordID );
			break;
			case EHitReactionMode.Weak:
				OnWeak( statSystem, entityID, m_weakRecordID );
			break;
			case EHitReactionMode.Tough:
				OnTough( statSystem, entityID, m_toughRecordID );
			break;
			case EHitReactionMode.Bulky:
				OnBulky( statSystem, entityID, m_bulkyRecordID );
			break;
			case EHitReactionMode.Regular:
				OnRegular( statSystem, entityID, m_regularRecordID );
			break;
			default:
				break;
		}
		if( GetPreviousHitReactionMode() == EHitReactionMode.Unstoppable && GetCurrentHitReactionModeState() != EHitReactionMode.Unstoppable )
		{
			SendOnUnstoppableRemovedSignal( false );
		}
	}

	private function SendOnUnstoppableRemovedSignal( b : Bool )
	{
		var signalTable : gameBoolSignalTable;
		var signalId : Uint16;
		signalTable = ( ( NPCPuppet )( GetOwner() ) ).GetAIControllerComponent().GetSignals();
		if( !( signalTable ) )
		{
			return;
		}
		signalId = signalTable.GetOrCreateSignal( 'OnUnstoppableStateSignal' );
		signalTable.Set( signalId, b );
	}

	private function OnRegular( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
		AnimationControllerComponent.SetInputFloat( ( ( NPCPuppet )( GetOwner() ) ), 'twitch_hit_scale', 0.80000001 );
	}

	private function OnForceImpact( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function OnForceStagger( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function OnForceKnockdown( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function OnFragile( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function OnWeak( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function OnTough( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function OnBulky( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function OnUnstoppable( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
		SendOnUnstoppableRemovedSignal( true );
	}

	private function OnUnstoppableTwitchMin( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
		AnimationControllerComponent.SetInputFloat( ( ( NPCPuppet )( GetOwner() ) ), 'twitch_hit_scale', 0.1 );
	}

	private function OnUnstoppableTwitchNone( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
		AnimationControllerComponent.SetInputFloat( ( ( NPCPuppet )( GetOwner() ) ), 'twitch_hit_scale', 0.0 );
	}

	private function OnStaggerMin( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function OnBulkyStaggerMin( statSystem : StatsSystem, entityID : EntityID, recordID : TweakDBID )
	{
		var tdbId : Uint64;
		tdbId = TDBID.ToNumber( recordID );
		statSystem.DefineModifierGroupFromRecord( tdbId, recordID );
		statSystem.ApplyModifierGroup( entityID, tdbId );
	}

	private function UpdateStanceState()
	{
		var stateAnimFeature : AnimFeature_NPCState;
		stateAnimFeature = new AnimFeature_NPCState;
		stateAnimFeature.state = ( ( Int32 )( GetCurrentStanceState() ) );
		AnimationControllerComponent.ApplyFeature( GetOwner(), m_stanceAnimFeatureName, stateAnimFeature );
		GetPuppetStateBlackboard().SetInt( GetAllBlackboardDefs().PuppetState.Stance, ( ( Int32 )( GetCurrentStanceState() ) ) );
		OnStanceStateChanged();
		switch( GetCurrentStanceState() )
		{
			case gamedataNPCStanceState.Stand:
				OnStand();
			break;
			case gamedataNPCStanceState.Crouch:
				OnCrouch();
			break;
			case gamedataNPCStanceState.Cover:
				OnCover();
			break;
			case gamedataNPCStanceState.Swim:
				OnSwim();
			break;
			case gamedataNPCStanceState.Vehicle:
				OnVehicle();
			break;
			default:
				break;
		}
		SetPreviousStanceState( GetCurrentStanceState() );
	}

	private function OnStanceStateChanged()
	{
		var stanceStateChangeEvent : StanceStateChangeEvent;
		var previousAnimWrapper : CName;
		var currentAnimWrapper : CName;
		previousAnimWrapper = GetAnimWrapperNameBasedOnStanceState( GetPreviousStanceState() );
		currentAnimWrapper = GetAnimWrapperNameBasedOnStanceState( GetCurrentStanceState() );
		if( IsNameValid( previousAnimWrapper ) && previousAnimWrapper != currentAnimWrapper )
		{
			AnimationControllerComponent.SetAnimWrapperWeightOnOwnerAndItems( GetOwner(), previousAnimWrapper, 0.0 );
		}
		AnimationControllerComponent.SetAnimWrapperWeightOnOwnerAndItems( GetOwner(), currentAnimWrapper, 1.0 );
		stanceStateChangeEvent = new StanceStateChangeEvent;
		stanceStateChangeEvent.state = GetCurrentStanceState();
		GetOwner().QueueEvent( stanceStateChangeEvent );
		if( GetCurrentStanceState() == gamedataNPCStanceState.VehicleWindow )
		{
			ToggleVehicleWindow( true );
		}
		else if( GetPreviousStanceState() == gamedataNPCStanceState.VehicleWindow )
		{
			ToggleVehicleWindow( false );
		}
	}

	private function ToggleVehicleWindow( toggle : Bool )
	{
		var mountInfo : MountingInfo;
		var vehicle : weak< VehicleObject >;
		mountInfo = GameInstance.GetMountingFacility( GetOwner().GetGame() ).GetMountingInfoSingleWithObjects( GetOwner() );
		vehicle = ( ( VehicleObject )( GameInstance.FindEntityByID( GetOwner().GetGame(), mountInfo.parentId ) ) );
		VehicleComponent.ToggleVehicleWindow( GetOwner().GetGame(), vehicle, mountInfo.slotId, toggle, 'Fast' );
	}

	private function OnStand() {}

	private function OnCrouch() {}

	private function OnCover() {}

	private function OnSwim() {}

	private function OnVehicle() {}
}

class NotifySecuritySystemCombatEvent extends Event
{
}

class NotifyNearbyAboutCombatEvent extends Event
{
}

