importonly abstract class IEffectorSystem extends IGameSystem
{
}

importonly class EffectorSystem extends IEffectorSystem
{
	public import function ApplyEffector( objID : EntityID, instigator : weak< GameObject >, recordID : TweakDBID, optional parentRecordID : TweakDBID, optional proxyEntityID : EntityID );
	public import function RemoveEffector( objID : EntityID, recordID : TweakDBID );
	public import function IsEffectorPresent( objID : EntityID, recordID : TweakDBID ) : Bool;
	public import function GetEffectorsList( objID : EntityID, outEffectors : array< weak< Effector > > );
	public import function GetEffectorsByID( objID : EntityID, recordID : TweakDBID, outEffectors : array< weak< Effector > > );
	public import function RemoveEffectorsByID( objID : EntityID, recordID : TweakDBID ) : Bool;
}

import class Effector extends IScriptable
{
	protected export virtual function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID );
	protected export virtual function Uninitialize( game : GameInstance );
	protected export virtual function ActionOn( owner : GameObject );
	protected virtual function ActionOff( owner : GameObject );
	protected virtual function RepeatedAction( owner : GameObject );
	protected import const function GetPrereqState() : PrereqState;
	protected import const function GetRecord() : TweakDBID;
	protected import const function GetParentRecord() : TweakDBID;
	protected import const function GetOwner() : GameObject;
	protected import const function GetInstigator() : GameObject;
	protected import const function GetProxyEntityID() : EntityID;

	protected function GetApplicationTargetAsStatsObjectID( effectorOwner : GameObject, applicationTarget : CName, out targetID : StatsObjectID ) : Bool
	{
		var weapon : WeaponObject;
		var hitPrereqState : GenericHitPrereqState;
		var item : ItemID;
		var vehicle : weak< VehicleObject >;
		switch( applicationTarget )
		{
			case 'Weapon':
				weapon = ScriptedPuppet.GetActiveWeapon( effectorOwner );
			if( !( weapon ) )
			{
				return false;
			}
			targetID = weapon.GetItemData().GetStatsObjectID();
			break;
			case 'Fists':
				if( effectorOwner.IsPlayer() )
				{
					item = EquipmentSystem.GetData( effectorOwner ).GetActiveItem( gamedataEquipmentArea.BaseFists );
					if( !( ItemID.IsValid( item ) ) )
					{
						return false;
					}
					targetID = GameInstance.GetTransactionSystem( effectorOwner.GetGame() ).GetItemData( effectorOwner, item ).GetStatsObjectID();
				}
			break;
			case 'Target':
				hitPrereqState = ( ( GenericHitPrereqState )( GetPrereqState() ) );
			if( hitPrereqState )
			{
				targetID = hitPrereqState.GetHitEvent().target.GetEntityID();
			}
			break;
			case 'DamageSource':
				hitPrereqState = ( ( GenericHitPrereqState )( GetPrereqState() ) );
			if( hitPrereqState )
			{
				targetID = hitPrereqState.GetHitEvent().attackData.GetInstigator().GetEntityID();
			}
			break;
			case 'Vehicle':
				VehicleComponent.GetVehicle( effectorOwner.GetGame(), effectorOwner, vehicle );
			if( vehicle )
			{
				targetID = vehicle.GetEntityID();
			}
			break;
			default:
				targetID = effectorOwner.GetEntityID();
			break;
		}
		return StatsObjectID.IsDefined( targetID );
	}

	protected function GetApplicationTarget( effectorOwner : GameObject, applicationTarget : CName, out targetID : EntityID ) : Bool
	{
		var weapon : WeaponObject;
		var hitPrereqState : GenericHitPrereqState;
		var vehicle : weak< VehicleObject >;
		switch( applicationTarget )
		{
			case 'Weapon':
				weapon = ScriptedPuppet.GetActiveWeapon( effectorOwner );
			if( !( weapon ) )
			{
				return false;
			}
			targetID = weapon.GetEntityID();
			break;
			case 'Target':
				hitPrereqState = ( ( GenericHitPrereqState )( GetPrereqState() ) );
			if( hitPrereqState )
			{
				targetID = hitPrereqState.GetHitEvent().target.GetEntityID();
			}
			break;
			case 'DamageSource':
				hitPrereqState = ( ( GenericHitPrereqState )( GetPrereqState() ) );
			if( hitPrereqState )
			{
				targetID = hitPrereqState.GetHitEvent().attackData.GetInstigator().GetEntityID();
			}
			break;
			case 'Vehicle':
				VehicleComponent.GetVehicle( effectorOwner.GetGame(), effectorOwner, vehicle );
			if( vehicle )
			{
				targetID = vehicle.GetEntityID();
			}
			break;
			case 'Player':
				targetID = GetPlayer( effectorOwner.GetGame() ).GetEntityID();
			break;
			default:
				targetID = effectorOwner.GetEntityID();
			break;
		}
		return EntityID.IsDefined( targetID );
	}

	protected function GetApplicationTarget( effectorOwner : GameObject, applicationTarget : CName, out target : weak< GameObject > ) : Bool
	{
		var weapon : WeaponObject;
		var hitPrereqState : GenericHitPrereqState;
		switch( applicationTarget )
		{
			case 'Weapon':
				weapon = ScriptedPuppet.GetActiveWeapon( effectorOwner );
			if( !( weapon ) )
			{
				return false;
			}
			target = weapon;
			break;
			case 'Target':
				hitPrereqState = ( ( GenericHitPrereqState )( GetPrereqState() ) );
			if( hitPrereqState )
			{
				target = hitPrereqState.GetHitEvent().target;
			}
			break;
			case 'DamageSource':
				hitPrereqState = ( ( GenericHitPrereqState )( GetPrereqState() ) );
			if( hitPrereqState )
			{
				target = hitPrereqState.GetHitEvent().attackData.GetInstigator();
			}
			break;
			case 'Vehicle':
				VehicleComponent.GetVehicle( effectorOwner.GetGame(), effectorOwner, target );
			break;
			case 'QuickHackSource':
				target = ( ( GameObject )( GameInstance.FindEntityByID( effectorOwner.GetGame(), StatusEffectHelper.GetStatusEffectWithTag( effectorOwner, 'Quickhack' ).GetInstigatorEntityID() ) ) );
			break;
			case 'Player':
				target = GetPlayer( effectorOwner.GetGame() );
			default:
				target = effectorOwner;
			break;
		}
		return target != NULL;
	}

}

