class QuickSlotButtonHoldEndEvent extends Event
{
	var dPadItemDirection : EDPadSlot;
	var rightStickAngle : Float;
	default rightStickAngle = -1;
	var tryExecuteCommand : Bool;
	default tryExecuteCommand = true;
}

class QuickSlotButtonHoldStartEvent extends Event
{
	var dPadItemDirection : EDPadSlot;
}

class QuickSlotButtonTap extends Event
{
	var dPadItemDirection : EDPadSlot;
}

class QuickSlotKeyboardTap extends Event
{
	var keyIndex : Int32;
}

class CallAction extends Event
{
	var calledAction : QuickSlotActionType;
}

abstract class QuickSlotsTransition extends DefaultTransition
{

	protected const function GetUIBlackboard( scriptInterface : StateGameScriptInterface ) : IBlackboard
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		blackboardSystem = scriptInterface.GetBlackboardSystem();
		blackboard = blackboardSystem.Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		return blackboard;
	}

	protected function SetUIBlackboardBoolVariable( scriptInterface : StateGameScriptInterface, id : BlackboardID_Bool, value : Bool )
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		blackboardSystem = scriptInterface.GetBlackboardSystem();
		blackboard = blackboardSystem.Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		blackboard.SetBool( id, value );
	}

	protected function SetUIBlackboardFloatVariable( scriptInterface : StateGameScriptInterface, id : BlackboardID_Float, value : Float )
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		blackboardSystem = scriptInterface.GetBlackboardSystem();
		blackboard = blackboardSystem.Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		blackboard.SetFloat( id, value );
	}

	protected function SetUIBlackboardIntVariable( scriptInterface : StateGameScriptInterface, id : BlackboardID_Int, value : Int32 )
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		blackboardSystem = scriptInterface.GetBlackboardSystem();
		blackboard = blackboardSystem.Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		blackboard.SetInt( id, value );
	}

	protected function SetUIBlackboardVector4Variable( scriptInterface : StateGameScriptInterface, id : BlackboardID_Vector4, value : Vector4 )
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		blackboardSystem = scriptInterface.GetBlackboardSystem();
		blackboard = blackboardSystem.Get( GetAllBlackboardDefs().UI_QuickSlotsData );
		blackboard.SetVector4( id, value );
	}

	protected function GetQuickSlotsManager( scriptInterface : StateGameScriptInterface ) : QuickSlotsManager
	{
		return ( ( PlayerPuppet )( scriptInterface.owner ) ).GetQuickSlotsManager();
	}

	protected const function CheckForAnyItemInEquipmentArea( const scriptInterface : StateGameScriptInterface, areaType : gamedataEquipmentArea ) : Bool
	{
		return EquipmentSystem.GetData( scriptInterface.executionOwner ).GetNumberOfItemsInEquipmentArea( areaType ) > 0;
	}

	protected const function HasAnyVehiclesUnlocked( const scriptInterface : StateGameScriptInterface ) : Int32
	{
		var vehicleSystem : VehicleSystem;
		var playerVehicleList : array< PlayerVehicle >;
		vehicleSystem = GameInstance.GetVehicleSystem( scriptInterface.GetGame() );
		vehicleSystem.GetPlayerUnlockedVehicles( playerVehicleList );
		return playerVehicleList.Size();
	}

	protected const function DoesVehicleSupportRadio( const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var vehObject : weak< VehicleObject >;
		VehicleComponent.GetVehicle( scriptInterface.GetGame(), scriptInterface.executionOwnerEntityID, vehObject );
		if( ( vehObject != ( ( CarObject )( vehObject ) ) ) && ( vehObject != ( ( BikeObject )( vehObject ) ) ) )
		{
			return false;
		}
		return true;
	}

	protected const function CheckNoRadialMenusRestriction( const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'NoRadialMenus' ) );
	}

	protected const function CheckVehicleSummonigRestriction( const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'VehicleSummoning' ) );
	}

	protected const function IsPlayerInWheelBlockingWorkspot( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return stateContext.IsStateActive( 'Locomotion', 'workspot' ) && GetPlayerPuppet( scriptInterface ).PlayerContainsWorkspotTag( 'BlockRadialWheels' );
	}

	protected const function IsVehicleDriverAllowedToSelectWeapons( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( stateContext.IsStateActive( 'Vehicle', 'drive' ) && !( VehicleTransition.CanEnterDriverCombat() ) )
		{
			return false;
		}
		return true;
	}

	protected const function IsplayerInStateAllowedToSelectWeapons( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var ladderState : CName;
		if( stateContext.IsStateMachineActive( 'LocomotionSwimming' ) )
		{
			return false;
		}
		ladderState = stateContext.GetStateMachineCurrentState( 'Locomotion' );
		if( ( ladderState == 'ladder' || ladderState == 'ladderSprint' ) || ladderState == 'ladderSlide' )
		{
			return false;
		}
		return true;
	}

}

