forked from Jaysyn/PRC8
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;
|
|
}
|