//::///////////////////////////////////////////////
//:: Name: x2_def_heartbeat
//:: Desc: Gelatinous Cube Heartbeat with Dispel & Acid Immunity Stack
//:: Author: Modified by Nwscript GPT (Original: Georg Zoeller)
//::///////////////////////////////////////////////

#include "x0_i0_spells"
#include "x2_i0_spells"

// Function declarations
void ApplyStackingAcidImmunity(object oTarget);
void ApplyDispelChallenge(object oTarget);
void DecrementAcidStack(object oTarget);

void main()
{
    // Run default creature AI
    ExecuteScript("nw_c2_default1", OBJECT_SELF);

    // One-time setup: make cube ghostly
    if (!GetLocalInt(OBJECT_SELF, "X2_L_GCUBE_SETUP"))
    {
        effect eGhost = SupernaturalEffect(EffectCutsceneGhost());
        ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, OBJECT_SELF);
        SetLocalInt(OBJECT_SELF, "X2_L_GCUBE_SETUP", TRUE);

        SendMessageToPC(GetFirstPC(), "Gelatinous Cube: Setup complete, ghost mode activated.");
    }

    // Scan for creatures in a 4m cube radius
    object oVictim = GetFirstObjectInShape(SHAPE_CUBE, 4.0f, GetLocation(OBJECT_SELF), TRUE, OBJECT_TYPE_CREATURE);

    while (GetIsObjectValid(oVictim))
    {
        if (spellsIsTarget(oVictim, SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF) && oVictim != OBJECT_SELF)
        {
            SendMessageToPC(GetFirstPC(), "Gelatinous Cube: Engulfing target - " + GetName(oVictim));
            EngulfAndDamage(oVictim, OBJECT_SELF);

            ApplyDispelChallenge(oVictim);
            ApplyStackingAcidImmunity(oVictim);
        }

        oVictim = GetNextObjectInShape(SHAPE_CUBE, 4.0f, GetLocation(OBJECT_SELF), TRUE, OBJECT_TYPE_CREATURE);
    }
}

// Applies a DC 40 Fortitude (Poison) check to target.
// On failure, applies Dispel Magic Best and visual effect.
void ApplyDispelChallenge(object oTarget)
{
    int bSuccess = !FortitudeSave(oTarget, 40, SAVING_THROW_TYPE_POISON, OBJECT_SELF);

    if (bSuccess)
    {
        // Use the creature's level for dispel
        effect eDispel = EffectDispelMagicBest(); 
        ApplyEffectToObject(DURATION_TYPE_INSTANT, eDispel, oTarget);

        // Dispel visual effect (ID 20)
        effect eVFX = EffectVisualEffect(VFX_IMP_DISPEL);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oTarget);

        SendMessageToPC(GetFirstPC(), "Gelatinous Cube: " + GetName(oTarget) + " failed Fort save ? Dispel Magic Best applied!");
    }
    else
    {
        SendMessageToPC(GetFirstPC(), "Gelatinous Cube: " + GetName(oTarget) + " resisted dispel (Fort save succeeded).");
    }
}

// Applies +5% Acid Immunity that stacks and expires in 2 minutes
void ApplyStackingAcidImmunity(object oTarget)
{
    int nStacks = GetLocalInt(oTarget, "GCUBE_ACID_IMMUNITY_STACKS");
    nStacks++;

    // Each stack = +5% acid immunity
    effect eImmunity = EffectDamageImmunityIncrease(DAMAGE_TYPE_ACID, 5);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eImmunity, oTarget, 120.0f); // 2 minutes

    SetLocalInt(oTarget, "GCUBE_ACID_IMMUNITY_STACKS", nStacks);

    SendMessageToPC(GetFirstPC(), "Gelatinous Cube: " + GetName(oTarget) + " gains +5% Acid Immunity. Total stacks: " + IntToString(nStacks));

    // Schedule decrement after 2 minutes
    DelayCommand(120.0f, DecrementAcidStack(oTarget));
}

// Removes one stack of acid immunity after expiration
void DecrementAcidStack(object oTarget)
{
    int nStacks = GetLocalInt(oTarget, "GCUBE_ACID_IMMUNITY_STACKS");

    if (nStacks > 0)
    {
        nStacks--;
        SetLocalInt(oTarget, "GCUBE_ACID_IMMUNITY_STACKS", nStacks);
        SendMessageToPC(GetFirstPC(), "Gelatinous Cube: " + GetName(oTarget) + "'s acid immunity stack expired. Remaining: " + IntToString(nStacks));
    }
}
