class OdaEmergencyListener extends CustomValueStatPoolsListener
{
	var m_owner : weak< NPCPuppet >;
	var m_healNumber : Int32;
	private var m_heal1HealthPercentage : Float;
	default m_heal1HealthPercentage = 70.f;
	private var m_heal2HealthPercentage : Float;
	default m_heal2HealthPercentage = 55.f;
	private var m_heal3HealthPercentage : Float;
	default m_heal3HealthPercentage = 40.f;
	private var m_heal4HealthPercentage : Float;
	default m_heal4HealthPercentage = 25.f;
	private var m_heal5HealthPercentage : Float;
	default m_heal5HealthPercentage = 10.f;

	public override function OnStatPoolValueChanged( oldValue : Float, newValue : Float, percToPoints : Float )
	{
		CheckHPValue( oldValue, newValue, percToPoints );
	}

	public function CheckHPValue( oldValue : Float, newValue : Float, percToPoints : Float )
	{
		if( ( ( oldValue > m_heal1HealthPercentage ) && ( newValue <= m_heal1HealthPercentage ) ) && ( m_healNumber == 0 ) )
		{
			SetRoamingBehaviorAuthorization();
		}
		else if( ( ( oldValue > m_heal2HealthPercentage ) && ( newValue <= m_heal2HealthPercentage ) ) && ( m_healNumber == 1 ) )
		{
			SetRoamingBehaviorAuthorization();
		}
		if( ( ( oldValue > m_heal3HealthPercentage ) && ( newValue <= m_heal3HealthPercentage ) ) && ( m_healNumber == 2 ) )
		{
			SetRoamingBehaviorAuthorization();
		}
		else if( ( ( oldValue > m_heal4HealthPercentage ) && ( newValue <= m_heal4HealthPercentage ) ) && ( m_healNumber == 3 ) )
		{
			SetRoamingBehaviorAuthorization();
		}
		if( ( ( oldValue > m_heal5HealthPercentage ) && ( newValue <= m_heal5HealthPercentage ) ) && ( m_healNumber == 4 ) )
		{
			SetRoamingBehaviorAuthorization();
		}
	}

	public function SetRoamingBehaviorAuthorization()
	{
		m_healNumber += 1;
		StatusEffectHelper.ApplyStatusEffect( m_owner, T"Oda.Emergency", m_owner.GetEntityID() );
	}

}

class OdaComponent extends ScriptableComponent
{
	private var m_owner : weak< NPCPuppet >;
	private var m_owner_id : EntityID;
	private var m_odaAIComponent : AIHumanComponent;
	private var m_actionBlackBoard : weak< IBlackboard >;
	private var m_statPoolSystem : StatPoolsSystem;
	private var m_statPoolType : gamedataStatPoolType;
	private var m_healthListener : OdaEmergencyListener;
	private var m_statusEffect_emergency : TweakDBID;
	private var m_targetTrackerComponent : TargetTrackerComponent;
	private var m_weakspotDestroyed : Bool;

	private function OnGameAttach()
	{
		m_owner = ( ( NPCPuppet )( GetOwner() ) );
		m_owner_id = m_owner.GetEntityID();
		m_odaAIComponent = m_owner.GetAIControllerComponent();
		m_actionBlackBoard = m_odaAIComponent.GetActionBlackboard();
		m_statPoolSystem = GameInstance.GetStatPoolsSystem( m_owner.GetGame() );
		m_healthListener = new OdaEmergencyListener;
		m_healthListener.SetValue( 70.0 );
		m_healthListener.m_owner = m_owner;
		m_statPoolSystem.RequestRegisteringListener( m_owner_id, gamedataStatPoolType.Health, m_healthListener );
		StatusEffectHelper.ApplyStatusEffect( m_owner, T"Oda.Masked", m_owner_id );
		m_targetTrackerComponent = m_owner.GetTargetTrackerComponent();
		m_statPoolSystem = GameInstance.GetStatPoolsSystem( m_owner.GetGame() );
		m_weakspotDestroyed = false;
	}

	public function OnGameDetach()
	{
		m_statPoolSystem.RequestUnregisteringListener( m_owner_id, gamedataStatPoolType.Health, m_healthListener );
		m_healthListener = NULL;
	}

