class PlayerVisionModeControllerInvalidateEvent extends Event
{
	var m_active : Bool;
}

struct PlayerVisionModeControllerInputListeners
{
	var m_buttonHold : Uint32;
	var m_buttonToggle : Uint32;
	var m_driverCombatButtonHold : Uint32;
	var m_driverCombatButtonActivate : Uint32;
}

struct PlayerVisionModeControllerInputActionsNames
{
	var m_buttonHold : CName;
	var m_buttonToggle : CName;
	var m_driverCombatButtonHold : CName;
	var m_driverCombatButtonActivate : CName;
}

struct PlayerVisionModeControllerInputActiveFlags
{
	var m_buttonHold : Bool;
	var m_buttonToggle : Bool;
	var m_driverCombatButtonHold : Bool;
	var m_driverCombatButtonActivate : Bool;
}

struct PlayerVisionModeControllerBBListeners
{
	var m_kerenzikov : CallbackHandle;
	var m_restrictedScene : CallbackHandle;
	var m_dead : CallbackHandle;
	var m_takedown : CallbackHandle;
	var m_deviceTakeover : CallbackHandle;
	var m_braindanceFPP : CallbackHandle;
	var m_braindanceActive : CallbackHandle;
	var m_veryHardLanding : CallbackHandle;
	var m_isBriefingActive : CallbackHandle;
}

struct PlayerVisionModeControllerBlackboardListenersFunctions
{
	var m_kerenzikov : CName;
	var m_restrictedScene : CName;
	var m_dead : CName;
	var m_takedown : CName;
	var m_deviceTakeover : CName;
	var m_braindanceFPP : CName;
	var m_braindanceActive : CName;
	var m_veryHardLanding : CName;
	var m_isBriefingActive : CName;
}

struct PlayerVisionModeControllerBBIds
{
	var m_kerenzikov : BlackboardDefinition;
	var m_restrictedScene : BlackboardDefinition;
	var m_dead : BlackboardDefinition;
	var m_takedown : BlackboardDefinition;
	var m_deviceTakeover : BlackboardDefinition;
	var m_braindanceFPP : BlackboardDefinition;
	var m_braindanceActive : BlackboardDefinition;
	var m_veryHardLanding : BlackboardDefinition;
	var m_isBriefingActive : BlackboardDefinition;
}

struct PlayerVisionModeControllerBBValuesIds
{
	var m_kerenzikov : BlackboardID_Int;
	var m_restrictedScene : BlackboardID_Int;
	var m_dead : BlackboardID_Int;
	var m_takedown : BlackboardID_Int;
	var m_deviceTakeover : BlackboardID_EntityID;
	var m_braindanceFPP : BlackboardID_Bool;
	var m_braindanceActive : BlackboardID_Bool;
	var m_veryHardLanding : BlackboardID_Int;
	var m_isBriefingActive : BlackboardID_Bool;
}

struct PlayerVisionModeControllerActiveFlags
{
	var m_kerenzikov : Bool;
	var m_restrictedScene : Bool;
	var m_dead : Bool;
	var m_takedown : Bool;
	var m_deviceTakeover : Bool;
	var m_braindanceFPP : Bool;
	var m_braindanceActive : Bool;
	var m_veryHardLanding : Bool;
	var m_noScanningRestriction : Bool;
	var m_hasNotCybereye : Bool;
	var m_isPhotoMode : Bool;
	var m_isBriefingActive : Bool;
}

enum PlayerVisionModeControllerRefreshPolicyEnum
{
	Persistent = 0,
	Eventful = 1,
}

struct PlayerVisionModeControllerRefreshPolicy
{
	var m_kerenzikov : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_restrictedScene : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_dead : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_takedown : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_deviceTakeover : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_braindanceFPP : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_braindanceActive : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_veryHardLanding : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_noScanningRestriction : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_hasNotCybereye : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_isPhotoMode : PlayerVisionModeControllerRefreshPolicyEnum;
	var m_isBriefingActive : PlayerVisionModeControllerRefreshPolicyEnum;
}

struct PlayerVisionModeControllerOtherVars
{
	var m_enabledByToggle : Bool;
	var m_active : Bool;
	var m_toggledDuringHold : Bool;
	var m_buttonHoldPressTime : Float;
	default m_buttonHoldPressTime = 0.0f;
	var m_buttonHoldTapTime : Float;
	default m_buttonHoldTapTime = 0.0f;
	var m_buttonHoldTapCount : Int32;
	default m_buttonHoldTapCount = 0;
}

class PlayerVisionModeController extends IScriptable
{

