/*
	--------------------------------------------------------------
	ObjCondition_Area_SE
	--------------------------------------------------------------

    A Condition which is marked complete when a player either
    (A) leaves a volume  or  (B)  enters a volume
    Can also be configured to check ZoneInfo regions.
	
	Enhancements and fixes:
	- Fixed GetLocation() ignoring HUD_World.World_Location
	- Aplied difficulty and player count scaling on duration
	- LastInAreaTime, LastOutOfAreaTime, bTimingOut changed to 
	  RequirementsMatchedTime and bRequirementsMatched
	- Added bCheckDependentsFirst
	

	Author :  			PooSH
	Original Author:	Alex Quick

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

class ObjCondition_Area_SE extends ObjCondition_Area
editinlinenew;

/**
	EAreaInstigator - determines which pawn must be used as Instigator:
	Instigator_Triggered 	Instigator stays the one which triggered this area or activated this objective. 
							Pawns inside this area do not affect Instigator value.
							This is default behavior of ObjCondition_Area
	Instigator_First		Instigator will be set to a pawn, which entered the area first.
							If Instigator leaves the area, the next pawn in the area will be used
							as Instigator and so on.
	Instigator_Last			Instigator will be set to a pawn, which entered the area first.	
*/

/*
enum EAreaInstigator
{
	Instigator_Triggered,
	Instigator_First,
	Instigator_Last
};
var() EAreaInstigator AreaInstigator;
*/

// if true, DependentConditions will be checked before the Duration
var(KF_ObjectiveCondition)	bool					bCheckDependentsFirst; 
// call DependentConditions[].FindInstigator()?
var(KF_ObjectiveCondition)	bool					bCheckDependentsInstigator; 
// Time since when requiremets are matched
// 0 - requrements are not matched at the current moment
var        			float       RequirementsMatchedTime; 
var					bool		bRequirementsMatched;

var protected		float 		OriginalDuration;


function PostBeginPlay(KF_StoryObjective MyOwner)
{
    Super.PostBeginPlay(MyOwner);
	
	OriginalDuration = Duration;
}


function Reset()
{
    Super.Reset();
	bRequirementsMatched = false;	
	RequirementsMatchedTime = 0; 
}


function ConditionActivated(pawn ActivatingPlayer)
{
    Super.ConditionActivated(ActivatingPlayer);
	
	Duration = OriginalDuration * GetTotalDifficultyModifier();
	bRequirementsMatched = false;	
	RequirementsMatchedTime = 0; 
}

function ConditionTick(Float DeltaTime)
{
	super.ConditionTick(DeltaTime);
	
	if ( CompletionMethod == Method_EnterArea ) 
		bRequirementsMatched = NumInVolume > 0
			&& (!bRequiresWholeTeam || NumInVolume >= GetObjOwner().StoryGI.GetTotalActivePlayers());
	else
		bRequirementsMatched = NumInVolume == 0
			|| (!bRequiresWholeTeam && NumInVolume < GetObjOwner().StoryGI.GetTotalActivePlayers());
	
	if (bRequirementsMatched) {
		if (bCheckDependentsFirst && !AllowCompletion())
			RequirementsMatchedTime = 0.f;
		else if ( RequirementsMatchedTime == 0.f )
			RequirementsMatchedTime = GetObjOwner().Level.TimeSeconds;
	}
	else	
		RequirementsMatchedTime = 0.f;	
}

/* returns the percentage of completion for this condition */
function       float        GetCompletionPct()
{
	if ( !bRequirementsMatched || RequirementsMatchedTime == 0.f )
		return 0.f;
		
	if ( Duration == 0.f )
		return float(bRequirementsMatched);
		
	return FClamp((GetObjOwner().Level.TimeSeconds - RequirementsMatchedTime) / Duration,0.f,1.f);
}


function        string      GetDataString()
{
     local string DataString;

/*   if( (CompletionMethod == Method_StayInArea && bTimingOut) ||
     (CompletionMethod == Method_EnterArea && !bTimingOut) )
     {
        DataString = FormatTime(FMax(Duration - (GetObjOwner().Level.TimeSeconds - LastInAreaTime),0.f))  ;
     }
*/

     if(bRequiresWholeTeam)
     {
        DataString@="["$NumInVolume$"/"$GetObjOwner().StoryGI.GetTotalActivePlayers()$"]" ;
     }

     return DataString ;
}



/* 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;
}

// fixes bug when location of KF_StoryObjective is returned instead of Volume  
// -- PooSH
function        vector       GetLocation(optional out Actor LocActor)
{
    local Volume MyAreaVolume;

    if(ConditionIsActive())
    {
		// first look if actor is defined in HUD world settings
		if ( GetWorldLocActor(LocActor) )
			return LocActor.Location;
			
		// if HUD world actor is not defined - try to use Volume, then - Zone
        MyAreaVolume = Volume(GetTargetActor(AreaVolumeName));
        if(MyAreaVolume != none) {
            LocActor = MyAreaVolume;
            return LocActor.Location;
        }
		// AssociatedZone is private and has no getter (including GetTargetActor()) 
        // else if( AreaZoneName != "" && AssociatedZone != none ) {
            // LocActor = AssociatedZone;
            // return LocActor.Location;
        // }
    }
	
	// return zero vector instead, if nothing found (not the KF_StoryObjective.Location)
	return vect(0,0,0);
}

defaultproperties
{
     bCheckDependentsInstigator=True
}
