Spell update

Added the following spells: Regenerate Light Wounds, Regenerate Moderate Wounds, Regenerate Serious Wounds, Regenerate Critical Wounds, Spirit Worm, Tortoise Shell, Speed of the Wind & Spiritual Weapon.  Updated Force Missiles & Chasing Perfection.  Updated Acid Fog to be more like pen & paper.  Updated release archive.
This commit is contained in:
Jaysyn904
2024-08-29 16:40:13 -04:00
parent 4915c49ece
commit 553461ec8c
44 changed files with 22171 additions and 19742 deletions

View File

@@ -15,9 +15,83 @@
//:: modified by mr_bumpkin Dec 4, 2003
//:: This spell isn't supposed to have a saving throw.
//:: modified by Jaysyn: 2024-08-25 14:41:58
#include "prc_inc_spells"
#include "prc_add_spell_dc"
void main()
{
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
//Declare major variables
object oCaster = GetAreaOfEffectCreator();
object oTarget = GetEnteringObject();
int nMetaMagic = PRCGetMetaMagicFeat();
effect eVis = EffectVisualEffect(VFX_IMP_ACID_S);
effect eSlow = EffectMovementSpeedDecrease(50);
float fDelay = PRCGetRandomDelay(1.0, 2.2);
int nPenetr = GetLocalInt(OBJECT_SELF, "X2_AoE_Caster_Level") + SPGetPenetr(oCaster);
if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, oCaster))
{
//Fire cast spell at event for the target
SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_ACID_FOG));
//Spell resistance check
if(!PRCDoResistSpell(oCaster, oTarget, nPenetr, fDelay))
{
//Roll Damage
//Enter Metamagic conditions
int nDamage = d6(2);
if (nMetaMagic & METAMAGIC_MAXIMIZE)
nDamage = 12;//Damage is at max
if (nMetaMagic & METAMAGIC_EMPOWER)
nDamage = nDamage + (nDamage/2); //Damage/Healing is +50%
// Acid Sheath adds +1 damage per die to acid descriptor spells
if (GetHasDescriptor(SPELL_ACID_FOG, DESCRIPTOR_ACID) && GetHasSpellEffect(SPELL_MESTILS_ACID_SHEATH, oCaster))
nDamage += 2;
nDamage += SpellDamagePerDice(oCaster, 2);
//slowing effect
SPApplyEffectToObject(DURATION_TYPE_PERMANENT, eSlow, oTarget,0.0f,FALSE);
// * BK: Removed this because it reduced damage, didn't make sense nDamage = d6();
//Set Damage Effect with the modified damage
effect eDam = PRCEffectDamage(oTarget, nDamage, GetLocalInt(OBJECT_SELF, "Acid_Fog_Damage"));
//Apply damage and visuals
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
PRCBonusDamage(oTarget);
}
}
PRCSetSchool();
}
//::///////////////////////////////////////////////
//:: Acid Fog: On Enter
//:: NW_S0_AcidFogA.nss
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
All creatures within the AoE take 2d6 acid damage
per round and upon entering if they fail a Fort Save
their movement is halved.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: May 17, 2001
//:://///////////////////////////////////////////
//:: modified by mr_bumpkin Dec 4, 2003
/* #include "prc_inc_spells"
#include "prc_add_spell_dc"
void main()
{
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
@@ -67,4 +141,4 @@ void main()
}
}
PRCSetSchool();
}
} */

View File

