enum EProgressBarType
{
	UPLOAD = 0,
	DURATION = 1,
}

enum EProgressBarContext
{
	QuickHack = 0,
	PhoneCall = 1,
}

enum EMappinDisplayMode
{
	PLAYSTYLE = 0,
	ROLE = 1,
	MINIMALISTIC = 2,
}

enum EUploadProgramState
{
	STARTED = 0,
	COMPLETED = 1,
}

class GameplayRoleChangeNotification extends Event
{
	var newRole : EGameplayRole;
	var oldRole : EGameplayRole;
}

class ToggleMappinsOnLookAtEvent extends Event
{
	var state : Bool;
}

class UploadProgramProgressEvent extends Event
{
	var state : EUploadProgramState;
	var progressBarType : EProgressBarType;
	default progressBarType = EProgressBarType.UPLOAD;
	var progressBarContext : EProgressBarContext;
	default progressBarContext = EProgressBarContext.QuickHack;
	var duration : Float;
	default duration = 3.0f;
	var iconRecord : weak< ChoiceCaptionIconPart_Record >;
	var action : ScriptableDeviceAction;
	var deviceActionQueue : DeviceActionQueue;
	var slotName : CName;
	var statPoolType : gamedataStatPoolType;
	default statPoolType = gamedataStatPoolType.Invalid;
}

class GameplayRoleMappinData extends MappinScriptData
{
	var m_mappinVisualState : EMappinVisualState;
	default m_mappinVisualState = EMappinVisualState.Default;
	var m_isTagged : Bool;
	var m_isQuest : Bool;
	var m_isIconic : Bool;
	var m_isBroken : Bool;
	var m_isScanningCluesBlocked : Bool;
	var m_isCurrentTarget : Bool;
	var m_visibleThroughWalls : Bool;
	var m_hasOffscreenArrow : Bool;
	var m_isShardRead : Bool;
	var m_range : Float;
	var m_duration : Float;
	var m_progressBarType : EProgressBarType;
	default m_progressBarType = EProgressBarType.UPLOAD;
	var m_progressBarContext : EProgressBarContext;
	default m_progressBarContext = EProgressBarContext.QuickHack;
	var m_gameplayRole : EGameplayRole;
	var m_braindanceLayer : braindanceVisionMode;
	default m_braindanceLayer = braindanceVisionMode.Default;
	var m_quality : gamedataQuality;
	var m_slotName : CName;
	var m_textureID : TweakDBID;
	var m_showOnMiniMap : Bool;
	default m_showOnMiniMap = true;
	var m_action : ScriptableDeviceAction;
}

class EvaluateGameplayRoleEvent extends Event
{
	var force : Bool;
}

class EvaluateMappinsVisualStateEvent extends Event
{
}

class ShowSingleMappinEvent extends Event
{
	var index : Int32;
}

class HideSingleMappinEvent extends Event
{
	var index : Int32;
}

class DeactivateQuickHackIndicatorEvent extends Event
{
}

class SetGameplayRoleEvent extends Event
{
	instanceeditable var gameplayRole : EGameplayRole;

	public constexpr export function GetFriendlyDescription() : String
	{
		return "Set Gameplay Role";
	}

}

class ToggleGameplayMappinVisibilityEvent extends Event
{
	instanceeditable var isHidden : Bool;

	public constexpr function GetFriendlyDescription() : String
	{
		return "Toggle Gameplay Mappin Visibility";
	}

}

class UnregisterAllMappinsEvent extends Event
{
}

class SetCurrentGameplayRoleEvent extends Event
{
	var gameplayRole : EGameplayRole;
}

enum EAxisType
{
	X = 0,
	Y = 1,
	Z = 2,
}

enum EMappinVisualState
{
	Default = 0,
	Available = 1,
	Unavailable = 2,
	Inactive = 3,
	None = 4,
}

enum EGameplayRole
{
	UnAssigned = 0,
	None = 1,
	Alarm = 2,
	ControlNetwork = 3,
	ControlOtherDevice = 4,
	ControlSelf = 5,
	CutPower = 6,
	Distract = 7,
	DropPoint = 8,
	ExplodeLethal = 9,
	ExplodeNoneLethal = 10,
	Fall = 11,
	FastTravel = 12,
	GrantInformation = 13,
	HazardWarning = 14,
	HideBody = 15,
	Loot = 16,
	OpenPath = 17,
	ClearPath = 18,
	Push = 19,
	ServicePoint = 20,
	Shoot = 21,
	SpreadGas = 22,
	StoreItems = 23,
	GenericRole = 24,
	ClearPathAd = 25,
	DistractVendingMachine = 26,
	NPC = 27,
	Clue = 28,
	PlayerStash = 29,
	Wardrobe = 30,
}

struct SDeviceMappinData
{
	var mappinName : CName;
	[ customEditor = "TweakDBGroupInheritance;MappinDefinition" ]
	instanceeditable var mappinType : TweakDBID;
	instanceeditable var mappinVariant : gamedataMappinVariant;
	instanceeditable var enabled : Bool;
	default enabled = true;
	instanceeditable var range : Float;
	default range = 30.f;
	instanceeditable var caption : String;
	instanceeditable var offset : Vector4;
	instanceeditable var position : Vector4;
	instanceeditable var permanent : Bool;
	var checkIfIsTarget : Bool;
	default checkIfIsTarget = true;
	var id : NewMappinID;
	var active : Bool;
	default active = false;
	var gameplayRole : EGameplayRole;
	var visualStateData : GameplayRoleMappinData;
}

class GameplayRoleComponent extends ScriptableComponent
{
	[ category = "Gameplay Role" ]
	private instanceeditable var m_gameplayRole : EGameplayRole;
	default m_gameplayRole = EGameplayRole.UnAssigned;
	[ category = "Gameplay Role" ]
	private instanceeditable var m_autoDeterminGameplayRole : Bool;
	default m_autoDeterminGameplayRole = true;
	private instanceeditable var m_mappinsDisplayMode : EMappinDisplayMode;
	default m_mappinsDisplayMode = EMappinDisplayMode.MINIMALISTIC;
	private instanceeditable var m_displayAllRolesAsGeneric : Bool;
	default m_displayAllRolesAsGeneric = false;
	private instanceeditable var m_alwaysCreateMappinAsDynamic : Bool;
	default m_alwaysCreateMappinAsDynamic = true;
	private instanceeditable var m_forcedMappinVisualState : EMappinVisualState;
	default m_forcedMappinVisualState = EMappinVisualState.None;
	private mutable instanceeditable var m_mappins : array< SDeviceMappinData >;
	private var m_offsetValue : Float;
	default m_offsetValue = 0.04f;
	private var m_isBeingScanned : Bool;
	private var m_isCurrentTarget : Bool;
	private var m_isShowingMappins : Bool;
	private var m_canShowMappinsByTask : Bool;
	private var m_canHideMappinsByTask : Bool;
	private var m_isHighlightedInFocusMode : Bool;
	private var m_currentGameplayRole : EGameplayRole;
	default m_currentGameplayRole = EGameplayRole.UnAssigned;
	private var m_isGameplayRoleInitialized : Bool;
	private var m_isForceHidden : Bool;
	private var m_isForcedVisibleThroughWalls : Bool;
	private var m_enabledMinimapMappins : array< gamedataMappinVariant >;

