PRC8/nwn/nwnprc/trunk/smp/phs_s_earthquake.nss
Jaysyn904 6ec137a24e Updated AMS marker feats
Updated AMS marker feats.  Removed arcane & divine marker feats.  Updated Dread Necromancer for epic progression. Updated weapon baseitem models.  Updated new weapons for crafting & npc equip.
 Updated prefix.  Updated release archive.
2024-02-11 14:01:05 -05:00

241 lines
9.0 KiB
Plaintext

/*:://////////////////////////////////////////////
//:: Spell Name Earthquake
//:: Spell FileName PHS_S_Earthquake
//:://////////////////////////////////////////////
//:: In Game Spell desctiption
//:://////////////////////////////////////////////
Evocation [Earth]
Level: Clr 8, Destruction 8, Drd 8, Earth 7
Components: V, S, DF
Casting Time: 1 standard action
Range: Long (40M)
Area: 26.67-M.-radius spread (S)
Duration: 1 round
Saving Throw: See text
Spell Resistance: No
When you cast earthquake, an intense but highly localized tremor rips the
ground. The shock knocks creatures down, collapses structures, opens cracks
in the ground, and more. The specific effect of an earthquake spell depends
on the nature of the terrain where it is cast.
Natural Interior (cave) Man-Made interior (building): The spell collapses
the roof or bring down supports and stonework, dealing 8d6 points of
bludgeoning damage to any creature caught under the cave-in (Reflex DC 15
half, and no pinning) and pinning that creature beneath the rubble (see
below).
Open Ground: Each creature standing in the area must make a DC 15 Reflex
save or fall down for the round. Fissures open in the earth, and every
creature on the ground has a 25% chance to fall into one (Reflex DC 20 to
avoid a fissure). At the end of the spell, all fissures grind shut, killing
any creatures still trapped within.
Pinned beneath Rubble: Any creature pinned beneath rubble takes 1d6 points
of bludgeoning damage per minute while pinned. A pinned creature is
effectivly knocked down, and requires a DC 25 Strength Check to escape,
each round.
//:://////////////////////////////////////////////
//:: Spell Effects Applied / Notes
//:://////////////////////////////////////////////
A massive AOE, and requires several saves.
The effect depends on the status of the area - and if it can be collapsed
at all! (no collapse = no damage, pinning or fissures, but the 1 round
of being stopped still applies)
The pinning is done via. delay command.
//:://////////////////////////////////////////////
//:: Created By: Jasperre
//::////////////////////////////////////////////*/
#include "PHS_INC_SPELLS"
// Call this to start pin checks
void WrapperDelayRemoval(float fDelay, object oTarget);
// This is called from WrapperDelayRemoval
// Does damage when nLastRound + 1 (the current round) is 10.
void PinCheck(int nSpellId, int nTimesCast, int nLastRound, object oTarget);
void main()
{
// Spell Hook Check.
if(!PHS_SpellHookCheck(PHS_SPELL_EARTHQUAKE)) return;
// Declare major variables
object oCaster = OBJECT_SELF;
object oTarget;
location lTarget = GetSpellTargetLocation();
object oArea = GetArea(oCaster);
int nSpellSaveDC = PHS_GetSpellSaveDC();
int nMetaMagic = PHS_GetMetaMagicFeat();
int bIndoors = GetIsAreaInterior(oArea);
int bNatural = GetIsAreaNatural(oArea);
//int bAboveGround = GetIsAreaAboveGround(oArea);
int nEffect;
int nDam;
float fDelay;
// 1 Round of duration
float f1Round = 6.0;
// Check if area can be earthquaked
if(GetLocalInt(oArea, "PHS_EARTHQUAKE_IMMUNE")) return;
// Declare Effects
effect eVis;// = EffectVisualEffect(VFX_IMP_ROCKEXPLODE);
effect eImpact;// = EffectVisualEffect(nVFX);
effect eDeath = EffectDeath();
effect ePin = EffectKnockdown();
effect eDur = EffectVisualEffect(VFX_DUR_STONEHOLD);
// Link effects
effect eLink = EffectLinkEffects(ePin, eDur);
// Get the right VFX based on indoors/outdoors
if(bIndoors == TRUE)
{
// Declare indoor visual effects
eVis = EffectVisualEffect(VFX_IMP_ROCKEXPLODE);
if(bNatural == TRUE)
{
eImpact = EffectVisualEffect(PHS_VFX_FNF_EARTHQUAKE_INSIDE_NATURAL);
}
else
{
eImpact = EffectVisualEffect(PHS_VFX_FNF_EARTHQUAKE_INSIDE_NOT_NATURAL);
}
}
else
{
// Declare outdoor visual effects
eVis = EffectVisualEffect(PHS_VFX_IMP_EARTHQUAKE_FISSURE);
eImpact = EffectVisualEffect(PHS_VFX_FNF_EARTHQUAKE_OUTSIDE);
}
// Apply AOE visual
PHS_ApplyLocationVFX(lTarget, eImpact);
// Get all targets in a sphere, 26.67M radius, creature objects.
// - No LOS needed. This affects anyone in the AOE.
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 26.67, lTarget, FALSE, OBJECT_TYPE_CREATURE);
// Loop targets
while(GetIsObjectValid(oTarget))
{
// PvP Check
if(!GetIsReactionTypeFriendly(oTarget, oCaster) &&
// Make sure they are not immune to spells
!PHS_TotalSpellImmunity(oTarget))
{
// Fire cast spell at event for the specified target
PHS_SignalSpellCastAt(oTarget, PHS_SPELL_EARTHQUAKE);
// Get a random small delay
fDelay = PHS_GetRandomDelay(0.2, 1.6)/10;
// If interior, we do damage and pinning
if(bIndoors)
{
// Roll damage for each target. 8d6
nDam = PHS_MaximizeOrEmpower(6, 8, nMetaMagic);
// Adjust the damage based on the Reflex Save, Evasion and Improved Evasion.
nDam = PHS_GetAdjustedDamage(SAVING_THROW_REFLEX, nDam, oTarget, nSpellSaveDC, SAVING_THROW_TYPE_NONE, oCaster, fDelay);
// Need to do damage to apply visuals and pinning.
if(nDam > 0)
{
// Apply effects to the currently selected target.
DelayCommand(fDelay, PHS_ApplyDamageVFXToObject(oTarget, eVis, nDam, DAMAGE_TYPE_BLUDGEONING));
// Apply the pinning
DelayCommand(fDelay, PHS_ApplyPermanent(oTarget, eDur));
// Delay a pin check
WrapperDelayRemoval(fDelay + f1Round, oTarget);
}
}
// Else, exterior, special fissures.
else
{
// Open Ground: Each creature standing in the area must make a DC 15 Reflex
// save or fall down for the round. Fissures open in the earth, and every
// creature on the ground has a 25% chance to fall into one (Reflex DC 20 to
// avoid a fissure). At the end of the spell, all fissures grind shut, killing
// any creatures still trapped within.
// First: 25% of a fissure. If they die, they die!
if(d100() <= 25)
{
// Fissure!
PHS_ApplyLocationVFX(GetLocation(oTarget), eVis);
// Reflex save DC 20 or die
if(!PHS_SavingThrow(SAVING_THROW_REFLEX, oTarget, 20, SAVING_THROW_TYPE_NONE, oCaster, fDelay))
{
// Apply knockdown for 6 seconds, then do the death.
DelayCommand(fDelay, PHS_ApplyDuration(oTarget, ePin, f1Round - fDelay));
// Delay death
DelayCommand(f1Round, PHS_ApplyInstant(oTarget, eDeath));
}
}
// Failing that, we will do a reflex save just to stay upright
else if(!PHS_SavingThrow(SAVING_THROW_REFLEX, oTarget, 15, SAVING_THROW_TYPE_NONE, oCaster, fDelay))
{
// Apply knockdown for 6 seconds
DelayCommand(fDelay, PHS_ApplyDuration(oTarget, ePin, f1Round - fDelay));
}
}
}
// Get Next Target
oTarget = GetNextObjectInShape(SHAPE_SPHERE, 26.67, lTarget, FALSE, OBJECT_TYPE_CREATURE);
}
}
void WrapperDelayRemoval(float fDelay, object oTarget)
{
int nSpell = GetSpellId();
int nCastTimes = GetLocalInt(OBJECT_SELF, "PHS_TIMES_CAST" + IntToString(nSpell));
nCastTimes++; // Add one to cast times
SetLocalInt(OBJECT_SELF, "TIMES_CAST" + IntToString(nSpell), nCastTimes);
DelayCommand(fDelay, PinCheck(nSpell, nCastTimes, 0, oTarget));
}
void PinCheck(int nSpellId, int nTimesCast, int nLastRound, object oTarget)
{
// Add one to current rounds
int nThisRound = nLastRound + 1;
if(!GetHasSpellEffect(nSpellId, oTarget) ||
GetLocalInt(oTarget, "PHS_TIMES_CAST" + IntToString(nSpellId)) != nTimesCast ||
PHS_AbilityCheck(oTarget, ABILITY_STRENGTH, 25))
{
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck))
{
if(GetEffectSpellId(eCheck) == nSpellId)
{
RemoveEffect(oTarget, eCheck);
}
eCheck = GetNextEffect(oTarget);
}
}
// Every 10th round, we do damage
else if(nThisRound == 10)
{
// reset it to 0
nThisRound = 0;
// Do damage
PHS_ApplyDamageToObject(oTarget, d6(), DAMAGE_TYPE_BLUDGEONING);
// Another delay
DelayCommand(6.0, PinCheck(nSpellId, nTimesCast, nThisRound, oTarget));
}
else
{
// Another delay
DelayCommand(6.0, PinCheck(nSpellId, nTimesCast, nThisRound, oTarget));
}
}