//=============================================================================
// KFMGA_Rollercoaster
//=============================================================================
// Specific implementation of the animated trap type with extensions for the
//      rollercoaster trap.  Mostly deals with timing of turning on damage
//      volumes, as well as the left/right movement of the trap.
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
// - Dan Weiss
//=============================================================================

class KFMGA_Rollercoaster extends KFMGA_AnimatedTrap;

/** Amount of time to move to the end position.  Cached from base class MovementTime */
var float MovementStartTime;

/** Amount of time to take to move back to the starting position.  If this is zero, gets set to match MovementTime */
var() float MovementBackTime;

/** Button to move left */
var() KFTrigger_MinigameButton MoveLeftButton;

/** Button to move right */
var() KFTrigger_MinigameButton MoveRightButton;

/** Which direction the coaster is travelling. Used to trigger client movement */
var repnotify int MoveDirection;

/** Default movement vector, cached from base class MovementVector */
var Vector CachedMovementVector;

/** Move vector in the opposite direction. If this is the zero vector, gets set to -MovementDirection */
var() Vector RightMoveVector;

/** Move time in the opposite direction.  If this is zero, gets set to match MovementTime */
var() float RightMovementTime;

/** Move back time in the opposite direction.  If this is zero, gets set to match MovementBackTime */
var() float RightMovementBackTime;

/** Physics volumes for the two ends of the coaster car.  Enabling/disabling in code to time better compared to Kismet, while leaving LD option for location and setup intact. */
var() KFDynamicPhysicsVolume LeftPhysicsVolume;
var() KFDynamicPhysicsVolume RightPhysicsVolume;

replication
{
    if (bNetDirty)
        MoveDirection;
}

simulated event PostBeginPlay()
{
    super.PostBeginPlay();

    //Cache off some values from base class
    MovementStartTime = MovementTime;
    CachedMovementVector = MovementVector;

    //Verify safe defaults on server/client
    if (MovementBackTime <= 0.f)
    {
        MovementBackTime = MovementTime;
    }

    if (VSize(RightMoveVector) <= 0.f)
    {
        RightMoveVector = -MovementVector;
    }

    if (RightMovementTime <= 0.f)
    {
        RightMovementTime = MovementTime;
    }

    if (RightMovementBackTime <= 0.f)
    {
        RightMovementBackTime = MovementBackTime;
    }

    if (LeftPhysicsVolume != none)
    {
        LeftPhysicsVolume.SetCollisionType(COLLIDE_NoCollision);
    }

    if (RightPhysicsVolume != none)
    {
        RightPhysicsVolume.SetCollisionType(COLLIDE_NoCollision);
    }
}

function bool CanBeActivated(KFTrigger_MinigameButton ActivationSource)
{
    return !bActivated;
}

/** Client activation is being handled a bit different due to need to know direction to move.
 *  For the rollercoaster, intercept bActivated and only respond to it if deactivating.
 */
simulated event ReplicatedEvent(name VarName)
{
    if (VarName == 'bActivated')
    {
        if (!bActivated)
        {
            PlayDeactivation();
        }
    }
    else if (VarName == 'MoveDirection')
    {
        if (MoveDirection >= 0)
        {
            PlayActivation();
        }
    }
    else
    {
        super.ReplicatedEvent(VarName);
    }
}

/** Big change from base implementation is that we're modifying MovementTime and MovementVector
 *      manually in the next handful of functions.  The original values are cached off at the start
 *      of play for reuse later, based on direction we're moving the rollercoaster trap.
 */
function Activated(KFTrigger_MinigameButton ActivationSource)
{
    if (!bActivated)
    {
        if (ActivationSource == MoveLeftButton)
        {
            MoveDirection = 0;
            if (LeftPhysicsVolume != none)
            {
                LeftPhysicsVolume.SetCollisionType(COLLIDE_TouchAll);
            }
        }
        else if (ActivationSource == MoveRightButton)
        {
            MoveDirection = 1;
            if (RightPhysicsVolume != none)
            {
                RightPhysicsVolume.SetCollisionType(COLLIDE_TouchAll);
            }
        }
    }    

    super.Activated(ActivationSource);
}

function Deactivated()
{
    super.Deactivated();

    if (bActivated)
    {
        MoveDirection = -1;
    }
}

simulated function PlayActivationIdle()
{
    MovementTime = MoveDirection == 0 ? MovementStartTime : RightMovementTime;
    super.PlayActivationIdle();
}

simulated function PlayDeactivation()
{
    MovementTime = MoveDirection == 0 ? MovementBackTime : RightMovementBackTime;
    super.PlayDeactivation();
}

simulated function SetMoveActivationCurve()
{
    //Left
    if (MoveDirection == 0)
    {
        MovementVector = CachedMovementVector;
    }
    //Right
    else
    {
        MovementVector = RightMoveVector;
    }
    super.SetMoveActivationCurve();
}

simulated state Moving
{
    //Reset linked physics volumes, regardless of direction moved
    simulated function EndMovement()
    {
        if (LeftPhysicsVolume != none)
        {
            LeftPhysicsVolume.SetCollisionType(COLLIDE_NoCollision);
        }

        if (RightPhysicsVolume != none)
        {
            RightPhysicsVolume.SetCollisionType(COLLIDE_NoCollision);
        }

        super.EndMovement();
    }
}

defaultproperties
{
    MoveDirection = -1
}