	private function DeterminGamplayRoleByTask()
	{
		GameInstance.GetDelaySystem( GetOwner().GetGame() ).QueueTask( this, NULL, 'DeterminGamplayRoleTask', gameScriptTaskExecutionStage.Any );
	}

	protected function DeterminGamplayRoleTask( data : ScriptTaskData )
	{
		DeterminGamplayRole();
	}

	protected virtual function ShowRoleMappinsByTask()
	{
		m_canShowMappinsByTask = true;
		m_canHideMappinsByTask = false;
		GameInstance.GetDelaySystem( GetOwner().GetGame() ).QueueTask( this, NULL, 'ShowRoleMappinsTask', gameScriptTaskExecutionStage.Any );
	}

	protected export function ShowRoleMappinsTask( data : ScriptTaskData )
	{
		if( m_canShowMappinsByTask )
		{
			m_canShowMappinsByTask = false;
			ShowRoleMappins();
		}
	}

	protected virtual function HideRoleMappinsByTask()
	{
		if( !( m_isShowingMappins ) )
		{
			return;
		}
		m_canShowMappinsByTask = false;
		m_canHideMappinsByTask = true;
		GameInstance.GetDelaySystem( GetOwner().GetGame() ).QueueTask( this, NULL, 'HideRoleMappinsTask', gameScriptTaskExecutionStage.Any );
	}

	protected export function HideRoleMappinsTask( data : ScriptTaskData )
	{
		if( m_canHideMappinsByTask )
		{
			m_canHideMappinsByTask = false;
			HideRoleMappins();
		}
	}

	protected virtual function ClearAllRoleMappinsByTask()
	{
		m_canShowMappinsByTask = false;
		m_canHideMappinsByTask = false;
		GameInstance.GetDelaySystem( GetOwner().GetGame() ).QueueTask( this, NULL, 'ClearAllRoleMappinsTask', gameScriptTaskExecutionStage.Any );
	}

	protected function ClearAllRoleMappinsTask( data : ScriptTaskData )
	{
		ClearAllRoleMappins();
	}

	protected event OnPostInitialize( evt : entPostInitializeEvent )
	{
		m_currentGameplayRole = m_gameplayRole;
		DeterminGamplayRole();
		InitializeQuickHackIndicator();
		InitializePhoneCallIndicator();
	}

	protected event OnPreUninitialize( evt : entPreUninitializeEvent )
	{
		UnregisterAllMappins();
	}

	protected export function OnGameAttach() {}

	protected export function OnGameDetach() {}

	protected event OnSetGameplayRole( evt : SetGameplayRoleEvent )
	{
		m_gameplayRole = evt.gameplayRole;
		SetCurrentGameplayRoleWithNotification( evt.gameplayRole );
		ReEvaluateGameplayRole();
	}

	protected event OnSetCurrentGameplayRole( evt : SetCurrentGameplayRoleEvent )
	{
		SetCurrentGameplayRoleWithNotification( evt.gameplayRole );
		ReEvaluateGameplayRole();
	}

	protected event OnReEvaluateGameplayRole( evt : EvaluateGameplayRoleEvent )
	{
		if( !( IsGameplayRoleStatic() ) || evt.force )
		{
			if( evt.force )
			{
				m_currentGameplayRole = m_gameplayRole;
			}
			ReEvaluateGameplayRole();
		}
	}

	private function SetCurrentGameplayRoleWithNotification( role : EGameplayRole )
	{
		var evt : GameplayRoleChangeNotification;
		if( m_currentGameplayRole != role )
		{
			evt = new GameplayRoleChangeNotification;
			evt.oldRole = m_currentGameplayRole;
			evt.newRole = role;
			GetOwner().QueueEvent( evt );
		}
		m_currentGameplayRole = role;
	}

	protected event OnLookedAtEvent( evt : LookedAtEvent )
	{
		m_isCurrentTarget = evt.isLookedAt;
	}

	protected event OnScanningLookedAt( evt : ScanningLookAtEvent )
	{
		m_isBeingScanned = evt.state;
	}

	private const function IsHighlightedInFocusMode() : Bool
	{
		return m_isHighlightedInFocusMode;
	}

	protected event OnLogicReady( evt : SetLogicReadyEvent )
	{
		RequestHUDRefresh();
	}

	protected event OnHUDInstruction( evt : HUDInstruction )
	{
		if( evt.braindanceInstructions.GetState() == InstanceState.ON )
		{
			if( GetOwner().IsBraindanceBlocked() || GetOwner().IsPhotoModeBlocked() )
			{
				m_isHighlightedInFocusMode = false;
				HideRoleMappinsByTask();
				return false;
			}
		}
		m_isForcedVisibleThroughWalls = evt.iconsInstruction.isForcedVisibleThroughWalls;
		if( evt.iconsInstruction.GetState() == InstanceState.ON )
		{
			m_isHighlightedInFocusMode = true;
			ShowRoleMappinsByTask();
		}
		else
		{
			if( evt.highlightInstructions.WasProcessed() )
			{
				m_isHighlightedInFocusMode = false;
				HideRoleMappinsByTask();
			}
		}
	}

	protected event OnUploadProgressStateChanged( evt : UploadProgramProgressEvent )
	{
		var visualData : GameplayRoleMappinData;
		var iconRecord : weak< ChoiceCaptionIconPart_Record >;
		visualData = new GameplayRoleMappinData;
		visualData.statPoolType = evt.statPoolType;
		visualData.m_action = evt.action;
		switch( evt.state )
		{
			case EUploadProgramState.STARTED:
			{
				visualData.m_mappinVisualState = EMappinVisualState.Default;
				visualData.m_duration = evt.duration;
				visualData.m_progressBarType = evt.progressBarType;
				visualData.m_progressBarContext = evt.progressBarContext;
				visualData.m_visibleThroughWalls = true;
				if( evt.progressBarContext == EProgressBarContext.QuickHack )
				{
					iconRecord = evt.action.GetInteractionIcon();
					if( iconRecord )
					{
						visualData.m_textureID = iconRecord.TexturePartID().GetID();
					}
					if( visualData.m_progressBarType == EProgressBarType.DURATION )
					{
						ActivateQuickHackDurationIndicator( visualData );
					}
					else if( !( HasActiveMappin( gamedataMappinVariant.QuickHackVariant ) ) )
					{
						ActivateQuickHackIndicator( visualData );
					}
				}
				else if( evt.progressBarContext == EProgressBarContext.PhoneCall )
				{
					iconRecord = evt.iconRecord;
					if( iconRecord )
					{
						visualData.m_textureID = iconRecord.TexturePartID().GetID();
					}
					ActivatePhoneCallIndicator( visualData );
				}
				break;
			}
			case EUploadProgramState.COMPLETED:
			{
				if( evt.progressBarContext == EProgressBarContext.QuickHack )
				{
					if( visualData.statPoolType == gamedataStatPoolType.QuickHackDuration )
					{
						DeactivateQuickHackDurationIndicator();
					}
					else if( GetQuickHackQueueSize() == 0 )
					{
						DeactivateQuickHackIndicator();
					}
					else
					{
						RemoveQuickhackMappinFromQueue();
					}
				}
				else if( evt.progressBarContext == EProgressBarContext.PhoneCall )
				{
					DeactivatePhoneCallIndicator();
				}
				break;
			}
		}
	}

