#include "cas_inc_rndloc"

void main()
{
    // ? Ensure we even got here
    SendMessageToPC(GetFirstPC(), "DEBUG: cas_firecannons script fired!");

    int nMsg = GetUserDefinedEventNumber();
    SendMessageToPC(GetFirstPC(), "DEBUG: UserDefined Event Number = " + IntToString(nMsg));
    if (nMsg != 1001) return; // Only respond to fire event

    object oSelf = OBJECT_SELF;
    object oPC = GetFirstPC(); // All debug messages go to the first PC
    string sCannonTag = GetTag(oSelf);

    SendMessageToPC(oPC, "DEBUG: cas_firecannons activated on object: " + sCannonTag);
    ActionSpeakString("Firing script activated.");

    // Validate tag format
    if (GetStringLength(sCannonTag) < 14)
    {
        SendMessageToPC(oPC, "ERROR: Invalid cannon tag format. Expected CAS_CANNONVFX#.");
        ActionSpeakString("ERROR: Invalid tag format.");
        return;
    }

    // Extract the numeric index from cannon tag
    string sIndex = GetSubString(sCannonTag, 13);
    if (sIndex == "")
    {
        SendMessageToPC(oPC, "ERROR: Could not extract index from cannon tag: " + sCannonTag);
        ActionSpeakString("ERROR: Tag missing index.");
        return;
    }

    // Build target waypoint tag
    string sTargetTag = "CAS_CANNONTARGET" + sIndex;
    SendMessageToPC(oPC, "DEBUG: Looking for target waypoint: " + sTargetTag);

    object oTarget = GetWaypointByTag(sTargetTag);
    if (!GetIsObjectValid(oTarget))
    {
        SendMessageToPC(oPC, "ERROR: Target waypoint not found: " + sTargetTag);
        ActionSpeakString("ERROR: No target found!");
        return;
    }

    // Build randomized target location
    location lSelf = GetLocation(oSelf);
    location lTarget = GetLocation(oTarget);
    vector vTarget = GetPositionFromLocation(lTarget);

    float fYOffset = RndFloat(20) * RndSign();
    float fZOffset = RndFloat(2);
    vTarget.y += fYOffset;
    vTarget.z += fZOffset;

    lTarget = Location(GetArea(oTarget), vTarget, GetFacing(oTarget));
    float fDistance = GetDistanceBetweenLocations(lTarget, lSelf);
    float fDelay = fDistance / 15.0;

    SendMessageToPC(oPC, "DEBUG: Target location set. Distance = " + FloatToString(fDistance));
    SetFacingPoint(vTarget);

    // Fire projectile
    ActionCastFakeSpellAtLocation(SPELL_FIREBALL, lTarget, PROJECTILE_PATH_TYPE_BALLISTIC);
    SendMessageToPC(oPC, "DEBUG: Projectile launched to " + sTargetTag);
    ActionSpeakString("Firing cannon!");

    // Main explosion effect
    DelayCommand(fDelay, ApplyEffectAtLocation(
        DURATION_TYPE_INSTANT,
        EffectVisualEffect(VFX_FNF_FIREBALL),
        lTarget));

    // Debris effect
    DelayCommand(fDelay + 0.1, ApplyEffectToObject(
        DURATION_TYPE_TEMPORARY,
        EffectVisualEffect(VFX_DUR_PROT_GREATER_STONESKIN),
        DestroyObjectReturn(CreateObject(
            OBJECT_TYPE_PLACEABLE,
            "plc_stones",
            lTarget, TRUE),
        IntToFloat(d6(4)))
    ));

    // Splash fire VFX
    int i, iCount = d3(3);
    for (i = 1; i <= iCount; i++)
    {
        location lSplash = RndLoc(lTarget, 6, 2, BASE_SHAPE_CIRCLE);
        DelayCommand(fDelay + 0.2, ApplyEffectToObject(
            DURATION_TYPE_TEMPORARY,
            EffectVisualEffect(VFX_FNF_FIREBALL),
            DestroyObjectReturn(CreateObject(
                OBJECT_TYPE_PLACEABLE,
                "plc_flamesmall",
                lSplash, TRUE),
            IntToFloat(d6(3)))
        ));
    }

    // Boom sound
    PlaySound("as_pl_cannon");
}
