//:://///////////////////////////////////////////// //:: Firebrand //:: x0_x0_Firebrand //:: Copyright (c) 2002 Bioware Corp. //::////////////////////////////////////////////// /* Evocation [Fire] Level: Sorcerer 5, Wizard 5, Components: V, S, M, Casting Time: 1 standard action Range: Medium (100 ft. + 10 ft./level) Area: One 5-ft.-radius burst/level (S) Duration: Instantaneous Saving Throw: Reflex half Spell Resistance: Yes The flask of alchemist's fire vanishes from you hand and the ground erupts beneath your foes, shooting multiple fountains of fiery liquid upward. Each burst deals 1d6 points of damage per caster level (maximum 10d6) to all creatures within the area. All subjects hit by the burst in the round the spell is cast or within the area in the following round take 1d6 points of fire damage per two caster levels (maximum 5d6). A character struck in the round the spell is cast can attempt to extinguish the flames on itself as a full-round action with a successful DC 15 Reflex save. Burst effects that overlap do not deal additional damage (a creature can be affected by only one burst). Material Component: A flask of alchemist's fire (worth 20 gp). // * Fires a flame arrow to every target in a // * colossal area // * Each target explodes into a small fireball for // * 1d6 damage / level (max = 15 levels) // * Only nLevel targets can be affected */ //::////////////////////////////////////////////// //:: Created By: Brent //:: Created On: July 29 2002 //::////////////////////////////////////////////// //:: Last Updated By: // // Altered to give targets reflex saves per pnp. // //:: altered by mr_bumpkin Dec 4, 2003 for prc stuff #include "prc_inc_spells" #include "prc_add_spell_dc" void DoFirebrand(int CasterLvl,int nD6Dice, int nCap, int nSpell, int nMIRV = VFX_IMP_MIRV, int nVIS = VFX_IMP_MAGBLUE, int nDAMAGETYPE = DAMAGE_TYPE_MAGICAL, int nONEHIT = FALSE); void main() { DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR"); SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_EVOCATION); /* Spellcast Hook Code Added 2003-06-20 by Georg If you want to make changes to all spells, check x2_inc_spellhook.nss to find out more */ if (!X2PreSpellCastCode()) { // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell return; } // End of Spell Cast Hook int CasterLvl = PRCGetCasterLevel(OBJECT_SELF); int nDamage = CasterLvl; if (nDamage > 15) nDamage = 15; // Changed to local function to add reflex save. DoFirebrand(CasterLvl,nDamage, 15, SPELL_FIREBRAND, VFX_IMP_MIRV_FLAME, VFX_IMP_FLAME_M, ChangedElementalDamage(OBJECT_SELF, DAMAGE_TYPE_FIRE), TRUE); DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR"); // Erasing the variable used to store the spell's spell school } //::////////////////////////////////////////////// //:: Created By: Brent //:: Created On: July 31, 2002 //::////////////////////////////////////////////// //:: Modified March 14 2003: Removed the option to hurt chests/doors //:: was potentially causing bugs when no creature targets available. //::////////////////////////////////////////////// //:: Created By: Brent //:: Created On: July 31, 2002 //::////////////////////////////////////////////// //:: Modified March 14 2003: Removed the option to hurt chests/doors //:: was potentially causing bugs when no creature targets available. void DoFirebrand(int CasterLvl,int nD6Dice, int nCap, int nSpell, int nMIRV = VFX_IMP_MIRV, int nVIS = VFX_IMP_MAGBLUE, int nDAMAGETYPE = DAMAGE_TYPE_MAGICAL, int nONEHIT = FALSE) { object oTarget = OBJECT_INVALID; int nDamage = 0; int nMetaMagic = PRCGetMetaMagicFeat(); int nCnt = 1; effect eMissile = EffectVisualEffect(nMIRV); effect eVis = EffectVisualEffect(nVIS); float fDist = 0.0; float fDelay = 0.0; float fDelay2, fTime; location lTarget = PRCGetSpellTargetLocation(); // missile spread centered around caster int nMissiles = CasterLvl; if (nMissiles > nCap) { nMissiles = nCap; } /* New Algorithm 1. Count # of targets 2. Determine number of missiles 3. First target gets a missile and all Excess missiles 4. Rest of targets (max nMissiles) get one missile */ int nEnemies = 0; int nCasterlvl = CasterLvl +SPGetPenetr(); oTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE); //Cycle through the targets within the spell shape until an invalid object is captured. while (GetIsObjectValid(oTarget) ) { // * caster cannot be harmed by this spell if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, OBJECT_SELF) && (oTarget != OBJECT_SELF)) { // GZ: You can only fire missiles on visible targets if (GetObjectSeen(oTarget,OBJECT_SELF)) { nEnemies++; } } oTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE); } if (nEnemies == 0) return; // * Exit if no enemies to hit int nExtraMissiles = nMissiles / nEnemies; // April 2003 // * if more enemies than missiles, need to make sure that at least // * one missile will hit each of the enemies if (nExtraMissiles <= 0) { nExtraMissiles = 1; } // by default the Remainder will be 0 (if more than enough enemies for all the missiles) int nRemainder = 0; if (nExtraMissiles >0) nRemainder = nMissiles % nEnemies; if (nEnemies > nMissiles) nEnemies = nMissiles; oTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE); //Cycle through the targets within the spell shape until an invalid object is captured. while (GetIsObjectValid(oTarget) && nCnt <= nEnemies) { // * caster cannot be harmed by this spell if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, OBJECT_SELF) && (oTarget != OBJECT_SELF) && (GetObjectSeen(oTarget,OBJECT_SELF))) { //Fire cast spell at event for the specified target SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpell)); // * recalculate appropriate distances fDist = GetDistanceBetween(OBJECT_SELF, oTarget); fDelay = fDist/(3.0 * log(fDist) + 2.0); // Firebrand. // It means that once the target has taken damage this round from the // spell it won't take subsequent damage if (nONEHIT == TRUE) { nExtraMissiles = 1; nRemainder = 0; } int i = 0; //-------------------------------------------------------------- // GZ: Moved SR check out of loop to have 1 check per target // not one check per missile, which would rip spell mantels // apart //-------------------------------------------------------------- if (!PRCDoResistSpell(OBJECT_SELF, oTarget,nCasterlvl, fDelay)) { int nDC = PRCGetSaveDC(oTarget,OBJECT_SELF); for (i=1; i <= nExtraMissiles + nRemainder; i++) { //Roll damage int nDam = d6(nD6Dice); //Enter Metamagic conditions if ((nMetaMagic & METAMAGIC_MAXIMIZE)) { nDam = nD6Dice*6;//Damage is at max } if ((nMetaMagic & METAMAGIC_EMPOWER)) { nDam = nDam + nDam/2; //Damage/Healing is +50% } nDam += SpellDamagePerDice(OBJECT_SELF, nD6Dice); if(i == 1) //nDam += ApplySpellBetrayalStrikeDamage(oTarget, OBJECT_SELF); fTime = fDelay; fDelay2 += 0.1; fTime += fDelay2; // Adjust damage for reflex save / evasion / imp evasion nDam = PRCGetReflexAdjustedDamage(nDam, oTarget, nDC, SAVING_THROW_TYPE_FIRE); // Always apply missle but only apply impact/damage if we really have damage. DelayCommand(fDelay2, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget)); if (nDam > 0) { //Set damage effect effect eDam = PRCEffectDamage(oTarget, nDam, nDAMAGETYPE); //Apply the MIRV and damage effect DelayCommand(fTime, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget,0.0f,TRUE,-1,CasterLvl)); DelayCommand(fTime, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget)); } } } // for else { // * apply a dummy visual effect SPApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget); } nCnt++;// * increment count of missiles fired nRemainder = 0; } oTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE); } }