Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
228 lines
8.6 KiB
Plaintext
228 lines
8.6 KiB
Plaintext
//::///////////////////////////////////////////////
|
|
//:: 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);
|
|
}
|
|
|
|
}
|