struct CachedItemLoadout
{
	persistent var itemID : ItemID;
	persistent var slot : TweakDBID;
}

class NPCBreachEvent extends Event
{
	var state : HackingMinigameState;
}

class DrawBetweenEntitiesEvent extends Event
{
	var shouldDraw : Bool;
	var fxResource : FxResource;
	var revealMaster : Bool;
	var revealSlave : Bool;
	var masterEntity : EntityID;
	var slaveEntity : EntityID;
}

class OverrideScannerPreset extends Event
{
	[ customEditor = "TweakDBGroupInheritance;ScannerModuleVisibilityPreset" ]
	editable var scannerPreset : TweakDBID;

	public constexpr function GetFriendlyDescription() : String
	{
		return "Override Scanner Preset";
	}

}

class ResetScannerPreset extends Event
{

	public constexpr function GetFriendlyDescription() : String
	{
		return "Reset Scanner Preset";
	}

}

class SecurityBreachPuppetNotificationEvent extends SecuritySystemInput
{
}

struct SecuritySystemData
{
	persistent var suppressIncomingEvents : Bool;
	persistent var suppressOutgoingEvents : Bool;

	public static function AreIncomingEventsSuppressed( self : SecuritySystemData ) : Bool
	{
		return self.suppressIncomingEvents;
	}

	public static function AreOutgoingEventsSuppressed( self : SecuritySystemData ) : Bool
	{
		return self.suppressOutgoingEvents;
	}

}

class ScriptedPuppetPS extends GamePuppetPS
{
	private var m_deviceLink : weak< PuppetDeviceLinkPS >;
	private var m_cooldownStorage : CooldownStorage;
	private persistent var m_isInitialized : EBOOL;
	private persistent var m_wasAttached : Bool;
	protected persistent var m_wasRevealedInNetworkPing : Bool;
	private var m_numberActions : Int32;
	protected var m_wasQuickHackAttempt : Bool;
	protected var m_hasDirectInteractionChoicesActive : Bool;
	private persistent var m_wasIncapacitated : Bool;
	private persistent var m_isBreached : Bool;
	private persistent var m_isDead : Bool;
	private persistent var m_isIncapacitated : Bool;
	private persistent var m_isAndroidTurnedOff : Bool;
	private persistent var m_isPreventionNotified : Bool;
	private persistent var m_securitySystemData : SecuritySystemData;
	private var m_activeContexts : array< gamedeviceRequestType >;
	protected var m_lastInteractionLayerTag : CName;
	private persistent var m_quickHacksExposed : Bool;
	private var m_currentCooldownID : Uint32;
	private persistent var m_reactionPresetID : TweakDBID;
	private persistent var m_isDefeatMechanicActive : Bool;
	default m_isDefeatMechanicActive = true;
	private persistent var m_leftHandLoadout : ItemID;
	private persistent var m_rightHandLoadout : ItemID;
	private persistent var m_customWeaponLoadout : array< CachedItemLoadout >;
	private persistent var m_genericMeleeLoadout : CachedItemLoadout;
	private persistent var m_genericRangedLoadout : CachedItemLoadout;
	private persistent var m_questForceScannerPreset : TweakDBID;
	private persistent var m_bountyID : TweakDBID;
	private persistent var m_transgressions : array< TweakDBID >;

	protected event OnInstantiated()
	{
		if( !( IsInitialized() ) )
		{
			Initialize();
		}
	}

	private function Initialize()
	{
		m_isInitialized = EBOOL.TRUE;
	}

	public const function IsInitialized() : Bool
	{
		return m_isInitialized == EBOOL.TRUE;
	}

	public const function WasAttached() : Bool
	{
		return m_wasAttached;
	}