	public function OnEnablePhotoMode( enable : Bool )
	{
		m_gameplayActiveFlags.m_isPhotoMode = !( enable );
	}

	public function RegisterOwner( owner : GameObject )
	{
		if( m_owner != NULL )
		{
			UnregisterBlackboardListeners();
		}
		m_owner = owner;
		if( owner != NULL )
		{
			InitInputActionsNames();
			RegisterInputListeners();
			InitPlayerVisionModeControllerRefreshPolicy();
			InitBlackboardIds();
			InitBlackboardValuesIds();
			InitBlackboardFunctions();
			RegisterBlackboardListeners();
			UpdateNoScanningRestriction();
			UpdateBlackboardValues();
		}
	}

	public function UnregisterOwner()
	{
		if( m_owner == NULL )
		{
		}
		else
		{
			UnregisterInputListeners();
			UnregisterBlackboardListeners();
		}
		m_owner = NULL;
	}

	public function OnInvalidateActiveState( evt : PlayerVisionModeControllerInvalidateEvent )
	{
		if( m_otherVars.m_active != evt.m_active )
		{
			m_otherVars.m_active = evt.m_active;
			if( evt.m_active )
			{
				ActivateVisionMode();
			}
			else
			{
				DeactivateVisionMode();
			}
		}
		ProcessFlagsRefreshPolicy();
	}

	private function InitInputActionsNames()
	{
		m_inputActionsNames.m_buttonHold = 'VisionHold';
		m_inputActionsNames.m_buttonToggle = 'VisionToggle';
		m_inputActionsNames.m_driverCombatButtonHold = 'DriverCombatVisionHold';
		m_inputActionsNames.m_driverCombatButtonActivate = 'DriverCombatControllerActivateVisionHold';
	}

	private function RegisterInputListeners()
	{
		m_owner.RegisterInputListener( this, 'VisionHold' );
		m_owner.RegisterInputListener( this, 'VisionToggle' );
		m_owner.RegisterInputListener( this, 'DriverCombatVisionHold' );
		m_owner.RegisterInputListener( this, 'DriverCombatControllerActivateVisionHold' );
	}

	private function InitPlayerVisionModeControllerRefreshPolicy()
	{
		m_gameplayActiveFlagsRefreshPolicy.m_kerenzikov = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
		m_gameplayActiveFlagsRefreshPolicy.m_restrictedScene = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
		m_gameplayActiveFlagsRefreshPolicy.m_dead = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
		m_gameplayActiveFlagsRefreshPolicy.m_takedown = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
		m_gameplayActiveFlagsRefreshPolicy.m_deviceTakeover = PlayerVisionModeControllerRefreshPolicyEnum.Eventful;
		m_gameplayActiveFlagsRefreshPolicy.m_braindanceFPP = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
		m_gameplayActiveFlagsRefreshPolicy.m_braindanceActive = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
		m_gameplayActiveFlagsRefreshPolicy.m_veryHardLanding = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
		m_gameplayActiveFlagsRefreshPolicy.m_noScanningRestriction = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
		m_gameplayActiveFlagsRefreshPolicy.m_isBriefingActive = PlayerVisionModeControllerRefreshPolicyEnum.Persistent;
	}

	private function InitBlackboardIds()
	{
		m_blackboardIds.m_kerenzikov = GetAllBlackboardDefs().PlayerStateMachine;
		m_blackboardIds.m_restrictedScene = GetAllBlackboardDefs().PlayerStateMachine;
		m_blackboardIds.m_dead = GetAllBlackboardDefs().PlayerStateMachine;
		m_blackboardIds.m_takedown = GetAllBlackboardDefs().PlayerStateMachine;
		m_blackboardIds.m_deviceTakeover = GetAllBlackboardDefs().DeviceTakeControl;
		m_blackboardIds.m_braindanceFPP = GetAllBlackboardDefs().Braindance;
		m_blackboardIds.m_braindanceActive = GetAllBlackboardDefs().Braindance;
		m_blackboardIds.m_veryHardLanding = GetAllBlackboardDefs().PlayerStateMachine;
		m_blackboardIds.m_isBriefingActive = GetAllBlackboardDefs().UIGameData;
	}