abstract class QuickSlotsDecisions extends QuickSlotsTransition
{
}

abstract class QuickSlotsEvents extends QuickSlotsTransition
{
}

abstract class QuickSlotsHoldDecisions extends QuickSlotsDecisions
{

	public const virtual function ToQuickSlotsReady( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		var hasCancelled : Bool;
		hasCancelled = stateContext.GetBoolParameter( 'RadialWheelCloseRequest' );
		if( scriptInterface.GetActionValue( 'CameraAim' ) > 0.0 )
		{
			SoftBlockAimingForTime( stateContext, scriptInterface, 0.1 );
		}
		if( hasCancelled || stateContext.IsStateActive( 'Vehicle', 'exitingCombat' ) )
		{
			stateContext.SetTemporaryFloatParameter( 'rightStickAngle', -1.0, true );
		}
		return hasCancelled || IsPlayerInAnyMenu( scriptInterface );
	}

	public const virtual function ToQuickSlotsBusy( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( scriptInterface.IsActionJustReleased( 'SelectWheelItem' ) )
		{
			return true;
		}
		return false;
	}

}

abstract class QuickSlotsHoldEvents extends QuickSlotsEvents
{
	var m_holdDirection : EDPadSlot;

	protected virtual function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		SetUIBlackboardBoolVariable( scriptInterface, GetAllBlackboardDefs().UI_QuickSlotsData.UIRadialContextRequest, true );
		NotifyQuickSlotsManagerButtonHoldStart( scriptInterface, m_holdDirection );
		stateContext.SetTemporaryFloatParameter( 'rightStickAngle', -1.0, true );
	}

	protected virtual function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var stickAngle : Float;
		stickAngle = GetStickAngle( stateContext.GetTemporaryFloatParameter( 'rightStickAngle' ), scriptInterface );
		SetUIBlackboardFloatVariable( scriptInterface, GetAllBlackboardDefs().UI_QuickSlotsData.UIRadialContextRightStickAngle, stickAngle );
		stateContext.SetTemporaryFloatParameter( 'rightStickAngle', stickAngle, true );
	}

	protected virtual function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) {}

	protected function NotifyQuickSlotsManagerButtonHoldStart( scriptInterface : StateGameScriptInterface, dPadItemDirection : EDPadSlot )
	{
		var evt : QuickSlotButtonHoldStartEvent;
		evt = new QuickSlotButtonHoldStartEvent;
		evt.dPadItemDirection = dPadItemDirection;
		scriptInterface.owner.QueueEvent( evt );
	}

	protected function NotifyQuickSlotsManagerButtonHoldEnd( stateContext : StateContext, scriptInterface : StateGameScriptInterface, dPadItemDirection : EDPadSlot, tryExecuteCommand : Bool )
	{
		var stateFloat : StateResultFloat;
		var evt : QuickSlotButtonHoldEndEvent;
		stateFloat = stateContext.GetTemporaryFloatParameter( 'rightStickAngle' );
		evt = new QuickSlotButtonHoldEndEvent;
		evt.dPadItemDirection = dPadItemDirection;
		evt.rightStickAngle = stateFloat.value;
		evt.tryExecuteCommand = tryExecuteCommand;
		if( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'NoRadialMenus' ) )
		{
			stateContext.SetTemporaryFloatParameter( 'rightStickAngle', -1.0, true );
			SetUIBlackboardFloatVariable( scriptInterface, GetAllBlackboardDefs().UI_QuickSlotsData.UIRadialContextRightStickAngle, -1.0 );
			evt.rightStickAngle = -1.0;
			evt.tryExecuteCommand = false;
		}
		scriptInterface.owner.QueueEvent( evt );
	}

	protected function GetRightStickAngle( stateFloat : StateResultFloat, scriptInterface : StateGameScriptInterface ) : Float
	{
		if( ( AbsF( scriptInterface.GetActionValue( 'UI_MoveX_Axis' ) ) + AbsF( scriptInterface.GetActionValue( 'UI_MoveY_Axis' ) ) ) < GetStaticFloatParameterDefault( "deadZone", 0.40000001 ) )
		{
			return stateFloat.value;
		}
		else
		{
			return Rad2Deg( AtanF( scriptInterface.GetActionValue( 'UI_MoveX_Axis' ), scriptInterface.GetActionValue( 'UI_MoveY_Axis' ) ) ) + 180.0;
		}
	}

	protected function GetLeftStickAngle( stateFloat : StateResultFloat, scriptInterface : StateGameScriptInterface ) : Float
	{
		if( ( AbsF( scriptInterface.GetActionValue( 'UI_LookX_Axis' ) ) + AbsF( scriptInterface.GetActionValue( 'UI_LookY_Axis' ) ) ) < GetStaticFloatParameterDefault( "deadZone", 0.40000001 ) )
		{
			return stateFloat.value;
		}
		else
		{
			return Rad2Deg( AtanF( scriptInterface.GetActionValue( 'UI_LookX_Axis' ), scriptInterface.GetActionValue( 'UI_LookY_Axis' ) ) ) + 180.0;
		}
	}

	protected function GetStickAngle( stateFloat : StateResultFloat, scriptInterface : StateGameScriptInterface ) : Float
	{
		var leftStickInDeadZone, rightStickInDeadZone : Bool;
		leftStickInDeadZone = ( AbsF( scriptInterface.GetActionValue( 'UI_LookX_Axis' ) ) + AbsF( scriptInterface.GetActionValue( 'UI_LookY_Axis' ) ) ) < GetStaticFloatParameterDefault( "deadZone", 0.40000001 );
		rightStickInDeadZone = ( AbsF( scriptInterface.GetActionValue( 'UI_MoveX_Axis' ) ) + AbsF( scriptInterface.GetActionValue( 'UI_MoveY_Axis' ) ) ) < GetStaticFloatParameterDefault( "deadZone", 0.40000001 );
		if( leftStickInDeadZone && rightStickInDeadZone )
		{
			return stateFloat.value;
		}
		else if( !( leftStickInDeadZone ) )
		{
			return Rad2Deg( AtanF( scriptInterface.GetActionValue( 'UI_LookX_Axis' ), scriptInterface.GetActionValue( 'UI_LookY_Axis' ) ) ) + 180.0;
		}
		else if( !( rightStickInDeadZone ) )
		{
			return Rad2Deg( AtanF( scriptInterface.GetActionValue( 'UI_MoveX_Axis' ), scriptInterface.GetActionValue( 'UI_MoveY_Axis' ) ) ) + 180.0;
		}
		else
		{
			return -1.0;
		}
	}

}