@@ -5,8 +5,8 @@
//:://////////////////////////////////////////////
/*
All creatures within the AoE take 2d6 acid damage
per round and upon entering if they fail a Fort Save
their movement is halved.
per round and their movement is halved.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
@@ -18,7 +18,8 @@
//:: modified by mr_bumpkin Dec 4, 2003
#include "prc_inc_spells"
//:: This spell isn't supposed to have a saving throw.
//:: modified by Jaysyn: 2024-08-25 14:41:58
void main()
{

View File

@@ -5,8 +5,8 @@
//:://////////////////////////////////////////////
/*
All creatures within the AoE take 2d6 acid damage
per round and upon entering if they fail a Fort Save
their movement is halved.
per round and their movement is halved.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
@@ -15,6 +15,10 @@
//:: modified by mr_bumpkin Dec 4, 2003
//:: This spell isn't supposed to have a saving throw.
//:: modified by Jaysyn: 2024-08-25 14:41:58
#include "prc_inc_spells"
#include "prc_add_spell_dc"
@@ -58,11 +62,6 @@ void main()
int nSaveType = ChangedSaveType(nDamageType);
float fDelay = PRCGetRandomDelay(0.4, 1.2);
if(PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, nSaveType, oCaster, fDelay))
{
// This script does nothing if it has Mettle else deal only 1/2 damage
nDamage = GetHasMettle(oTarget, SAVING_THROW_FORT) ? 0 : nDamage / 2;
}
//Fire cast spell at event for the affected target
SignalEvent(oTarget, EventSpellCastAt(oCaster, SPELL_ACID_FOG));
//Spell resistance check

View File

@@ -1,5 +1,10 @@
/**@file Chasing Perfection
[sp_chasperfect.nss]
//::///////////////////////////////////////////////
//:: [Chasing Perfection]
//:: [sp_chasperfect.nss]
//:: [Tenjac & Jaysyn 20240807]
//::
//::///////////////////////////////////////////////
/**@file Chasing Perfection
(Player's Handbook II, p. 106)
Transmutation
@@ -23,13 +28,7 @@ enhancement bonus to each of its ability scores.
Material Component: A statuette of a celestial or
fiend worth 50 gp.
**/
////////////////////////////////////////////////////
// Author: Tenjac & Jaysyn
// Date: 2024/08/07
////////////////////////////////////////////////////
**/////////////////////////////////////////////////
#include "prc_inc_sp_tch"
#include "prc_sp_func"
#include "prc_add_spell_dc"
@@ -42,9 +41,10 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel, int nEvent)
if(nMetaMagic & METAMAGIC_EXTEND)
fDur += fDur;
PRCSignalSpellEvent(oTarget, FALSE, SPELL_CHASING_PERFECTION, oCaster);
//:: Fire spell cast at event for target
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, PRCGetSpellId(), FALSE));
// Check for existing ability enhancing spells
//:: Check for existing ability enhancing spells
effect eExistingSpellEffect = GetFirstEffect(oTarget);
int nBoostSTR = 4;
@@ -128,17 +128,22 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel, int nEvent)
void main()
{
//:: Check the Spellhook
//:: Run the Spellhook
if (!X2PreSpellCastCode()) return;
//:: Set the Spell School
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
//:: Declare major variables
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
int nCasterLevel = PRCGetCasterLevel(oCaster);
//:: Prevent spell stacking
PRCRemoveEffectsFromSpell(oTarget, PRCGetSpellId());
int nEvent = GetLocalInt(oCaster, PRC_SPELL_EVENT); //use bitwise & to extract flags
if(!nEvent) //normal cast
{
if(GetLocalInt(oCaster, PRC_SPELL_HOLD) && oCaster == oTarget)

View File

@@ -1,10 +1,12 @@
//::///////////////////////////////////////////////
//:: Force Missiles
//:: sp_forcemissiles
//:: Copyright (c) 2022 PRC
//:: [Force Missiles]
//:: [sp_forcemissiles.nss]
//:: Created By: Jaysyn / Tsurani Nevericy
//:: Created On: 20220726
//:: Last Updated By: Jaysyn
//:: Last Updated On: 2024-08-16 10:01:17
//:://////////////////////////////////////////////
/*/
Force Missiles
/**@file Force Missiles
(Spell Compendium, p. 98)
Evocation [Force]
@@ -33,109 +35,106 @@ You gain one missile for every four caster levels. You can make more than one
missile strike a single target, if desired. However,you must designate targets
before rolling for spell resistance or damage.
/*/
//:://////////////////////////////////////////////
//:: Created By: Tsurani Nevericy
//:: Created On: 05/15/2024
//:://////////////////////////////////////////////
//:: Last Updated By: Tsurani Nevericy
//:: Last Updated On: 05/15/2024
//:://////////////////////////////////////////////
#include "prc_sp_func"
#include "prc_inc_spells"
*///////////////////////////////////////////////////////////
#include "x2_inc_spellhook"
#include "prc_inc_spells"
void SendMissileBomb(object oCaster, object oTarget, float fDelay=0.0, float fTime=0.0)
{
int nMetaMagic = PRCGetMetaMagicFeat();
int nCasterLevel = PRCGetCasterLevel(oCaster);
int nPenetr = nCasterLevel + SPGetPenetr();
int nMetaMagic = PRCGetMetaMagicFeat();
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_MIRV), oTarget);
location lLoc = GetLocation(oTarget);
object oLoop = GetFirstObjectInShape(SHAPE_SPHERE, 5.0, lLoc, TRUE);
object oLoop = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(5.0), lLoc, TRUE);
while (GetIsObjectValid(oLoop))
{
SignalEvent(oLoop, EventSpellCastAt(oCaster, PRCGetSpellId()));
int nDam;
if (oLoop == oTarget)
{
int nDam = d6(2);
nDam = d6(2);
if (nMetaMagic == METAMAGIC_MAXIMIZE)
nDam = 12;
nDam = 12;
if (nMetaMagic == METAMAGIC_EMPOWER)
nDam += nDam/2;
nDam += nDam/2;
DelayCommand(fTime, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDam, DAMAGE_TYPE_MAGICAL), oLoop));
DelayCommand(fTime, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_IMP_MAGBLUE, FALSE, 4.0f), oLoop));
}
else if (!PRCDoResistSpell(oCaster, oLoop, FloatToInt(fDelay)))
else if (!PRCDoResistSpell(oCaster, oLoop, nPenetr, fDelay))
{
int nDam = d6(1);
nDam = d6(1);
if (nMetaMagic == METAMAGIC_MAXIMIZE)
nDam = 6;
nDam = 6;
if (nMetaMagic == METAMAGIC_EMPOWER)
nDam += nDam/2;
nDam += nDam/2;
DelayCommand(fTime, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDam, DAMAGE_TYPE_MAGICAL), oLoop));
DelayCommand(fTime, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_IMP_MAGBLUE), oLoop));
}
oLoop = GetNextObjectInShape(SHAPE_SPHERE, 5.0, lLoc, TRUE);
oLoop = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(5.0), lLoc, TRUE);
}
}
//Implements the spell impact, put code here
// if called in many places, return TRUE if
// stored charges should be decreased
// eg. touch attack hits
//
// Variables passed may be changed if necessary
int DoSpell(object oCaster, object oTarget, int nCasterLevel, int nEvent)
void main()
{
int nMetaMagic = PRCGetMetaMagicFeat();
int nSaveDC = PRCGetSaveDC(oTarget, oCaster);
int nPenetr = nCasterLevel + SPGetPenetr();
int i;
int nTargets;
int nCnt = 1;
float fDist, fDelay, fDelay2, fTime;
//:: Check the Spellhook
if (!X2PreSpellCastCode()) return;
if (nCasterLevel > 40) nCasterLevel = 40;
int nMissiles = nCasterLevel/4;
if (nMissiles < 1) nMissiles = 1;
//:: Set the Spell School
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
location lTarget = PRCGetSpellTargetLocation();
//:: Declare major variables
int i;
object oCaster = OBJECT_SELF;
object oTarget;
float fDist, fDelay, fDelay2 = 0.0, fTime;
int nTargets = 0;
int nCnt = 1;
int nCasterLevel = PRCGetCasterLevel(oCaster);
int nPenetr = nCasterLevel + SPGetPenetr();
if (nCasterLevel > 40) nCasterLevel = 40;
int nMissiles = nCasterLevel / 4;
if (nMissiles < 1) nMissiles = 1;
location lTarget = GetSpellTargetLocation();
oTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(30.0), lTarget, TRUE, OBJECT_TYPE_CREATURE);
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 9.144, lTarget, TRUE, OBJECT_TYPE_CREATURE);
while (GetIsObjectValid(oTarget))
{
if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, oCaster) && oTarget != oCaster)
{
nTargets++;
}
oTarget = GetNextObjectInShape(SHAPE_SPHERE, 9.144, lTarget, TRUE, OBJECT_TYPE_CREATURE);
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(30.0), lTarget, TRUE, OBJECT_TYPE_CREATURE);
}
if (!nTargets)
return FALSE;
if (nTargets == 0)
return;
int nExtraMissiles = nMissiles / nTargets;
if (nExtraMissiles <= 0)
if (nExtraMissiles < 1)
nExtraMissiles = 1;
int nRemainder = 0;
int nRemainder = nMissiles % nTargets;
if (nTargets > nMissiles) nTargets = nMissiles;
oTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(30.0), lTarget, TRUE, OBJECT_TYPE_CREATURE);
nRemainder = nMissiles % nTargets;
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, 9.144, lTarget, TRUE, OBJECT_TYPE_CREATURE);
while (GetIsObjectValid(oTarget) && nCnt <= nTargets)
{
if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, oCaster) && oTarget != oCaster)
{
if (!PRCDoResistSpell(oCaster, oTarget, FloatToInt(fDelay)))
if (!PRCDoResistSpell(oCaster, oTarget, nPenetr, fDelay))
{
int i;
for (i=1; i <= nExtraMissiles + nRemainder; i++)
for (i = 0; i < nExtraMissiles + nRemainder; i++)
{
fDist = GetDistanceBetween(oCaster, oTarget);
fDelay = fDist/(3.0 * log(fDist) + 2.0);
fDelay = fDist / (3.0 * log(fDist) + 2.0);
fTime = fDelay;
fDelay2 += 0.1;
fTime += fDelay2;
@@ -149,49 +148,8 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel, int nEvent)
nCnt++;
nRemainder = 0;
}
oTarget = GetNextObjectInShape(SHAPE_SPHERE, 9.144, lTarget, TRUE, OBJECT_TYPE_CREATURE);
}
return TRUE;
}
void main()
{
//:: Check the Spellhook
if (!X2PreSpellCastCode()) return;
//:: Set the Spell School
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
int nCasterLevel = PRCGetCasterLevel(oCaster);
int i;
int nTargets;
int nCnt = 1;
float fDist, fDelay, fDelay2, fTime;
int nEvent = GetLocalInt(oCaster, PRC_SPELL_EVENT); //use bitwise & to extract flags
if(!nEvent) //normal cast
{
if(GetLocalInt(oCaster, PRC_SPELL_HOLD) && oCaster == oTarget)
{ //holding the charge, casting spell on self
SetLocalSpellVariables(oCaster, 1); //change 1 to number of charges
return;
}
DoSpell(oCaster, oTarget, nCasterLevel, nEvent);
}
else
{
if(nEvent & PRC_SPELL_EVENT_ATTACK)
{
if(DoSpell(oCaster, oTarget, nCasterLevel, nEvent))
DecrementSpellCharges(oCaster);
}
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(30.0), lTarget, TRUE, OBJECT_TYPE_CREATURE);
}
//:: Unset the Spell school
PRCSetSchool();
}
//::///////////////////////////////////////////////////////////////////
PRCSetSchool();
}