	private function InitBlackboardValuesIds()
	{
		m_blackboardValuesIds.m_kerenzikov = GetAllBlackboardDefs().PlayerStateMachine.Locomotion;
		m_blackboardValuesIds.m_restrictedScene = GetAllBlackboardDefs().PlayerStateMachine.HighLevel;
		m_blackboardValuesIds.m_dead = GetAllBlackboardDefs().PlayerStateMachine.Vitals;
		m_blackboardValuesIds.m_takedown = GetAllBlackboardDefs().PlayerStateMachine.Takedown;
		m_blackboardValuesIds.m_deviceTakeover = GetAllBlackboardDefs().DeviceTakeControl.ActiveDevice;
		m_blackboardValuesIds.m_braindanceFPP = GetAllBlackboardDefs().Braindance.IsFPP;
		m_blackboardValuesIds.m_braindanceActive = GetAllBlackboardDefs().Braindance.IsActive;
		m_blackboardValuesIds.m_veryHardLanding = GetAllBlackboardDefs().PlayerStateMachine.Landing;
		m_blackboardValuesIds.m_isBriefingActive = GetAllBlackboardDefs().UIGameData.IsBriefingActive;
	}

	private function InitBlackboardFunctions()
	{
		m_blackboardListenersFunctions.m_kerenzikov = 'OnKerenzikovChanged';
		m_blackboardListenersFunctions.m_restrictedScene = 'OnRestrictedSceneChanged';
		m_blackboardListenersFunctions.m_dead = 'OnDeadChanged';
		m_blackboardListenersFunctions.m_takedown = 'OnTakedownChanged';
		m_blackboardListenersFunctions.m_deviceTakeover = 'OnDeviceTakeoverChanged';
		m_blackboardListenersFunctions.m_braindanceFPP = 'OnBraindanceFPPChanged';
		m_blackboardListenersFunctions.m_braindanceActive = 'OnBraindanceActiveChanged';
		m_blackboardListenersFunctions.m_veryHardLanding = 'OnVeryHardLandingChanged';
		m_blackboardListenersFunctions.m_isBriefingActive = 'OnBriefingChange';
	}

	private function RegisterBlackboardListeners()
	{
		var blackboardSystem : BlackboardSystem;
		if( m_owner != NULL )
		{
			blackboardSystem = GameInstance.GetBlackboardSystem( m_owner.GetGame() );
		}
		if( blackboardSystem != NULL )
		{
			m_blackboardListeners.m_kerenzikov = blackboardSystem.GetLocalInstanced( m_owner.GetEntityID(), m_blackboardIds.m_kerenzikov ).RegisterListenerInt( m_blackboardValuesIds.m_kerenzikov, this, m_blackboardListenersFunctions.m_kerenzikov );
			m_blackboardListeners.m_restrictedScene = blackboardSystem.GetLocalInstanced( m_owner.GetEntityID(), m_blackboardIds.m_restrictedScene ).RegisterListenerInt( m_blackboardValuesIds.m_restrictedScene, this, m_blackboardListenersFunctions.m_restrictedScene );
			m_blackboardListeners.m_dead = blackboardSystem.GetLocalInstanced( m_owner.GetEntityID(), m_blackboardIds.m_dead ).RegisterListenerInt( m_blackboardValuesIds.m_dead, this, m_blackboardListenersFunctions.m_dead );
			m_blackboardListeners.m_takedown = blackboardSystem.GetLocalInstanced( m_owner.GetEntityID(), m_blackboardIds.m_takedown ).RegisterListenerInt( m_blackboardValuesIds.m_takedown, this, m_blackboardListenersFunctions.m_takedown );
			m_blackboardListeners.m_deviceTakeover = blackboardSystem.Get( m_blackboardIds.m_deviceTakeover ).RegisterListenerEntityID( m_blackboardValuesIds.m_deviceTakeover, this, m_blackboardListenersFunctions.m_deviceTakeover );
			m_blackboardListeners.m_braindanceFPP = blackboardSystem.Get( m_blackboardIds.m_braindanceFPP ).RegisterListenerBool( m_blackboardValuesIds.m_braindanceFPP, this, m_blackboardListenersFunctions.m_braindanceFPP );
			m_blackboardListeners.m_braindanceActive = blackboardSystem.Get( m_blackboardIds.m_braindanceActive ).RegisterListenerBool( m_blackboardValuesIds.m_braindanceActive, this, m_blackboardListenersFunctions.m_braindanceActive );
			m_blackboardListeners.m_veryHardLanding = blackboardSystem.GetLocalInstanced( m_owner.GetEntityID(), m_blackboardIds.m_veryHardLanding ).RegisterListenerInt( m_blackboardValuesIds.m_veryHardLanding, this, m_blackboardListenersFunctions.m_veryHardLanding );
			m_blackboardListeners.m_isBriefingActive = blackboardSystem.Get( m_blackboardIds.m_isBriefingActive ).RegisterListenerBool( m_blackboardValuesIds.m_isBriefingActive, this, m_blackboardListenersFunctions.m_isBriefingActive );
		}
		else
		{
		}
	}