abstract class QuickSlotsTapDecisions extends QuickSlotsDecisions
{

	public const virtual function ToQuickSlotsReady( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return GetInStateTime() > GetStaticFloatParameterDefault( "durationTime", 2.0 );
	}

	public const virtual function ToQuickSlotsBusy( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return GetInStateTime() > GetStaticFloatParameterDefault( "singleTapStayTime", 0.5 );
	}

}

abstract class QuickSlotsTapEvents extends QuickSlotsEvents
{

	protected virtual function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) {}

	protected function CallActionRequest( scriptInterface : StateGameScriptInterface, actionType : QuickSlotActionType )
	{
		var evt : CallAction;
		evt = new CallAction;
		evt.calledAction = actionType;
		scriptInterface.owner.QueueEvent( evt );
	}

}

class QuickSlotsReadyDecisions extends QuickSlotsDecisions
{
}

class QuickSlotsReadyEvents extends QuickSlotsEvents
{
	var shouldSendEvent : Bool;
	default shouldSendEvent = true;
	var timePressed : Float;

	protected export function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		SetUIBlackboardBoolVariable( scriptInterface, GetAllBlackboardDefs().UI_QuickSlotsData.UIRadialContextRequest, false );
	}

	protected export function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var dpadAction : DPADActionPerformed;
		var value : Float;
		if( scriptInterface.IsActionJustHeld( 'CallVehicle' ) )
		{
			dpadAction = new DPADActionPerformed;
			dpadAction.action = EHotkey.DPAD_RIGHT;
			dpadAction.successful = true;
			dpadAction.state = EUIActionState.COMPLETED;
			scriptInterface.GetUISystem().QueueEvent( dpadAction );
			shouldSendEvent = true;
			return;
		}
		value = scriptInterface.GetActionValue( 'CallVehicle' );
		if( value > 0.0 )
		{
			timePressed += timeDelta;
			if( ( timePressed > 0.1 ) && shouldSendEvent )
			{
				dpadAction = new DPADActionPerformed;
				dpadAction.action = EHotkey.DPAD_RIGHT;
				dpadAction.successful = true;
				dpadAction.state = EUIActionState.STARTED;
				scriptInterface.GetUISystem().QueueEvent( dpadAction );
				shouldSendEvent = false;
			}
			return;
		}
		if( ( timePressed > 0.0 ) && ( value == 0.0 ) )
		{
			timePressed = 0.0;
			dpadAction = new DPADActionPerformed;
			dpadAction.action = EHotkey.DPAD_RIGHT;
			dpadAction.successful = false;
			dpadAction.state = EUIActionState.ABORTED;
			scriptInterface.GetUISystem().QueueEvent( dpadAction );
		}
		shouldSendEvent = true;
	}

}

