Added Elven blades to Weaponmaster prereqs Fixed Beckon the Frozen Fixed bug with Fire Brand Fixed duration bug with Improved Invisibility Added Soul Eater to Shifter prereqs Fixed ability based class prereqs in prc_prereq.nss Update Eye of Gruumsh for epic levels Update Ur-Priest for epic levels Update Forsaker for epic levels Update Anima Mage for epic levels Update Serene Guardian for epic levels Bladesinger abilities can use chain shirts Fixed Elemental Abjuration Fixed bug with prc cache creature. Forsakers can use non-magic items (heal kits, alchemy, etc) Updated ruleset.2da for NWNEE update Updated AotS bonus feats -Notes Added 3.5e Template index Added 3.5e update booklet Removed release archive
258 lines
9.6 KiB
Plaintext
258 lines
9.6 KiB
Plaintext
//::///////////////////////////////////////////////
|
|
//:: 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);
|
|
}
|
|
|
|
}
|