import class ContinuousEffector extends Effector
{
	protected virtual function ContinuousAction( owner : GameObject, instigator : GameObject );
}

class TestEffector extends Effector
{

	protected override function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID )
	{
	}

	protected override function ActionOn( owner : GameObject )
	{
	}

	protected override function ActionOff( owner : GameObject )
	{
	}

}

class StatPoolEffector extends Effector
{

	protected override function ActionOff( owner : GameObject )
	{
	}

	protected override function ActionOn( owner : GameObject )
	{
	}

}

class SenseSwitchEffector extends Effector
{

	public static function SenseSwitch( senseComponent : SenseComponent, condition : Bool )
	{
		if( condition )
		{
			senseComponent.RemoveHearingMappin();
		}
		else
		{
			senseComponent.CreateHearingMappin();
		}
		senseComponent.Toggle( condition );
	}

	protected override function ActionOn( owner : GameObject )
	{
		var ownerPuppet : ScriptedPuppet;
		var senseComponent : SenseComponent;
		ownerPuppet = ( ( ScriptedPuppet )( owner ) );
		senseComponent = ownerPuppet.GetSensesComponent();
		SenseSwitch( senseComponent, false );
	}

	protected override function ActionOff( owner : GameObject )
	{
		var ownerPuppet : ScriptedPuppet;
		var senseComponent : SenseComponent;
		ownerPuppet = ( ( ScriptedPuppet )( owner ) );
		senseComponent = ownerPuppet.GetSensesComponent();
		SenseSwitch( senseComponent, true );
	}

}