class OnlyVehicleEvents extends QuickSlotsReadyEvents
{

	public export const function ToCycleObjective( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return ( scriptInterface.IsActionJustReleased( 'CycleObjectives' ) && !( IsInInputContextState( stateContext, 'uiPhoneContext' ) ) ) && CheckConsumableLootDataCondition( scriptInterface );
	}

}

class OnlyVehicleDecisions extends QuickSlotsReadyDecisions
{
	private var m_executionOwner : weak< GameObject >;
	private var m_statusEffectListener : DefaultTransitionStatusEffectListener;
	private var m_hasStatusEffect : Bool;

	protected export function OnAttach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		m_statusEffectListener = new DefaultTransitionStatusEffectListener;
		m_statusEffectListener.m_transitionOwner = this;
		scriptInterface.GetStatusEffectSystem().RegisterListener( scriptInterface.owner.GetEntityID(), m_statusEffectListener );
		m_executionOwner = scriptInterface.executionOwner;
		UpdateHasStatusEffect();
	}

	protected export function OnDetach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		m_statusEffectListener = NULL;
	}

	public override function OnStatusEffectApplied( statusEffect : weak< StatusEffect_Record > )
	{
		if( !( m_hasStatusEffect ) )
		{
			if( statusEffect.GameplayTagsContains( 'CustomVehicleSummon' ) )
			{
				m_hasStatusEffect = true;
				EnableOnEnterCondition( true );
			}
		}
	}

	public override function OnStatusEffectRemoved( statusEffect : weak< StatusEffect_Record > )
	{
		if( m_hasStatusEffect )
		{
			if( statusEffect.GameplayTagsContains( 'CustomVehicleSummon' ) )
			{
				UpdateHasStatusEffect();
			}
		}
	}

	protected function UpdateHasStatusEffect()
	{
		m_hasStatusEffect = StatusEffectSystem.ObjectHasStatusEffectWithTag( m_executionOwner, 'CustomVehicleSummon' );
		EnableOnEnterCondition( m_hasStatusEffect );
	}

	protected constexpr const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'CustomVehicleSummon' );
	}

	public const function ToQuickSlotsReady( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'CustomVehicleSummon' ) ) )
		{
			return true;
		}
		return false;
	}

}

class QuickSlotsBusyDecisions extends QuickSlotsDecisions
{

	public const function ToQuickSlotsReady( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return GetInStateTime() > GetStaticFloatParameterDefault( "busyDuration", 2.0 );
	}

}

class QuickSlotsBusyEvents extends QuickSlotsEvents
{

	protected function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) {}
}

class QuickSlotsDisabledDecisions extends QuickSlotsDecisions
{
	private var m_executionOwner : weak< GameObject >;
	private var m_hasStatusEffect : Bool;

	protected const function ShouldDisableRadialForReplacer( const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var playerStatsBB : IBlackboard;
		playerStatsBB = scriptInterface.GetBlackboardSystem().Get( GetAllBlackboardDefs().UI_PlayerStats );
		return playerStatsBB.GetBool( GetAllBlackboardDefs().UI_PlayerStats.isReplacer ) && !( scriptInterface.executionOwner.IsVRReplacer() );
	}