	private function UnregisterInputListeners()
	{
		m_owner.UnregisterInputListener( this );
	}

	private function UnregisterBlackboardListeners()
	{
		var blackboardSystem : BlackboardSystem;
		blackboardSystem = GameInstance.GetBlackboardSystem( m_owner.GetGame() );
		blackboardSystem.Get( m_blackboardIds.m_kerenzikov ).UnregisterListenerInt( m_blackboardValuesIds.m_kerenzikov, m_blackboardListeners.m_kerenzikov );
		blackboardSystem.Get( m_blackboardIds.m_restrictedScene ).UnregisterListenerInt( m_blackboardValuesIds.m_restrictedScene, m_blackboardListeners.m_restrictedScene );
		blackboardSystem.Get( m_blackboardIds.m_dead ).UnregisterListenerInt( m_blackboardValuesIds.m_dead, m_blackboardListeners.m_dead );
		blackboardSystem.Get( m_blackboardIds.m_takedown ).UnregisterListenerInt( m_blackboardValuesIds.m_takedown, m_blackboardListeners.m_takedown );
		blackboardSystem.Get( m_blackboardIds.m_deviceTakeover ).UnregisterListenerEntityID( m_blackboardValuesIds.m_deviceTakeover, m_blackboardListeners.m_deviceTakeover );
		blackboardSystem.Get( m_blackboardIds.m_braindanceFPP ).UnregisterListenerBool( m_blackboardValuesIds.m_braindanceFPP, m_blackboardListeners.m_braindanceFPP );
		blackboardSystem.Get( m_blackboardIds.m_braindanceActive ).UnregisterListenerBool( m_blackboardValuesIds.m_braindanceActive, m_blackboardListeners.m_braindanceActive );
		blackboardSystem.Get( m_blackboardIds.m_veryHardLanding ).UnregisterListenerInt( m_blackboardValuesIds.m_veryHardLanding, m_blackboardListeners.m_veryHardLanding );
		blackboardSystem.Get( m_blackboardIds.m_isBriefingActive ).UnregisterListenerBool( m_blackboardValuesIds.m_isBriefingActive, m_blackboardListeners.m_isBriefingActive );
	}

	private function VerifyActivation()
	{
		var inputActive : Bool;
		var forced : Bool;
		var active : Bool;
		var isScannerVisibility : worlduiEntryVisibility;
		var isScannerForceHidden : Bool;
		inputActive = ( ( !( m_inputActiveFlags.m_driverCombatButtonHold ) && m_inputActiveFlags.m_buttonHold ) || m_inputActiveFlags.m_buttonToggle ) || ( m_inputActiveFlags.m_driverCombatButtonHold && m_inputActiveFlags.m_driverCombatButtonActivate );
		forced = m_gameplayActiveFlags.m_braindanceActive && !( m_gameplayActiveFlags.m_braindanceFPP );
		m_gameplayActiveFlags.m_hasNotCybereye = !( RPGManager.HasStatFlag( m_owner, gamedataStatType.HasCybereye ) );
		m_gameplayActiveFlags.m_isPhotoMode = GameInstance.GetPhotoModeSystem( m_owner.GetGame() ).IsPhotoModeActive();
		isScannerVisibility = GameInstance.GetUISystem( m_owner.GetGame() ).GetHudEntryForcedVisibility( 'scanner' );
		isScannerForceHidden = isScannerVisibility == worlduiEntryVisibility.ForceHide;
		if( !( forced ) && ( ( ( ( ( ( ( ( ( ( ( ( !( inputActive ) || m_gameplayActiveFlags.m_kerenzikov ) || m_gameplayActiveFlags.m_restrictedScene ) || m_gameplayActiveFlags.m_dead ) || m_gameplayActiveFlags.m_takedown ) || m_gameplayActiveFlags.m_deviceTakeover ) || m_gameplayActiveFlags.m_braindanceActive ) || m_gameplayActiveFlags.m_isBriefingActive ) || m_gameplayActiveFlags.m_veryHardLanding ) || m_gameplayActiveFlags.m_noScanningRestriction ) || m_gameplayActiveFlags.m_hasNotCybereye ) || m_gameplayActiveFlags.m_isPhotoMode ) || isScannerForceHidden ) )
		{
			active = false;
		}
		else
		{
			active = true;
		}
		InvalidateActivationState( active );
	}

