//:://///////////////////////////////////////////// //:: Firebrand //:: x0_x0_Firebrand //:: Copyright (c) 2002 Bioware Corp. //::////////////////////////////////////////////// /* // * 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), FALSE); 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); } }