	protected export function OnGameAttached( evt : GameAttachedEvent ) : EntityNotificationType
	{
		m_wasAttached = true;
		if( !( IsInitialized() ) )
		{
			Initialize();
		}
		InitializeCooldownStorage();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	protected function InitializeCooldownStorage()
	{
		if( !( m_cooldownStorage ) )
		{
			m_cooldownStorage = new CooldownStorage;
			m_cooldownStorage.Initialize( GetID(), GetClassName(), GetGameInstance() );
		}
	}

	protected const function ExecutePSAction( action : ScriptableDeviceAction, persistentState : PersistentState )
	{
		if( !( EntityID.IsDefined( action.GetRequesterID() ) ) )
		{
			action.RegisterAsRequester( PersistentID.ExtractEntityID( GetID() ) );
		}
		GameInstance.GetPersistencySystem( GetGameInstance() ).QueuePSEvent( persistentState.GetID(), persistentState.GetClassName(), action );
	}

	public function GetCooldownStorage() : CooldownStorage
	{
		return m_cooldownStorage;
	}

	public function GetPlayerCooldownStorage() : CooldownStorage
	{
		var player : PlayerPuppet;
		player = ( ( PlayerPuppet )( GetPlayerMainObject() ) );
		if( player )
		{
			return player.GetCooldownStorage();
		}
		return NULL;
	}

	protected const function GetPlayerMainObject() : GameObject
	{
		return GameInstance.GetPlayerSystem( GetGameInstance() ).GetLocalPlayerMainGameObject();
	}

	public function StoreBountyData( bountyID : TweakDBID, const transgressions : ref< array< TweakDBID > > )
	{
		m_bountyID = bountyID;
		m_transgressions = transgressions;
	}

	public const function GetBountyID() : TweakDBID
	{
		return m_bountyID;
	}

	public const function GetTransgressions() : array< TweakDBID >
	{
		return m_transgressions;
	}

	public const function GetSecurityAreas( optional includeInactive : Bool, optional returnOnlyDirectlyConnected : Bool ) : array< SecurityAreaControllerPS >
	{
		return GetDeviceLink().GetSecurityAreas( includeInactive, returnOnlyDirectlyConnected );
	}

	public const function GetSecuritySystem() : SecuritySystemControllerPS
	{
		var link : PuppetDeviceLinkPS;
		var secSys : SecuritySystemControllerPS;
		link = GetDeviceLink();
		if( link )
		{
			secSys = link.GetSecuritySystem();
			if( secSys && !( secSys.IsDisabled() ) )
			{
				return secSys;
			}
		}
		return NULL;
	}

	public function OnSecuritySystemOutput( evt : SecuritySystemOutput ) : EntityNotificationType
	{
		if( evt.GetOriginalInputEvent().HasCustomRecipients() )
		{
			return EntityNotificationType.SendThisEventToEntity;
		}
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public const function DetermineSecurityAreaTypeForEntityID( entityID : EntityID ) : ESecurityAreaType
	{
		if( GetDeviceLink() )
		{
			return GetDeviceLink().GetSecuritySystem().DetermineSecurityAreaTypeForEntityID( entityID );
		}
		return ESecurityAreaType.DISABLED;
	}

	public const function GetAccessPoint() : AccessPointControllerPS
	{
		if( GetDeviceLink() )
		{
			return GetDeviceLink().GetBackdoorAccessPoint();
		}
		return NULL;
	}

	public const function GetWasIncapacitated() : Bool
	{
		return m_wasIncapacitated;
	}

	public const function IsConnectedToAccessPoint() : Bool
	{
		if( GetDeviceLink() )
		{
			return GetDeviceLink().HasNetworkBackdoor();
		}
		return false;
	}

	public const function IsConnectedToSecuritySystem() : Bool
	{
		if( GetDeviceLink() )
		{
			return GetDeviceLink().IsConnectedToSecuritySystem();
		}
		return false;
	}

	public constexpr static function GetNPCsConnectedToThisAPCount() : Int32
	{
		return 666;
	}

	public const function GetNetworkName() : String
	{
		if( GetDeviceLink() )
		{
			return GetDeviceLink().GetNetworkName();
		}
		return "";
	}

	public const function CheckMasterConnectedClassTypes() : ConnectedClassTypes
	{
		var emptyReturn : ConnectedClassTypes;
		if( GetDeviceLink() )
		{
			return GetDeviceLink().CheckMasterConnectedClassTypes();
		}
		return emptyReturn;
	}

	public const function GetActiveContexts() : array< gamedeviceRequestType >
	{
		return m_activeContexts;
	}

	public const function HasDirectInteractionChoicesActive() : Bool
	{
		return m_hasDirectInteractionChoicesActive;
	}

	public function SetHasDirectInteractionChoicesActive( hasInteraction : Bool )
	{
		m_hasDirectInteractionChoicesActive = hasInteraction;
	}

	public const function GetLeftHandLoadout() : ItemID
	{
		return m_leftHandLoadout;
	}

	public const function GetRightHandLoadout() : ItemID
	{
		return m_rightHandLoadout;
	}

	public const function GetCustomWeaponLoadout() : array< CachedItemLoadout >
	{
		return m_customWeaponLoadout;
	}

	public const function GetGenericMeleeLoadout() : CachedItemLoadout
	{
		return m_genericMeleeLoadout;
	}

	public const function GetGenericRangedLoadout() : CachedItemLoadout
	{
		return m_genericRangedLoadout;
	}

	public const function GetForcedScannerPreset() : TweakDBID
	{
		return m_questForceScannerPreset;
	}

	public function SetForcedScannerPreset( preset : TweakDBID )
	{
		m_questForceScannerPreset = preset;
	}

	public const function DrawBetweenEntities( shouldDraw : Bool, focusModeOnly : Bool, fxResource : FxResource, masterID : EntityID, slaveID : EntityID, revealMaster : Bool, revealSlave : Bool, optional onlyRemoveWeakLink : Bool, optional isEyeContact : Bool, optional isPermanent : Bool )
	{
		var registerLinkRequest : RegisterNetworkLinkRequest;
		var unregisterLinkRequest : UnregisterNetworkLinkBetweenTwoEntitiesRequest;
		var unregisterLinkRequestByID : UnregisterNetworkLinksByIDRequest;
		var newLink : SNetworkLinkData;
		var masterPuppet : ScriptedPuppet;
		var slavePuppet : ScriptedPuppet;
		var currentID : EntityID;
		newLink.slaveID = slaveID;
		newLink.masterID = masterID;
		newLink.permanent = isPermanent;
		if( shouldDraw )
		{
			masterPuppet = ( ( ScriptedPuppet )( GameInstance.FindEntityByID( GetGameInstance(), masterID ) ) );
			slavePuppet = ( ( ScriptedPuppet )( GameInstance.FindEntityByID( GetGameInstance(), slaveID ) ) );
			newLink.weakLink = isEyeContact;
			if( masterPuppet != NULL )
			{
				newLink.masterPos = masterPuppet.GetWorldPosition();
			}
			if( slavePuppet != NULL )
			{
				newLink.slavePos = slavePuppet.GetWorldPosition();
			}
			newLink.linkType = ELinkType.NETWORK;
			newLink.isDynamic = true;
			newLink.fxResource = fxResource;
			newLink.revealMaster = revealMaster;
			newLink.revealSlave = revealSlave;
			newLink.drawLink = true;
			if( focusModeOnly )
			{
				newLink.isNetrunner = true;
			}
			else
			{
				newLink.isPing = true;
			}
			registerLinkRequest = new RegisterNetworkLinkRequest;
			registerLinkRequest.linksData.PushBack( newLink );
			GetNetworkSystem().QueueRequest( registerLinkRequest );
		}
		else
		{
			if( EntityID.IsDefined( masterID ) && EntityID.IsDefined( slaveID ) )
			{
				unregisterLinkRequest = new UnregisterNetworkLinkBetweenTwoEntitiesRequest;
				unregisterLinkRequest.firstID = slaveID;
				unregisterLinkRequest.secondID = masterID;
				unregisterLinkRequest.onlyRemoveWeakLink = onlyRemoveWeakLink;
				GetNetworkSystem().QueueRequest( unregisterLinkRequest );
			}
			else
			{
				if( EntityID.IsDefined( masterID ) )
				{
					currentID = masterID;
				}
				else if( EntityID.IsDefined( slaveID ) )
				{
					currentID = slaveID;
				}
				unregisterLinkRequestByID = new UnregisterNetworkLinksByIDRequest;
				unregisterLinkRequestByID.ID = currentID;
				GetNetworkSystem().QueueRequest( unregisterLinkRequestByID );
			}
		}
	}

	protected const function GetOwnerEntity() : weak< ScriptedPuppet >
	{
		return ( ( ScriptedPuppet )( GameInstance.FindEntityByID( GetGameInstance(), PersistentID.ExtractEntityID( GetID() ) ) ) );
	}

	private constexpr static function CanPerformReprimend() : Bool
	{
		return true;
	}

	public const function IsQuickHacksExposed() : Bool
	{
		if( GetNetworkSystem().QuickHacksExposedByDefault() )
		{
			if( GetOwnerEntity().GetAttitudeTowards( GetPlayer( GetGameInstance() ) ) == EAIAttitude.AIA_Friendly )
			{
				return false;
			}
			return true;
		}
		else
		{
			if( GetFact( GetGameInstance(), 'cheat_expose_npc_quick_hacks' ) > 0 )
			{
				return true;
			}
			return m_quickHacksExposed;
		}
	}

	public const function WasRevealedInNetworkPing() : Bool
	{
		return m_wasRevealedInNetworkPing || GetDeviceLink().WasRevealedInNetworkPing();
	}

	public function SetRevealedInNetworkPing( wasRevealed : Bool )
	{
		if( m_wasRevealedInNetworkPing == wasRevealed )
		{
			return;
		}
		m_wasRevealedInNetworkPing = wasRevealed;
		GetDeviceLink().SetRevealedInNetworkPing( m_wasRevealedInNetworkPing );
	}

	protected const function GetNetworkSystem() : NetworkSystem
	{
		return ( ( NetworkSystem )( GameInstance.GetScriptableSystemsContainer( GetGameInstance() ).Get( 'NetworkSystem' ) ) );
	}

	public export function OnDeviceAttachment( evt : DeviceLinkEstablished ) : EntityNotificationType
	{
		m_deviceLink = ( ( PuppetDeviceLinkPS )( evt.deviceLinkPS ) );
		if( !( IsFinal() ) )
		{
		}
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public function OnSetWasQuickHacked( evt : SetQuickHackEvent ) : EntityNotificationType
	{
		SetWasQuickHacked( evt.wasQuickHacked );
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public function OnSetWasQuickHackedAtempt( evt : SetQuickHackAttemptEvent ) : EntityNotificationType
	{
		m_wasQuickHackAttempt = evt.wasQuickHackAttempt;
		SetHasQuickHackBegunUpload( evt.wasQuickHackAttempt );
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public const function GetDeviceLink() : PuppetDeviceLinkPS
	{
		var link : PuppetDeviceLinkPS;
		var evt : AcquireDeviceLink;
		if( m_deviceLink )
		{
			return m_deviceLink;
		}
		else
		{
			link = PuppetDeviceLinkPS.AcquirePuppetDeviceLink( GetGameInstance(), GetMyEntityID() );
			if( link )
			{
				evt = new AcquireDeviceLink;
				GameInstance.GetPersistencySystem( GetGameInstance() ).QueuePSEvent( GetID(), GetClassName(), evt );
				return link;
			}
		}
		return NULL;
	}

	private export function OnAcquireDeviceLink( evt : AcquireDeviceLink ) : EntityNotificationType
	{
		if( !( m_deviceLink ) )
		{
			m_deviceLink = PuppetDeviceLinkPS.AcquirePuppetDeviceLink( GetGameInstance(), GetMyEntityID() );
		}
		return EntityNotificationType.DoNotNotifyEntity;
	}

	private function SetIsBreached( isBreached : Bool )
	{
		m_isBreached = isBreached;
	}

	public const function IsBreached() : Bool
	{
		return m_isBreached || GetDeviceLink().IsBreached();
	}

	public const function GetOwnerEntityWeak() : weak< Entity >
	{
		return GameInstance.FindEntityByID( GetGameInstance(), GetMyEntityID() );
	}

	protected const function GetMyEntityID() : EntityID
	{
		return PersistentID.ExtractEntityID( GetID() );
	}

	public function SetWasIncapacitated( wasIncapacitated : Bool )
	{
		var emptyLoadout : CachedItemLoadout;
		m_wasIncapacitated = wasIncapacitated;
		if( wasIncapacitated )
		{
			m_leftHandLoadout = ItemID();
			m_rightHandLoadout = ItemID();
			m_customWeaponLoadout.Clear();
			m_genericMeleeLoadout = emptyLoadout;
			m_genericRangedLoadout = emptyLoadout;
		}
	}

	public export function OnCacheLoadout( evt : CacheItemEquippedToHandsEvent ) : EntityNotificationType
	{
		var tmpCustomLoadout : CachedItemLoadout;
		if( m_wasIncapacitated == false )
		{
			switch( evt.m_slot )
			{
				case T"AttachmentSlots.WeaponLeft":
					m_leftHandLoadout = evt.m_itemID;
				break;
				case T"AttachmentSlots.WeaponRight":
					m_rightHandLoadout = evt.m_itemID;
				break;
				case T"AttachmentSlots.ItemSlotSniperRifle":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.ItemSlotSMG":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.ItemSlotTechRifle":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.ItemSlotHandgunLeftJackie":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.ItemSlotHandgunRightJackie":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.LeftShoulderChandelier":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.RightShoulderChandelier":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.RightShoulderTrack":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.LeftShoulderTrack":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.RightShoulderMine":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.LeftShoulder":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.RightShoulder":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.LeftShoulderMine":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.RightShoulderSelf":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.LeftShoulderSelf":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.MetalstormWeapon":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.MetalstormWeaponExplosive":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.MetalstormWeaponRaiseSequence":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.Cannon":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.CannonLaser":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.ChimeraMelee":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.Laser":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.RailGun":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.ChimeraGasCloud":
					tmpCustomLoadout.itemID = evt.m_itemID;
				tmpCustomLoadout.slot = evt.m_slot;
				m_customWeaponLoadout.PushBack( tmpCustomLoadout );
				break;
				case T"AttachmentSlots.ItemSlotGenericMelee":
					m_genericMeleeLoadout.itemID = evt.m_itemID;
				m_genericMeleeLoadout.slot = evt.m_slot;
				break;
				case T"AttachmentSlots.ItemSlotHammer":
					m_genericMeleeLoadout.itemID = evt.m_itemID;
				m_genericMeleeLoadout.slot = evt.m_slot;
				break;
				case T"AttachmentSlots.ItemSlotKatana":
					m_genericMeleeLoadout.itemID = evt.m_itemID;
				m_genericMeleeLoadout.slot = evt.m_slot;
				break;
				case T"AttachmentSlots.ItemSlotKnifeRight":
					m_genericMeleeLoadout.itemID = evt.m_itemID;
				m_genericMeleeLoadout.slot = evt.m_slot;
				break;
				case T"AttachmentSlots.ItemSlotKnifeLeft":
					m_genericMeleeLoadout.itemID = evt.m_itemID;
				m_genericMeleeLoadout.slot = evt.m_slot;
				break;
				case T"AttachmentSlots.ItemSlotGenericRanged":
					m_genericRangedLoadout.itemID = evt.m_itemID;
				m_genericRangedLoadout.slot = evt.m_slot;
				break;
				case T"AttachmentSlots.ItemSlotHandgunRight":
					m_genericRangedLoadout.itemID = evt.m_itemID;
				m_genericRangedLoadout.slot = evt.m_slot;
				break;
				case T"AttachmentSlots.ItemSlotHandgunLeft":
					m_genericRangedLoadout.itemID = evt.m_itemID;
				m_genericRangedLoadout.slot = evt.m_slot;
				break;
			}
		}
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public function DetermineInteractionState( interaction : InteractionComponent, context : GetActionsContext, objectActionsCallbackController : weak< gameObjectActionsCallbackController > )
	{
		var choices : array< InteractionChoice >;
		var actionRecords : array< weak< ObjectAction_Record > >;
		if( !( GetHudManager().IsQuickHackPanelOpened() ) )
		{
			SetHasDirectInteractionChoicesActive( false );
			if( !( m_cooldownStorage ) )
			{
				m_cooldownStorage = new CooldownStorage;
				m_cooldownStorage.Initialize( GetID(), GetClassName(), GetGameInstance() );
			}
			if( !( IsNameValid( context.interactionLayerTag ) ) )
			{
				context.interactionLayerTag = m_lastInteractionLayerTag;
			}
			if( context.requestType == gamedeviceRequestType.Direct )
			{
				GetOwnerEntity().GetRecord().ObjectActions( actionRecords );
				GetValidChoices( actionRecords, context, objectActionsCallbackController, true, choices );
				if( choices.Size() > 0 )
				{
					SetHasDirectInteractionChoicesActive( true );
				}
			}
		}
		PushChoicesToInteractionComponent( interaction, context, choices );
	}

	public const function GetValidChoices( const actions : ref< array< weak< ObjectAction_Record > > >, const context : ref< GetActionsContext >, objectActionsCallbackController : weak< gameObjectActionsCallbackController >, checkPlayerQuickHackList : Bool, choices : ref< array< InteractionChoice > > )
	{
		var i, j : Int32;
		var choice : InteractionChoice;
		var instigator : weak< GameObject >;
		var actionRecord : weak< ObjectAction_Record >;
		var puppetAction : ScriptableDeviceAction;
		var compareAction : PuppetAction;
		var actionList : array< TweakDBID >;
		var isRemote : Bool;
		var actionType : gamedataObjectActionType;
		var choiceAdded : Bool;
		var isQuickhack : Bool;
		var ownerEntity : weak< ScriptedPuppet >;
		var ownerIsActive : Bool;
		ownerEntity = GetOwnerEntity();
		ownerIsActive = ScriptedPuppet.IsActive( ownerEntity );
		instigator = context.processInitiatorObject;
		for( i = 0; i < actions.Size(); i += 1 )
		{
			choiceAdded = false;
			actionType = actions[ i ].ObjectActionType().Type();
			switch( actionType )
			{
				case gamedataObjectActionType.Direct:
				case gamedataObjectActionType.Item:
				case gamedataObjectActionType.Payment:
					isRemote = false;
				break;
				case gamedataObjectActionType.Remote:
				case gamedataObjectActionType.DeviceQuickHack:
				case gamedataObjectActionType.PuppetQuickHack:
				case gamedataObjectActionType.VehicleQuickHack:
				case gamedataObjectActionType.MinigameUpload:
					isRemote = true;
				break;
				default:
					isRemote = false;
			}
			if( ( !( isRemote ) && context.requestType == gamedeviceRequestType.Direct ) || ( isRemote && context.requestType == gamedeviceRequestType.Remote ) )
			{
				actionRecord = actions[ i ];
				puppetAction = GetAction( actionRecord );
				puppetAction.RegisterAsRequester( PersistentID.ExtractEntityID( GetID() ) );
				puppetAction.SetExecutor( instigator );
				puppetAction.CreateInteraction();
				puppetAction.SetObjectActionID( actions[ i ].GetID() );
				puppetAction.SetUp( this );
				isQuickhack = puppetAction.IsQuickHack();
				if( !( isQuickhack ) )
				{
					if( !( objectActionsCallbackController.HasObjectAction( actionRecord ) ) )
					{
						objectActionsCallbackController.AddObjectAction( actionRecord );
					}
				}
				if( puppetAction.IsPossible( ownerEntity, , objectActionsCallbackController ) )
				{
					if( isQuickhack || puppetAction.IsVisible( context, objectActionsCallbackController ) )
					{
						if( isQuickhack )
						{
							if( checkPlayerQuickHackList )
							{
								if( actionList.Size() == 0 )
								{
									actionList = RPGManager.GetPlayerQuickHackList( GetPlayer( ownerEntity.GetGame() ) );
								}
								if( !( actionList.Contains( actions[ i ].GetID() ) ) )
								{
									continue;
								}
							}
							if( !( ownerIsActive ) )
							{
								puppetAction.SetInactiveWithReason( false, "LocKey#7018" );
							}
							else if( !( puppetAction.IsVisible( context ) ) )
							{
								puppetAction.SetInactiveWithReason( false, "LocKey#7019" );
							}
						}
						choice = puppetAction.GetInteractionChoice();
						choice.data.PushBack( puppetAction );
						if( !( puppetAction.CanPayCost( NULL, true ) ) )
						{
							ChoiceTypeWrapper.SetType( choice.choiceMetaData.type, gameinteractionsChoiceType.Inactive );
						}
						for( j = 0; j < choices.Size(); j += 1 )
						{
							compareAction = ( ( PuppetAction )( choices[ j ].data[ 0 ] ) );
							if( compareAction )
							{
								if( actionRecord.Priority() >= compareAction.GetObjectActionRecord().Priority() )
								{
									choices.Insert( j, choice );
									choiceAdded = true;
									break;
								}
							}
						}
						if( !( choiceAdded ) )
						{
							choices.PushBack( choice );
						}
					}
					else
					{
						puppetAction.SetInactiveWithReason( false, "LocKey#7009" );
					}
				}
			}
		}
	}

	protected const function GetAction( actionRecord : weak< ObjectAction_Record > ) : PuppetAction
	{
		var puppetAction : PuppetAction;
		var breachAction : AccessBreach;
		var isRemoteBreach : Bool;
		var isPhysicalBreach : Bool;
		var isSuicideBreach : Bool;
		if( !( actionRecord ) )
		{
			return NULL;
		}
		isRemoteBreach = actionRecord.ActionName() == 'RemoteBreach';
		isSuicideBreach = actionRecord.ActionName() == 'SuicideBreach';
		isPhysicalBreach = actionRecord.ActionName() == 'PhysicalBreach';
		if( ( isPhysicalBreach || isRemoteBreach ) || isSuicideBreach )
		{
			breachAction = new AccessBreach;
			if( IsConnectedToAccessPoint() )
			{
				breachAction.SetProperties( GetNetworkName(), GetNPCsConnectedToThisAPCount(), GetAccessPoint().GetMinigameAttempt(), isRemoteBreach, isSuicideBreach );
			}
			else
			{
				breachAction.SetProperties( "SQUAD_NETWORK", 1, 1, isRemoteBreach, isSuicideBreach );
			}
			puppetAction = breachAction;
		}
		else if( actionRecord.ActionName() == 'Ping' )
		{
			puppetAction = new PingSquad;
		}
		else
		{
			puppetAction = new PuppetAction;
		}
		return puppetAction;
	}

	private const function Sts_Ep1_12_ActiveForQHack_Hack() : Bool
	{
		var storyTier : gameStoryTier;
		if( GetOwnerEntity().GetRecordID() == T"Character.sts_ep1_12_droid_miniboss" )
		{
			storyTier = GetOwnerEntity().GetAIControllerComponent().GetStoryTier();
			if( storyTier == gameStoryTier.Cinematic )
			{
				return true;
			}
		}
		return false;
	}

	public const function GetAllChoices( const actions : ref< array< weak< ObjectAction_Record > > >, const context : ref< GetActionsContext >, puppetActions : ref< array< PuppetAction > > )
	{
		var i : Int32;
		var instigator : weak< GameObject >;
		var puppetAction : PuppetAction;
		var isRemote : Bool;
		var actionType : gamedataObjectActionType;
		var isBreached : Bool;
		var isQuickHackExposed : Bool;
		var attiudeTowardsPlayer : EAIAttitude;
		var isPuppetActive : Bool;
		isBreached = IsBreached();
		isQuickHackExposed = IsQuickHacksExposed();
		attiudeTowardsPlayer = GetOwnerEntity().GetAttitudeTowards( GetPlayer( GetGameInstance() ) );
		isPuppetActive = ScriptedPuppet.IsActive( GetOwnerEntity() );
		instigator = context.processInitiatorObject;
		for( i = 0; i < actions.Size(); i += 1 )
		{
			actionType = actions[ i ].ObjectActionType().Type();
			switch( actionType )
			{
				case gamedataObjectActionType.Direct:
				case gamedataObjectActionType.Item:
				case gamedataObjectActionType.Payment:
					isRemote = false;
				break;
				case gamedataObjectActionType.Remote:
				case gamedataObjectActionType.DeviceQuickHack:
				case gamedataObjectActionType.PuppetQuickHack:
				case gamedataObjectActionType.VehicleQuickHack:
				case gamedataObjectActionType.MinigameUpload:
					isRemote = true;
				break;
				default:
					isRemote = false;
			}
			if( isRemote && context.requestType == gamedeviceRequestType.Remote )
			{
				if( !( TweakDBInterface.GetBool( actions[ i ].GetID() + T".isQuickHack", false ) ) )
				{
					continue;
				}
				puppetAction = GetAction( actions[ i ] );
				puppetAction.SetExecutor( instigator );
				puppetAction.RegisterAsRequester( PersistentID.ExtractEntityID( GetID() ) );
				puppetAction.SetObjectActionID( actions[ i ].GetID() );
				puppetAction.SetUp( this );
				if( puppetAction.IsQuickHack() )
				{
					if( ( ( ( AccessBreach )( puppetAction ) ) != NULL ) && isBreached )
					{
						puppetAction.SetInactiveWithReason( !( isBreached ), "LocKey#27728" );
					}
					else if( !( isQuickHackExposed ) && ( ( ( AccessBreach )( puppetAction ) ) == NULL ) )
					{
						if( attiudeTowardsPlayer != EAIAttitude.AIA_Friendly )
						{
							puppetAction.SetInactiveWithReason( false, "LocKey#7017" );
						}
						else
						{
							puppetAction.SetInactiveWithReason( false, "LocKey#27694" );
						}
					}
					else if( !( isPuppetActive ) || Sts_Ep1_12_ActiveForQHack_Hack() )
					{
						puppetAction.SetInactiveWithReason( false, "LocKey#7018" );
					}
					puppetActions.PushBack( puppetAction );
				}
			}
		}
	}

	public static function RemoveDuplicatedChoices( choices : ref< array< InteractionChoice > > )
	{
		var i, i2 : Int32;
		for( i = choices.Size() - 1; i >= 0; i -= 1 )
		{
			for( i2 = 0; i2 < choices.Size(); i2 += 1 )
			{
				if( i2 == i )
				{
					break;
				}
				if( choices[ i ].choiceMetaData.tweakDBID == choices[ i2 ].choiceMetaData.tweakDBID )
				{
					choices.Erase( i );
					break;
				}
			}
		}
	}

	private function PushChoicesToInteractionComponent( interactionComponent : InteractionComponent, const context : ref< GetActionsContext >, choices : ref< array< InteractionChoice > > )
	{
		var shouldPushChoices : Bool;
		var maxDirectChoices : Int32;
		maxDirectChoices = 4;
		if( IsNameValid( context.interactionLayerTag ) )
		{
			interactionComponent.ResetChoices( context.interactionLayerTag );
		}
		else
		{
			interactionComponent.ResetChoices();
		}
		if( choices.Size() == 0 )
		{
			return;
		}
		switch( context.requestType )
		{
			case gamedeviceRequestType.Direct:
				shouldPushChoices = true;
			if( choices.Size() > maxDirectChoices )
			{
				choices.Resize( maxDirectChoices );
			}
			break;
			default:
				if( !( IsFinal() ) )
				{
				}
		}
		if( shouldPushChoices )
		{
			if( context.interactionLayerTag == 'AerialTakedown' )
			{
				PushAerialTakedownActionEventToPSM( GetOwnerEntity() );
			}
			else
			{
				interactionComponent.SetChoices( choices, context.interactionLayerTag );
			}
			m_lastInteractionLayerTag = context.interactionLayerTag;
		}
	}

	private function PushAerialTakedownActionEventToPSM( target : weak< GameObject > )
	{
		var takedownEvent : StartTakedownEvent;
		var player : PlayerPuppet;
		var takedownAction : PuppetAction;
		takedownEvent = new StartTakedownEvent;
		player = ( ( PlayerPuppet )( GetPlayerMainObject() ) );
		takedownEvent.slideTime = 0.30000001;
		takedownEvent.target = target;
		takedownEvent.actionName = 'LeapToTarget';
		player.QueueEvent( takedownEvent );
		takedownAction = new PuppetAction;
		takedownAction.RegisterAsRequester( target.GetEntityID() );
		takedownAction.SetExecutor( player );
		takedownAction.SetObjectActionID( T"Takedown.AerialTakedown" );
		takedownAction.SetUp( this );
		takedownAction.ProcessRPGAction( target.GetGame() );
	}

	public virtual function GenerateContext( requestType : gamedeviceRequestType, providedClearance : Clearance, optional providedProcessInitiator : GameObject, optional providedRequestor : EntityID ) : GetActionsContext
	{
		var generatedContext : GetActionsContext;
		generatedContext.clearance = providedClearance;
		if( EntityID.IsDefined( providedRequestor ) )
		{
			generatedContext.requestorID = providedRequestor;
		}
		else
		{
			generatedContext.requestorID = PersistentID.ExtractEntityID( GetID() );
		}
		generatedContext.requestType = requestType;
		if( requestType == gamedeviceRequestType.Remote )
		{
			generatedContext.interactionLayerTag = 'remote';
		}
		else if( requestType == gamedeviceRequestType.Direct )
		{
			generatedContext.interactionLayerTag = 'direct';
		}
		if( providedProcessInitiator )
		{
			generatedContext.processInitiatorObject = providedProcessInitiator;
		}
		else
		{
			if( ( ( ScriptedPuppet )( GetOwnerEntity() ) ).IsPlayerAround() )
			{
				generatedContext.processInitiatorObject = GameInstance.GetPlayerSystem( GetGameInstance() ).GetLocalPlayerMainGameObject();
			}
			else
			{
			}
		}
		return generatedContext;
	}

	public constexpr static function OnObjectAction( evt : ScriptableDeviceAction ) : EntityNotificationType
	{
		return EntityNotificationType.SendThisEventToEntity;
	}

	public static function ActionSecurityBreachNotificationStatic( lastKnownPosition : Vector4, whoBreached : GameObject, reporterHandle : weak< GameObject >, type : ESecurityNotificationType ) : SecuritySystemInput
	{
		var action : SecuritySystemInput;
		var canPerformReprimand : Bool;
		action = new SecuritySystemInput;
		if( whoBreached )
		{
			canPerformReprimand = true;
		}
		else
		{
			canPerformReprimand = false;
		}
		action.SetProperties( lastKnownPosition, whoBreached, reporterHandle.GetDeviceLink(), type, canPerformReprimand, false );
		action.AddDeviceName( "DebugNPC" );
		return action;
	}

	public const function CheckFlatheadTakedownAvailability( const context : ref< GetActionsContext > ) : Bool
	{
		var owner : weak< ScriptedPuppet >;
		var flathead : weak< GameObject >;
		var navigationPath : NavigationPath;
		var attitudeTowardsPlayer : EAIAttitude;
		owner = GetOwnerEntity();
		if( !( SubCharacterSystem.GetInstance( owner.GetGame() ).IsFlatheadFollowing() ) )
		{
			return false;
		}
		if( !( owner.IsAggressive() ) )
		{
			return false;
		}
		attitudeTowardsPlayer = owner.GetAttitudeAgent().GetAttitudeTowards( context.processInitiatorObject.GetAttitudeAgent() );
		if( attitudeTowardsPlayer == EAIAttitude.AIA_Friendly )
		{
			return false;
		}
		if( !( AIActionHelper.CheckFlatheadStatPoolRequirements( owner.GetGame(), "Takedown" ) ) )
		{
			return false;
		}
		flathead = ( ( SubCharacterSystem )( GameInstance.GetScriptableSystemsContainer( owner.GetGame() ).Get( 'SubCharacterSystem' ) ) ).GetFlathead();
		navigationPath = GameInstance.GetAINavigationSystem( owner.GetGame() ).CalculatePathForCharacter( flathead.GetWorldPosition(), owner.GetWorldPosition(), 0.5, owner );
		if( navigationPath == NULL )
		{
			return false;
		}
		return true;
	}

	public export function OnSetExposeQuickHacks( evt : SetExposeQuickHacks ) : EntityNotificationType
	{
		var networkAction : PuppetAction;
		var i, j : Int32;
		var minigamePrograms : array< TweakDBID >;
		var minigameBB : IBlackboard;
		var activeTraps : array< TweakDBID >;
		var puppetActions : array< weak< ObjectAction_Record > >;
		var TS : TransactionSystem;
		var lootShardID : TweakDBID;
		var lootMaterialsID : TweakDBID;
		var lootMoneyID : TweakDBID;
		TS = GameInstance.GetTransactionSystem( GetOwnerEntity().GetGame() );
		minigameBB = GameInstance.GetBlackboardSystem( GetOwnerEntity().GetGame() ).Get( GetAllBlackboardDefs().HackingMinigame );
		minigamePrograms = ( ( array< TweakDBID > )( minigameBB.GetVariant( GetAllBlackboardDefs().HackingMinigame.ActivePrograms ) ) );
		activeTraps = ( ( array< TweakDBID > )( minigameBB.GetVariant( GetAllBlackboardDefs().HackingMinigame.ActiveTraps ) ) );
		if( minigameBB )
		{
			if( minigamePrograms.Size() > 0 )
			{
				m_isBreached = true;
			}
			if( minigamePrograms.Size() < 3 )
			{
				if( ( ( Bool )GameInstance.GetStatsSystem( GetPlayerMainObject().GetGame() ).GetStatValue( GetPlayerMainObject().GetEntityID(), gamedataStatType.MinigameNextInstanceBufferExtensionPerk ) ) )
				{
					( ( PlayerPuppet )( GetPlayerMainObject() ) ).SetBufferModifier( minigamePrograms.Size() );
				}
			}
			else if( minigamePrograms.Size() >= 3 )
			{
				if( GameInstance.GetStatsSystem( GetPlayerMainObject().GetGame() ).GetStatValue( GetPlayerMainObject().GetEntityID(), gamedataStatType.ThreeOrMoreProgramsMemoryRegPerk ) == 1.0 )
				{
					StatusEffectHelper.ApplyStatusEffect( GetPlayerMainObject(), T"BaseStatusEffect.ThreeOrMoreProgramsMemoryRegPerk1", GetPlayerMainObject().GetEntityID() );
				}
				if( GameInstance.GetStatsSystem( GetPlayerMainObject().GetGame() ).GetStatValue( GetPlayerMainObject().GetEntityID(), gamedataStatType.ThreeOrMoreProgramsMemoryRegPerk ) == 2.0 )
				{
					StatusEffectHelper.ApplyStatusEffect( GetPlayerMainObject(), T"BaseStatusEffect.ThreeOrMoreProgramsMemoryRegPerk2", GetPlayerMainObject().GetEntityID() );
				}
				if( ( ( Bool )GameInstance.GetStatsSystem( GetPlayerMainObject().GetGame() ).GetStatValue( GetPlayerMainObject().GetEntityID(), gamedataStatType.ThreeOrMoreProgramsCooldownRedPerk ) ) )
				{
					StatusEffectHelper.ApplyStatusEffect( GetPlayerMainObject(), T"BaseStatusEffect.ThreeOrMoreProgramsCooldownRedPerk", GetPlayerMainObject().GetEntityID() );
				}
				if( ( ( Bool )GameInstance.GetStatsSystem( GetPlayerMainObject().GetGame() ).GetStatValue( GetPlayerMainObject().GetEntityID(), gamedataStatType.MinigameNextInstanceBufferExtensionPerk ) ) )
				{
					( ( PlayerPuppet )( GetPlayerMainObject() ) ).SetBufferModifier( 3 );
				}
			}
			TweakDBInterface.GetCharacterRecord( GetOwnerEntity().GetRecordID() ).ObjectActions( puppetActions );
			lootShardID = T"MinigameAction.NetworkLootShard";
			lootMaterialsID = T"MinigameAction.NetworkLootMaterials";
			lootMoneyID = T"MinigameAction.NetworkLootMoney";
			for( j = 0; j < activeTraps.Size(); j += 1 )
			{
				if( activeTraps[ j ] == T"MinigameTraps.MaterialBonus" )
				{
					TS.GiveItemByItemQuery( GetPlayerMainObject(), T"Query.QuickHackMaterial", 1 );
				}
				else if( activeTraps[ j ] == T"MinigameTraps.SquadBuff" )
				{
					StatusEffectHelper.ApplyStatusEffect( GetOwnerEntity(), T"MinigameAction.BuffDamageReductionMinigame", GetPlayerMainObject().GetEntityID() );
				}
			}
			for( i = 0; i < minigamePrograms.Size(); i += 1 )
			{
				if( minigamePrograms[ i ] == lootShardID )
				{
					TS.GiveItemByItemQuery( GetPlayerMainObject(), T"Query.CombatCyberdeckProgram" );
				}
				else if( minigamePrograms[ i ] == lootMaterialsID )
				{
					TS.GiveItemByItemQuery( GetPlayerMainObject(), T"Query.QuickHackMaterial", 3 );
				}
				else if( minigamePrograms[ i ] == lootMoneyID )
				{
					RPGManager.GiveReward( GetPlayerMainObject().GetGame(), T"QuestRewards.MinigameMoney", GetOwnerEntity().GetEntityID() );
				}
				FilterRedundantPrograms( minigamePrograms );
				for( j = 0; j < puppetActions.Size(); j += 1 )
				{
					if( puppetActions[ j ].GetID() == minigamePrograms[ i ] )
					{
						networkAction = new PuppetAction;
						networkAction.RegisterAsRequester( PersistentID.ExtractEntityID( GetID() ) );
						networkAction.SetExecutor( GetPlayerMainObject() );
						networkAction.SetObjectActionID( minigamePrograms[ i ] );
						networkAction.SetUp( this );
						networkAction.ProcessRPGAction( GetGameInstance() );
					}
				}
			}
		}
		ForceExposeQuickHack( true );
		CheckMasterRunnerAchievement( minigamePrograms.Size() );
		return EntityNotificationType.SendThisEventToEntity;
	}

	private function FilterRedundantPrograms( programs : ref< array< TweakDBID > > )
	{
		if( programs.Contains( T"MinigameAction.NetworkTurretShutdown" ) && programs.Contains( T"MinigameAction.NetworkTurretFriendly" ) )
		{
			programs.Remove( T"MinigameAction.NetworkTurretShutdown" );
		}
	}

	private function ForceExposeQuickHack( shouldForce : Bool )
	{
		m_quickHacksExposed = shouldForce;
	}

	public const function IsActionReady( actionID : TweakDBID ) : Bool
	{
		return m_cooldownStorage.IsActionReady( actionID );
	}

	public export function OnActionCooldownEvent( evt : ActionCooldownEvent ) : EntityNotificationType
	{
		m_cooldownStorage.ResolveCooldownEvent( evt );
		GetPlayerCooldownStorage().ResolveCooldownEvent( evt );
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public function ManuallyTriggerActionCooldown( actionID : TweakDBID )
	{
		m_cooldownStorage.ManuallyTriggerCooldown( actionID );
	}

	protected function ActionSetExposeQuickHacks() : SetExposeQuickHacks
	{
		var action : SetExposeQuickHacks;
		action = new SetExposeQuickHacks;
		action.clearanceLevel = DefaultActionsParametersHolder.GetQuestClearance();
		action.SetUp( this );
		action.SetProperties();
		action.AddDeviceName( "NPC Hijack action" );
		return action;
	}

	public const function GetNumberActions() : Int32
	{
		return m_numberActions;
	}

	public const function HasActiveContext( context : gamedeviceRequestType ) : Bool
	{
		var i : Int32;
		for( i = 0; i < m_activeContexts.Size(); i += 1 )
		{
			if( m_activeContexts[ i ] == context )
			{
				return true;
			}
		}
		return false;
	}

	public function AddActiveContext( context : gamedeviceRequestType )
	{
		if( !( HasActiveContext( context ) ) )
		{
			m_activeContexts.PushBack( context );
		}
	}

	public function RemoveActiveContext( context : gamedeviceRequestType )
	{
		var i : Int32;
		for( i = m_activeContexts.Size() - 1; i >= 0; i -= 1 )
		{
			if( m_activeContexts[ i ] == context )
			{
				m_activeContexts.Erase( i );
				break;
			}
		}
	}

	public function SetReactionPresetID( presetID : TweakDBID )
	{
		m_reactionPresetID = presetID;
	}

	public const function GetReactionPresetID() : TweakDBID
	{
		return m_reactionPresetID;
	}

	public const function IsDefeatMechanicActive() : Bool
	{
		return m_isDefeatMechanicActive;
	}

	public function SetIsDefeatMechanicActive( isDefeatMechanicActive : Bool )
	{
		m_isDefeatMechanicActive = isDefeatMechanicActive;
	}

	protected const function CheckMasterRunnerAchievement( minigameProgramsCompleted : Int32 )
	{
		var achievementRequest : AddAchievementRequest;
		var dataTrackingSystem : DataTrackingSystem;
		var achievement : gamedataAchievement;
		achievement = gamedataAchievement.MasterRunner;
		if( minigameProgramsCompleted >= 3 )
		{
			achievementRequest = new AddAchievementRequest;
			achievementRequest.achievement = achievement;
			dataTrackingSystem.QueueRequest( achievementRequest );
		}
	}

	public function SetIsDead( isDead : Bool )
	{
		m_isDead = isDead;
	}

	public const function GetIsDead() : Bool
	{
		return m_isDead;
	}

	public function SetIsIncapacitated( isIncapacitated : Bool )
	{
		m_isIncapacitated = isIncapacitated;
	}

	public const function GetIsIncapacitated() : Bool
	{
		return m_isIncapacitated;
	}

	public function SetIsAndroidTurnedOff( isAndroidTurnedOff : Bool )
	{
		m_isAndroidTurnedOff = isAndroidTurnedOff;
	}

	public const function GetIsAndroidTurnedOff() : Bool
	{
		return m_isAndroidTurnedOff;
	}

	public function SetIsPreventionNotified( isPreventionNotified : Bool )
	{
		m_isPreventionNotified = isPreventionNotified;
	}

	public const function IsPreventionNotified() : Bool
	{
		return m_isPreventionNotified;
	}

	protected const function GetHudManager() : HUDManager
	{
		return ( ( HUDManager )( GameInstance.GetScriptableSystemsContainer( GetGameInstance() ).Get( 'HUDManager' ) ) );
	}

	protected constexpr static function OnTargetAssessmentRequest( evt : TargetAssessmentRequest ) : EntityNotificationType
	{
		return EntityNotificationType.SendThisEventToEntity;
	}

	protected function OnPingSquad( evt : PingSquad ) : EntityNotificationType
	{
		var request : ClearPingedSquadRequest;
		if( evt.ShouldForward() )
		{
			if( evt.GetRequesterID() == GetMyEntityID() )
			{
				request = new ClearPingedSquadRequest;
				GameInstance.QueueScriptableSystemRequest( GetGameInstance(), 'NetworkSystem', request );
			}
			GetDeviceLink().PingDevicesNetwork();
		}
		return EntityNotificationType.DoNotNotifyEntity;
	}

}

