class ActivatedDeviceTrapDestruction extends ActivatedDeviceTrap
{
	default m_controllerTypeName = 'ActivatedDeviceController';
	protected const instanceeditable var m_physicalMeshNames : array< CName >;
	protected var m_physicalMeshes : array< PhysicalMeshComponent >;
	protected const instanceeditable var m_hideMeshNames : array< CName >;
	protected var m_hideMeshes : array< IPlacedComponent >;
	protected const instanceeditable var m_hitColliderNames : array< CName >;
	protected var m_hitColliders : array< IPlacedComponent >;
	protected instanceeditable var m_impulseVector : Vector4;
	protected const editable var physicalMeshImpactVFX : array< FxResource >;
	protected const editable var m_componentsToEnableNames : array< CName >;
	protected var m_componentsToEnable : array< IPlacedComponent >;
	protected var hitCount : Int32;
	protected var m_wasAttackPerformed : Bool;
	protected var m_alreadyPlayedVFXComponents : array< CName >;
	protected var m_shouldCheckPhysicalCollisions : Bool;
	protected var m_lastEntityHit : weak< IScriptable >;
	protected instanceeditable var m_timeToActivatePhysics : Float;

	protected event OnRequestComponents( ri : EntityRequestComponentsInterface )
	{
		var i : Int32;
		super.OnRequestComponents( ri );
		EntityRequestComponentsInterface.RequestComponent( ri, 'animationSlots', 'SlotComponent', false );
		for( i = 0; i < m_physicalMeshNames.Size(); i += 1 )
		{
			EntityRequestComponentsInterface.RequestComponent( ri, m_physicalMeshNames[ i ], 'PhysicalMeshComponent', true );
		}
		for( i = 0; i < m_hideMeshNames.Size(); i += 1 )
		{
			EntityRequestComponentsInterface.RequestComponent( ri, m_hideMeshNames[ i ], 'IPlacedComponent', true );
		}
		for( i = 0; i < m_hitColliderNames.Size(); i += 1 )
		{
			EntityRequestComponentsInterface.RequestComponent( ri, m_hitColliderNames[ i ], 'IPlacedComponent', true );
		}
		for( i = 0; i < m_componentsToEnableNames.Size(); i += 1 )
		{
			EntityRequestComponentsInterface.RequestComponent( ri, m_componentsToEnableNames[ i ], 'IPlacedComponent', true );
		}
	}

	protected event OnTakeControl( ri : EntityResolveComponentsInterface )
	{
		var i : Int32;
		super.OnTakeControl( ri );
		for( i = 0; i < m_physicalMeshNames.Size(); i += 1 )
		{
			m_physicalMeshes.PushBack( ( ( PhysicalMeshComponent )( EntityResolveComponentsInterface.GetComponent( ri, m_physicalMeshNames[ i ] ) ) ) );
		}
		for( i = 0; i < m_hideMeshNames.Size(); i += 1 )
		{
			m_hideMeshes.PushBack( ( ( IPlacedComponent )( EntityResolveComponentsInterface.GetComponent( ri, m_hideMeshNames[ i ] ) ) ) );
		}
		for( i = 0; i < m_hitColliderNames.Size(); i += 1 )
		{
			m_hitColliders.PushBack( ( ( IPlacedComponent )( EntityResolveComponentsInterface.GetComponent( ri, m_hitColliderNames[ i ] ) ) ) );
		}
		for( i = 0; i < m_componentsToEnableNames.Size(); i += 1 )
		{
			m_componentsToEnable.PushBack( ( ( IPlacedComponent )( EntityResolveComponentsInterface.GetComponent( ri, m_componentsToEnableNames[ i ] ) ) ) );
		}
		m_controller = ( ( ActivatedDeviceController )( EntityResolveComponentsInterface.GetComponent( ri, 'controller' ) ) );
	}

	protected event OnGameAttached()
	{
		super.OnGameAttached();
		if( GetDevicePS().IsActivated() )
		{
			HidePhysicalMeshes();
			HideMeshes();
			EnableComponents();
		}
	}

	protected event OnActivateDevice( evt : ActivateDevice )
	{
		var vfxEnableTimer : TimerEvent;
		vfxEnableTimer = new TimerEvent;
		GameInstance.GetDelaySystem( GetGame() ).DelayEvent( this, vfxEnableTimer, GetDevicePS().GetAnimationTime() );
		ActivatePhysicalMeshes();
		HideMeshes();
		RefreshAnimation();
		SetGameplayRoleToNone();
	}

	protected event OnTimerEvent( evt : TimerEvent )
	{
		m_shouldCheckPhysicalCollisions = true;
	}

	protected event OnTrapPhysicsActivationEvent( evt : TrapPhysicsActivationEvent ) {}