	protected export function OnAttach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		EnableOnEnterCondition( true );
	}

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var shouldEnter : Bool;
		shouldEnter = ( ( ( ( ( ( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.SceneTier ) >= GetStaticIntParameterDefault( "minBlockedSceneTier", 2 ) ) || scriptInterface.IsPlayerInBraindance() ) || ShouldDisableRadialForReplacer( scriptInterface ) ) || ( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vitals ) == ( ( Int32 )( gamePSMVitals.Dead ) ) ) ) || IsPlayerInWheelBlockingWorkspot( stateContext, scriptInterface ) ) || StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'FastForward' ) ) || StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'Cyberspace' );
		return shouldEnter && !( IsPocketRadioOverrideActive( scriptInterface ) );
	}

	public export const function ToQuickSlotsReady( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return ( ( ( ( ( ( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.SceneTier ) < GetStaticIntParameterDefault( "minBlockedSceneTier", 2 ) ) && !( scriptInterface.IsPlayerInBraindance() ) ) && !( ShouldDisableRadialForReplacer( scriptInterface ) ) ) && ( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vitals ) != ( ( Int32 )( gamePSMVitals.Dead ) ) ) ) && !( IsPlayerInWheelBlockingWorkspot( stateContext, scriptInterface ) ) ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'FastForward' ) ) ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'Cyberspace' ) );
	}

	public export const function ToCycleObjective( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return ( scriptInterface.IsActionJustReleased( 'CycleObjectives' ) && !( IsInInputContextState( stateContext, 'uiPhoneContext' ) ) ) && CheckConsumableLootDataCondition( scriptInterface );
	}

	public export const function ToPocketRadioWheel( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return scriptInterface.IsActionJustHeld( 'PocketRadio' ) && IsPocketRadioOverrideActive( scriptInterface );
	}

	private const function IsPocketRadioOverrideActive( const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var player : PlayerPuppet;
		player = ( ( PlayerPuppet )( scriptInterface.executionOwner ) );
		if( !( player ) )
		{
			return false;
		}
		return player.GetPocketRadio().IsRestrictionOverwritten();
	}

}

class QuickSlotsDisabledEvents extends QuickSlotsEvents
{

	protected export function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		SetUIBlackboardBoolVariable( scriptInterface, GetAllBlackboardDefs().UI_QuickSlotsData.UIRadialContextRequest, false );
		ForceDisableRadialWheel( scriptInterface );
	}

	protected export function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		var dpadAction : DPADActionPerformed;
		if( scriptInterface.IsActionJustReleased( 'CallVehicle' ) )
		{
			dpadAction = new DPADActionPerformed;
			dpadAction.action = EHotkey.DPAD_RIGHT;
			scriptInterface.GetUISystem().QueueEvent( dpadAction );
		}
	}

}

class CycleObjectiveDecisions extends QuickSlotsTapDecisions
{

	protected export function OnAttach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.RegisterInputListener( this, 'CycleObjectives' );
		EnableOnEnterCondition( false );
	}

	protected export function OnDetach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.UnregisterInputListener( this );
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( ListenerAction.IsButtonJustReleased( action ) )
		{
			EnableOnEnterCondition( true );
		}
	}

	protected const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		EnableOnEnterCondition( false );
		return ( scriptInterface.IsActionJustReleased( 'CycleObjectives' ) && !( IsInInputContextState( stateContext, 'uiPhoneContext' ) ) ) && CheckConsumableLootDataCondition( scriptInterface );
	}

}

class CycleObjectiveEvents extends QuickSlotsTapEvents
{

	protected override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnEnter( stateContext, scriptInterface );
		GameInstance.GetJournalManager( scriptInterface.GetGame() ).TrackPrevNextEntry( true );
	}

}

class WeaponWheelDecisions extends QuickSlotsHoldDecisions
{

	protected export function OnAttach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.RegisterInputListener( this, 'WeaponWheel' );
		EnableOnEnterCondition( scriptInterface.IsActionJustHeld( 'WeaponWheel' ) );
	}

	protected export function OnDetach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.UnregisterInputListener( this );
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( ListenerAction.IsButtonJustPressed( action ) )
		{
			EnableOnEnterCondition( true );
		}
		if( ListenerAction.IsButtonJustReleased( action ) )
		{
			EnableOnEnterCondition( false );
		}
	}

	protected const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return ( ( ( ( ( ( ( ( ( ( scriptInterface.IsActionJustHeld( 'WeaponWheel' ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'NoRadialMenus' ) ) ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'NoWeaponWheel' ) ) ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'FocusModeLocomotion' ) ) ) && !( IsPlayingAsReplacer( scriptInterface ) ) ) && !( stateContext.IsStateMachineActive( 'CombatGadget' ) ) ) && !( stateContext.IsStateMachineActive( 'Consumable' ) ) ) && stateContext.GetStateMachineCurrentState( 'Vehicle' ) != 'entering' ) && stateContext.GetStateMachineCurrentState( 'Vehicle' ) != 'switchSeats' ) && !( IsVehicleBlockingCombat( scriptInterface ) ) ) && IsVehicleDriverAllowedToSelectWeapons( stateContext, scriptInterface ) ) && IsplayerInStateAllowedToSelectWeapons( stateContext, scriptInterface );
	}

}