	private function ActivateVisionMode()
	{
		GameInstance.GetVisionModeSystem( m_owner.GetGame() ).GetScanningController().EnterMode( m_owner, gameScanningMode.Heavy );
		if( !( m_owner.GetHudManager().IsQuickHackPanelOpened() ) )
		{
			GameInstance.GetTargetingSystem( m_owner.GetGame() ).AimSnap( m_owner );
		}
		SendPSMBoolParameter( 'InterruptSprint', true, gamestateMachineParameterAspect.Temporary );
		SendPSMBoolParameter( 'OnInterruptSprintFail_BlockSprintStartOnce', true, gamestateMachineParameterAspect.Conditional );
		ApplyFocusModeLocomotionRestriction();
		GameInstance.GetVisionModeSystem( m_owner.GetGame() ).EnterMode( m_owner, gameVisionModeType.Focus );
		SetBlackboardIntVariable( GetAllBlackboardDefs().PlayerStateMachine, GetAllBlackboardDefs().PlayerStateMachine.Vision, ( ( Int32 )( gamePSMVision.Focus ) ) );
		SetFocusModeAnimFeature( true );
		SetupLockToggleInput();
		SetupLockHoldInput();
		GameInstance.GetAudioSystem( m_owner.GetGame() ).NotifyGameTone( 'Scanning' );
		m_otherVars.m_enabledByToggle = m_inputActiveFlags.m_buttonToggle;
	}

	private function DeactivateVisionMode()
	{
		GameInstance.GetVisionModeSystem( m_owner.GetGame() ).EnterMode( m_owner, gameVisionModeType.Default );
		GameInstance.GetVisionModeSystem( m_owner.GetGame() ).GetScanningController().EnterMode( m_owner, gameScanningMode.Inactive );
		SetBlackboardIntVariable( GetAllBlackboardDefs().PlayerStateMachine, GetAllBlackboardDefs().PlayerStateMachine.Vision, ( ( Int32 )( gamePSMVision.Default ) ) );
		SendPSMBoolParameter( 'VisionToggled', false, gamestateMachineParameterAspect.Temporary );
		SendPSMBoolParameter( 'ReevaluateAiming', true, gamestateMachineParameterAspect.Temporary );
		SendPSMBoolParameter( 'OnInterruptSprintFail_BlockSprintStartOnce', false, gamestateMachineParameterAspect.Conditional );
		SetFocusModeAnimFeature( false );
		SetupLockToggleInput();
		GameInstance.GetAudioSystem( m_owner.GetGame() ).NotifyGameTone( 'NotScanning' );
		GameInstance.GetTargetingSystem( m_owner.GetGame() ).BreakAimSnap( m_owner );
		RemoveFocusModeLocomotionRestriction();
		m_otherVars.m_enabledByToggle = false;
		m_otherVars.m_toggledDuringHold = false;
	}

	private function ProcessFlagsRefreshPolicy()
	{
		if( m_gameplayActiveFlagsRefreshPolicy.m_kerenzikov == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_kerenzikov = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_restrictedScene == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_restrictedScene = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_dead == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_dead = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_takedown == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_takedown = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_deviceTakeover == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_deviceTakeover = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_braindanceFPP == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_braindanceFPP = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_braindanceActive == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_braindanceActive = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_veryHardLanding == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_veryHardLanding = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_noScanningRestriction == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_noScanningRestriction = false;
		}
		if( m_gameplayActiveFlagsRefreshPolicy.m_isBriefingActive == PlayerVisionModeControllerRefreshPolicyEnum.Eventful )
		{
			m_gameplayActiveFlags.m_isBriefingActive = false;
		}
	}