	protected function ActivatePhysicalMeshes()
	{
		var i : Int32;
		var rotatedVector : Vector4;
		rotatedVector = Vector4.RotByAngleXY( m_impulseVector, -( GetWorldYaw() ) );
		for( i = 0; i < m_physicalMeshes.Size(); i += 1 )
		{
			m_physicalMeshes[ i ].CreatePhysicalBodyInterface().SetIsKinematic( false );
			m_physicalMeshes[ i ].CreatePhysicalBodyInterface().AddLinearImpulse( rotatedVector, false );
		}
		for( i = 0; i < m_hideMeshes.Size(); i += 1 )
		{
			m_hideMeshes[ i ].Toggle( false );
		}
	}

	protected function HidePhysicalMeshes()
	{
		var i : Int32;
		for( i = 0; i < m_physicalMeshes.Size(); i += 1 )
		{
			m_physicalMeshes[ i ].Toggle( false );
		}
	}

	protected function EnableComponents()
	{
		var i : Int32;
		for( i = 0; i < m_physicalMeshes.Size(); i += 1 )
		{
			m_componentsToEnable[ i ].Toggle( true );
		}
	}

	protected function HideMeshes()
	{
		var i : Int32;
		for( i = 0; i < m_hideMeshes.Size(); i += 1 )
		{
			m_hideMeshes[ i ].Toggle( false );
		}
	}

	protected event OnHit( evt : gameHitEvent )
	{
		var i : Int32;
		if( !( GetDevicePS().IsDisabled() ) )
		{
			for( i = 0; i < m_hitColliders.Size(); i += 1 )
			{
				if( m_hitColliders[ i ] == evt.hitComponent )
				{
					hitCount = hitCount + 1;
					if( ( hitCount > 0 ) && !( GetDevicePS().IsON() ) )
					{
						GetDevicePS().ActivateThisDevice();
					}
				}
			}
		}
	}

	protected event OnPhysicalCollisionEvent( evt : PhysicalCollisionEvent )
	{
		var i : Int32;
		var transform : WorldTransform;
		var position : WorldPosition;
		if( !( m_shouldCheckPhysicalCollisions ) )
		{
			return false;
		}
		if( ( evt.otherEntity != this ) && !( m_alreadyPlayedVFXComponents.Contains( ( ( IPlacedComponent )( evt.myComponent ) ).GetName() ) ) )
		{
			m_lastEntityHit = evt.otherEntity;
			m_alreadyPlayedVFXComponents.PushBack( ( ( IPlacedComponent )( evt.myComponent ) ).GetName() );
			if( !( m_wasAttackPerformed ) )
			{
				DoAttack( GetDevicePS().GetAttackType() );
				m_wasAttackPerformed = true;
				Distract();
			}
			for( i = 0; i < physicalMeshImpactVFX.Size(); i += 1 )
			{
				if( FxResource.IsValid( physicalMeshImpactVFX[ i ] ) )
				{
					WorldPosition.SetVector4( position, evt.worldPosition );
					WorldTransform.SetWorldPosition( transform, position );
					CreateFxInstance( physicalMeshImpactVFX[ i ], transform );
				}
			}
		}
	}

	public function GetLastEntityHit() : weak< IScriptable >
	{
		return m_lastEntityHit;
	}

	protected override function RefreshAnimation()
	{
		var m_animFeature : AnimFeature_SimpleDevice;
		if( GetDevicePS().IsActivated() )
		{
			m_animFeature = new AnimFeature_SimpleDevice;
			m_animFeature.isOpen = true;
			AnimationControllerComponent.ApplyFeature( this, 'deviceCrates', m_animFeature );
		}
	}

}

class TrapPhysicsActivationEvent extends Event
{
}

class EffectObjectProvider_PhysicalCollisionTrapEntities extends EffectObjectProvider_Scripted
{

	public function Process( ctx : EffectScriptContext, providerCtx : EffectProviderScriptContext )
	{
		var lastEntityHit : weak< IScriptable >;
		var entitiesInArea : array< Entity >;
		var i : Int32;
		entitiesInArea = ( ( ActivatedDeviceTrap )( EffectScriptContext.GetSource( ctx ) ) ).GetEntitiesInArea();
		for( i = 0; i < entitiesInArea.Size(); i += 1 )
		{
			EffectProviderScriptContext.AddTarget( ctx, providerCtx, entitiesInArea[ i ] );
		}
		lastEntityHit = ( ( ActivatedDeviceTrapDestruction )( EffectScriptContext.GetSource( ctx ) ) ).GetLastEntityHit();
		if( ( ( ScriptedPuppet )( lastEntityHit ) ) && !( entitiesInArea.Contains( ( ( Entity )( lastEntityHit ) ) ) ) )
		{
			EffectProviderScriptContext.AddTarget( ctx, providerCtx, ( ( Entity )( lastEntityHit ) ) );
		}
	}

}

