class KF_StoryCheckPointVolumeSE extends  KF_StoryCheckPointVolume;

var array<PlayerStart> ForeignPSList;
var transient bool bPSListInit;

simulated function PostBeginPlay()
{
	local	KF_DialogueSpot  DlgSpot;

	if( Level.NetMode==NM_Client )
		return;

	/* No KFO Gametype, no Initialization */
	StoryGI = KFStoryGameInfo(Level.Game);
	if(StoryGI == none)
	{
        return;
	}

	if(RestartFromCheckPoint != "" &&
	RestartFromCheckPoint != CheckPointName &&
	StoryGI != none )
	{
		ForcedRestartCheckPoint = StoryGI.FindCheckPointNamed(RestartFromCheckPoint);
	}

	// cache all the DialogueSpots in the map -  we'll need this to store the states for each one
	foreach DynamicActors(class 'KF_DialogueSpot', DlgSpot)
	{
		SavedDialogue.length = SavedDialogue.length + 1;
		SavedDialogue[SavedDialogue.length-1].DialogueActor = DlgSpot;
		SavedDialogue[SavedDialogue.length-1].DialogueTriggerStates.length = DlgSpot.Dialogues.length ;
	}
}

// copy-pasted from KFStoryGameInfo to allow use in non-story games
function int GetTotalActivePlayers()
{
    local int LivingCount;
    local Controller C;

    for ( C=Level.ControllerList; C!=None; C=C.NextController )
    {
        if ((C.PlayerReplicationInfo != None) &&
        C.bIsPlayer && !C.PlayerReplicationInfo.bOutOfLives &&
        !C.PlayerReplicationInfo.bOnlySpectator )
        {
            LivingCount ++ ;
        }
    }

//  log("TOTAL PLAYERS : "@LivingCount);

    return LivingCount ;
}

// bIncludeBots now can be enabled without bRespawnPlayers
function CheckPointActivated( Pawn CheckPointInstigator, bool bForceActivate, optional bool bShowMessage)
{
	local KF_StoryCheckPointVolume	OldCheckpoint;
	local Controller C;

	/* Check for a human controlled pawn */
	if( CheckPointInstigator != none && CheckPointInstigator.Controller != none ) {
		ActivatingPlayer = CheckPointInstigator.Controller;
		if(ActivatingPlayer != none && PlayerController(ActivatingPlayer) != none &&
		ActivatingPlayer.Pawn != none )
			Instigator = ActivatingPlayer.Pawn ;
	}

	if( !bForceActivate && bRequiresWholeTeam && GetNumPlayersInVolume() < GetTotalActivePlayers())
		return;

	if(!bIsActive || bForceActivate || !bSingleActivationOnly)
	{
        // log("===============================================",'Story_Debug');
	    // log("CheckPointActivated! - "@CheckPointName,'Story_Debug');

		bIsActive = true;

		if(!bPendingFullRestart) {
			TriggerActivationEvents();

			if(bRespawnOnWipe)
                SaveStoryState();
        }

		if(StoryGI != none)
		{
			OldCheckPoint = StoryGI.CurrentCheckPoint ;
			StoryGI.CurrentCheckPoint = self ;

            for ( C=Level.ControllerList; C!=None; C=C.NextController )
            {
                if(KFPlayerController_Story(C) != none)
                {
                    KFPlayerController_Story(C).CurrentCheckPoint = self;
                }
            }

			if(bShowMessage)
			{
				BroadcastLocalizedMessage( StoryGI.default.CheckPointMessageClass , 0, ActivatingPlayer.PlayerReplicationinfo, None, self );
			}
		}

		UpdateSpawnAvailability();
		ResetPlayerCheckpointStats();

		if( bRespawnPlayers || bIncludeBots )
		{
            if ( RespawnDelay > 0 )
                DelayedRespawnDeadPlayers();
            else 
                RespawnTimerPop();
		}

		if( bTeleportstragglers)
		{
			TeleportLivingPlayers();
		}

		// if(Instigator == none)
		// {
			// log("Warning - No human instigator found when Activating "@self@".  Some actors require a human instigator to trigger successfully . (Movers) ");
		// }

		if(bDebugCheckPoint)
		{
			PrintDebugText(ActivatingPlayer.PlayerReplicationInfo.PlayerName@"activated"@CheckPointName);
		}
	}
}

function InitPlayerStarts()
{
	local NavigationPoint			N;
	local PlayerStart				PS;
    
    for( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint ) {
        PS = PlayerStart(N);
        if( PS!=None ) {
            if(Encompasses(PS) )
                PSList[PSList.Length] = PS;
            else
                ForeignPSList[ForeignPSList.Length] = PS;
        }
    }   
    bPSListInit = true;
}

