class ObjCondition_Use_SE extends ObjCondition_Use
editinlinenew;

/*
	--------------------------------------------------------------
	ObjCondition_Use_SE
	--------------------------------------------------------------

    Enhanced version of ObjCondition_Use.
	
	- Fixed a bug when GetCompletionPct() could return value > 1
	- Added bCheckDependentsFirst
	- ConditionTick() stops using if bCheckDependentsFirst and DependentConditions incomplete
	- HoldUseSeconds use difficulty modifiers
	- if Screen_CountStyle == Count_Down, then seconds left are displayed on the HUD
	- If UseActor uses collision cylinder, it will be always taken 
	  in place, not only when it is blocking actors
	

	Author :  			PooSH
	Original Author:	Alex Quick

	--------------------------------------------------------------
*/

// if true, DependentConditions the progression
var(KF_ObjectiveCondition)				bool					bCheckDependentsFirst; 
// call DependentConditions[].FindInstigator()?
var(KF_ObjectiveCondition)				bool					bCheckDependentsInstigator; 

var(Audio)                              sound                  	UsingSound;
var	protected							sound					OriginalUsingSound;

var protected transient 				float					InitialHoldUseSeconds;



function Reset()
{
	ResetSound();
    Super.Reset();
	SetTargetActor(CurrentUserName,none);
}

function ResetSound()
{
	local Actor MyUseActor;
	
	// restore original ambient sound (mostly - none)
	if ( UsingSound != OriginalUsingSound ) {
		MyUseActor = GetTargetActor(UseActorName);
		if ( MyUseActor != none && MyUseActor.AmbientSound != OriginalUsingSound )
			MyUseActor.AmbientSound = OriginalUsingSound;
	}
}

function PostBeginPlay(KF_StoryObjective MyOwner)
{
	local Actor MyUseActor;
	
    Super.PostBeginPlay(MyOwner);
	
	InitialHoldUseSeconds = HoldUseSeconds;
	MyUseActor = GetTargetActor(UseActorName);
	if ( MyUseActor != none )
		OriginalUsingSound = MyUseActor.AmbientSound;
}


function SetObjOwner(KF_StoryObjective NewOwner)
{
	ResetSound(); // just to be sure we won't leave ambient sound for old actor
	super.SetObjOwner(NewOwner);
}

function ConditionActivated(pawn ActivatingPlayer)
{
	if ( InitialHoldUseSeconds > 0 )
		HoldUseSeconds = InitialHoldUseSeconds * GetTotalDifficultyModifier();
	
    Super.ConditionActivated(ActivatingPlayer);
}

function ConditionTick(float DeltaTime)
{
    Super.ConditionTick(DeltaTime);

	// stop using objective, if we don't match condition
	if ( bCheckDependentsFirst && GetTargetActor(CurrentUserName) != none && !AllowCompletion() )
		StopUsingObj(Pawn(GetTargetActor(CurrentUserName)));
}

function bool     IsTouchingUseActor(pawn Toucher)
{
    local Actor A;
    local float DistSq;
	local Actor MyUseActor;

	MyUseActor = GetTargetActor(UseActorName);
	 
    if(Toucher != none && MyUseActor != none)
    {
        foreach Toucher.TouchingActors(class 'Actor', A)
        {
            if(A == MyUseActor)
            {
                return true;
            }
        }

		// added bUseCylinderCollision in cases use actor doesn't want block actors (e.g. use blocking volume)
		// but just wants to collide with actors
		// -- PooSH
        if( MyUseActor.bBlockActors || MyUseActor.bUseCylinderCollision )
        {
            DistSq = VsizeSquared(MyUseActor.Location - Toucher.Location) ;
            if(DistSq <= Square( (MyUseActor.CollisionRadius + (Toucher.CollisionRadius)) * 1.25 )  )
            {
                return true;
            }
        }
    }

    return false;
}

function Startedusing(pawn User)
{
    local Pawn CurrentUser;
    local KF_UseableMover ControlledMover;
	local Actor MyUseActor;
	local Pawn OriginalIntigator;
	local bool bCantUse;
	
	if ( bComplete )
		return; // no point of using already completed objective
		
	MyUseActor = GetTargetActor(UseActorName);
    ControlledMover = KF_UseableMover(GetTargetActor(ControlledMoverName));
    CurrentUser = Pawn(GetTargetActor(CurrentUserName));		
	
	if(CurrentUser == none && IsTouchingUseActor(User))
    {
		OriginalIntigator = GetInstigator();
		// Instigator must be set to check DependentConditions
		if ( OriginalIntigator != User )
			SetTargetActor(InstigatorName, User); 
		bCantUse = bCheckDependentsFirst && !AllowCompletion();
		if ( bCantUse ) {
			SetTargetActor(InstigatorName, OriginalIntigator); // restore original instigator
			return;		
		}
		
        SetTargetActor(InstigatorName,User);
        SetTargetActor(CurrentUserName,User);
		LastUseTime = User.Level.TimeSeconds;

		if(AllowCompletion())
		{
            bWasUsed = true;
        }

        if(ControlledMover != none)
        {
            ControlledMover.StartedUsing();
        }
		
		if ( HoldUseSeconds > 0 && UsingSound != none ) {
			MyUseActor.AmbientSound = UsingSound;
			MyUseActor.NetUpdateTime = MyUseActor.Level.TimeSeconds - 1;		
		}
	}
}

function StopUsingObj(pawn User)
{
	ResetSound();
	super.StopUsingObj(User);
	// ensure that we are not going abouve 100%
	if ( FinishedUseSeconds > HoldUseSeconds )
		FinishedUseSeconds = HoldUseSeconds;
}



// fixed progress going above 100% -- PooSH
function       float        GetCompletionPct()
{
	return fclamp(super.GetCompletionPct(), 0.f, 1.f);
}


// count down style shows remaining time  -- PooSH
function        string      GetDataString()
{
     if(HoldUseSeconds > 0)
     {
		if ( HUD_Screen.Screen_CountStyle == 0 ) {
			return string( (1.f-(GetRemainingUseTime() / HoldUseSeconds))*100.f) $"%" ;
		}
		else {
			return string(GetRemainingUseTime()) ;
		}
     }

     return "" ;
}

/* Overriden to skip inactive dependencies  -- PooSH */
function    bool AllowCompletion()
{
    local int i;
	local array<Pawn> MyInstigators;

	if ( DependentConditions.length > 0 ) {
		MyInstigators = GetInstigatorList();
		for(i = 0 ; i < DependentConditions.length ; i ++) {
			if ( DependentConditions[i].ConditionIsActive() ) {
				if( !DependentConditions[i].bComplete 
					|| (bCheckDependentsInstigator && !DependentConditions[i].FindInstigator(MyInstigators)) ) 
				{
					return false;
				}
			}
		}
	}
    return true;
}

defaultproperties
{
     bCheckDependentsInstigator=True
}