View File

@@ -0,0 +1,178 @@
//::///////////////////////////////////////////////
//:: [Regenerate X Wounds]
//:: [sp_regen_wounds.nss]
//:: [Jaysyn - PRC8 2024-08-29 12:26:52]
//::
//:: Handles all Regen X Wounds spells
//::
//::///////////////////////////////////////////////
/**@file Regenerate X Wounds
(Masters of the Wild: A Guidebook to Barbarians,
Druids, and Rangers)
Conjuration (Healing)
Level: Cleric 1-4, Druid 1-4,
Components: V, S,
Casting Time: 1 action
Range: Touch
Target: Living creature touched
Duration: 10 rounds + 1 round/level
Saving Throw: Will negates (harmless)
Spell Resistance: Yes (harmless)
With a touch of your hand, you boost the subject's
life energy, granting him or her the fast healing
ability for the duration of the spell.
This healing applies only to damage sustained during
the spell's duration, not to that from previous injuries.
The subject heals 1 hit point per round of such
damage until the spell ends and is automatically stabilized
if he or she begins dying from hit point loss during that time.
Regenerate light wounds does not restore hit points lost from
starvation, thirst, or suffocation, nor does it allow a creature
to regrow or attach lost body parts.
The effects of multiple regenerate spells do not stack, only
the highest-level effect applies.
Applying a second regenerate spell of equal level extends the
first spell's duration by the full duration of the second spell.
*//////////////////////////////////////////////////
#include "x2_inc_spellhook"
#include "prc_inc_spells"
void main()
{
//:: Check the Spellhook
if (!X2PreSpellCastCode()) return;
//:: Set the Spell School
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
//:: Declare major variables
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
int nSpellId = PRCGetSpellId();
int nMetamagic = PRCGetMetaMagicFeat();
int nRegenRate = 0;
int nDuration = 10 + PRCGetCasterLevel(oCaster); // Duration in rounds
int nCurrentHP = GetCurrentHitPoints(oTarget);
int nInitialHP = GetLocalInt(oTarget, "INITIAL_HIT_POINTS");
//:: Update Initial HP if the current HP are higher than the stored Initial HP
if (nCurrentHP > nInitialHP)
{
nInitialHP = nCurrentHP;
SetLocalInt(oTarget, "INITIAL_HIT_POINTS", nInitialHP);
if(DEBUG) DoDebug("sp_regen_wounds: Updated Initial HP to " + IntToString(nInitialHP) + ".");
}
if (GetRacialType(oTarget) != RACIAL_TYPE_CONSTRUCT && GetRacialType(oTarget) != RACIAL_TYPE_UNDEAD)
{
if(DEBUG) DoDebug("sp_regen_wounds: Initial HP = " + IntToString(nInitialHP) + ".");
switch (nSpellId)
{
case SPELL_REGEN_LIGHT_WOUNDS:
{
nRegenRate = 1;
break;
}
case SPELL_REGEN_MODERATE_WOUNDS:
{
nRegenRate = 2;
break;
}
case SPELL_REGEN_SERIOUS_WOUNDS:
{
nRegenRate = 3;
break;
}
case SPELL_REGEN_CRITICAL_WOUNDS:
{
nRegenRate = 4;
break;
}
default: return;
}
if (nMetamagic == METAMAGIC_EXTEND)
{
nDuration *= 2;
}
// Get the current regeneration effect and its duration
int nCurrentRegen = GetLocalInt(oTarget, "REGEN_RATE");
int nExistingDuration = 0;
int bSameSpell = FALSE;
effect eExisting = GetFirstEffect(oTarget);
while (GetIsEffectValid(eExisting))
{
if (GetEffectTag(eExisting) == "REGEN_WOUNDS")
{
if(DEBUG) DoDebug("sp_regen_wounds: Found existing Regeneration effect via EffectTag.");
if (nCurrentRegen == nRegenRate)
{
bSameSpell = TRUE;
if(DEBUG) DoDebug("sp_regen_wounds: Same regeneration spell detected.");
nExistingDuration = GetEffectDurationRemaining(eExisting) / 6; // Convert seconds to rounds
if(DEBUG) DoDebug("sp_regen_wounds: Existing Duration = " + IntToString(nExistingDuration));
if (nRegenRate >= nCurrentRegen)
{
// Remove existing effect if new spell is stronger
RemoveEffect(oTarget, eExisting);
}
else
{
// Don't apply weaker spell
PRCSetSchool();
return;
}
}
else if (nRegenRate >= nCurrentRegen)
{
// Remove existing effect if new spell is stronger
RemoveEffect(oTarget, eExisting);
}
}
eExisting = GetNextEffect(oTarget);
}
// Only add the duration if the new spell is the same
if (bSameSpell)
{
nDuration += nExistingDuration;
if(DEBUG) DoDebug("sp_regen_wounds: Same regeneration spell detected, " + IntToString(nDuration) + " rounds remaining.");
}
// Set the new regeneration rate and duration
SetLocalInt(oTarget, "REGEN_RATE", nRegenRate);
SetLocalInt(oTarget, "REGEN_WOUNDS_REMAINING", nDuration);
effect eVis = EffectVisualEffect(1330); //:: VFX_DUR_BF_IOUN_STONE_GREEN
effect eFakeRegen = EffectRunScript("rs_regen_wounds", "rs_regen_wounds", "rs_regen_wounds", 6.0f, IntToString(nRegenRate));
eFakeRegen = SetEffectSpellId(eFakeRegen, nSpellId);
eFakeRegen = EffectLinkEffects(eVis, eFakeRegen);
eFakeRegen = TagEffect(eFakeRegen, "REGEN_WOUNDS");
//:: Remove any old effect & prevent spell stacking
PRCRemoveEffectsFromSpell(oTarget, nSpellId);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFakeRegen, oTarget, RoundsToSeconds(nDuration));
}
else
{
SendMessageToPC(oCaster, "Regenerate Wounds only works on living creatures.");
//:: Unset the Spell School
PRCSetSchool();
return;
}
}

