importonly abstract class IWorkspotGameSystem extends IGameSystem
{
}

import enum WorkspotSlidingBehaviour
{
	PlayAtResourcePosition,
	DontPlayAtResourcePosition,
	SlideActorAndRotateDevice,
}

importonly class ExtendedWorkspotInfo extends IScriptable
{
	import var isActive : Bool;
	import var entering : Bool;
	import var exiting : Bool;
	import var playingSyncAnim : Bool;
	import var inReaction : Bool;
	import var inMotion : Bool;
}

import final class PlayInDeviceCallbackEvent extends Event
{
	import var wasPlayInDeviceSuccessful : Bool;
}

importonly final class WorkspotGameSystem extends IWorkspotGameSystem
{
	public import function PlayInDeviceSimple( device : GameObject, actor : GameObject, allowCameraMov : Bool, optional actorDataCompName : CName, optional deviceDataCompName : CName, optional syncSlotName : CName, optional slideTime : Float, optional slideBehaviour : WorkspotSlidingBehaviour, optional callbackEventRecipient : Entity );
	public import function PlayInDevice( device : GameObject, actor : GameObject, optional workspotStateFlavourName, actorDataCompName, deviceDataCompName, syncSlotName : CName, optional slideTime : Float, optional slideBehaviour : WorkspotSlidingBehaviour, optional callbackEventRecipient : Entity );
	public import function StopInDevice( actor : GameObject, optional posDelta : Vector4, optional orientDelta : Quaternion );
	public import function GetDeviceUser( deviceID : EntityID ) : GameObject;
	public import function MountToVehicle( parent : GameObject, child : GameObject, slideTime : Float, animDelay : Float, workspotResourceContainer : CName, slotName : CName, optional syncronizedObjects : array< EntityID >, optional entrySlotName : CName, optional animVariables : array< CName > ) : Bool;
	public import function SwitchSeatVehicle( parent : GameObject, child : GameObject, workspotResourceContainer : CName, slotName : CName, optional exitSlotName : CName, optional activateAnimVariables : array< CName >, optional deactivateAnimVariables : array< CName > );
	public import function UnmountFromVehicle( parent : GameObject, child : GameObject, optional instant : Bool, optional posDelta : Vector4, optional orientDelta : Quaternion, optional exitSlotName : CName );
	public import function IsInVehicleWorkspot( vehicle, child : GameObject, slotName : CName ) : Bool;
	public import function StopNpcInWorkspot( actor : GameObject );
	public import function IsActorInWorkspot( actor : GameObject ) : Bool;
	public import function GetExtendedInfo( actor : GameObject ) : ExtendedWorkspotInfo;
	public import function SendDebugCommand( mode : workWorkspotDebugMode, entId : String );
	public import function SendDebugCommandEnt( mode : workWorkspotDebugMode, obj : GameObject );
	public import function SendDebugCommandFunctionalTests( mode : workWorkspotDebugMode, obj : GameObject, redscript : IScriptable );
	public import function SendFastExitSignal( actor : GameObject, optional dirLS : Vector3, optional stayInWorkspotIfFailed : Bool, optional playSlowExitIfFailed : Bool, optional instant : Bool, optional tryBlendToWalk : Bool );
	public import function SendJumpCommandEnt( actor : GameObject, entryId : Int32, instant : Bool );
	public import function SendJumpToAnimEnt( actor : GameObject, animName : CName, instant : Bool );
	public import function SendJumpToTagCommandEnt( actor : GameObject, entryTag : CName, instant : Bool, optional deviceId : EntityID );
	public import function SendSlowExitSignal( actor : GameObject, optional animationName : CName, optional dontWaitForCurrentAnimationToFinish : Bool );
	public import function SendDynamicSyncBindSignal( actor : GameObject, master : GameObject );
	public import function SendDynamicSyncUnbindSignal( actor : GameObject );
	public import function SendPlaySignal( actor : GameObject );
	public import function SendForwardSignal( actor : GameObject );
	public import function SendReactionSignal( actor : GameObject, reactionName : CName ) : Bool;
	public import function ResetPlaybackToStart( actor : GameObject );
	public import function HardResetPlaybackToStart( actor : GameObject );
	public import function GetIdOfExitAnim( actor : GameObject, animName : CName ) : Int32;
	public import function SendEventToConnectedSpots( actor : GameObject, eventName : CName ) : Bool;
	public import function IsReactionAvailable( actor : GameObject, reactionName : CName ) : Bool;
	public import function HasExitNodes( actor : GameObject, fastExit : Bool, slowExit : Bool, optional performNavmeshChecks : Bool ) : Bool;
	public import function IsWorkspotEnabled( actor : GameObject ) : Bool;
	public import function PlayNpcInWorkspot( npc : GameObject, master : GameObject, referenceEntity : GameObject, actorDataCompName : CName, optional syncSlotName : CName, optional slideTime : Float, optional syncOffsetSourceCompName : CName );
	public import function SynchronizeItemWithOwner( item : ItemObject, owner : GameObject );
}

