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.
208 lines
7.8 KiB
Plaintext
208 lines
7.8 KiB
Plaintext
/*:://////////////////////////////////////////////
|
|
//:: Spell Name Chain Lightning
|
|
//:: Spell FileName SMP_S_ChainLight
|
|
//:://////////////////////////////////////////////
|
|
//:: In Game Spell desctiption
|
|
//:://////////////////////////////////////////////
|
|
Evocation [Electricity]
|
|
Level: Air 6, Sor/Wiz 6
|
|
Components: V, S, F
|
|
Casting Time: 1 standard action
|
|
Range: Long (40M)
|
|
Targets: One primary target, plus one secondary target/level, within a 10M radius.
|
|
Enemies only, Creatures first.
|
|
Duration: Instantaneous
|
|
Saving Throw: Reflex half
|
|
Spell Resistance: Yes
|
|
|
|
This spell creates an electrical discharge that begins as a single stroke
|
|
commencing from your fingertips. Unlike lightning bolt, chain lightning
|
|
strikes one object or creature initially, then arcs to other targets.
|
|
|
|
The bolt deals 1d6 points of electricity damage per caster level (maximum
|
|
20d6) to the primary target. After it strikes, lightning can arc to a number
|
|
of secondary targets equal to your caster level (maximum 20). The secondary
|
|
bolts each strike one target and deal half as much damage as the primary one
|
|
did (rounded down).
|
|
|
|
Each target can attempt a Reflex saving throw for half damage. You choose
|
|
secondary targets as you like, but they must all be within 30 feet of the
|
|
primary target, and no target can be struck more than once. You can choose
|
|
to affect fewer secondary targets than the maximum.
|
|
|
|
Focus: A bit of fur; a piece of amber, glass, or a crystal rod; plus one
|
|
silver pin for each of your caster levels.
|
|
//:://////////////////////////////////////////////
|
|
//:: Spell Effects Applied / Notes
|
|
//:://////////////////////////////////////////////
|
|
Say, 20d6 to primary target, it'd be 10d6 to all secondary ones.
|
|
|
|
As spell, mainly copied a bit from bioware as its the same way Id to it.
|
|
|
|
Note that it has more "advanced" targeting: if we target a door, all doors
|
|
in the area are hit before other things, while the same is in the case of
|
|
placables and creatures.
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Jasperre
|
|
//::////////////////////////////////////////////*/
|
|
|
|
#include "SMP_INC_SPELLS"
|
|
|
|
// ZZaaapp! Returns the total targets affected of nTargetType's.
|
|
int ChainLightningTargets(location lTarget, float fDelay, int nDice, int nMetaMagic, object oCaster, int nSpellSaveDC, int nLimit, int nTargetTypes, object oFirstTarget);
|
|
|
|
void main()
|
|
{
|
|
// Spell Hook Check.
|
|
if(!SMP_SpellHookCheck()) return;
|
|
|
|
// Declare major variables
|
|
object oCaster = OBJECT_SELF;
|
|
object oFirstTarget = GetSpellTargetObject();
|
|
location lTarget = GetLocation(oFirstTarget);
|
|
int nCasterLevel = SMP_GetCasterLevel();
|
|
int nSpellSaveDC = SMP_GetSpellSaveDC();
|
|
int nDice = SMP_LimitInteger(nCasterLevel, 20);
|
|
int nMetaMagic = SMP_GetMetaMagicFeat();
|
|
int nTotalSecondaryAffected;
|
|
|
|
// Delay increases by 0.1/target, from 0.0
|
|
float fDelay = 0.0;
|
|
|
|
// Declare effects
|
|
int nDam;
|
|
effect eLightningBeam = EffectBeam(VFX_BEAM_LIGHTNING, oCaster, BODY_NODE_HAND);
|
|
effect eVis = EffectVisualEffect(VFX_IMP_LIGHTNING_S);
|
|
|
|
// Initial target damage
|
|
if(GetIsObjectValid(oFirstTarget) && GetIsReactionTypeHostile(oFirstTarget) &&
|
|
!GetFactionEqual(oFirstTarget))
|
|
{
|
|
// Apply lightning effect
|
|
SMP_ApplyDuration(oFirstTarget, eLightningBeam, 0.5);
|
|
|
|
// Signal spell cast at
|
|
SMP_SignalSpellCastAt(oFirstTarget, SMP_SPELL_CHAIN_LIGHTNING);
|
|
|
|
// Spell Resistance and Immunity check
|
|
if(!SMP_SpellResistanceCheck(oCaster, oFirstTarget, fDelay))
|
|
{
|
|
// New damage
|
|
nDam = SMP_MaximizeOrEmpower(6, nDice, nMetaMagic);
|
|
|
|
// Reflex save
|
|
nDam = SMP_GetAdjustedDamage(SAVING_THROW_REFLEX, nDam, oFirstTarget, nSpellSaveDC, SAVING_THROW_TYPE_ELECTRICITY, oCaster);
|
|
|
|
// Apply damage if any
|
|
if(nDam > 0)
|
|
{
|
|
DelayCommand(fDelay, SMP_ApplyDamageVFXToObject(oFirstTarget, eVis, nDam, DAMAGE_TYPE_ELECTRICAL));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Stop if it can't work (PvP, etc)
|
|
return;
|
|
}
|
|
// Now, we target all of that object type
|
|
int nTargetType = GetObjectType(oFirstTarget);
|
|
|
|
// Round dice by half
|
|
nDice = SMP_LimitInteger(nDice/2, 10);
|
|
|
|
// Do first one
|
|
int nRemaining = ChainLightningTargets(lTarget, fDelay, nDice, nMetaMagic, oCaster, nSpellSaveDC, nCasterLevel, nTargetType, oFirstTarget);
|
|
|
|
// If no targets left, stop
|
|
if(nRemaining <= 0) return;
|
|
|
|
// Next, do the other 2 at once!
|
|
if(nTargetType == OBJECT_TYPE_CREATURE)
|
|
{
|
|
nTargetType = OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE;
|
|
}
|
|
else if(nTargetType == OBJECT_TYPE_DOOR)
|
|
{
|
|
nTargetType = OBJECT_TYPE_CREATURE | OBJECT_TYPE_PLACEABLE;
|
|
}
|
|
else //if(nTargetType == OBJECT_TYPE_PLACEABLE)
|
|
{
|
|
nTargetType = OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR;
|
|
}
|
|
|
|
// New loop of remaining targets, up to nRemaining
|
|
ChainLightningTargets(lTarget, fDelay, nDice, nMetaMagic, oCaster, nSpellSaveDC, nRemaining, nTargetType, oFirstTarget);
|
|
}
|
|
|
|
int ChainLightningTargets(location lTarget, float fDelay, int nDice, int nMetaMagic, object oCaster, int nSpellSaveDC, int nLimit, int nTargetTypes, object oFirstTarget)
|
|
{
|
|
// Total affected can be up to nLimit.
|
|
int nTotalSecondaryAffected = FALSE;
|
|
|
|
// Declare effects
|
|
effect eVis = EffectVisualEffect(VFX_IMP_LIGHTNING_S);
|
|
// No sound
|
|
effect eLightningBeam = EffectBeam(VFX_BEAM_SILENT_LIGHTNING, oFirstTarget, BODY_NODE_CHEST);
|
|
|
|
// Note: eLightningBeam will be silent every other beam, to lessen the
|
|
// impact of it's sounds firing.
|
|
int bBeam = FALSE;// When TRUE.
|
|
|
|
// Damage
|
|
int nDam;
|
|
|
|
// Get objects with nTargetTypes as variable. 10M
|
|
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lTarget, TRUE, nTargetTypes);
|
|
while(GetIsObjectValid(oTarget) && nTotalSecondaryAffected <= nLimit)
|
|
{
|
|
// Faction check - Cannot hit original target neither
|
|
if(oTarget != oFirstTarget && GetIsReactionTypeHostile(oTarget) &&
|
|
!GetFactionEqual(oTarget))
|
|
{
|
|
// Visual effect of lightning for a short duration
|
|
DelayCommand(fDelay, SMP_ApplyDuration(oTarget, eLightningBeam, 0.5));
|
|
|
|
// Signal spell cast at event
|
|
SMP_SignalSpellCastAt(oTarget, SMP_SPELL_CHAIN_LIGHTNING);
|
|
|
|
// Spell Resistance and Immunity check
|
|
if(!SMP_SpellResistanceCheck(oCaster, oTarget, fDelay))
|
|
{
|
|
// New damage
|
|
nDam = SMP_MaximizeOrEmpower(6, nDice, nMetaMagic);
|
|
|
|
// Reflex save
|
|
nDam = SMP_GetAdjustedDamage(SAVING_THROW_REFLEX, nDam, oFirstTarget, nSpellSaveDC, SAVING_THROW_TYPE_ELECTRICITY, oCaster);
|
|
|
|
// Apply damage if any
|
|
if(nDam > 0)
|
|
{
|
|
DelayCommand(fDelay, SMP_ApplyDamageVFXToObject(oTarget, eVis, nDam, DAMAGE_TYPE_ELECTRICAL));
|
|
}
|
|
}
|
|
// Make the lightning beam effect start from oTarget now
|
|
// - Remember bBeam!
|
|
if(bBeam == TRUE)
|
|
{
|
|
// LOUD
|
|
eLightningBeam = EffectBeam(VFX_BEAM_LIGHTNING, oTarget, BODY_NODE_CHEST);
|
|
bBeam = FALSE;
|
|
}
|
|
else //if(bBeam == FALSE)
|
|
{
|
|
// No sound
|
|
eLightningBeam = EffectBeam(VFX_BEAM_SILENT_LIGHTNING, oTarget, BODY_NODE_CHEST);
|
|
bBeam = TRUE;
|
|
}
|
|
// Increase delay by 0.1.
|
|
fDelay += 0.1;
|
|
// Increase targets by 1
|
|
nTotalSecondaryAffected++;
|
|
}
|
|
// Next in 10M
|
|
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lTarget, TRUE, nTargetTypes);
|
|
}
|
|
return nTotalSecondaryAffected;
|
|
}
|