View File

@@ -0,0 +1,87 @@
//::///////////////////////////////////////////////
//:: [Speed of the Wind]
//:: [sp_speed_wind.nss]
//:: [Yaballa: 7/9/2003]
//:: Modified by: Jaysyn 2024-08-20 20:06:06
//::
//::///////////////////////////////////////////////
/**@file Speed of the Wind
(Masters of the Wild: A Guidebook to Barbarians, Druids, and Rangers)
Transmutation
Level: Druid 2,
Components: V, S,
Casting Time: 1 action
Range: Touch
Target: Living creature touched
Duration: 10 minutes/level
Saving Throw: Will negates
Spell Resistance: Yes
With this spell, you can grant the ephemeral quickness
of a sudden breeze. The subject gains a +4 enhancement
bonus to Dexterity and a -2 enhancement penalty to
Constitution.
*/////////////////////////////////////////////////
#include "x2_inc_spellhook"
void ApplySpeedOfTheWindEffect(object oTarget, int nCasterLevel, int nMetamagic)
{
//:: Declare variables
int nDuration = nCasterLevel;
//:: Handle metamagic
if(nMetamagic & METAMAGIC_EXTEND)
{
nDuration = nDuration * 2;
}
//:: Set up effects
effect eDex = EffectAbilityIncrease(ABILITY_DEXTERITY, 4);
effect eCon = EffectAbilityDecrease(ABILITY_CONSTITUTION, 2);
effect eVis1 = EffectVisualEffect(VFX_IMP_IMPROVE_ABILITY_SCORE);
effect eVis2 = EffectVisualEffect(VFX_IMP_HEAD_EVIL);
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEUTRAL);
effect eLink = EffectLinkEffects(eDex, eCon);
eLink = EffectLinkEffects(eLink, eDur);
// Add visual effects to indicate the spell's impact
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, TurnsToSeconds(nDuration));
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis1, oTarget);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis2, oTarget);
}
void main()
{
//:: Check the Spellhook
if (!X2PreSpellCastCode()) return;
//:: Set the Spell School
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
//:: Declare major variables
object oCaster = OBJECT_SELF;
object oTarget = GetSpellTargetObject();
int nCasterLevel = PRCGetCasterLevel(oCaster);
int nMetamagic = PRCGetMetaMagicFeat();
//:: Fire spell cast at event for target
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, PRCGetSpellId(), FALSE));
//:: If the target is Undead or a Construct, exit the script
if (MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD || MyPRCGetRacialType(oTarget) == RACIAL_TYPE_CONSTRUCT)
{
SendMessageToPC(oCaster, "Only creatures with Constitution scores can be affected by Speed of the Wind");
//:: Unset the Spell school
PRCSetSchool();
return;
}
//:: Prevent spell stacking
PRCRemoveEffectsFromSpell(oTarget, PRCGetSpellId());
//:: Apply the Speed of the Wind effects to the target
ApplySpeedOfTheWindEffect(oTarget, nCasterLevel, nMetamagic);
//:: Unset the Spell school
PRCSetSchool();
}

