import struct ImpactPointData
{
	import var worldPosition : WorldPosition;
	import var worldNormal : Vector4;
	import var forceMagnitude : Float;
	import var impulseMagnitude : Float;
	import var maxForceMagnitude : Float;
	import var maxImpulseMagnitude : Float;
}

importonly final class MechanicalComponentImpactEvent extends Event
{
	import var otherEntity : weak< Entity >;
	import var impactPoints : array< ImpactPointData >;
}

import class MechanicalImpactComponent extends IComponent
{
	private var c_impulseMagThreshold : Float;
	default c_impulseMagThreshold = 10000.f;

	protected event OnMechanicalComponentImpactEvent( evt : MechanicalComponentImpactEvent )
	{
		var otherVehicleObject : VehicleObject;
		var filteredInstigator : GameObject;
		var filteredImpactPoint : ImpactPointData;
		otherVehicleObject = ( ( VehicleObject )( evt.otherEntity ) );
		if( otherVehicleObject && FilterOutVehicleImpact( evt.impactPoints, otherVehicleObject, filteredImpactPoint, filteredInstigator ) )
		{
			ProcessVehicleImpact( otherVehicleObject, filteredInstigator, filteredImpactPoint );
		}
	}

	private function FilterOutVehicleImpact( const impactPoints : ref< array< ImpactPointData > >, const vehicleObject : VehicleObject, outImpactPoint : ref< ImpactPointData >, outInstigator : ref< GameObject > ) : Bool
	{
		var i : Int32;
		var currentImpactPoint : ImpactPointData;
		var ownerPuppet : NPCPuppet;
		var instigator : GameObject;
		ownerPuppet = ( ( NPCPuppet )( GetEntity() ) );
		if( !( ownerPuppet ) )
		{
			return false;
		}
		instigator = VehicleComponent.GetDriver( ownerPuppet.GetGame(), vehicleObject, vehicleObject.GetEntityID() );
		if( vehicleObject.IsVehicleAccelerateQuickhackActive() )
		{
			instigator = GameInstance.GetPlayerSystem( ownerPuppet.GetGame() ).GetLocalPlayerControlledGameObject();
		}
		if( !( instigator.IsPlayerControlled() ) )
		{
			return false;
		}
		for( i = 0; i < impactPoints.Size(); i += 1 )
		{
			currentImpactPoint = impactPoints[ i ];
			if( currentImpactPoint.impulseMagnitude < c_impulseMagThreshold )
			{
				continue;
			}
			outImpactPoint = currentImpactPoint;
			outInstigator = instigator;
			return true;
		}
		return false;
	}

	private function ProcessVehicleImpact( vehicleObject : VehicleObject, const instigator : weak< GameObject >, const impactPoint : ref< ImpactPointData > )
	{
		var vehicleHitEvent : gameVehicleHitEvent;
		var ownerPuppet : NPCPuppet;
		ownerPuppet = ( ( NPCPuppet )( GetEntity() ) );
		if( !( ownerPuppet ) )
		{
			return;
		}
		vehicleHitEvent = new gameVehicleHitEvent;
		vehicleHitEvent.preyVelocity = ownerPuppet.GetVelocity();
		vehicleHitEvent.vehicleVelocity = impactPoint.worldNormal * Vector4.Length( vehicleObject.GetLinearVelocity() );
		vehicleHitEvent.target = ownerPuppet;
		vehicleHitEvent.hitPosition = WorldPosition.ToVector4( impactPoint.worldPosition );
		vehicleHitEvent.hitDirection = impactPoint.worldNormal;
		vehicleHitEvent.attackData = new AttackData;
		vehicleHitEvent.attackData.SetInstigator( instigator );
		vehicleHitEvent.attackData.SetSource( vehicleObject );
		ownerPuppet.QueueEvent( vehicleHitEvent );
	}

}