function DebugPlayerStarts()
{
	local NavigationPoint			N;
	local PlayerStart				PS;
    
    ClearStayingDebugLines();
    for( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint ) {
        PS = PlayerStart(N);
        if( PS!=None ) {
            if(PS.bEnabled)
            {
                DrawStayingDebugLine(N.Location, N.Location + (100 * vect(0,0,1)), 0,255,0);
            }
            else
            {
                DrawStayingDebugLine(N.Location, N.Location + (100 * vect(0,0,1)), 255,0,0);
            }  
        }
    }   
}
        
        
function UpdateSpawnAvailability()
{
	local int i;

    if ( !bPSListInit ) 
        InitPlayerStarts();
    
    if( PSList.Length>0 ) {    
        for ( i=0; i<PSList.Length; ++i )
            PSList[i].bEnabled = true;
        for ( i=0; i<ForeignPSList.Length; ++i )
            ForeignPSList[i].bEnabled = false;   
        // debug
        //DebugPlayerStarts();
	}
	else {
        for ( i=0; i<ForeignPSList.Length; ++i )
            ForeignPSList[i].bEnabled = true;      
		log("Warning -  No Playerstarts associated with "@self@": Respawns may fail.");
    }
}


// allows respawning bots only (excluding players)
function RespawnDeadPlayers()
{
    local int i;
	local Controller C;
	local KFPlayerController KFPC;
	local PlayerController PC;
	local KFPlayerReplicationInfo KFPRI;
    local bool bWaveInProgress, bBalanceTeams;

	bPendingRespawn = false;
    bWaveInProgress = KFGameType(Level.Game).bWaveInProgress;
    bBalanceTeams = KFGameType(Level.Game).bBalanceTeams;
    KFGameType(Level.Game).bWaveInProgress = false;
    KFGameType(Level.Game).bBalanceTeams = false;

	For ( C= Level.ControllerList; C!=None; C=C.NextController )
	{
		if ( C.PlayerReplicationInfo != none )
		{
			/* I'm guessing we are still using Perks in Story mode ? ... will leave this in for now */
			KFPC = KFPlayerController(C);
			if ( KFPC != none )
			{
				KFPRI = KFPlayerReplicationInfo(C.PlayerReplicationinfo);
				if ( KFPRI != none )
				{
					KFPC.bChangedVeterancyThisWave = false;

					if ( KFPRI.ClientVeteranSkill != KFPC.SelectedVeterancy )
					{
						KFPC.SendSelectedVeterancyToServer();
					}
				}
			}

			if ( C.PlayerReplicationInfo.bOnlySpectator || !C.PlayerReplicationInfo.bOutOfLives ) 
				continue;

            if ( C.PlayerReplicationInfo.bBot ) {
                if ( !bIncludeBots )
                    continue;
            }
            else if ( !bRespawnPlayers )
                continue;

			C.PlayerReplicationInfo.bOutOfLives = false;
			C.PlayerReplicationInfo.NumLives = 0;

            PC = PlayerController(C);
			if( PC != none )
			{
				PC.GotoState('PlayerWaiting');
				PC.SetViewTarget(C);
				PC.ClientSetBehindView(false);
				PC.bBehindView = False;
			}

			if(KFPlayerController_Story(C) != none)
			{
				KFPLayerController_Story(C).NumCheckPointRespawns ++ ;
			}

			LastRespawnedPlayer = C;

			// Make sure the dude we're respawning hast at least some cash.
		    C.PlayerReplicationInfo.Score = Max(KFGameType(Level.Game).MinRespawnCash, int(C.PlayerReplicationInfo.Score));
			C.ServerReStartPlayer();
            
            if ( C.Pawn != none ) {
                if ( bTeleportStragglers ) {
                    for ( i=0; i<PSList.Length; ++i )
                        if ( PSList[i].Accept(C.Pawn, none) ) 
                            break;
                }
                        
                if( PC != none )
                    PC.ClientSetViewTarget(PC.Pawn);
            }
		}
	}
    
    KFGameType(Level.Game).bWaveInProgress = bWaveInProgress;
    KFGameType(Level.Game).bBalanceTeams = bBalanceTeams;

	LastRespawnedPlayer = none;

	/* Full Checkpoint restart (everyone was wiped out) */
	if(bPendingFullRestart && StoryGI != none)
	{
		bPendingFullRestart = false;
		StoryGI.NotifyTeamRestarted();
	}
}

function TeleportLivingPlayers()
{
	local Controller		C;
    local bool bTeleportMe;
    local int i;

	For ( C= Level.ControllerList; C!=None; C=C.NextController )
	{
        bTeleportMe = false;

		if ( C.PlayerReplicationInfo != none )
		{
			if(C.bIsPlayer
                && !C.PlayerReplicationInfo.bOutOfLives
                && !C.PlayerReplicationInfo.bOnlySpectator
                && C.Pawn != none && C.Pawn.Health > 0 
                && C.Pawn.PhysicsVolume != self 
                && ((C.PlayerReplicationInfo.bBot && bIncludeBots) || (!C.PlayerReplicationInfo.bBot && bRespawnPlayers)) )
			{
                if(TeleportExclusionVolume != none)
                    bTeleportMe = !TeleportExclusionVolume.Encompasses(C.Pawn);
                else
                    bTeleportMe = TeleportStragglerDist == 0 || VSize(C.Pawn.Location - Location) >= TeleportStragglerDist;

                if(bTeleportMe){ 
                    for ( i=0; i<PSList.Length; ++i )
                        if ( PSList[i].Accept(C.Pawn, none) ) 
                            break;
                    if ( i == PSList.Length )
                        log("Unable to teleport " $ C.Pawn $ " to " $ self, 'StoryCheckPoint');
				}
			}
		}
	}
}

function SaveStoryState()
{
    if ( StoryGI != none )
        super.SaveStoryState();
}

defaultproperties
{
}