	protected event OnDefeated( evt : DefeatedEvent )
	{
		StatusEffectHelper.ApplyStatusEffect( m_owner, T"AdamSmasher.InvulnerableDefeated", m_owner_id );
	}

	public function GetCombatTarget() : weak< NPCPuppet >
	{
		return ( ( weak< weak< NPCPuppet > > )( m_odaAIComponent.GetBehaviorArgument( 'CombatTarget' ) ) );
	}

	protected event OnAIEvent( aiEvent : AIEvent )
	{
		if( aiEvent.name == 'BladesOn' )
		{
			GameObject.StartReplicatedEffectEvent( m_owner, 'blade_light_on' );
			GameObject.BreakReplicatedEffectLoopEvent( m_owner, 'screen_swipe' );
		}
		if( aiEvent.name == 'BladesOff' )
		{
			GameObject.BreakReplicatedEffectLoopEvent( m_owner, 'blade_light_on' );
			GameObject.StartReplicatedEffectEvent( m_owner, 'screen_swipe' );
		}
		if( aiEvent.name == 'StealthMode' )
		{
			GameObject.BreakReplicatedEffectLoopEvent( m_owner, 'screen_swipe' );
		}
	}

	protected event OnStatusEffectApplied( evt : ApplyStatusEffectEvent )
	{
		var tags : array< CName >;
		tags = evt.staticData.GameplayTags();
		if( StatusEffectSystem.ObjectHasStatusEffect( m_owner, T"BaseStatusEffect.Defeated" ) )
		{
			GameObject.BreakReplicatedEffectLoopEvent( m_owner, 'blade_light_on' );
		}
		if( tags.Contains( 'BossSuicide' ) )
		{
			StatusEffectHelper.ApplyStatusEffect( m_owner, T"BaseStatusEffect.SuicideWithWeapon", m_owner.GetEntityID() );
			StatusEffectHelper.ApplyStatusEffect( m_owner, T"Sasquatch.ForceStaggerSuicide", m_owner_id );
		}
		if( tags.Contains( 'BossGrenadeHackEffect' ) )
		{
			StatusEffectHelper.ApplyStatusEffect( m_owner, T"BaseStatusEffect.OdaSuicideWithGrenade", m_owner_id );
		}
		if( tags.Contains( 'WeakspotDestruction' ) )
		{
			StatusEffectHelper.RemoveStatusEffect( m_owner, T"Oda.CloakedOda" );
			StatusEffectHelper.RemoveStatusEffect( m_owner, T"Oda.Cloaked" );
		}
		if( tags.Contains( 'OdaStatusEffect' ) )
		{
			EvaluateAppearance();
		}
		if( tags.Contains( 'Cloak' ) )
		{
			ApplyBlockStaggerStatusEffect();
		}
		if( tags.Contains( 'Heal' ) )
		{
			RemoveBlockStaggerStatusEffect();
			ApplyForceStaggerStatusEffect();
		}
		if( tags.Contains( 'OdaStealthWrappers' ) )
		{
			AnimationControllerComponent.SetAnimWrapperWeight( m_owner, 'OdaSearchingCustom', 1.0 );
		}
		if( StatusEffectSystem.ObjectHasStatusEffect( m_owner, T"Oda.Main_boss_oda_allow_knockdown" ) )
		{
			StatusEffectHelper.ApplyStatusEffect( m_owner, T"BaseStatusEffect.Knockdown", m_owner.GetEntityID() );
		}
	}

	private function DestroyAllWeakspots()
	{
		var weakspots : array< weak< WeakspotObject > >;
		var scriptWeakspot : ScriptedWeakspotObject;
		var i : Int32;
		m_owner.GetWeakspotComponent().GetWeakspots( weakspots );
		if( weakspots.Size() > 0 )
		{
			for( i = 0; i < weakspots.Size(); i += 1 )
			{
				scriptWeakspot = ( ( ScriptedWeakspotObject )( weakspots[ i ] ) );
				scriptWeakspot.DestroyWeakspot( m_owner );
				ScriptedWeakspotObject.Kill( weakspots[ i ] );
			}
		}
	}