class VehicleWheelDecisions extends QuickSlotsHoldDecisions
{

	protected export function OnAttach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.RegisterInputListener( this, 'CallVehicle' );
		EnableOnEnterCondition( scriptInterface.IsActionJustHeld( 'CallVehicle' ) );
	}

	protected export function OnDetach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.UnregisterInputListener( this );
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( ListenerAction.IsButtonJustPressed( action ) )
		{
			EnableOnEnterCondition( true );
		}
		if( ListenerAction.IsButtonJustReleased( action ) )
		{
			EnableOnEnterCondition( false );
		}
	}

	protected export const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var vehicleType : gamedataVehicleType;
		vehicleType = ( ( PlayerPuppet )( scriptInterface.executionOwner ) ).GetQuickSlotsManager().GetActiveVehicleType();
		return !( VehicleSystem.IsSummoningVehiclesRestricted( scriptInterface.GetGame() ) ) && ( ( scriptInterface.IsActionJustPressed( 'CallVehicle' ) && GameInstance.GetVehicleSystem( scriptInterface.executionOwner.GetGame() ).IsActivePlayerVehicleOnCooldown( vehicleType ) ) || scriptInterface.IsActionJustHeld( 'CallVehicle' ) );
	}

	public const override function ToQuickSlotsReady( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		if( VehicleSystem.IsSummoningVehiclesRestricted( scriptInterface.GetGame() ) )
		{
			return true;
		}
		return super.ToQuickSlotsReady( stateContext, scriptInterface );
	}

}

class VehicleInsideWheelDecisions extends QuickSlotsHoldDecisions
{

	protected export function OnAttach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.RegisterInputListener( this, 'VehicleInsideWheel' );
		EnableOnEnterCondition( scriptInterface.IsActionJustHeld( 'VehicleInsideWheel' ) );
	}

	protected export function OnDetach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.UnregisterInputListener( this );
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( ListenerAction.IsButtonJustPressed( action ) )
		{
			EnableOnEnterCondition( true );
		}
		if( ListenerAction.IsButtonJustReleased( action ) )
		{
			EnableOnEnterCondition( false );
		}
	}

	protected const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		return ( ( scriptInterface.IsActionJustHeld( 'VehicleInsideWheel' ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'VehicleBlockRadioInput' ) ) ) && DoesVehicleSupportRadio( scriptInterface ) ) && ( scriptInterface.localBlackboard.GetInt( GetAllBlackboardDefs().PlayerStateMachine.Vehicle ) > ( ( Int32 )( gamePSMVehicle.Default ) ) );
	}

	protected const override function ToQuickSlotsReady( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		return super.ToQuickSlotsReady( stateContext, scriptInterface ) || IsRadioDisabled( scriptInterface );
	}

	protected const function IsRadioDisabled( scriptInterface : StateGameScriptInterface ) : Bool
	{
		var blackboardSystem : BlackboardSystem;
		var blackboard : IBlackboard;
		blackboardSystem = scriptInterface.GetBlackboardSystem();
		blackboard = blackboardSystem.Get( GetAllBlackboardDefs().UIGameData );
		return !( blackboard.GetBool( GetAllBlackboardDefs().UIGameData.Popup_Radio_Enabled ) );
	}

}

class VehicleWheelEvents extends QuickSlotsHoldEvents
{

	protected override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		m_holdDirection = EDPadSlot.VehicleWheel;
		super.OnEnter( stateContext, scriptInterface );
	}

	protected override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
	}

	protected function OnExitToQuickSlotsBusy( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, true );
	}

	protected override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, false );
	}

}

class VehicleInsideWheelEvents extends QuickSlotsHoldEvents
{

	protected override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		m_holdDirection = EDPadSlot.VehicleInsideWheel;
		super.OnEnter( stateContext, scriptInterface );
	}

	protected override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
	}

	protected function OnExitToQuickSlotsBusy( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, true );
	}

	protected override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, false );
	}

}