import final class ConnectedWorkspotNotificationEvent extends Event
{
	import var evtName : CName;
}

import final class WorkspotStartedEvent extends Event
{
	import var nodeId : GlobalNodeID;
	import var tags : array< CName >;
}

import final class WorkspotFinishedEvent extends Event
{
	import var nodeId : GlobalNodeID;
	import var tags : array< CName >;
}

import final class ReactionFinishedEvent extends Event
{
}

import final class SetupWorkspotActionEvent extends StimuliData
{
}

import final class WorkspotResourceComponent extends IPlacedComponent
{
	editable var shouldCrouch : Bool;
}

import enum workWorkspotDebugMode
{
	VisualLogToogle,
	VisualLogOn,
	VisualLogOff,
	VisualStateToogle,
	VisualStateOn,
	VisualStateOff,
	RecorderOn,
	RecorderOff,
	PlaybackOn,
	PlaybackOff,
	Invalid,
	FunctionalTests,
}

import struct WorkEntryId
{
	import var id : Uint32;
}

import class WorkspotCondition extends IScriptable
{

	public const virtual function CheckCondition( ent : Entity ) : Bool
	{
		return true;
	}

}

class TestConditon extends WorkspotCondition
{

	protected const override function CheckCondition( const ent : Entity ) : Bool
	{
		return true;
	}

}

class TestFalseConditon extends WorkspotCondition
{

	protected const override function CheckCondition( const ent : Entity ) : Bool
	{
		return false;
	}

}

class IsUnarmedCondition extends WorkspotCondition
{

	protected const override function CheckCondition( ent : Entity ) : Bool
	{
		var items : array< weak< ItemObject > >;
		var obj : GameObject;
		obj = ( ( GameObject )( ent ) );
		if( !( obj ) )
		{
			return true;
		}
		if( !( obj.IsNPC() ) )
		{
			return false;
		}
		return !( AIActionHelper.GetItemsFromWeaponSlots( obj, items ) );
	}

}

class HasMeleeWeaponEquippedCondition extends WorkspotCondition
{

	protected const override function CheckCondition( ent : Entity ) : Bool
	{
		var items : array< weak< ItemObject > >;
		var obj : GameObject;
		var transactionSystem : TransactionSystem;
		var i : Int32;
		obj = ( ( GameObject )( ent ) );
		if( !( obj ) )
		{
			return true;
		}
		if( !( obj.IsNPC() ) )
		{
			return false;
		}
		if( !( AIActionHelper.GetItemsFromWeaponSlots( obj, items ) ) )
		{
			return false;
		}
		transactionSystem = GameInstance.GetTransactionSystem( obj.GetGame() );
		for( i = 0; i < items.Size(); i += 1 )
		{
			if( transactionSystem.HasTag( obj, WeaponObject.GetMeleeWeaponTag(), items[ i ].GetItemID() ) )
			{
				return true;
			}
		}
		return false;
	}

}

class HasRangedWeaponEquippedCondition extends WorkspotCondition
{

	protected const override function CheckCondition( ent : Entity ) : Bool
	{
		var items : array< weak< ItemObject > >;
		var obj : GameObject;
		var transactionSystem : TransactionSystem;
		var i : Int32;
		obj = ( ( GameObject )( ent ) );
		if( !( obj ) )
		{
			return true;
		}
		if( !( obj.IsNPC() ) )
		{
			return false;
		}
		if( !( AIActionHelper.GetItemsFromWeaponSlots( obj, items ) ) )
		{
			return false;
		}
		transactionSystem = GameInstance.GetTransactionSystem( obj.GetGame() );
		for( i = 0; i < items.Size(); i += 1 )
		{
			if( transactionSystem.HasTag( obj, WeaponObject.GetRangedWeaponTag(), items[ i ].GetItemID() ) )
			{
				return true;
			}
		}
		return false;
	}

}

enum WorkspotWeaponConditionEnum
{
	None = 0,
	Any = 1,
	Ranged = 2,
	OneHandedRanged = 3,
	Melee = 4,
	MeleeCyberware = 5,
	LMG = 6,
	HMG = 7,
}