	protected event OnStatusEffectRemoved( evt : RemoveStatusEffect )
	{
		var tags : array< CName >;
		tags = evt.staticData.GameplayTags();
		if( tags.Contains( 'OdaStatusEffect' ) )
		{
			EvaluateAppearance();
		}
		if( tags.Contains( 'Cloak' ) )
		{
			RemoveForceStaggerStatusEffect();
			if( StatusEffectSystem.ObjectHasStatusEffect( m_owner, T"BaseStatusEffect.Cloaked_Exit" ) )
			{
				PlayMalfunctionFX();
			}
			GameObject.StartReplicatedEffectEvent( m_owner, 'exit_cloak' );
		}
		if( evt.staticData.GetID() == T"Oda.Masked" )
		{
			SetFactValue( m_owner.GetGame(), 'q112_oda_mask_destroyed', 1 );
		}
		if( tags.Contains( 'OdaStealthWrappers' ) )
		{
			AnimationControllerComponent.SetAnimWrapperWeight( m_owner, 'OdaSearchingCustom', 0.0 );
		}
		if( tags.Contains( 'Madness' ) )
		{
			StatusEffectHelper.ApplyStatusEffect( m_owner, T"BaseStatusEffect.SuicideWithWeapon", m_owner.GetEntityID() );
			StatusEffectHelper.ApplyStatusEffect( m_owner, T"Sasquatch.ForceStaggerSuicide", m_owner_id );
		}
	}

	protected event OnNonStealthQuickHackVictimEvent( evt : NonStealthQuickHackVictimEvent )
	{
		NPCStatesComponent.AlertPuppet( m_owner );
	}

	public function ApplyForceStaggerStatusEffect()
	{
		StatusEffectHelper.ApplyStatusEffect( m_owner, T"Oda.ForceStaggerOda", m_owner.GetEntityID() );
	}

	public function ApplyBlockStaggerStatusEffect()
	{
		StatusEffectHelper.ApplyStatusEffect( m_owner, T"Oda.BlockStaggerOda", m_owner.GetEntityID() );
	}

	public function RemoveForceStaggerStatusEffect()
	{
		StatusEffectHelper.RemoveStatusEffect( m_owner, T"Oda.ForceStaggerOda" );
	}

	public function RemoveBlockStaggerStatusEffect()
	{
		StatusEffectHelper.RemoveStatusEffect( m_owner, T"Oda.BlockStaggerOda" );
	}

	public function PlayMalfunctionFX()
	{
		GameObject.StartReplicatedEffectEvent( m_owner, 'hacks_cyberware_malfunction' );
	}

	public function EvaluateAppearance()
	{
		if( !( StatusEffectSystem.ObjectHasStatusEffect( m_owner, T"Oda.Masked" ) ) )
		{
			m_owner.ScheduleAppearanceChange( 'oda_oda_mask_damage' );
		}
		else
		{
			m_owner.ScheduleAppearanceChange( 'oda_oda' );
		}
	}

	protected event OnSmartBulletDeflectedEvent( evt : SmartBulletDeflectedEvent )
	{
		SetFactValue( m_owner.GetGame(), 'q112_oda_mask_deflected_bullet', 1 );
	}

	protected event OnHit( evt : gameHitEvent )
	{
		if( StatusEffectSystem.ObjectHasStatusEffect( m_owner, T"Oda.Healing" ) )
		{
			StatusEffectHelper.RemoveStatusEffect( m_owner, T"Oda.CloakedOda" );
			StatusEffectHelper.RemoveStatusEffect( m_owner, T"Oda.Cloaked" );
		}
	}

	protected event OnLookedAtEvent( evt : LookedAtEvent ) {}

	protected function OnDeactivate() {}

	protected event OnDamageDealt( evt : gameTargetDamageEvent )
	{
		var weapon : weak< WeaponObject >;
		weapon = ScriptedPuppet.GetActiveWeapon( m_owner );
		if( weapon && WeaponObject.IsOfType( weapon.GetItemID(), gamedataItemType.Cyb_MantisBlades ) )
		{
			SetFactValue( m_owner.GetGame(), 'q112_oda_dealt_damage_with_mantis', 1 );
		}
	}

}