class WeaponWheelEvents extends QuickSlotsHoldEvents
{

	protected override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		m_holdDirection = EDPadSlot.WeaponsWheel;
		super.OnEnter( stateContext, scriptInterface );
	}

	protected override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
	}

	protected function OnExitToQuickSlotsBusy( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, true );
	}

	protected override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, false );
	}

}

class PocketRadioWheelEvents extends QuickSlotsHoldEvents
{

	protected override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		m_holdDirection = EDPadSlot.PocketRadio;
		super.OnEnter( stateContext, scriptInterface );
	}

	protected override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
	}

	protected function OnExitToQuickSlotsBusy( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, true );
	}

	protected override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, false );
	}

}

class PocketRadioWheelDecisions extends QuickSlotsHoldDecisions
{

	protected export function OnAttach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.RegisterInputListener( this, 'PocketRadio' );
		EnableOnEnterCondition( scriptInterface.IsActionJustHeld( 'PocketRadio' ) );
	}

	protected export function OnDetach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.UnregisterInputListener( this );
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( ListenerAction.IsButtonJustPressed( action ) )
		{
			EnableOnEnterCondition( true );
		}
		if( ListenerAction.IsButtonJustReleased( action ) )
		{
			EnableOnEnterCondition( false );
		}
	}

	protected const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var player : PlayerPuppet;
		player = ( ( PlayerPuppet )( scriptInterface.executionOwner ) );
		if( !( player ) )
		{
			return false;
		}
		if( scriptInterface.IsActionJustHeld( 'PocketRadio' ) )
		{
			if( scriptInterface.localBlackboard.GetBool( GetAllBlackboardDefs().PlayerStateMachine.MountedToVehicle ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'MetroRide' ) ) )
			{
				return false;
			}
			if( IsInInputContextState( stateContext, 'deviceControlContext' ) )
			{
				if( !( StatusEffectSystem.ObjectHasStatusEffectWithTag( scriptInterface.executionOwner, 'BinocularView' ) ) )
				{
					return false;
				}
			}
			return !( player.GetPocketRadio().IsRestricted() );
		}
		return false;
	}

	protected const override function ToQuickSlotsReady( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		return super.ToQuickSlotsReady( stateContext, scriptInterface ) || IsRadioDisabled( scriptInterface );
	}

	protected const function IsRadioDisabled( scriptInterface : StateGameScriptInterface ) : Bool
	{
		var player : PlayerPuppet;
		player = ( ( PlayerPuppet )( scriptInterface.executionOwner ) );
		if( !( player ) )
		{
			return true;
		}
		return player.GetPocketRadio().IsRestricted();
	}

}

class VehicleVisualCustomizationEvents extends QuickSlotsHoldEvents
{

	protected override function OnEnter( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		m_holdDirection = EDPadSlot.VehicleVisualCustomization;
		super.OnEnter( stateContext, scriptInterface );
	}

	protected override function OnUpdate( timeDelta : Float, stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnUpdate( timeDelta, stateContext, scriptInterface );
	}

	protected function OnExitToQuickSlotsBusy( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, true );
	}

	protected override function OnExit( stateContext : StateContext, scriptInterface : StateGameScriptInterface )
	{
		super.OnExit( stateContext, scriptInterface );
		NotifyQuickSlotsManagerButtonHoldEnd( stateContext, scriptInterface, m_holdDirection, false );
	}

}

class VehicleVisualCustomizationDecisions extends QuickSlotsHoldDecisions
{

