//:://////////////////////////////////////////////
//:: Telflammar Shadowlord: Shadow Jump
//:: tfshad_jump
//:://////////////////////////////////////////////
/** @file
    Shadow Jump (Su):
    A Telflammar Shadowlord can travel between
    shadows as if by means of a Dimension Door spell.
    The limitation is that the magical transport
    must begin and end in an area with at least some
    shadow or darkness. The shadowlord can jump up
    to a total of 20 feet per class level per day
    in this way. This amount can be split up among
    many jumps, but each jump, no matter how small,
    counts as a 10-foot increment.


    The shadow requirement is waived, since it's not
    possible to detect without builder intervention.
    This script also contains an implementation of
    Shadow Pounce.
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////


#include "prc_inc_combat"
#include "prc_inc_sneak"
#include "prc_inc_teleport"

void main()
{
    // Declare major variables
    object oCaster   = OBJECT_SELF;
    location lTarget = PRCGetSpellTargetLocation();
    location lCaster = GetLocation(oCaster);
    effect eVis      = EffectVisualEffect(VFX_DUR_PROT_SHADOW_ARMOR);
    float fDistance  = GetDistanceBetweenLocations(lCaster,lTarget);
    int iLevel       = GetLevelByClass(CLASS_TYPE_SHADOWLORD, oCaster);

    // Get the feat ID
    int iFeat = FEAT_SHADOWJUMP - 1 + GetLevelByClass(CLASS_TYPE_SHADOWLORD, oCaster);

    // Check if we're targeting some creature instead of just a spot on the floor
    object oTarget = PRCGetSpellTargetObject();
    if(GetIsObjectValid(oTarget))
        lTarget = GetLocation(oTarget);

    // Check if teleportation is possible
    if(!GetCanTeleport(oCaster, lTarget, TRUE, TRUE))
    {
        IncrementRemainingFeatUses(oCaster, iFeat);
        return;
    }

    vector vOrigin = GetPositionFromLocation(GetLocation(oCaster));
    vector vDest   = GetPositionFromLocation(lTarget);

    // Calculate the amount of jump range remaining
    int iLeftUse = 1; // Init to 1 to account for the use taken by the engine when activating the feat
    while(GetHasFeat(iFeat, oCaster))
    {
        DecrementRemainingFeatUses(oCaster, iFeat);
        iLeftUse++;
    }

    // Return the feat uses for now.
    /// @TODO This is inefficient, make it so that the uses are only returned after calculating how many will be left after the jump.
    int nCount = iLeftUse;
    while(nCount)
    {
        IncrementRemainingFeatUses(oCaster, iFeat);
        nCount--;
    }

    // Calculate the maximum distance jumpable
    float fMaxDis = FeetToMeters(iLeftUse * 20.0);

    // If the target is too far, abort
    if(fDistance > fMaxDis)
    {//                              "Your target is too far!"
        FloatingTextStrRefOnCreature(16825300, oCaster);
        return;
    }

    // Reduce feat uses based on the distance teleported
    nCount = FloatToInt(fDistance / FeetToMeters(10.0));
    // The minimum of 10 feet
    if(!nCount) nCount = 1;
    // Take away the required number of uses.
    while(nCount)
    {
        DecrementRemainingFeatUses(oCaster, iFeat);
        nCount--;
    }

    // Calculate the locations to apply the VFX at
    vOrigin = Vector(vOrigin.x + 2.0, vOrigin.y - 0.2, vOrigin.z);
    vDest   = Vector(vDest.x + 2.0, vDest.y - 0.2, vDest.z);

    // Do VFX
    ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eVis, Location(GetArea(oCaster), vOrigin, 0.0), 0.8);
    DelayCommand(0.1, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eVis, Location(GetArea(oCaster), vDest, 0.0), 0.7));

    // Schedule the jump itself
    DelayCommand(0.8, AssignCommand(oCaster, JumpToLocation(lTarget)));

    // Class level 4 gives the Shadow Pounce ability, which gives one a full attack at the end of a jump
    if(iLevel >= 4)
    {
        DelayCommand(1.0f, PerformAttackRound(oTarget, oCaster, EffectVisualEffect(-1), 0.0, 0, 0, 0, FALSE, "", "", FALSE, FALSE, TRUE));
    }
}