#include "xstp_inc_jump"
//#include "jump_include"

int TargetHasRequiredRing(object oTarget)
{
    object oLeftRing = GetItemInSlot(INVENTORY_SLOT_LEFTRING, oTarget);
    object oRightRing = GetItemInSlot(INVENTORY_SLOT_RIGHTRING, oTarget);

    if (GetTag(oLeftRing) == "I_CAS_SLUTSNATCHER" || GetTag(oRightRing) == "I_CAS_SLUTSNATCHER")
    {
        return TRUE;
    }
    return FALSE;
}


void SpeakStringDelayed(object oTarget, string sString)
{
    ActionSpeakString(sString);
}
vector Lerp(vector vStart, vector vEnd, float fFraction)
{
    return Vector(
        vStart.x + fFraction * (vEnd.x - vStart.x),
        vStart.y + fFraction * (vEnd.y - vStart.y),
        vStart.z + fFraction * (vEnd.z - vStart.z)
    );
}

location GetIntermediateLocation(object oTarget, object oUser, float fFraction)
{
    vector vTarget = GetPosition(oTarget);
    vector vUser = GetPosition(oUser);
    vector vIntermediate = Lerp(vTarget, vUser, fFraction);
    return Location(GetArea(oTarget), vIntermediate, GetFacing(oTarget));
}

void JumpTarget(object oTarget, object oUser, float fFraction)
{
    location lIntermediate = GetIntermediateLocation(oTarget, oUser, fFraction);
    AssignCommand(oTarget, ActionJumpToLocation(lIntermediate));
}

// Custom function to move the target towards the activator
void PullTargetTowardsActivator(object oTarget, object oActivator)
{
    // Get the current locations
    vector vTargetPos = GetPosition(oTarget);
    vector vActivatorPos = GetPosition(oActivator);

    // Calculate the new position closer to the activator
    vector vNewPos = Lerp(vTargetPos, vActivatorPos, 0.5); // Adjust the fraction as needed

    // Move the target
    location lNewTarget = Location(GetArea(oTarget), vNewPos, GetFacing(oTarget));
    AssignCommand(oTarget, ActionJumpToLocation(lNewTarget));
}



// Function to cycle the paralysis effect and jump
void CycleParalysisAndJump(object oTarget, object oUser, int nCycles, float fFraction)

{
    if (nCycles > 0)
    {
        // Apply the paralysis effect
        effect eImmobilize = EffectCutSceneParalysis();
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eImmobilize, oTarget, 6.0);

        // Schedule to remove the paralysis effect and then jump
        DelayCommand(6.0, RemoveEffect(oTarget, eImmobilize));
        DelayCommand(6.0, JumpTarget(oTarget, oUser, fFraction));

        // Schedule the next cycle
        DelayCommand(7.0, CycleParalysisAndJump(oTarget, oUser, nCycles - 1, fFraction));
    }
}

int CheckValidErf(string sPrefix)
{
    if (sPrefix == "cac" ||
    sPrefix == "hvh" || 
    sPrefix == "mds" || 
    sPrefix == "poe" ||
    sPrefix == "scd" ||
    sPrefix == "ggd" ||
    sPrefix == "bhm")
    return FALSE;
    
    else return TRUE;
}

// Custom function to jump the target towards the player


void main()
{
  
    object oItem = GetEventParamObject(0);
    object oTarget = GetEventParamObject(1);
    object oUser = GetEventParamObject(2);
        // Retrieve the area object where the user is located
    object oArea = GetArea(oUser);

    // Check if XS_NO_JUMP_TOOL is set in this area
    int nNoJumpTool = GetLocalInt(oArea, "XS_NO_JUMP_TOOL");
    if (nNoJumpTool == 1)
    {
        SendMessageToPC(oUser, "The jump tool cannot be used in this area.");
        return;
    }
        
    string sPrefix = GetResRefErfPrefix(GetResRef(oArea));
    if (!CheckValidErf(sPrefix))
    {
        SendMessageToPC(oUser, "Jumpers can't be used in epic dungeons!");
        return;
    }

    // Check if the script should verify the target's equipment.
    if (!TargetHasRequiredRing(oTarget))
    {
        SendMessageToPC(oUser, "Target does not have the required item equipped in either ring slot.");
        return;
    }
    // Check distance
    if(GetDistanceBetween(oUser, oTarget) > 20.0)
    {
        SendMessageToPC(oUser, "The target is not close enough.");
        return;
    }

    // Apply effects
    effect eBeam = EffectBeam(VFX_BEAM_CHAIN, oUser, BODY_NODE_CHEST);
    effect eEntangleVFX = EffectVisualEffect(VFX_DUR_ENTANGLE);
    effect eImmobilize = EffectParalyze();

    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBeam, oTarget, 24.0); // 5 seconds
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEntangleVFX, oTarget, 24.0); // 10 minutes
    DelayCommand(11.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eImmobilize, oTarget, 6.0)); // 10 minutes

    // Command the target to speak
    AssignCommand(oTarget, ActionSpeakString("The target is wrapped up in magical rope, paralyzing them!"));

    // Get the initial locations
    location lUserLocation = GetLocation(oUser);
    location lTargetLocation = GetLocation(oTarget);

    // Start moving the target back and forth
      PullTargetTowardsActivator(oTarget, oUser);
      
      DelayCommand(6.0, PullTargetTowardsActivator(oTarget, oUser));
      
      DelayCommand(12.0, PullTargetTowardsActivator(oTarget, oUser));
      
      DelayCommand(18.0, PullTargetTowardsActivator(oTarget, oUser));
      
      DelayCommand(24.0, PullTargetTowardsActivator(oTarget, oUser));
}