	protected event OnPerformedAction( evt : PerformedAction )
	{
		EvaluateMappins();
	}

	private function ActivateQuickHackDurationIndicator( visualData : GameplayRoleMappinData )
	{
		HideRoleMappins();
		ToggleMappin( gamedataMappinVariant.Zzz15_QuickHackDurationVariant, true, true, visualData );
	}

	private function DeactivateQuickHackDurationIndicator()
	{
		ToggleMappin( gamedataMappinVariant.Zzz15_QuickHackDurationVariant, false );
		RequestHUDRefresh();
	}

	private function ActivateQuickHackIndicator( visualData : GameplayRoleMappinData )
	{
		HideRoleMappins();
		ToggleMappin( gamedataMappinVariant.QuickHackVariant, true, true, visualData );
	}

	private function DeactivateQuickHackIndicator()
	{
		ToggleMappin( gamedataMappinVariant.QuickHackVariant, false );
		RequestHUDRefresh();
	}

	protected event OnDeactivateQuickHackIndicator( evt : DeactivateQuickHackIndicatorEvent )
	{
		DeactivateQuickHackIndicator();
	}

	private function GetQuickHackQueueSize() : Int32
	{
		var i : Int32;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].mappinVariant == gamedataMappinVariant.QuickHackVariant )
			{
				return m_mappins[ i ].visualStateData.m_action.GetDeviceActionQueueSize();
			}
		}
		return 0;
	}

	private function ActivatePhoneCallIndicator( visualData : GameplayRoleMappinData )
	{
		ToggleMappin( gamedataMappinVariant.PhoneCallVariant, true, true, visualData );
	}

	private function DeactivatePhoneCallIndicator()
	{
		ToggleMappin( gamedataMappinVariant.PhoneCallVariant, false );
	}

	protected event OnEvaluateMappinVisualStateEvent( evt : EvaluateMappinsVisualStateEvent )
	{
		if( m_isShowingMappins )
		{
			HideRoleMappins();
			ShowRoleMappins();
		}
	}

	protected event OnShowSingleMappin( evt : ShowSingleMappinEvent )
	{
		ShowSingleMappin( evt.index );
	}

	protected event OnHideSingleMappin( evt : HideSingleMappinEvent )
	{
		HideSingleMappin( evt.index );
	}

	private function DeterminGamplayRole()
	{
		if( m_autoDeterminGameplayRole && m_currentGameplayRole == EGameplayRole.UnAssigned )
		{
			m_currentGameplayRole = GetOwner().DeterminGameplayRole();
		}
		if( m_currentGameplayRole != EGameplayRole.None && m_currentGameplayRole != EGameplayRole.UnAssigned )
		{
			InitializeGamepleyRoleMappin();
		}
	}

	private function InitializeQuickHackIndicator()
	{
		var mappin : SDeviceMappinData;
		mappin.mappinType = T"Mappins.DeviceMappinDefinition";
		mappin.enabled = false;
		mappin.active = false;
		mappin.permanent = true;
		mappin.checkIfIsTarget = false;
		mappin.mappinVariant = gamedataMappinVariant.QuickHackVariant;
		mappin.gameplayRole = EGameplayRole.None;
		AddMappin( mappin );
		mappin.mappinType = T"Mappins.DeviceMappinHackDurationDefinition";
		mappin.enabled = false;
		mappin.active = false;
		mappin.permanent = true;
		mappin.checkIfIsTarget = false;
		mappin.mappinVariant = gamedataMappinVariant.Zzz15_QuickHackDurationVariant;
		mappin.gameplayRole = EGameplayRole.None;
		AddMappin( mappin );
	}

	private function InitializePhoneCallIndicator()
	{
		var mappin : SDeviceMappinData;
		mappin.mappinType = T"Mappins.DeviceMappinDefinition";
		mappin.enabled = false;
		mappin.active = false;
		mappin.permanent = true;
		mappin.checkIfIsTarget = false;
		mappin.mappinVariant = gamedataMappinVariant.PhoneCallVariant;
		mappin.gameplayRole = EGameplayRole.None;
		AddMappin( mappin );
	}

	private function InitializeGamepleyRoleMappin()
	{
		if( GetOwner().IsAttached() )
		{
			if( m_currentGameplayRole == EGameplayRole.UnAssigned || m_currentGameplayRole == EGameplayRole.None )
			{
				m_currentGameplayRole = GetOwner().DeterminGameplayRole();
			}
			m_isGameplayRoleInitialized = AddMappin( GetMappinDataForGamepleyRole( m_currentGameplayRole ) );
		}
	}

	private const function GetMappinDataForGamepleyRole( role : EGameplayRole ) : SDeviceMappinData
	{
		var mappin : SDeviceMappinData;
		if( ( role != EGameplayRole.None && role != EGameplayRole.UnAssigned ) || !( HasMappin( role ) ) )
		{
			mappin.enabled = false;
			mappin.active = false;
			mappin.range = 35.0;
			mappin.mappinVariant = GetCurrentMappinVariant( role );
			mappin.mappinType = T"Mappins.DeviceMappinDefinition";
		}
		mappin.gameplayRole = role;
		return mappin;
	}

	private const function GetCurrentMappinVariant( role : EGameplayRole ) : gamedataMappinVariant
	{
		var mappinVariant : gamedataMappinVariant;
		if( m_displayAllRolesAsGeneric )
		{
			mappinVariant = gamedataMappinVariant.GenericRoleVariant;
		}
		else if( m_mappinsDisplayMode == EMappinDisplayMode.PLAYSTYLE )
		{
			mappinVariant = GetPlaystyleMappinVariant();
		}
		else if( m_mappinsDisplayMode == EMappinDisplayMode.ROLE )
		{
			mappinVariant = GetRoleMappinVariant( role );
		}
		else if( m_mappinsDisplayMode == EMappinDisplayMode.MINIMALISTIC )
		{
			mappinVariant = GetMinimalisticMappinVariant();
		}
		return mappinVariant;
	}

	private const function GetMinimalisticMappinVariant() : gamedataMappinVariant
	{
		var mappinVariant : gamedataMappinVariant;
		if( GetOwner().IsAnyClueEnabled() )
		{
			mappinVariant = gamedataMappinVariant.FocusClueVariant;
		}
		else if( GetOwner().IsContainer() )
		{
			mappinVariant = gamedataMappinVariant.LootVariant;
		}
		else if( !( GetOwner().IsActive() ) )
		{
			mappinVariant = gamedataMappinVariant.Invalid;
		}
		else if( GetOwner().IsPlayerStash() )
		{
			mappinVariant = gamedataMappinVariant.Zzz07_PlayerStashVariant;
		}
		else if( GetOwner().IsWardrobe() )
		{
			mappinVariant = gamedataMappinVariant.Zzz08_WardrobeVariant;
		}
		else if( GetOwner().IsNPC() )
		{
			if( GetOwner().IsInvestigating() || GetOwner().HasHighlight( EFocusForcedHighlightType.INVALID, EFocusOutlineType.DISTRACTION ) )
			{
				mappinVariant = gamedataMappinVariant.EffectDistractVariant;
			}
			else if( GetOwner().IsHackingPlayer() )
			{
				mappinVariant = gamedataMappinVariant.NetrunnerVariant;
			}
			else if( GetOwner().IsActiveBackdoor() )
			{
				mappinVariant = gamedataMappinVariant.EffectControlNetworkVariant;
			}
			else
			{
				mappinVariant = gamedataMappinVariant.Invalid;
			}
		}
		else if( GetOwner().IsBodyDisposalPossible() )
		{
			mappinVariant = gamedataMappinVariant.EffectHideBodyVariant;
		}
		else if( GetOwner().IsActiveBackdoor() )
		{
			mappinVariant = gamedataMappinVariant.EffectControlNetworkVariant;
		}
		else if( GetOwner().IsExplosive() )
		{
			mappinVariant = gamedataMappinVariant.EffectExplodeLethalVariant;
		}
		else if( ( ( DisposalDevice )( GetOwner() ) ) && !( GetOwner().IsQuickHackAble() ) )
		{
			mappinVariant = gamedataMappinVariant.EffectHideBodyVariant;
		}
		else if( GetOwner().HasImportantInteraction() )
		{
			mappinVariant = gamedataMappinVariant.ImportantInteractionVariant;
		}
		else if( GetOwner().IsControllingDevices() )
		{
			mappinVariant = gamedataMappinVariant.EffectControlOtherDeviceVariant;
		}
		else if( GetOwner().HasAnyDirectInteractionActive() )
		{
			mappinVariant = gamedataMappinVariant.GenericRoleVariant;
		}
		else
		{
			mappinVariant = gamedataMappinVariant.Invalid;
		}
		return mappinVariant;
	}

	private const function GetPlaystyleMappinVariant() : gamedataMappinVariant
	{
		var mappinVariant : gamedataMappinVariant;
		if( GetOwner().IsAnyClueEnabled() )
		{
			mappinVariant = gamedataMappinVariant.FocusClueVariant;
		}
		else if( ( GetOwner().IsNetrunner() && GetOwner().IsSolo() ) && GetOwner().IsTechie() )
		{
			mappinVariant = gamedataMappinVariant.NetrunnerSoloTechieVariant;
		}
		else if( GetOwner().IsNetrunner() && GetOwner().IsSolo() )
		{
			mappinVariant = gamedataMappinVariant.NetrunnerSoloVariant;
		}
		else if( GetOwner().IsNetrunner() && GetOwner().IsTechie() )
		{
			mappinVariant = gamedataMappinVariant.NetrunnerTechieVariant;
		}
		else if( GetOwner().IsSolo() && GetOwner().IsTechie() )
		{
			mappinVariant = gamedataMappinVariant.SoloTechieVariant;
		}
		else if( GetOwner().IsNetrunner() )
		{
			mappinVariant = gamedataMappinVariant.NetrunnerVariant;
		}
		else if( GetOwner().IsTechie() )
		{
			mappinVariant = gamedataMappinVariant.TechieVariant;
		}
		else if( GetOwner().IsSolo() )
		{
			mappinVariant = gamedataMappinVariant.SoloVariant;
		}
		else
		{
			mappinVariant = gamedataMappinVariant.GenericRoleVariant;
		}
		return mappinVariant;
	}

	private const function GetRoleMappinVariant( role : EGameplayRole ) : gamedataMappinVariant
	{
		var mappinVariant : gamedataMappinVariant;
		if( GetOwner().IsAnyClueEnabled() )
		{
			mappinVariant = gamedataMappinVariant.FocusClueVariant;
		}
		else
		{
			switch( role )
			{
				case EGameplayRole.Alarm:
					mappinVariant = gamedataMappinVariant.EffectAlarmVariant;
				break;
				case EGameplayRole.ControlNetwork:
					mappinVariant = gamedataMappinVariant.EffectControlNetworkVariant;
				break;
				case EGameplayRole.ControlOtherDevice:
					mappinVariant = gamedataMappinVariant.EffectControlOtherDeviceVariant;
				break;
				case EGameplayRole.ControlSelf:
					mappinVariant = gamedataMappinVariant.EffectControlSelfVariant;
				break;
				case EGameplayRole.CutPower:
					mappinVariant = gamedataMappinVariant.EffectCutPowerVariant;
				break;
				case EGameplayRole.Distract:
					mappinVariant = gamedataMappinVariant.EffectDistractVariant;
				break;
				case EGameplayRole.DropPoint:
					mappinVariant = gamedataMappinVariant.EffectDropPointVariant;
				break;
				case EGameplayRole.ExplodeLethal:
					mappinVariant = gamedataMappinVariant.EffectExplodeLethalVariant;
				break;
				case EGameplayRole.ExplodeNoneLethal:
					mappinVariant = gamedataMappinVariant.EffectExplodeNonLethalVariant;
				break;
				case EGameplayRole.Fall:
					mappinVariant = gamedataMappinVariant.EffectFallVariant;
				break;
				case EGameplayRole.FastTravel:
					mappinVariant = gamedataMappinVariant.FastTravelVariant;
				break;
				case EGameplayRole.GrantInformation:
					mappinVariant = gamedataMappinVariant.EffectGrantInformationVariant;
				break;
				case EGameplayRole.Clue:
					mappinVariant = gamedataMappinVariant.FocusClueVariant;
				break;
				case EGameplayRole.HazardWarning:
					mappinVariant = gamedataMappinVariant.HazardWarningVariant;
				break;
				case EGameplayRole.HideBody:
					mappinVariant = gamedataMappinVariant.EffectHideBodyVariant;
				break;
				case EGameplayRole.Loot:
					mappinVariant = gamedataMappinVariant.EffectLootVariant;
				break;
				case EGameplayRole.OpenPath:
					mappinVariant = gamedataMappinVariant.EffectOpenPathVariant;
				break;
				case EGameplayRole.Push:
					mappinVariant = gamedataMappinVariant.EffectPushVariant;
				break;
				case EGameplayRole.ServicePoint:
					mappinVariant = gamedataMappinVariant.EffectServicePointVariant;
				break;
				case EGameplayRole.Shoot:
					mappinVariant = gamedataMappinVariant.EffectShootVariant;
				break;
				case EGameplayRole.SpreadGas:
					mappinVariant = gamedataMappinVariant.EffectSpreadGasVariant;
				break;
				case EGameplayRole.StoreItems:
					mappinVariant = gamedataMappinVariant.EffectStoreItemsVariant;
				break;
				case EGameplayRole.GenericRole:
					mappinVariant = gamedataMappinVariant.GenericRoleVariant;
				break;
				default:
					mappinVariant = gamedataMappinVariant.Invalid;
				break;
			}
		}
		return mappinVariant;
	}

	private function HasOffscreenArrow() : Bool
	{
		if( GetOwner().IsNPC() && ( GetOwner().IsInvestigating() || GetOwner().HasHighlight( EFocusForcedHighlightType.INVALID, EFocusOutlineType.DISTRACTION ) ) )
		{
			return true;
		}
		return false;
	}

	private function ReEvaluateGameplayRole()
	{
		var isShowingMappins : Bool;
		var oldRole : EGameplayRole;
		var newRole : EGameplayRole;
		var evt : GameplayRoleChangeNotification;
		isShowingMappins = m_isShowingMappins;
		oldRole = m_currentGameplayRole;
		ClearAllRoleMappins();
		DeterminGamplayRole();
		newRole = m_currentGameplayRole;
		if( isShowingMappins )
		{
			ShowRoleMappinsByTask();
		}
		if( GetCurrentGameplayRole() == EGameplayRole.None )
		{
			UpdateDefaultHighlight();
		}
		if( newRole != oldRole )
		{
			evt = new GameplayRoleChangeNotification;
			evt.oldRole = oldRole;
			evt.newRole = newRole;
			GetOwner().QueueEvent( evt );
		}
	}

	private function GetMappinSystem() : MappinSystem
	{
		return GameInstance.GetMappinSystem( GetOwner().GetGame() );
	}

	private function GetUISystem() : UISystem
	{
		return GameInstance.GetUISystem( GetOwner().GetGame() );
	}

	private virtual function EvaluateMappins()
	{
		var i : Int32;
		var isRoleValid : Bool;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].gameplayRole != EGameplayRole.None && m_mappins[ i ].gameplayRole != EGameplayRole.UnAssigned )
			{
				isRoleValid = GetOwner().IsGameplayRoleValid( m_mappins[ i ].gameplayRole );
				ToggleMappin( i, isRoleValid );
			}
		}
	}

	private function EvaluatePositions()
	{
		var currentOffset : Vector4;
		var currentPos : Vector4;
		var offsetValue : Float;
		var slotTransform : WorldTransform;
		var i : Int32;
		var direction : Int32;
		direction = 0;
		slotTransform = GetOwner().GetPlaystyleMappinSlotWorldTransform();
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( !( m_mappins[ i ].enabled ) )
			{
				continue;
			}
			else if( direction != 0 )
			{
				direction *= -1;
				offsetValue += ( m_offsetValue * ( ( Float )( direction ) ) );
			}
			else if( direction == 0 )
			{
				offsetValue = 0.0;
				direction = 1;
			}
			currentOffset = m_mappins[ i ].offset;
			currentOffset.X = currentOffset.X + offsetValue;
			currentPos = WorldPosition.ToVector4( WorldTransform.TransformPoint( slotTransform, currentOffset ) );
			m_mappins[ i ].position = currentPos;
			currentOffset = Vector4( 0.0, 0.0, 0.0, 0.0 );
			currentPos = Vector4( 0.0, 0.0, 0.0, 0.0 );
		}
	}

	private function GetNextAxis( currentAxis : EAxisType ) : EAxisType
	{
		var nextAxis : EAxisType;
		var axisValue : Int32;
		if( ( ( Int32 )( currentAxis ) ) < 3 )
		{
			axisValue += 1;
			nextAxis = ( ( EAxisType )( axisValue ) );
		}
		else
		{
			nextAxis = ( ( EAxisType )( 0 ) );
		}
		return nextAxis;
	}

	public function ShowRoleMappins()
	{
		var i : Int32;
		var visualData : GameplayRoleMappinData;
		var shouldUpdate : Bool;
		var shouldUpdateVariant : Bool;
		var currentVariant : gamedataMappinVariant;
		var invalidID : NewMappinID;
		var owner : GameObject;
		var lootContainer : gameLootContainerBase;
		var deviceBase : DeviceBase;
		owner = GetOwner();
		lootContainer = ( ( gameLootContainerBase )( owner ) );
		deviceBase = ( ( DeviceBase )( owner ) );
		if( ( deviceBase && !( deviceBase.IsLogicReady() ) ) || ( lootContainer && !( lootContainer.IsLogicReady() ) ) )
		{
			return;
		}
		if( HasActiveMappin( gamedataMappinVariant.QuickHackVariant ) || HasActiveMappin( gamedataMappinVariant.Zzz15_QuickHackDurationVariant ) )
		{
			return;
		}
		if( IsForceHidden() )
		{
			return;
		}
		if( !( m_isGameplayRoleInitialized ) )
		{
			InitializeGamepleyRoleMappin();
		}
		EvaluateMappins();
		if( !( m_alwaysCreateMappinAsDynamic ) )
		{
			EvaluatePositions();
		}
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( !( m_mappins[ i ].enabled ) )
			{
				continue;
			}
			if( m_mappins[ i ].gameplayRole == EGameplayRole.None || m_mappins[ i ].gameplayRole == EGameplayRole.UnAssigned )
			{
				continue;
			}
			else if( m_mappins[ i ].gameplayRole == EGameplayRole.Loot && GameInstance.GetSceneSystem( GetOwner().GetGame() ).GetScriptInterface().IsRewindableSectionActive() )
			{
				break;
			}
			m_isShowingMappins = true;
			m_canShowMappinsByTask = false;
			m_canHideMappinsByTask = false;
			currentVariant = GetCurrentMappinVariant( m_mappins[ i ].gameplayRole );
			if( currentVariant != m_mappins[ i ].mappinVariant )
			{
				m_mappins[ i ].mappinVariant = currentVariant;
				shouldUpdate = true;
				shouldUpdateVariant = true;
			}
			visualData = CreateRoleMappinData( m_mappins[ i ] );
			if( !( shouldUpdate ) && !( CompareRoleMappinsData( visualData, m_mappins[ i ].visualStateData ) ) )
			{
				shouldUpdate = true;
			}
			if( m_mappins[ i ].id != invalidID && shouldUpdate )
			{
				UpdateSingleMappinData( i, visualData, shouldUpdateVariant );
				return;
			}
			else if( m_mappins[ i ].id == invalidID )
			{
				ShowSingleMappin( i );
			}
			else if( m_mappins[ i ].id != invalidID )
			{
				ActivateSingleMappin( i );
			}
		}
	}

	private function CreateRoleMappinData( const data : ref< SDeviceMappinData > ) : GameplayRoleMappinData
	{
		var roleMappinData : GameplayRoleMappinData;
		var showOnMiniMap : Bool;
		roleMappinData = new GameplayRoleMappinData;
		if( m_forcedMappinVisualState != EMappinVisualState.None )
		{
			roleMappinData.m_mappinVisualState = m_forcedMappinVisualState;
		}
		else
		{
			roleMappinData.m_mappinVisualState = GetOwner().DeterminGameplayRoleMappinVisuaState( data );
		}
		roleMappinData.m_isTagged = GetOwner().IsTaggedinFocusMode();
		roleMappinData.m_isQuest = GetOwner().IsQuest() || ( GetOwner().IsAnyClueEnabled() && !( GetOwner().IsClueInspected() ) );
		roleMappinData.m_visibleThroughWalls = ( m_isForcedVisibleThroughWalls || GetOwner().IsObjectRevealed() ) || IsCurrentTarget();
		roleMappinData.m_range = GetOwner().DeterminGameplayRoleMappinRange( data );
		roleMappinData.m_isCurrentTarget = IsCurrentTarget();
		roleMappinData.m_gameplayRole = m_currentGameplayRole;
		roleMappinData.m_braindanceLayer = GetOwner().GetBraindanceLayer();
		roleMappinData.m_quality = GetOwner().GetLootQuality();
		roleMappinData.m_isIconic = GetOwner().GetIsIconic();
		roleMappinData.m_isBroken = GetOwner().GetIsBroken();
		roleMappinData.m_hasOffscreenArrow = HasOffscreenArrow();
		roleMappinData.m_isScanningCluesBlocked = GetOwner().IsAnyClueEnabled() && GetOwner().IsScaningCluesBlocked();
		roleMappinData.m_textureID = GetIconIdForMappinVariant( data.mappinVariant );
		if( data.mappinVariant == gamedataMappinVariant.Zzz07_PlayerStashVariant || data.mappinVariant == gamedataMappinVariant.Zzz08_WardrobeVariant )
		{
			showOnMiniMap = true;
		}
		else if( ( roleMappinData.m_isQuest && ( roleMappinData.m_textureID != T"MappinIcons.ShardMappin" ) ) || roleMappinData.m_isTagged )
		{
			showOnMiniMap = true;
		}
		else if( data.mappinVariant != gamedataMappinVariant.LootVariant && ( roleMappinData.m_isCurrentTarget || roleMappinData.m_visibleThroughWalls ) )
		{
			showOnMiniMap = true;
		}
		else
		{
			showOnMiniMap = m_enabledMinimapMappins.Contains( data.mappinVariant );
		}
		if( roleMappinData.m_textureID == T"MappinIcons.ShardMappin" )
		{
			roleMappinData.m_isShardRead = IsShardRead();
		}
		roleMappinData.m_showOnMiniMap = showOnMiniMap;
		return roleMappinData;
	}

	private function IsShardRead() : Bool
	{
		var shard : ShardCaseContainer;
		var isRead : Bool;
		isRead = false;
		shard = ( ( ShardCaseContainer )( GetOwner() ) );
		if( shard )
		{
			isRead = shard.IsShardRead();
		}
		return isRead;
	}

	private function CompareRoleMappinsData( data1 : GameplayRoleMappinData, data2 : GameplayRoleMappinData ) : Bool
	{
		if( ( data1 == NULL ) && ( data2 != NULL ) )
		{
			return false;
		}
		else if( ( data1 != NULL ) && ( data2 == NULL ) )
		{
			return false;
		}
		else if( data1.m_isTagged != data2.m_isTagged )
		{
			return false;
		}
		else if( data1.m_mappinVisualState != data2.m_mappinVisualState )
		{
			return false;
		}
		else if( data1.m_visibleThroughWalls != data2.m_visibleThroughWalls )
		{
			return false;
		}
		else if( data1.m_isCurrentTarget != data2.m_isCurrentTarget )
		{
			return false;
		}
		else if( data1.m_isQuest != data2.m_isQuest )
		{
			return false;
		}
		else if( data1.m_isIconic != data2.m_isIconic )
		{
			return false;
		}
		else if( data1.m_isBroken != data2.m_isBroken )
		{
			return false;
		}
		else if( data1.m_textureID != data2.m_textureID )
		{
			return false;
		}
		else if( data1.m_quality != data2.m_quality )
		{
			return false;
		}
		else if( data1.m_isScanningCluesBlocked != data2.m_isScanningCluesBlocked )
		{
			return false;
		}
		else if( data1.m_gameplayRole != data2.m_gameplayRole )
		{
			return false;
		}
		else if( data1.m_braindanceLayer != data2.m_braindanceLayer )
		{
			return false;
		}
		else if( data1.m_showOnMiniMap != data2.m_showOnMiniMap )
		{
			return false;
		}
		return true;
	}

	private function GetIconIdForMappinVariant( mappinVariant : gamedataMappinVariant ) : TweakDBID
	{
		var id : TweakDBID;
		if( mappinVariant == gamedataMappinVariant.NPCVariant )
		{
			id = T"MappinIcons.NPCMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.FastTravelVariant )
		{
			id = T"MappinIcons.FastTravelMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.DistractVariant )
		{
			id = T"MappinIcons.DistractMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.LootVariant )
		{
			if( GetOwner().IsShardContainer() )
			{
				id = T"MappinIcons.ShardMappin";
			}
			else if( GetOwner().IsQuest() )
			{
				id = T"MappinIcons.QuestMappin";
			}
			else if( GetOwner().IsAmmoLoot() )
			{
				id = T"MappinIcons.LootAmmoGenericMappin";
			}
			else if( GetOwner().GetIsIconic() )
			{
				id = T"MappinIcons.LootMappinIconic";
			}
			else
			{
				id = T"MappinIcons.LootMappin";
			}
		}
		else if( mappinVariant == gamedataMappinVariant.EffectExplodeLethalVariant )
		{
			id = T"MappinIcons.ExplosiveDevice";
		}
		else if( mappinVariant == gamedataMappinVariant.EffectDropPointVariant )
		{
			id = T"MappinIcons.DropPointMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.FocusClueVariant )
		{
			id = T"MappinIcons.ClueMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.PhoneCallVariant )
		{
			id = T"MappinIcons.PhoneCallMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.EffectControlNetworkVariant )
		{
			id = T"MappinIcons.BackdoorDeviceMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.EffectControlOtherDeviceVariant )
		{
			id = T"MappinIcons.ControlPanleDeviceMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.NetrunnerVariant )
		{
			id = T"MappinIcons.EnemyNetrunnerMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.EffectHideBodyVariant )
		{
			id = T"MappinIcons.HideBodyMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.ImportantInteractionVariant )
		{
			if( GetOwner().IsQuickHackAble() )
			{
				id = T"MappinIcons.HackableDeviceMappin";
			}
			else
			{
				id = T"MappinIcons.InteractiveDeviceMappin";
			}
		}
		else if( mappinVariant == gamedataMappinVariant.GenericRoleVariant )
		{
			id = T"MappinIcons.GenericDeviceMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.Zzz07_PlayerStashVariant )
		{
			id = T"MappinIcons.PlayerStashMappin";
		}
		else if( mappinVariant == gamedataMappinVariant.Zzz08_WardrobeVariant )
		{
			id = T"MappinIcons.WardrobeMappin";
		}
		return id;
	}

	public function HideRoleMappins()
	{
		var i : Int32;
		var invalidID : NewMappinID;
		m_isShowingMappins = false;
		m_canShowMappinsByTask = false;
		m_canHideMappinsByTask = false;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].gameplayRole == EGameplayRole.None && m_mappins[ i ].gameplayRole == EGameplayRole.UnAssigned )
			{
				continue;
			}
			if( m_mappins[ i ].permanent && m_mappins[ i ].active )
			{
				continue;
			}
			if( m_mappins[ i ].active || ( !( m_mappins[ i ].active ) && m_mappins[ i ].id != invalidID ) )
			{
				DeactivateSingleMappin( i );
			}
		}
	}

	private function ClearAllRoleMappins()
	{
		var i : Int32;
		m_canShowMappinsByTask = false;
		m_canHideMappinsByTask = false;
		for( i = m_mappins.Size() - 1; i >= 0; i -= 1 )
		{
			if( m_mappins[ i ].gameplayRole != EGameplayRole.None && m_mappins[ i ].gameplayRole != EGameplayRole.UnAssigned )
			{
				if( m_mappins[ i ].active )
				{
					HideSingleMappin( i );
				}
				m_mappins.Erase( i );
			}
		}
	}

	public function UnregisterAllRoleMappins()
	{
		var i : Int32;
		m_isShowingMappins = false;
		m_canShowMappinsByTask = false;
		m_canHideMappinsByTask = false;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].gameplayRole == EGameplayRole.None || m_mappins[ i ].gameplayRole == EGameplayRole.UnAssigned )
			{
				continue;
			}
			if( m_mappins[ i ].active )
			{
				HideSingleMappin( i );
			}
		}
	}

	protected event OnUnregisterAllMappinsEvent( evt : UnregisterAllMappinsEvent )
	{
		UnregisterAllMappins();
	}

	public function UnregisterAllMappins()
	{
		var i : Int32;
		var invalidID : NewMappinID;
		m_isShowingMappins = false;
		m_canShowMappinsByTask = false;
		m_canHideMappinsByTask = false;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].active || m_mappins[ i ].id != invalidID )
			{
				HideSingleMappin( i );
			}
		}
	}

	private function HideSingleMappin_Event( index : Int32 )
	{
		var evt : HideSingleMappinEvent;
		evt = new HideSingleMappinEvent;
		evt.index = index;
		QueueEntityEvent( evt );
	}

	private function HideSingleMappin( index : Int32 )
	{
		var invalidID : NewMappinID;
		GetMappinSystem().UnregisterMappin( m_mappins[ index ].id );
		m_mappins[ index ].id = invalidID;
		m_mappins[ index ].active = false;
		if( !( IsFinal() ) )
		{
		}
	}

	private function DeactivateSingleMappin( index : Int32 )
	{
		m_mappins[ index ].active = false;
		GetMappinSystem().SetMappinActive( m_mappins[ index ].id, false );
		if( !( IsFinal() ) )
		{
		}
	}

	private function ShowSingleMappin_Event( index : Int32 )
	{
		var evt : ShowSingleMappinEvent;
		if( ( index < 0 ) || ( index > ( m_mappins.Size() - 1 ) ) )
		{
			return;
		}
		m_mappins[ index ].active = true;
		evt = new ShowSingleMappinEvent;
		evt.index = index;
		QueueEntityEvent( evt );
	}

	private function ShowSingleMappin( index : Int32, visualData : GameplayRoleMappinData, optional bindPositionToSlotName : CName )
	{
		var mappinData : MappinData;
		var slotname : CName;
		var slotTransform : WorldTransform;
		var currentPos : Vector4;
		if( ( index < 0 ) || ( index > ( m_mappins.Size() - 1 ) ) )
		{
			return;
		}
		mappinData.mappinType = m_mappins[ index ].mappinType;
		mappinData.variant = m_mappins[ index ].mappinVariant;
		mappinData.active = true;
		mappinData.debugCaption = m_mappins[ index ].caption;
		mappinData.scriptData = visualData;
		mappinData.visibleThroughWalls = visualData.m_visibleThroughWalls;
		m_mappins[ index ].active = true;
		m_mappins[ index ].visualStateData = visualData;
		if( IsMappinDynamic() )
		{
			if( m_mappins[ index ].mappinVariant == gamedataMappinVariant.PhoneCallVariant )
			{
				slotname = GetOwner().GetPhoneCallIndicatorSlotName();
			}
			else if( m_mappins[ index ].mappinVariant == gamedataMappinVariant.QuickHackVariant )
			{
				slotname = GetOwner().GetQuickHackIndicatorSlotName();
			}
			else if( m_mappins[ index ].mappinVariant == gamedataMappinVariant.Zzz15_QuickHackDurationVariant )
			{
				slotname = 'durationBar';
			}
			else
			{
				slotname = GetOwner().GetRoleMappinSlotName();
			}
			if( IsNameValid( bindPositionToSlotName ) )
			{
				GetOwner().GetUISlotComponent().GetSlotTransform( bindPositionToSlotName, slotTransform );
				currentPos = WorldPosition.ToVector4( WorldTransform.TransformPoint( slotTransform, m_mappins[ index ].offset ) );
				m_mappins[ index ].id = GetMappinSystem().RegisterMappin( mappinData, currentPos );
			}
			else
			{
				if( IsNameValid( slotname ) )
				{
					m_mappins[ index ].id = GetMappinSystem().RegisterMappinWithObject( mappinData, GetOwner(), slotname );
				}
				else
				{
					m_mappins[ index ].id = GetMappinSystem().RegisterMappin( mappinData, m_mappins[ index ].position );
				}
			}
		}
		else
		{
			m_mappins[ index ].id = GetMappinSystem().RegisterMappin( mappinData, m_mappins[ index ].position );
		}
		GetMappinSystem().SetMappinActive( m_mappins[ index ].id, true );
		if( !( IsFinal() ) )
		{
		}
	}

	private function ShowSingleMappin( index : Int32 )
	{
		var mappinData : MappinData;
		var visualData : GameplayRoleMappinData;
		var slotname : CName;
		var worldOffset : Vector3;
		if( ( index < 0 ) || ( index > ( m_mappins.Size() - 1 ) ) )
		{
			return;
		}
		visualData = CreateRoleMappinData( m_mappins[ index ] );
		mappinData.mappinType = m_mappins[ index ].mappinType;
		mappinData.variant = m_mappins[ index ].mappinVariant;
		mappinData.active = true;
		mappinData.debugCaption = m_mappins[ index ].caption;
		mappinData.scriptData = visualData;
		mappinData.visibleThroughWalls = visualData.m_visibleThroughWalls;
		m_mappins[ index ].active = true;
		m_mappins[ index ].visualStateData = visualData;
		if( IsMappinDynamic() )
		{
			if( m_mappins[ index ].mappinVariant == gamedataMappinVariant.PhoneCallVariant )
			{
				slotname = GetOwner().GetPhoneCallIndicatorSlotName();
			}
			else if( m_mappins[ index ].mappinVariant == gamedataMappinVariant.QuickHackVariant )
			{
				slotname = GetOwner().GetQuickHackIndicatorSlotName();
			}
			else if( m_mappins[ index ].mappinVariant == gamedataMappinVariant.Zzz15_QuickHackDurationVariant )
			{
				slotname = 'durationBar';
			}
			else
			{
				slotname = GetOwner().GetRoleMappinSlotName();
			}
			if( m_mappins[ index ].mappinVariant == gamedataMappinVariant.LootVariant && GetOwner().IsNPC() )
			{
				worldOffset = Vector3( 0.0, 0.0, 0.16 );
			}
			m_mappins[ index ].id = GetMappinSystem().RegisterMappinWithObject( mappinData, GetOwner(), slotname, worldOffset );
		}
		else
		{
			m_mappins[ index ].id = GetMappinSystem().RegisterMappin( mappinData, m_mappins[ index ].position );
		}
		GetMappinSystem().SetMappinActive( m_mappins[ index ].id, true );
		if( !( IsFinal() ) )
		{
		}
	}

	private function UpdateSingleMappinData( index : Int32, visualData : GameplayRoleMappinData, shouldUpdateVariant : Bool )
	{
		if( ( index < 0 ) || ( index > ( m_mappins.Size() - 1 ) ) )
		{
			return;
		}
		if( shouldUpdateVariant )
		{
			HideSingleMappin( index );
			ShowSingleMappin( index, visualData );
			return;
		}
		m_mappins[ index ].visualStateData = visualData;
		GetMappinSystem().SetMappinScriptData( m_mappins[ index ].id, visualData );
	}

	private function ActivateSingleMappin( index : Int32 )
	{
		m_mappins[ index ].active = true;
		GetMappinSystem().SetMappinActive( m_mappins[ index ].id, true );
		if( !( IsFinal() ) )
		{
		}
	}

	public const function HasActiveMappin( mappinVariant : gamedataMappinVariant ) : Bool
	{
		var i : Int32;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].mappinVariant == mappinVariant && m_mappins[ i ].active )
			{
				return true;
			}
		}
		return false;
	}

	private const function HasMappin( mappinVariant : gamedataMappinVariant ) : Bool
	{
		var i : Int32;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].mappinVariant == mappinVariant )
			{
				return true;
			}
		}
		return false;
	}

	private const function HasMappin( const data : ref< SDeviceMappinData > ) : Bool
	{
		var i : Int32;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( ( m_mappins[ i ].mappinVariant == data.mappinVariant && ( m_mappins[ i ].mappinType == data.mappinType ) ) && m_mappins[ i ].caption == data.caption )
			{
				return true;
			}
		}
		return false;
	}

	private const function HasMappin( gameplayRole : EGameplayRole ) : Bool
	{
		var i : Int32;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].gameplayRole == gameplayRole )
			{
				return true;
			}
		}
		return false;
	}

	private function IsMappinDataValid( const mappinData : ref< SDeviceMappinData > ) : Bool
	{
		return mappinData.mappinVariant != gamedataMappinVariant.Invalid && TDBID.IsValid( mappinData.mappinType );
	}

	private function IsMappinDynamic() : Bool
	{
		return m_alwaysCreateMappinAsDynamic || GetOwner().IsNetworkLinkDynamic();
	}

	private const function IsCurrentTarget() : Bool
	{
		return m_isBeingScanned || m_isCurrentTarget;
	}

	public function AddQuickhackMappinToQueue( visualData : GameplayRoleMappinData )
	{
		var i : Int32;
		var evt : QueueQuickHackEvent;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].mappinVariant == gamedataMappinVariant.QuickHackVariant && m_mappins[ i ].active )
			{
				evt = new QueueQuickHackEvent;
				evt.mappinID = m_mappins[ i ].id;
				evt.data = visualData;
				GetUISystem().QueueEvent( evt );
				return;
			}
		}
	}

	public function RemoveQuickhackMappinFromQueue()
	{
		var i : Int32;
		var evt : DequeueQuickHackEvent;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].mappinVariant == gamedataMappinVariant.QuickHackVariant && m_mappins[ i ].active )
			{
				evt = new DequeueQuickHackEvent;
				evt.mappinID = m_mappins[ i ].id;
				GetUISystem().QueueEvent( evt );
				return;
			}
		}
	}

	public function ToggleMappin( mappinVariant : gamedataMappinVariant, enable : Bool, show : Bool, visualData : GameplayRoleMappinData, optional bindPositionToSlotName : CName )
	{
		var i : Int32;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].mappinVariant == mappinVariant )
			{
				m_mappins[ i ].enabled = enable;
				if( !( enable ) )
				{
					if( m_mappins[ i ].active )
					{
						HideSingleMappin( i );
					}
				}
				else if( show && !( m_mappins[ i ].active ) )
				{
					EvaluatePositions();
					ShowSingleMappin( i, visualData, bindPositionToSlotName );
				}
			}
		}
	}

	public function ToggleMappin( mappinVariant : gamedataMappinVariant, enable : Bool, show : Bool )
	{
		var i : Int32;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].mappinVariant == mappinVariant )
			{
				m_mappins[ i ].enabled = enable;
				if( !( enable ) )
				{
					if( m_mappins[ i ].active )
					{
						HideSingleMappin( i );
					}
				}
				else if( show && !( m_mappins[ i ].active ) )
				{
					EvaluatePositions();
					ShowSingleMappin( i );
				}
			}
		}
	}

	public function ToggleMappin( mappinVariant : gamedataMappinVariant, enable : Bool )
	{
		var i : Int32;
		for( i = 0; i < m_mappins.Size(); i += 1 )
		{
			if( m_mappins[ i ].mappinVariant == mappinVariant )
			{
				ToggleMappin( i, enable );
			}
		}
	}

	public function ToggleMappin( mappinIndex : Int32, enable : Bool )
	{
		if( mappinIndex >= m_mappins.Size() )
		{
			return;
		}
		m_mappins[ mappinIndex ].enabled = enable;
		if( !( enable ) && m_mappins[ mappinIndex ].active )
		{
			HideSingleMappin( mappinIndex );
		}
	}

	public function AddMappin( const data : ref< SDeviceMappinData > ) : Bool
	{
		if( IsMappinDataValid( data ) && !( HasMappin( data ) ) )
		{
			m_mappins.PushBack( data );
			return true;
		}
		return false;
	}

	public const function GetCurrentGameplayRole() : EGameplayRole
	{
		return m_currentGameplayRole;
	}

	public const function IsGameplayRoleStatic() : Bool
	{
		return m_gameplayRole != EGameplayRole.UnAssigned;
	}

	public const function GetForcedMappinVisualState() : EMappinVisualState
	{
		return m_forcedMappinVisualState;
	}

	protected function UpdateDefaultHighlight()
	{
		var updateHighlightEvt : ForceUpdateDefaultHighlightEvent;
		updateHighlightEvt = new ForceUpdateDefaultHighlightEvent;
		GetOwner().QueueEvent( updateHighlightEvt );
	}

	private function IsForceHidden() : Bool
	{
		return m_isForceHidden;
	}

	private function SetForceHidden( isHidden : Bool )
	{
		m_isForceHidden = isHidden;
		if( isHidden )
		{
			HideRoleMappins();
		}
		else
		{
			RequestHUDRefresh();
		}
	}

	protected event OnToggleGameplayMappinVisibilityEvent( evt : ToggleGameplayMappinVisibilityEvent )
	{
		SetForceHidden( evt.isHidden );
	}

	private function RequestHUDRefresh()
	{
		var request : RefreshActorRequest;
		var owner : GameObject;
		var hudManager : HUDManager;
		var modules : array< weak< HUDModule > >;
		owner = GetOwner();
		if( owner )
		{
			hudManager = owner.GetHudManager();
		}
		if( !( hudManager ) )
		{
			return;
		}
		modules.PushBack( hudManager.GetIconsModule() );
		request = RefreshActorRequest.Construct( owner.GetEntityID(), , modules );
		hudManager.QueueRequest( request );
	}

	public function EnableMappinVariantOnMinimap( mappinVariant : gamedataMappinVariant )
	{
		if( !( m_enabledMinimapMappins.Contains( mappinVariant ) ) )
		{
			m_enabledMinimapMappins.PushBack( mappinVariant );
		}
	}

}