View File

@@ -0,0 +1,216 @@
//::///////////////////////////////////////////////
//:: [Spiritual Weapon]
//:: [sp_spiritweapon.nss]
//:: [Jaysyn 2024-08-23 07:58:14]
//::
//::
//::///////////////////////////////////////////////
/**@ Spiritual Weapon
(Player's Handbook v.3.5, p. 283)
Evocation [Force]
Level: Cleric 2, Knight of the Chalice 2, War 2, Mysticism 2,
Components: V, S, DF,
Casting Time: 1 standard action
Range: Medium (100 ft. + 10 ft./level)
Effect: Magic weapon of force
Duration: 1 round/level (D)
Saving Throw: None
Spell Resistance: Yes
A weapon made of pure force springs into existence and attacks
opponents at a distance, as you direct it, dealing 1d8 force
damage per hit, +1 point per three caster levels (maximum +5
at 15th level). The weapon takes the shape of a weapon
favored by your deity or a weapon with some spiritual
significance or symbolism to you (see below) and has the
same threat range and critical multipliers as a real weapon
of its form. It strikes the opponent you designate, starting
with one attack in the round the spell is cast and continuing
each round thereafter on your turn. It uses your base attack
bonus (possibly allowing it multiple attacks per round in
subsequent rounds) plus your Wisdom modifier as its attack
bonus. It strikes as a spell, not as a weapon, so, for
example, it can damage creatures that have damage
reduction. As a force effect, it can strike incorporeal
creatures without the normal miss chance associated with
incorporeality. The weapon always strikes from your
direction. It does not get a flanking bonus or help a
combatant get one. Your feats (such as Weapon Focus)
or combat actions (such as charge) do not affect the
weapon. If the weapon goes beyond the spell range, if
it goes out of your sight, or if you are not directing
it, the weapon returns to you and hovers.
Each round after the first, you can use a move action to
redirect the weapon to a new target. If you do not,
the weapon continues to attack the previous round's
target. On any round that the weapon switches targets,
it gets one attack. Subsequent rounds of attacking that
target allow the weapon to make multiple attacks if your
base attack bonus would allow it to. Even if the spiritual
weapon is a ranged weapon, use the spell's range, not the
weapon's normal range increment, and switching targets
still is a move action.
A spiritual weapon cannot be attacked or harmed by
physical attacks, but dispel magic, disintegrate, a
sphere of annihilation, or a rod of cancellation affects it.
A spiritual weapon's AC against touch attacks is 12 (10 +
size bonus for Tiny object).
If an attacked creature has spell resistance, you make a
caster level check (1d20 + caster level) against that
spell resistance the first time the spiritual weapon
strikes it. If the weapon is successfully resisted, the
spell is dispelled. If not, the weapon has its normal
full effect on that creature for the duration of the spell.
*///////////////////////////////////////////////////////////
#include "x2_inc_spellhook"
#include "inc_spirit_weapn"
void main()
{
//:: Check the Spellhook
if (!X2PreSpellCastCode()) return;
//:: Set the Spell School
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
int nRunEvent = GetRunningEvent();
if (nRunEvent == EVENT_NPC_ONSPELLCASTAT)
{
// Get the caster of the spell
object oCaster = GetLastSpellCaster();
int nCasterLevel = GetCasterLevel(oCaster);
if(DEBUG) DoDebug("sp_spiritweapon: EVENT_NPC_ONSPELLCASTAT triggered.");
// Get the spell ID
int nSpellId = GetLastSpell();
if(DEBUG) DoDebug("sp_spiritweapon: Dispel spell ID: " + IntToString(nSpellId));
// Check if the spell ID is a dispel spell
if (nSpellId == SPELL_DISPEL_MAGIC || nSpellId == SPELL_LESSER_DISPEL || nSpellId == SPELL_GREATER_DISPELLING || nSpellId == SPELL_MORDENKAINENS_DISJUNCTION
|| nSpellId == SPELL_SLASHING_DISPEL || nSpellId == SPELL_DISPELLING_TOUCH || nSpellId == SPELL_PIXIE_DISPEL || nSpellId == SPELL_GREAT_WALL_OF_DISPEL)
{
// Get the target of the spell
object oTarget = OBJECT_SELF;
if(DEBUG) DoDebug("sp_spiritweapon: Spell targeted at: " + GetName(oTarget));
// Check if the target is OBJECT_SELF
if (oTarget == OBJECT_SELF)
{
// Retrieve the original caster of the Spiritual Weapon spell from oSummon
object oSummon = OBJECT_SELF;
object oOriginalCaster = GetLocalObject(oSummon, "MY_CASTER");
// Ensure oOriginalCaster is valid
if (GetIsObjectValid(oOriginalCaster))
{
if(DEBUG) DoDebug("sp_spiritweapon: Original caster found. Caster level: " + IntToString(GetCasterLevel(oOriginalCaster)));
// Determine the DC for the dispel check
int nDispelDC = 11 + GetCasterLevel(oOriginalCaster);
if(DEBUG) DoDebug("sp_spiritweapon: Dispel DC: " + IntToString(nDispelDC));
// Determine the maximum cap for the dispel check
int nDispelCap = 0;
if (nSpellId == SPELL_LESSER_DISPEL)
nDispelCap = 5;
else if (nSpellId == SPELL_DISPEL_MAGIC || nSpellId == SPELL_SLASHING_DISPEL || nSpellId == SPELL_DISPELLING_TOUCH || nSpellId == SPELL_PIXIE_DISPEL || nSpellId == INVOKE_VORACIOUS_DISPELLING)
nDispelCap = 10;
else if (nSpellId == SPELL_GREATER_DISPELLING || nSpellId == SPELL_GREAT_WALL_OF_DISPEL)
nDispelCap = 15;
else if (nSpellId == SPELL_MORDENKAINENS_DISJUNCTION)
nDispelCap = 0; // No cap for Disjunction
// Roll for the dispel check
int nDispelRoll = d20();
int nCappedCasterLevel = nCasterLevel;
if (nDispelCap > 0 && nCasterLevel > nDispelCap)
nCappedCasterLevel = nDispelCap;
nDispelRoll += nCappedCasterLevel;
if(DEBUG) DoDebug("sp_spiritweapon: Dispel roll: " + IntToString(nDispelRoll) + " (Caster Level: " + IntToString(nCappedCasterLevel) + ", Cap: " + IntToString(nDispelCap) + ")");
// Compare the dispel result to the DC
if (nDispelRoll >= nDispelDC)
{
if(DEBUG) DoDebug("sp_spiritweapon: Dispel check succeeded.");
// Dispel succeeded, destroy oSummon and the item in its right hand
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oSummon);
if(DEBUG) DoDebug("sp_spiritweapon: Dispel Magic succeeded. Destroying Spiritual Weapon and its right hand item.");
// Set flags and destroy objects with delays
SetPlotFlag(oWeapon, FALSE);
SetPlotFlag(oSummon, FALSE);
SetImmortal(oSummon, FALSE);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_DISPEL), oSummon);
// Destroy the weapon and summon with delays
if (GetIsObjectValid(oWeapon))
{
DelayCommand(0.5f, DestroyObject(oWeapon));
if(DEBUG) DoDebug("sp_spiritweapon: Spiritual Weapon destruction scheduled.");
}
else
{
if(DEBUG) DoDebug("sp_spiritweapon: No weapon found in right hand.");
}
DelayCommand(1.0f, DestroyObject(oSummon));
if(DEBUG) DoDebug("sp_spiritweapon: Spiritual Weapon Summon destruction scheduled.");
}
else
{
RegisterSummonEvents(oSummon);
if(DEBUG) DoDebug("sp_spiritweapon: Dispel check failed.");
}
}
else
{
if(DEBUG) DoDebug("sp_spiritweapon: Original caster not found.");
}
}
}
return;
}
//:: Declare major variables
object oCaster = OBJECT_SELF;
location lTarget = PRCGetSpellTargetLocation();
int nClass = PRCGetLastSpellCastClass();
int nDuration = PRCGetCasterLevel(oCaster);
int nSwitch = GetPRCSwitch(PRC_SUMMON_ROUND_PER_LEVEL);
int nMetaMagic = PRCGetMetaMagicFeat();
effect eSummon = EffectSummonCreature("prc_spirit_weapn");
effect eVis = EffectVisualEffect(1200); //:: VFX_FNF_STRIKE_HOLY_SILENT
if(nDuration < 1)
nDuration = 1;
//:: Make metamagic check for extend
if(nMetaMagic & METAMAGIC_EXTEND)
nDuration *= 2; //Duration is +100%
float fDuration = nSwitch ? RoundsToSeconds(nDuration * nSwitch):
TurnsToSeconds(nDuration);
//:: Apply the VFX impact and summon effect
MultisummonPreSummon();
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eSummon, lTarget, fDuration);
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eVis, lTarget);
DelayCommand(1.0, CreateSpiritualWeapon(oCaster, fDuration, nClass));
//:: Unset the Spell school
PRCSetSchool();
}

