class OvershieldMinValueListener extends ScriptStatPoolsListener
{
	var m_effector : weak< ScaleOvershieldDecayOverTimeEffector >;

	protected event OnStatPoolMinValueReached( value : Float )
	{
		if( m_effector )
		{
			m_effector.MarkForReset();
		}
	}

}

class ScaleOvershieldDecayOverTimeEffector extends ContinuousEffector
{
	var m_effectApplied : Bool;
	var m_decayModifier : gameStatModifierData;
	var m_owner : weak< GameObject >;
	var m_overshieldListener : OvershieldMinValueListener;
	var m_delayTime : Float;
	var m_elapsedTime : Float;
	var m_bValue : Float;
	var m_kInitValue : Float;
	var m_kValue : Float;
	var m_maxDecay : Float;
	var m_maxValueApplied : Bool;
	var m_markedForReset : Bool;

	protected override function Initialize( record : TweakDBID, game : GameInstance, parentRecord : TweakDBID )
	{
		m_effectApplied = false;
		m_maxValueApplied = false;
		m_markedForReset = false;
		m_elapsedTime = 0.0;
		m_bValue = TweakDBInterface.GetFloat( record + T".b", 2.0 );
		m_kInitValue = TweakDBInterface.GetFloat( record + T".kInit", -1.0 );
		m_kValue = TweakDBInterface.GetFloat( record + T".k", 2.0 );
		m_maxDecay = TweakDBInterface.GetFloat( record + T".maxDecay", 200.0 );
		m_delayTime = TweakDBInterface.GetFloat( record + T".delayTime", 0.5 );
	}

	public function MarkForReset()
	{
		m_markedForReset = true;
	}

	protected function ResetDecayModifier()
	{
		RemoveModifier();
		m_effectApplied = false;
		m_maxValueApplied = false;
		m_markedForReset = false;
	}

	protected function AddModifier()
	{
		var statsSystem : StatsSystem;
		var decayAmount : Float;
		statsSystem = GameInstance.GetStatsSystem( m_owner.GetGame() );
		decayAmount = PowF( m_bValue, m_kInitValue + ( m_kValue * m_elapsedTime ) );
		if( decayAmount < 1.0 )
		{
			return;
		}
		if( decayAmount >= m_maxDecay )
		{
			decayAmount = m_maxDecay;
			m_maxValueApplied = true;
		}
		m_decayModifier = RPGManager.CreateStatModifier( gamedataStatType.OvershieldDecayRate, gameStatModifierType.Additive, decayAmount );
		statsSystem.AddModifier( m_owner.GetEntityID(), m_decayModifier );
	}

	protected function RemoveModifier()
	{
		var statsSystem : StatsSystem;
		if( m_decayModifier )
		{
			statsSystem = GameInstance.GetStatsSystem( m_owner.GetGame() );
			statsSystem.RemoveModifier( m_owner.GetEntityID(), m_decayModifier );
			m_decayModifier = NULL;
		}
	}

	protected export override function ActionOn( owner : GameObject )
	{
		m_owner = owner;
		m_overshieldListener = new OvershieldMinValueListener;
		m_overshieldListener.m_effector = this;
		GameInstance.GetStatPoolsSystem( owner.GetGame() ).RequestRegisteringListener( m_owner.GetEntityID(), gamedataStatPoolType.Overshield, m_overshieldListener );
	}

	protected export override function ActionOff( owner : GameObject )
	{
		GameInstance.GetStatPoolsSystem( owner.GetGame() ).RequestUnregisteringListener( owner.GetEntityID(), gamedataStatPoolType.Overshield, m_overshieldListener );
		m_overshieldListener = NULL;
	}

	protected export override function ContinuousAction( owner : GameObject, instigator : GameObject )
	{
		var statPoolSys : StatPoolsSystem;
		var statsSys : StatsSystem;
		var overshieldThresholdPercent : Float;
		var currentOvershieldPercent : Float;
		statPoolSys = GameInstance.GetStatPoolsSystem( owner.GetGame() );
		statsSys = GameInstance.GetStatsSystem( owner.GetGame() );
		if( m_markedForReset )
		{
			ResetDecayModifier();
		}
		if( statPoolSys.IsStatPoolModificationDelayed( owner.GetEntityID(), gamedataStatPoolType.Overshield ) )
		{
			return;
		}
		overshieldThresholdPercent = statsSys.GetStatValue( owner.GetEntityID(), gamedataStatType.OvershieldDecayStartThreshold );
		currentOvershieldPercent = statPoolSys.GetStatPoolValue( owner.GetEntityID(), gamedataStatPoolType.Overshield );
		if( m_effectApplied )
		{
			if( overshieldThresholdPercent >= currentOvershieldPercent )
			{
				RemoveModifier();
				m_elapsedTime = 0.0;
				m_effectApplied = false;
			}
			else if( !( m_maxValueApplied ) )
			{
				m_elapsedTime += m_delayTime;
				RemoveModifier();
				AddModifier();
			}
		}
		else if( currentOvershieldPercent > overshieldThresholdPercent )
		{
			m_elapsedTime = 0.0;
			AddModifier();
			m_effectApplied = true;
		}
	}

}

