////////////////////////////////////////////////////////////////////////////////////
//
// DoBurst() - Do a damaging burst at the spell's target location.
//        nDieSize - size of die to roll.
//        nBonusDam - bonus damage per die.
//        nDice - number of dice to roll
//        nBurstEffect - VFX_xxx or AOE_xxx of burst vfx.
//        nVictimEffect - VFX_xxx of target impact.
//        nDamageType - DAMAGE_TYPE_xxx of the type of damage dealt
//        nSaveType - SAVING_THROW_xxx of type of save to use
//        bCasterImmune - Indicates whether the caster is immune to the spell
//        nSchool - SPELL_SCHOOL_xxx of the spell's school
//        nSpellID - ID # of the spell, if -1 PRCGetSpellId() is used
//        fAOEDuration - if > 0, then nBurstEffect should be an AOE_xxx vfx, it
//             will be played at the target location for this duration.  If this is
//             0 then nBurstEffect should be a VFX_xxx vfx.
//
////////////////////////////////////////////////////////////////////////////////////

#include "prc_inc_spells"
#include "prc_add_spell_dc"

void DoBurst (int nCasterLvl, int nDieSize, int nBonusDam, int nDice, int nBurstEffect,
     int nVictimEffect, float fRadius, int nDamageType, int nBonusDamageType, int nSaveType,
     int bCasterImmune = FALSE,
     int nSchool = SPELL_SCHOOL_EVOCATION, int nSpellID = -1,
     float fAOEDuration = 0.0f)
{
     PRCSetSchool(nSchool);

     // Get the spell ID if it was not given.
     if (-1 == nSpellID) nSpellID = PRCGetSpellId();

     // Get the spell target location as opposed to the spell target.
     location lTarget = PRCGetSpellTargetLocation();

        int nPenetr = nCasterLvl + SPGetPenetr();
     // Get the effective caster level and hand it to the SR engine.


     // Adjust the damage type of necessary, if the damage & bonus damage types are the
     // same we need to copy the adjusted damage type to the bonus damage type.
     int nSameDamageType = nDamageType == nBonusDamageType;
     nDamageType = PRCGetElementalDamageType(nDamageType, OBJECT_SELF);
     if (nSameDamageType) nBonusDamageType = nDamageType;

     // Apply the specified vfx to the location.  If we were given an aoe vfx then
     // fAOEDuration will be > 0.
     if (fAOEDuration > 0.0)
          ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY,
               EffectAreaOfEffect(nBurstEffect, "****", "****", "****"), lTarget, fAOEDuration);
     else
          ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(nBurstEffect), lTarget);

     effect eVis = EffectVisualEffect(nVictimEffect);
     effect eDamage, eBonusDamage;
     float fDelay;

     // Declare the spell shape, size and the location.  Capture the first target object in the shape.
     // Cycle through the targets within the spell shape until an invalid object is captured.
     object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, fRadius, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
     while (GetIsObjectValid(oTarget))
     {
          // Filter out the caster if he is supposed to be immune to the burst.
          if (!(bCasterImmune && OBJECT_SELF == oTarget))
          {
               if(spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF))
               {
                    //Fire cast spell at event for the specified target
                    PRCSignalSpellEvent(oTarget, TRUE, nSpellID);

                    fDelay = PRCGetSpellEffectDelay(lTarget, oTarget);
                    if (!PRCDoResistSpell(OBJECT_SELF, oTarget,nPenetr, fDelay))
                    {
                         int nSaveDC = PRCGetSaveDC(oTarget, OBJECT_SELF);

                         int nDam = 0;
                         int nDam2 = 0;
                         if (nSameDamageType)
                         {
                              // Damage damage type is the simple case, just get the total damage
                              // of the spell's type, apply metamagic and roll the save.

                              // Roll damage for each target
                              nDam = PRCGetMetaMagicDamage(nDamageType, nDice, nDieSize, nBonusDam);
                			// Acid Sheath adds +1 damage per die to acid descriptor spells
                			if (GetHasDescriptor(nSpellID, DESCRIPTOR_ACID) && GetHasSpellEffect(SPELL_MESTILS_ACID_SHEATH, OBJECT_SELF))
                				nDam += nDice;  
                			nDam += SpellDamagePerDice(OBJECT_SELF, nDice);	

                              // Adjust damage for reflex save / evasion / imp evasion
                              nDam = PRCGetReflexAdjustedDamage(nDam, oTarget, nSaveDC, nSaveType);
                         }
                         else
                         {
                              // Damage of different types is a bit more complicated, we need to
                              // calculate the bonus damage ourselves, figure out if the save was
                              // 1/2 or no damage, and apply appropriately to the secondary damage
                              // type.

                              // Calculate base and bonus damage.
                              nDam = PRCGetMetaMagicDamage(nDamageType, nDice, nDieSize, 0);
                			// Acid Sheath adds +1 damage per die to acid descriptor spells
                			if (GetHasDescriptor(nSpellID, DESCRIPTOR_ACID) && GetHasSpellEffect(SPELL_MESTILS_ACID_SHEATH, OBJECT_SELF))
                				nDam += nDice;  
                			nDam += SpellDamagePerDice(OBJECT_SELF, nDice);	
                              nDam2 = nDice * nBonusDam;

                              // Adjust damage for reflex save / evasion / imp evasion.  We need to
                              // deal with damage being constant, damage being 0, and damage being
                              // some percentage of the total (should be 1/2).
                              int nAdjustedDam = PRCGetReflexAdjustedDamage(nDam, oTarget, nSaveDC, nSaveType);
                              if (0 == nAdjustedDam)
                              {
                                   // Evasion zero'ed out the damage, clear both damage values.
                                   nDam = 0;
                                   nDam2 = 0;
                              }
                              else if (nAdjustedDam < nDam)
                              {
                                   // Assume 1/2 damage, and half the bonus damage.
                                   nDam = nAdjustedDam;
                                   nDam2 /= 2;
                              }
                         }

                         //Set the damage effect
                         if (nDam > 0)
                         {
                              eDamage = PRCEffectDamage(oTarget, nDam, nDamageType);

                              // Apply effects to the currently selected target.
                              DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget));
                              PRCBonusDamage(oTarget);

                              // This visual effect is applied to the target object not the location as above.
                              DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
                         }

                         // Apply bonus damage if it is a different type.
                         if (nDam2 > 0)
                         {
                              DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT,
                                   PRCEffectDamage(oTarget, nDam2, nBonusDamageType), oTarget));
                         }
                    }
               }
          }

          oTarget = MyNextObjectInShape(SHAPE_SPHERE, fRadius, lTarget, FALSE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
     }

     // Let the SR engine know that we are done and clear out school local var.

     PRCSetSchool();
}

// Test main
//void main(){}