class PrimaryWeaponTypeCondition extends WorkspotCondition
{
	protected editable var weaponType : WorkspotWeaponConditionEnum;

	protected const override function CheckCondition( ent : Entity ) : Bool
	{
		var obj : GameObject;
		var npc : NPCPuppet;
		var weaponTag : CName;
		var items : array< weak< NPCEquipmentItem_Record > >;
		var i : Int32;
		obj = ( ( GameObject )( ent ) );
		if( !( obj ) )
		{
			return true;
		}
		if( !( obj.IsNPC() ) )
		{
			return false;
		}
		switch( weaponType )
		{
			case WorkspotWeaponConditionEnum.Ranged:
				weaponTag = WeaponObject.GetRangedWeaponTag();
			break;
			case WorkspotWeaponConditionEnum.OneHandedRanged:
				weaponTag = WeaponObject.GetOneHandedRangedWeaponTag();
			break;
			case WorkspotWeaponConditionEnum.Melee:
				weaponTag = WeaponObject.GetMeleeWeaponTag();
			break;
			case WorkspotWeaponConditionEnum.MeleeCyberware:
				weaponTag = 'Meleeware';
			break;
			case WorkspotWeaponConditionEnum.LMG:
				weaponTag = 'LMG';
			break;
			case WorkspotWeaponConditionEnum.HMG:
				weaponTag = 'HMG';
			break;
			default:
				return true;
		}
		npc = ( ( NPCPuppet )( obj ) );
		AIActionTransactionSystem.CalculateEquipmentItems( npc, 'PrimaryEquipment', items );
		for( i = 0; i < items.Size(); i += 1 )
		{
			if( items[ i ].Item().TagsContains( weaponTag ) )
			{
				return true;
			}
		}
		return false;
	}

}

class EquippedWeaponTypeCondition extends WorkspotCondition
{
	protected editable var weaponType : WorkspotWeaponConditionEnum;

	protected export const override function CheckCondition( ent : Entity ) : Bool
	{
		var obj : GameObject;
		var hasAnyWeaponEquipped : Bool;
		var items : array< weak< ItemObject > >;
		var weaponTag : CName;
		var transactionSystem : TransactionSystem;
		var i : Int32;
		obj = ( ( GameObject )( ent ) );
		if( !( obj ) )
		{
			return true;
		}
		if( !( obj.IsNPC() ) )
		{
			return false;
		}
		hasAnyWeaponEquipped = AIActionHelper.GetItemsFromWeaponSlots( obj, items );
		if( weaponType == WorkspotWeaponConditionEnum.None )
		{
			return !( hasAnyWeaponEquipped );
		}
		switch( weaponType )
		{
			case WorkspotWeaponConditionEnum.Ranged:
				weaponTag = WeaponObject.GetRangedWeaponTag();
			break;
			case WorkspotWeaponConditionEnum.OneHandedRanged:
				weaponTag = WeaponObject.GetOneHandedRangedWeaponTag();
			break;
			case WorkspotWeaponConditionEnum.Melee:
				weaponTag = WeaponObject.GetMeleeWeaponTag();
			break;
			case WorkspotWeaponConditionEnum.MeleeCyberware:
				weaponTag = 'Meleeware';
			break;
			case WorkspotWeaponConditionEnum.LMG:
				weaponTag = 'LMG';
			break;
			case WorkspotWeaponConditionEnum.HMG:
				weaponTag = 'HMG';
			break;
			default:
				return true;
		}
		transactionSystem = GameInstance.GetTransactionSystem( obj.GetGame() );
		for( i = 0; i < items.Size(); i += 1 )
		{
			if( transactionSystem.HasTag( obj, weaponTag, items[ i ].GetItemID() ) )
			{
				return true;
			}
		}
		return false;
	}

}

enum WorkspotConditionOperators
{
	OR = 0,
	AND = 1,
}

class LogicalCondition extends WorkspotCondition
{
	protected editable var operation : WorkspotConditionOperators;
	protected const editable inlined var conditions : array< WorkspotCondition >;

	public export const override function CheckCondition( ent : Entity ) : Bool
	{
		var i : Int32;
		if( operation == WorkspotConditionOperators.OR )
		{
			for( i = 0; i < conditions.Size(); i += 1 )
			{
				if( conditions[ i ].CheckCondition( ent ) )
				{
					return true;
				}
			}
			return false;
		}
		else if( operation == WorkspotConditionOperators.AND )
		{
			for( i = 0; i < conditions.Size(); i += 1 )
			{
				if( !( conditions[ i ].CheckCondition( ent ) ) )
				{
					return false;
				}
			}
			return true;
		}
		return false;
	}

}