	protected export function OnAttach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.RegisterInputListener( this, 'VehicleVisualCustomization' );
		EnableOnEnterCondition( scriptInterface.IsActionJustHeld( 'VehicleVisualCustomization' ) );
	}

	protected export function OnDetach( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface )
	{
		scriptInterface.executionOwner.UnregisterInputListener( this );
	}

	protected event OnAction( action : ListenerAction, consumer : ListenerActionConsumer )
	{
		if( ListenerAction.IsButtonJustPressed( action ) )
		{
			EnableOnEnterCondition( true );
		}
		if( ListenerAction.IsButtonJustReleased( action ) )
		{
			EnableOnEnterCondition( false );
		}
	}

	protected const function EnterCondition( const stateContext : StateContext, const scriptInterface : StateGameScriptInterface ) : Bool
	{
		var player : PlayerPuppet;
		var notificationEvent : UIInGameNotificationEvent;
		var customizationTeaserMessage : String;
		var playerStateMachineBlackboard : IBlackboard;
		var isNotInDriverCombat : Bool;
		var isNotInVehicleScene : Bool;
		var isNotQuestBlocked : Bool;
		var isNotModInCooldown : Bool;
		var isNotInPhoneCall : Bool;
		var isNotModBlockedByDamage : Bool;
		var isNotInCombat : Bool;
		var isNotVisualCustomizationTeaser : Bool;
		var isNotFastForwardAvailable : Bool;
		var isNotFastForward : Bool;
		var isNotRemoteControlling : Bool;
		player = ( ( PlayerPuppet )( scriptInterface.executionOwner ) );
		if( !( player ) )
		{
			return false;
		}
		if( scriptInterface.IsActionJustHeld( 'VehicleVisualCustomization' ) )
		{
			playerStateMachineBlackboard = GameInstance.GetBlackboardSystem( player.GetGame() ).GetLocalInstanced( GameInstance.GetPlayerSystem( player.GetGame() ).GetLocalPlayerControlledGameObject().GetEntityID(), GetAllBlackboardDefs().PlayerStateMachine );
			isNotInDriverCombat = !( StatusEffectSystem.ObjectHasStatusEffect( player, T"BaseStatusEffect.DriverCombat" ) );
			isNotInVehicleScene = !( StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'VehicleScene' ) );
			isNotQuestBlocked = GameInstance.GetQuestsSystem( player.GetGame() ).GetFact( 'unlock_car_hud_dpad' ) != 0;
			isNotModInCooldown = !( StatusEffectSystem.ObjectHasStatusEffect( player, T"BaseStatusEffect.VehicleVisualModCooldown" ) );
			isNotInPhoneCall = ( !( StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'PhoneCall' ) ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'PhoneNoTexting' ) ) ) && !( StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'PhoneNoCalling' ) );
			isNotModBlockedByDamage = !( player.GetMountedVehicle().GetVehiclePS().GetIsVehicleVisualCustomizationBlockedByDamage() );
			isNotInCombat = !( player.IsInCombat() );
			isNotVisualCustomizationTeaser = !( player.GetMountedVehicle().GetVehicleComponent().GetIsVehicleVisualCustomizationTeaser() );
			isNotFastForwardAvailable = !( StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'FastForwardHintActive' ) );
			isNotFastForward = !( StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'FastForward' ) );
			isNotRemoteControlling = playerStateMachineBlackboard.GetBool( GetAllBlackboardDefs().PlayerStateMachine.IsControllingDevice );
			if( ( ( ( ( ( ( ( ( ( isNotInVehicleScene && isNotQuestBlocked ) && isNotModInCooldown ) && isNotModBlockedByDamage ) && isNotFastForwardAvailable ) && isNotFastForward ) && isNotVisualCustomizationTeaser ) && isNotInDriverCombat ) && isNotInPhoneCall ) && !( isNotRemoteControlling ) ) && isNotInCombat )
			{
				return true;
			}
			else
			{
				if( player.GetMountedVehicle().GetVehicleComponent().GetIsVehicleVisualCustomizationEnabled() )
				{
					if( player.GetMountedVehicle().GetVehicleComponent().GetIsVehicleVisualCustomizationTeaser() )
					{
						customizationTeaserMessage = ( ( ( GetLocalizedText( "LocKey#96055" ) + ": " ) + GetLocalizedText( "LocKey#52901" ) ) + " >> " ) + GetLocalizedText( "LocKey#28266" );
						player.GetMountedVehicle().GetVehicleComponent().VisualCustomizationBlockedNotification( customizationTeaserMessage );
					}
					else
					{
						notificationEvent = new UIInGameNotificationEvent;
						notificationEvent.m_title = GetLocalizedText( "LocKey#96051" );
						notificationEvent.m_notificationType = UIInGameNotificationType.ActionRestriction;
						scriptInterface.GetUISystem().QueueEvent( notificationEvent );
					}
				}
				EnableOnEnterCondition( false );
				return false;
			}
		}
		return false;
	}

	protected const override function ToQuickSlotsReady( stateContext : StateContext, scriptInterface : StateGameScriptInterface ) : Bool
	{
		var player : PlayerPuppet;
		player = ( ( PlayerPuppet )( scriptInterface.executionOwner ) );
		return super.ToQuickSlotsReady( stateContext, scriptInterface ) || StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'VehicleVisualModCooldown' );
	}

}