class SpawnSubCharacterEffector extends Effector
{
	var m_owner : weak< GameObject >;
	var m_subCharacterTDBID : TweakDBID;

	protected override function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID )
	{
		var str : String;
		str = TweakDBInterface.GetString( record + T".subCharacterRecord", "" );
		m_subCharacterTDBID = TDBID.Create( str );
	}

	protected override function Uninitialize( game : GameInstance )
	{
		ActionOff( m_owner );
	}

	protected override function ActionOn( owner : GameObject )
	{
		var scs : SubCharacterSystem;
		var request : SpawnUniqueSubCharacterRequest;
		m_owner = owner;
		scs = ( ( SubCharacterSystem )( GameInstance.GetScriptableSystemsContainer( owner.GetGame() ).Get( 'SubCharacterSystem' ) ) );
		if( scs )
		{
			request = new SpawnUniqueSubCharacterRequest;
			request.subCharacterID = m_subCharacterTDBID;
			GameInstance.GetDelaySystem( owner.GetGame() ).DelayScriptableSystemRequest( 'SubCharacterSystem', request, 3.0 );
		}
	}

	protected override function ActionOff( owner : GameObject )
	{
		var scs : SubCharacterSystem;
		var request : DespawnUniqueSubCharacterRequest;
		scs = ( ( SubCharacterSystem )( GameInstance.GetScriptableSystemsContainer( owner.GetGame() ).Get( 'SubCharacterSystem' ) ) );
		if( scs )
		{
			request = new DespawnUniqueSubCharacterRequest;
			request.subCharacterID = m_subCharacterTDBID;
			scs.QueueRequest( request );
		}
	}

}

class DOTContinuousEffector extends ContinuousEffector
{

	protected override function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID )
	{
	}

	protected override function ActionOn( owner : GameObject )
	{
	}

	protected override function ContinuousAction( owner : GameObject, instigator : GameObject )
	{
	}

}

class ForceDismembermentEffector extends Effector
{
	var m_bodyPart : gameDismBodyPart;
	var m_woundType : gameDismWoundType;
	var m_isCritical : Bool;
	var m_skipDeathAnim : Bool;
	var m_shouldKillNPC : Bool;
	var m_dismembermentChance : Float;
	var m_effectorRecord : ForceDismembermentEffector_Record;

	protected override function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID )
	{
		var str : String;
		m_effectorRecord = TweakDBInterface.GetForceDismembermentEffectorRecord( record );
		str = m_effectorRecord.BodyPart();
		m_bodyPart = ( ( gameDismBodyPart )( ( ( Int32 )( EnumValueFromString( "gameDismBodyPart", str ) ) ) ) );
		str = m_effectorRecord.WoundType();
		m_woundType = ( ( gameDismWoundType )( ( ( Int32 )( EnumValueFromString( "gameDismWoundType", str ) ) ) ) );
		m_isCritical = m_effectorRecord.IsCritical();
		m_skipDeathAnim = m_effectorRecord.SkipDeathAnim();
		m_shouldKillNPC = m_effectorRecord.ShouldKillNPC();
		m_dismembermentChance = m_effectorRecord.DismembermentChance();
	}

	protected override function ActionOn( owner : GameObject )
	{
		var puppet : weak< ScriptedPuppet >;
		var player : weak< PlayerPuppet >;
		var rand : Float;
		player = ( ( PlayerPuppet )( GameInstance.GetPlayerSystem( owner.GetGame() ).GetLocalPlayerMainGameObject() ) );
		puppet = ( ( ScriptedPuppet )( owner ) );
		if( !( puppet ) || !( player ) )
		{
			return;
		}
		rand = RandF();
		if( rand <= m_dismembermentChance )
		{
			DismembermentComponent.RequestDismemberment( puppet, m_bodyPart, m_woundType, Vector4.EmptyVector(), m_isCritical );
		}
		if( m_shouldKillNPC || m_bodyPart == gameDismBodyPart.HEAD )
		{
			StatusEffectHelper.ApplyStatusEffect( puppet, T"BaseStatusEffect.ForceKill", player.GetEntityID() );
		}
	}

}