	private var m_gameplayActiveFlagsRefreshPolicy : PlayerVisionModeControllerRefreshPolicy;
	private var m_blackboardIds : PlayerVisionModeControllerBBIds;
	private var m_blackboardValuesIds : PlayerVisionModeControllerBBValuesIds;
	private var m_blackboardListenersFunctions : PlayerVisionModeControllerBlackboardListenersFunctions;
	private var m_blackboardListeners : PlayerVisionModeControllerBBListeners;
	private var m_gameplayActiveFlags : PlayerVisionModeControllerActiveFlags;
	private var m_inputActionsNames : PlayerVisionModeControllerInputActionsNames;
	private var m_inputListeners : PlayerVisionModeControllerInputListeners;
	private var m_inputActiveFlags : PlayerVisionModeControllerInputActiveFlags;
	private var m_otherVars : PlayerVisionModeControllerOtherVars;
	private var m_owner : weak< GameObject >;

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		var time : Float;
		var evt : ToggleNewPlayerFlashlightEvent;
		time = EngineTime.ToFloat( GameInstance.GetEngineTime( m_owner.GetGame() ) );
		if( ListenerAction.GetName( action ) == m_inputActionsNames.m_buttonToggle )
		{
			if( ListenerAction.GetValue( action ) > 0.0 )
			{
				if( m_otherVars.m_enabledByToggle )
				{
					m_inputActiveFlags.m_buttonToggle = !( m_inputActiveFlags.m_buttonToggle );
				}
				else
				{
					m_inputActiveFlags.m_buttonToggle = !( m_inputActiveFlags.m_buttonToggle );
				}
				if( m_inputActiveFlags.m_buttonToggle && m_inputActiveFlags.m_buttonHold )
				{
					m_otherVars.m_toggledDuringHold = true;
				}
			}
			VerifyActivation();
		}
		else if( ListenerAction.GetName( action ) == m_inputActionsNames.m_buttonHold )
		{
			if( !( IsFinal() ) )
			{
				if( ListenerAction.IsButtonJustPressed( action ) )
				{
					m_otherVars.m_buttonHoldPressTime = time;
					if( time >= ( m_otherVars.m_buttonHoldTapTime + 0.2 ) )
					{
						m_otherVars.m_buttonHoldTapCount = 0;
					}
					if( ( m_otherVars.m_buttonHoldTapCount % 2 ) == 1 )
					{
						evt = new ToggleNewPlayerFlashlightEvent;
						GetPlayer( m_owner.GetGame() ).QueueEvent( evt );
						return true;
					}
				}
				else if( ListenerAction.IsButtonJustReleased( action ) && ( time < ( m_otherVars.m_buttonHoldPressTime + 0.2 ) ) )
				{
					m_otherVars.m_buttonHoldTapTime = time;
					m_otherVars.m_buttonHoldTapCount += 1;
				}
			}
			if( ListenerAction.GetValue( action ) > 0.0 )
			{
				m_inputActiveFlags.m_buttonHold = true;
				m_otherVars.m_toggledDuringHold = false;
			}
			else
			{
				m_inputActiveFlags.m_buttonHold = false;
				if( !( m_otherVars.m_toggledDuringHold ) )
				{
					m_inputActiveFlags.m_buttonToggle = false;
				}
			}
			VerifyActivation();
		}
		else if( ListenerAction.GetName( action ) == m_inputActionsNames.m_driverCombatButtonHold )
		{
			if( ListenerAction.GetType( action ) == gameinputActionType.BUTTON_PRESSED )
			{
				if( IsPlayerInDriverCombat() )
				{
					m_inputActiveFlags.m_driverCombatButtonHold = true;
				}
			}
			else if( ListenerAction.GetType( action ) == gameinputActionType.BUTTON_RELEASED )
			{
				m_inputActiveFlags.m_driverCombatButtonHold = false;
				m_inputActiveFlags.m_driverCombatButtonActivate = false;
			}
			VerifyActivation();
		}
		else if( ListenerAction.GetName( action ) == m_inputActionsNames.m_driverCombatButtonActivate )
		{
			if( ListenerAction.IsButtonJustPressed( action ) )
			{
				if( m_inputActiveFlags.m_driverCombatButtonHold )
				{
					m_inputActiveFlags.m_driverCombatButtonActivate = true;
				}
			}
			VerifyActivation();
		}
	}

	public function ForceInputOff()
	{
		m_inputActiveFlags.m_buttonToggle = false;
		m_inputActiveFlags.m_buttonHold = false;
		m_inputActiveFlags.m_driverCombatButtonHold = false;
		m_inputActiveFlags.m_driverCombatButtonActivate = false;
		VerifyActivation();
	}

	protected event OnKerenzikovChanged( value : Int32 )
	{
		if( value == ( ( Int32 )( gamePSMLocomotionStates.Kereznikov ) ) )
		{
			m_gameplayActiveFlags.m_kerenzikov = true;
		}
		else
		{
			m_gameplayActiveFlags.m_kerenzikov = false;
		}
		VerifyActivation();
	}

	protected event OnRestrictedSceneChanged( value : Int32 )
	{
		if( ( value >= ( ( Int32 )( gamePSMHighLevel.SceneTier4 ) ) ) && ( value <= ( ( Int32 )( gamePSMHighLevel.SceneTier5 ) ) ) )
		{
			m_gameplayActiveFlags.m_restrictedScene = true;
		}
		else
		{
			m_gameplayActiveFlags.m_restrictedScene = false;
		}
		VerifyActivation();
	}

	protected event OnDeadChanged( value : Int32 )
	{
		if( value == ( ( Int32 )( gamePSMVitals.Dead ) ) )
		{
			m_gameplayActiveFlags.m_dead = true;
		}
		else
		{
			m_gameplayActiveFlags.m_dead = false;
		}
		VerifyActivation();
	}

	protected event OnTakedownChanged( value : Int32 )
	{
		if( value == ( ( Int32 )( gamePSMTakedown.Takedown ) ) )
		{
			m_gameplayActiveFlags.m_takedown = true;
		}
		else
		{
			m_gameplayActiveFlags.m_takedown = false;
		}
		VerifyActivation();
	}

	protected event OnDeviceTakeoverChanged( value : EntityID )
	{
		var empty : EntityID;
		if( value != empty )
		{
			m_gameplayActiveFlags.m_deviceTakeover = true;
		}
		else
		{
			m_gameplayActiveFlags.m_deviceTakeover = false;
		}
		VerifyActivation();
	}

	protected event OnBraindanceFPPChanged( value : Bool )
	{
		m_gameplayActiveFlags.m_braindanceFPP = value;
		VerifyActivation();
	}

	protected event OnBraindanceActiveChanged( value : Bool )
	{
		m_gameplayActiveFlags.m_braindanceActive = value;
		VerifyActivation();
	}

	protected event OnBriefingChange( value : Bool )
	{
		m_gameplayActiveFlags.m_isBriefingActive = value;
		VerifyActivation();
	}

	protected event OnVeryHardLandingChanged( value : Int32 )
	{
		if( value == ( ( Int32 )( gamePSMLandingState.VeryHardLand ) ) )
		{
			m_gameplayActiveFlags.m_veryHardLanding = true;
		}
		else
		{
			m_gameplayActiveFlags.m_veryHardLanding = false;
		}
		VerifyActivation();
	}

	public function UpdateNoScanningRestriction()
	{
		var hasNoScanningRestriction : Bool;
		hasNoScanningRestriction = StatusEffectSystem.ObjectHasStatusEffectWithTag( m_owner, 'NoScanning' );
		if( hasNoScanningRestriction != m_gameplayActiveFlags.m_noScanningRestriction )
		{
			m_gameplayActiveFlags.m_noScanningRestriction = hasNoScanningRestriction;
			VerifyActivation();
		}
	}

	private function UpdateBlackboardValues()
	{
		var blackboardSystem : BlackboardSystem;
		var takeoverDevice : EntityID;
		var empty : EntityID;
		blackboardSystem = GameInstance.GetBlackboardSystem( m_owner.GetGame() );
		m_gameplayActiveFlags.m_kerenzikov = blackboardSystem.Get( m_blackboardIds.m_kerenzikov ).GetInt( m_blackboardValuesIds.m_kerenzikov );
		m_gameplayActiveFlags.m_restrictedScene = blackboardSystem.Get( m_blackboardIds.m_restrictedScene ).GetInt( m_blackboardValuesIds.m_restrictedScene );
		m_gameplayActiveFlags.m_dead = blackboardSystem.Get( m_blackboardIds.m_dead ).GetInt( m_blackboardValuesIds.m_dead );
		m_gameplayActiveFlags.m_takedown = blackboardSystem.Get( m_blackboardIds.m_takedown ).GetInt( m_blackboardValuesIds.m_takedown );
		m_gameplayActiveFlags.m_braindanceFPP = blackboardSystem.Get( m_blackboardIds.m_braindanceFPP ).GetBool( m_blackboardValuesIds.m_braindanceFPP );
		m_gameplayActiveFlags.m_braindanceActive = blackboardSystem.Get( m_blackboardIds.m_braindanceActive ).GetBool( m_blackboardValuesIds.m_braindanceActive );
		m_gameplayActiveFlags.m_veryHardLanding = blackboardSystem.Get( m_blackboardIds.m_veryHardLanding ).GetInt( m_blackboardValuesIds.m_veryHardLanding );
		m_gameplayActiveFlags.m_isBriefingActive = blackboardSystem.Get( m_blackboardIds.m_isBriefingActive ).GetBool( m_blackboardValuesIds.m_isBriefingActive );
		takeoverDevice = blackboardSystem.Get( m_blackboardIds.m_deviceTakeover ).GetEntityID( m_blackboardValuesIds.m_deviceTakeover );
		if( takeoverDevice != empty )
		{
			m_gameplayActiveFlags.m_deviceTakeover = true;
		}
		else
		{
			m_gameplayActiveFlags.m_deviceTakeover = false;
		}
	}

	private function InvalidateActivationState( active : Bool )
	{
		var invalidateEvent : PlayerVisionModeControllerInvalidateEvent;
		invalidateEvent = new PlayerVisionModeControllerInvalidateEvent;
		invalidateEvent.m_active = active;
		m_owner.QueueEvent( invalidateEvent );
	}

	private function ApplyFocusModeLocomotionRestriction()
	{
		StatusEffectHelper.ApplyStatusEffect( m_owner, T"GameplayRestriction.FocusModeLocomotion" );
	}

	private function SetBlackboardIntVariable( definition : BlackboardDefinition, id : BlackboardID_Int, value : Int32 )
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		blackboardSystem = GameInstance.GetBlackboardSystem( m_owner.GetGame() );
		blackboard = blackboardSystem.GetLocalInstanced( m_owner.GetEntityID(), definition );
		if( blackboard )
		{
			blackboard.SetInt( id, value );
		}
	}

	private function IsPlayerInDriverCombat() : Bool
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		var currentState : Int32;
		blackboardSystem = GameInstance.GetBlackboardSystem( m_owner.GetGame() );
		blackboard = blackboardSystem.GetLocalInstanced( m_owner.GetEntityID(), GetAllBlackboardDefs().PlayerStateMachine );
		currentState = blackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vehicle );
		if( currentState == ( ( Int32 )( gamePSMVehicle.DriverCombat ) ) )
		{
			return true;
		}
		return false;
	}

	private function SetFocusModeAnimFeature( newState : Bool )
	{
		var animFeature : AnimFeature_FocusMode;
		animFeature = new AnimFeature_FocusMode;
		animFeature.isFocusModeActive = newState;
		AnimationControllerComponent.ApplyFeature( m_owner, 'FocusMode', animFeature );
	}

	protected const function SetupLockToggleInput()
	{
		SendPSMBoolParameter( 'lockToggleInput', m_inputActiveFlags.m_buttonToggle, gamestateMachineParameterAspect.Permanent );
		SendPSMBoolParameter( 'lockToggleInput', m_inputActiveFlags.m_driverCombatButtonActivate, gamestateMachineParameterAspect.Permanent );
	}

	protected const function SetupLockHoldInput()
	{
		SendPSMBoolParameter( 'lockHoldInput', m_inputActiveFlags.m_buttonHold, gamestateMachineParameterAspect.Permanent );
		SendPSMBoolParameter( 'lockHoldInput', m_inputActiveFlags.m_driverCombatButtonHold, gamestateMachineParameterAspect.Permanent );
	}

	protected const function SendPSMBoolParameter( id : CName, value : Bool, aspect : gamestateMachineParameterAspect )
	{
		var psmEvent : PSMPostponedParameterBool;
		psmEvent = new PSMPostponedParameterBool;
		psmEvent.id = id;
		psmEvent.value = value;
		psmEvent.aspect = aspect;
		m_owner.QueueEvent( psmEvent );
	}

	private function GetVisionAimSnapParams() : AimRequest
	{
		var aimSnapParams : AimRequest;
		aimSnapParams.duration = 0.25;
		aimSnapParams.adjustPitch = true;
		aimSnapParams.adjustYaw = true;
		aimSnapParams.endOnAimingStopped = true;
		aimSnapParams.endOnCameraInputApplied = true;
		aimSnapParams.precision = 0.1;
		aimSnapParams.easeIn = true;
		aimSnapParams.easeOut = true;
		aimSnapParams.checkRange = true;
		aimSnapParams.processAsInput = true;
		aimSnapParams.bodyPartsTracking = true;
		aimSnapParams.bptMaxDot = 0.5;
		aimSnapParams.bptMaxSwitches = -1.0;
		aimSnapParams.bptMinInputMag = 0.5;
		aimSnapParams.bptMinResetInputMag = 0.1;
		return aimSnapParams;
	}

	private function RemoveFocusModeLocomotionRestriction()
	{
		StatusEffectHelper.RemoveStatusEffect( m_owner, T"GameplayRestriction.FocusModeLocomotion" );
	}

	private function HasMeleeWeaponEquipped() : Bool
	{
		var weapon : WeaponObject;
		var transactionSystem : TransactionSystem;
		transactionSystem = GameInstance.GetTransactionSystem( m_owner.GetGame() );
		weapon = ( ( WeaponObject )( transactionSystem.GetItemInSlot( m_owner, T"AttachmentSlots.WeaponRight" ) ) );
		if( weapon )
		{
			if( transactionSystem.HasTag( m_owner, WeaponObject.GetMeleeWeaponTag(), weapon.GetItemID() ) )
			{
				return true;
			}
		}
		return false;
	}

}