View File

@@ -0,0 +1,134 @@
//::///////////////////////////////////////////////
//:: [Spirit Worm]
//:: [sp_spiritworm.nss]
//:: [Jaysyn - PRC8 2024-08-20 20:42:32]
//::
//::
//::///////////////////////////////////////////////
/**@file Spirit Worm
(Spell Compendium, p. 202)
Necromancy
Level: Sorcerer 1, Wizard 1,
Components: V, S, M,
Casting Time: 1 standard action
Range: Touch
Target: Living creature touched
Duration: 1 round/level, up to 5 rounds; see text
Saving Throw: Fortitude negates; see text
Spell Resistance: Yes
You press the bit of blackened bone against your
foe and intone the spell. The bone vanishes,
leaving a mottled bruise where it touched.
You create a lingering decay in the spirit and
body of the target. If the target fails its saving
throw, it takes 1 point of Constitution damage each
round while the spell lasts (maximum 5 points).
The victim can attempt a Fortitude saving throw
each round, and success negates the Constitution
damage for that round and ends the spell.
Material Component: A piece of fire-blackened
ivory or bone carved in the shape of a segmented
worm.
*/////////////////////////////////////////////////
#include "prc_inc_sp_tch"
#include "prc_add_spell_dc"
void SpiritWormDamage(object oTarget, object oCaster, int nDuration, int nMetaMagic, int nSpellID)
{
//:: Exit if the target is dead or duration has expired
if (GetIsDead(oTarget) || nDuration <= 0)
return;
//:: Calculate caster level and spell penetration
int nCasterLevel = PRCGetCasterLevel(oCaster);
int nPenetr = nCasterLevel + SPGetPenetr();
//:: Check for spell resistance
if (!PRCDoResistSpell(oCaster, oTarget, nPenetr))
{
//:: Calculate Fortitude Save DC
int nFortSaveDC = PRCGetSpellSaveDC(nSpellID, -1, oCaster);
int bSuccess = FortitudeSave(oTarget, nFortSaveDC, SAVING_THROW_TYPE_NEGATIVE, oCaster);
if (!bSuccess)
{
//:: Apply Constitution Damage
effect eDamage = EffectAbilityDecrease(ABILITY_CONSTITUTION, 1);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget);
//:: Reduce duration and apply damage in the next round
nDuration--;
DelayCommand(6.0f, SpiritWormDamage(oTarget, oCaster, nDuration, nMetaMagic, nSpellID));
}
else
{
//:: Indicate successful save
effect eSuccess = EffectVisualEffect(VFX_IMP_FORTITUDE_SAVING_THROW_USE);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eSuccess, oTarget);
}
}
}
void main()
{
//:: Check the Spellhook
if (!X2PreSpellCastCode()) return;
//:: Set the Spell School
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
//:: Declare major variables
int nSpellID = PRCGetSpellId();
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
int nCasterLvl = PRCGetCasterLevel(oCaster);
int nMetaMagic = PRCGetMetaMagicFeat();
int nPenetr = nCasterLvl + SPGetPenetr();
int nDuration = nCasterLvl;
//:: Limit the duration to a maximum of 5 rounds
if (nDuration > 5) nDuration = 5;
if (nMetaMagic & METAMAGIC_EXTEND)
nDuration *= 2;
//:: Only affect hostile targets
if (!GetIsReactionTypeFriendly(oTarget, oCaster))
{
SignalEvent(oTarget, EventSpellCastAt(oCaster, nSpellID));
//:: Calculate Fortitude Save DC
int nFortSaveDC = PRCGetSpellSaveDC(nSpellID, -1, oCaster);
int bSuccess = FortitudeSave(oTarget, nFortSaveDC, SAVING_THROW_TYPE_NEGATIVE, oCaster);
if (bSuccess)
{
//:: Indicate successful save
effect eSuccess = EffectVisualEffect(VFX_IMP_FORTITUDE_SAVING_THROW_USE);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eSuccess, oTarget);
}
else
{
//:: Check for spell resistance
if (!PRCDoResistSpell(oCaster, oTarget, nPenetr))
{
//:: Setup initial visual effect
effect eVis = EffectVisualEffect(VFX_IMP_NEGATIVE_ENERGY);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
//:: Prevent spell stacking
PRCRemoveEffectsFromSpell(oTarget, PRCGetSpellId());
//:: Apply Constitution Damage Per Round
SpiritWormDamage(oTarget, oCaster, nDuration, nMetaMagic, nSpellID);
}
}
}
//:: Unset the Spell School
PRCSetSchool();
}

