#include "cas_inc_rndloc"

//::///////////////////////////////////////////////
//:: cas_firecannons
//:: Fires a projectile from the cannon to the nearest
//:: waypoint tagged CAS_CANNONTARGET, with random inaccuracy,
//:: explosion VFX, debris, and splash fire effects.
//:: Requires: cas_inc_rndloc
//:://////////////////////////////////////////////

#include "cas_inc_rndloc"

void CreateCannonDebris(location lLoc)
{
    object oDebris = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_stones", lLoc, TRUE);
    ApplyEffectToObject(
        DURATION_TYPE_TEMPORARY,
        EffectVisualEffect(VFX_DUR_PROT_GREATER_STONESKIN),
        oDebris);
    DestroyObject(oDebris, IntToFloat(d6(4)));
}

void CreateCannonSplash(location lLoc)
{
    object oSplash = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_flamesmall", lLoc, TRUE);
    ApplyEffectToObject(
        DURATION_TYPE_TEMPORARY,
        EffectVisualEffect(VFX_FNF_FIREBALL),
        oSplash);
    DestroyObject(oSplash, IntToFloat(d6(3)));
}

//::///////////////////////////////////////////////
//:: cas_firecannons
//:: Fires a cannonball to the nearest waypoint with tag
//:: CAS_CANNONTARGET, adds explosion, debris, and splash
//:: Uses: cas_inc_rndloc (RndFloat, RndSign, RndLoc)
//:://////////////////////////////////////////////

#include "cas_inc_rndloc"

void main()
{
    object oSelf = OBJECT_SELF;

    // Find nearest cannon target waypoint
    object oTarget = GetNearestObjectByTag("CAS_CANNONTARGET", oSelf);
    if (!GetIsObjectValid(oTarget)) return;

    // Get source and target locations
    location lSelf = GetLocation(oSelf);
    location lTarget = GetLocation(oTarget);
    vector vTarget = GetPositionFromLocation(lTarget);

    // Apply randomized inaccuracy to target
    float fYOffset = RndFloat(20) * RndSign(); // ±20 Y offset
    float fZOffset = RndFloat(2);              // +0 to +2 Z offset
    vTarget.y += fYOffset;
    vTarget.z += fZOffset;

    lTarget = Location(GetArea(oTarget), vTarget, GetFacing(oTarget));

    // Calculate delay for projectile travel
    float fDistance = GetDistanceBetweenLocations(lTarget, lSelf);
    float fDelay = fDistance / 15.0;

    // Face the cannon toward the target
    SetFacingPoint(vTarget);

    // Launch projectile using a fake spell
    ActionCastFakeSpellAtLocation(SPELL_FIREBALL, lTarget, PROJECTILE_PATH_TYPE_BALLISTIC);

    // Main explosion effect
    DelayCommand(fDelay, ApplyEffectAtLocation(
        DURATION_TYPE_INSTANT,
        EffectVisualEffect(VFX_FNF_FIREBALL),
        lTarget));

    // Debris effect (e.g., broken stones)
    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)))
    ));

    // Random splash fire effects around the impact
    int i;
    int iCount = d3(3); // 1 to 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)))
        ));
    }

    // Optional cannon sound
    PlaySound("as_pl_cannon");
}