View File

@@ -0,0 +1,123 @@
//::///////////////////////////////////////////////
//:: [Tortoise Shell]
//:: [sp_tortiseshell.nss]
//:: [Jaysyn 2024-08-20 22:12:12]
//::
//::///////////////////////////////////////////////
/**@file Tortoise Shell
(Spell Compendium, p. 221)
Transmutation
Level: Druid 6,
Components: V, S, DF,
Casting Time: 1 standard action
Range: Touch
Target: Living creature touched
Duration: 10 minutes/level
Saving Throw: None
Spell Resistance: Yes (harmless)
In the blink of an eye, the creature you touched
grows the armor plating of a tortoise across its
torso and a tough, leathery skin elsewhere.
Tortoise shell grants a +6 enhancement bonus to
the subject's existing natural armor bonus. This
enhancement bonus increases by 1 for every three
caster levels beyond 11th, to a maximum of +9 at
20th level.
The enhancement bonus provided by tortoise shell
stacks with the target's natural armor bonus, but
not with other enhancement bonuses to natural
armor. A creature without natural armor has an
effective natural armor of +0, much as a character
wearing only normal clothing has an armor bonus of
+0.
Tortoise shell slows a creature's movement as if
it were wearing heavy armor. An elf subject to
tortoise shell, for example, would have a speed
of 20 feet and could run only 60 feet per round.
The spell affects only a creature's speed; tortoise
shell doesn't carry an armor check penalty or an
arcane spell failure chance.
*/////////////////////////////////////////////////
#include "x2_inc_spellhook"
void main()
{
//:: Check the Spellhook
if (!X2PreSpellCastCode()) return;
//:: Set the Spell School
PRCSetSchool(GetSpellSchool(PRCGetSpellId()));
//:: Declare major variables
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
//:: Prevent spell stacking
PRCRemoveEffectsFromSpell(oTarget, PRCGetSpellId());
//:: Get the caster's level and check for Extend Spell feat
int nCasterLevel = PRCGetCasterLevel(oCaster);
int nMetaMagic = PRCGetMetaMagicFeat();
//:: Calculate the enhancement bonus
int nBonus = 6 + (nCasterLevel > 11 ? (nCasterLevel - 11) / 3 : 0);
nBonus = nBonus > 9 ? 9 : nBonus; // Max bonus is +9
//:: Initialize existing natural armor bonus
int nExistingNaturalArmor = 0;
//:: Check for items in inventory that provide Natural AC bonus
object oItem = GetItemInSlot(INVENTORY_SLOT_NECK, oTarget);
if (GetIsObjectValid(oItem))
{
//:: Directly get the Armor Class value from the item
int nItemAC = GetItemACValue(oItem);
if (nItemAC > nExistingNaturalArmor)
{
nExistingNaturalArmor = nItemAC;
}
}
//:: Calculate the final bonus to apply
int nFinalBonus = nBonus - nExistingNaturalArmor;
if (nFinalBonus < 0) nFinalBonus = 0; // Ensure no negative bonus
//:: Determine the base duration of the effects (10 minutes per caster level)
float fBaseDuration = TurnsToSeconds(10 * nCasterLevel);
//:: Check if the caster has the Extend Spell feat
float fDuration = (nMetaMagic & METAMAGIC_EXTEND) ? fBaseDuration * 2.0 : fBaseDuration;
//:: Setup the natural armor effect
effect eNaturalArmor = EffectACIncrease(nFinalBonus);
//:: Setup the movement speed penalty effect
//:: Normal speed is 30 feet per round, spell reduces to 20 feet per round (1/3 slower)
int nSpeedDecreasePercent = 33; // Percentage to slow the movement speed
effect eSlow = EffectMovementSpeedDecrease(nSpeedDecreasePercent);
//:: Create the visual effects
effect eVFXNaturalArmor = EffectVisualEffect(VFX_IMP_HEAD_NATURE);
effect eVFXMovementSpeed = EffectVisualEffect(VFX_IMP_SLOW);
effect eVFXACBonus = EffectVisualEffect(VFX_IMP_AC_BONUS);
effect eVFXBarkskin = EffectVisualEffect(VFX_DUR_PROT_BARKSKIN);
//:: Combine primary effects
effect eLink = EffectLinkEffects(eNaturalArmor, eSlow);
eLink = EffectLinkEffects(eLink, eVFXBarkskin);
//:: Apply the primary effects with duration
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDuration);
//:: Apply visual effects instantly
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVFXNaturalArmor, oTarget);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVFXMovementSpeed, oTarget);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVFXACBonus, oTarget);
//:: Unset the Spell school
PRCSetSchool();
}