From 31a0ccbf16ba146ac06cd1abb77e2075cf4c20b8 Mon Sep 17 00:00:00 2001 From: Jaysyn904 <68194417+Jaysyn904@users.noreply.github.com> Date: Sat, 10 Aug 2024 08:57:45 -0400 Subject: [PATCH] Added missing Force Missiles spell script Added missing Force Missiles spell script. Fixed a few minor typos. --- nwn/nwnprc/trunk/2das/iprp_spellcost.2DA | 7 +- nwn/nwnprc/trunk/include/prc_inc_descrptr.nss | 4 +- nwn/nwnprc/trunk/spells/sp_forcemissiles.nss | 194 ++++++++++++++++++ nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml | 2 +- 4 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 nwn/nwnprc/trunk/spells/sp_forcemissiles.nss diff --git a/nwn/nwnprc/trunk/2das/iprp_spellcost.2DA b/nwn/nwnprc/trunk/2das/iprp_spellcost.2DA index 0321900a..f708ab49 100644 --- a/nwn/nwnprc/trunk/2das/iprp_spellcost.2DA +++ b/nwn/nwnprc/trunk/2das/iprp_spellcost.2DA @@ -249,4 +249,9 @@ 245 Crystallize 16823673 14202 6 246 BasiliskMask 16836737 18708 8 247 GorgonMask 16836803 18729 8 -248 SPELL_FORCE_MISSILES 16790488 2480 4 +248 Bigbys_Interposing_Hand 2683 459 5 +249 Illithid_Mindblast 83865 789 3 +250 Psionic_Mass_Concussion 84464 763 5 +251 MONSTER_MindBlast 3891 551 3 +252 MONSTER_CharmMonster 3893 552 3 +253 SPELL_FORCE_MISSILES 16790488 2480 4 diff --git a/nwn/nwnprc/trunk/include/prc_inc_descrptr.nss b/nwn/nwnprc/trunk/include/prc_inc_descrptr.nss index c37dbe1b..bbee255f 100644 --- a/nwn/nwnprc/trunk/include/prc_inc_descrptr.nss +++ b/nwn/nwnprc/trunk/include/prc_inc_descrptr.nss @@ -148,7 +148,7 @@ int GetIsElementalSpell(int nSpellID, int nDescriptor = -1); int GetIsOfSubschool(int nSpellID, int nSubschoolFlag); /** - * Returns an integer value containing the bitflags of descriptors set in prc_splls.2da + * Returns an integer value containing the bitflags of descriptors set in prc_spells.2da * for a given SpellID * * @param nSpellID row number of tested spell in spells.2da @@ -157,7 +157,7 @@ int GetIsOfSubschool(int nSpellID, int nSubschoolFlag); int GetDescriptorFlags(int nSpellID); /** - * Returns an integer value containing the bitflags of subschools set in prc_splls.2da + * Returns an integer value containing the bitflags of subschools set in prc_spells.2da * for a given SpellID * * @param nSpellID row number of tested spell in spells.2da diff --git a/nwn/nwnprc/trunk/spells/sp_forcemissiles.nss b/nwn/nwnprc/trunk/spells/sp_forcemissiles.nss new file mode 100644 index 00000000..ad4c0274 --- /dev/null +++ b/nwn/nwnprc/trunk/spells/sp_forcemissiles.nss @@ -0,0 +1,194 @@ +//:://///////////////////////////////////////////// +//:: Force Missiles +//:: sp_forcemissiles +//:: Copyright (c) 2022 PRC +//::////////////////////////////////////////////// +/*/ +Force Missiles +(Spell Compendium, p. 98) + +Evocation [Force] +Level: Sorcerer 4, Wizard 4, +Components: V, S, +Casting Time: 1 Standard Action +Range: Medium (100 ft. + 10 ft./level) +Target: Up to four creatures, no two of which are more than 30 ft. apart +Duration: Instantaneous +Saving Throw: None +Spell Resistance: Yes + +Sparking bolts of blue magic, like giant magic missiles, streak from your +outstretched hand to strike your foes and explode in sparkling bursts. + +You create powerful missiles of magical force, each of which darts from your +fingertips and unerringly strikes its target, dealing 2d6 points of damage. +The missile then explodes in a burst of force that deals half this amount of +damage to any creatures adjacent to the primary target. + +The missile strikes unerringly, even if the target is in melee or has anything +less than total cover or concealment. A caster cannot single out specific parts +of a creature. + +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" + +void SendMissileBomb(object oCaster, object oTarget, float fDelay=0.0, float fTime=0.0) +{ + 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); + while (GetIsObjectValid(oLoop)) + { + SignalEvent(oLoop, EventSpellCastAt(oCaster, PRCGetSpellId())); + if (oLoop == oTarget) + { + int nDam = d6(2); + if (nMetaMagic == METAMAGIC_MAXIMIZE) + nDam = 12; + if (nMetaMagic == METAMAGIC_EMPOWER) + 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))) + { + int nDam = d6(1); + if (nMetaMagic == METAMAGIC_MAXIMIZE) + nDam = 6; + if (nMetaMagic == METAMAGIC_EMPOWER) + 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); + } +} + +//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) +{ + int nMetaMagic = PRCGetMetaMagicFeat(); + int nSaveDC = PRCGetSaveDC(oTarget, oCaster); + int nPenetr = nCasterLevel + SPGetPenetr(); + int i; + int nTargets; + int nCnt = 1; + float fDist, fDelay, fDelay2, fTime; + + if (nCasterLevel > 40) nCasterLevel = 40; + int nMissiles = nCasterLevel/4; + if (nMissiles < 1) nMissiles = 1; + + location lTarget = PRCGetSpellTargetLocation(); + + 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); + } + if (!nTargets) + return FALSE; + + int nExtraMissiles = nMissiles / nTargets; + + if (nExtraMissiles <= 0) + nExtraMissiles = 1; + + int nRemainder = 0; + + if (nTargets > nMissiles) nTargets = nMissiles; + + 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))) + { + int i; + for (i=1; i <= nExtraMissiles + nRemainder; i++) + { + fDist = GetDistanceBetween(oCaster, oTarget); + fDelay = fDist/(3.0 * log(fDist) + 2.0); + fTime = fDelay; + fDelay2 += 0.1; + fTime += fDelay2; + DelayCommand(fDelay2, SendMissileBomb(oCaster, oTarget, fDelay, fTime)); + } + } + else + { + ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_MIRV), oTarget); + } + nCnt++; + nRemainder = 0; + } + oTarget = GetNextObjectInShape(SHAPE_SPHERE, 9.144, lTarget, TRUE, OBJECT_TYPE_CREATURE); + } + + return TRUE; +} + +void main() +{ + object oCaster = OBJECT_SELF; + object oTarget = PRCGetSpellTargetObject(); + + int nCasterLevel = PRCGetCasterLevel(oCaster); + int i; + int nTargets; + int nCnt = 1; + float fDist, fDelay, fDelay2, fTime; + + PRCSetSchool(GetSpellSchool(PRCGetSpellId())); + + if (!X2PreSpellCastCode()) return; + + 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); + } + } + PRCSetSchool(); +} + +//:://///////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml index 22591d90..c62ca84c 100644 --- a/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml +++ b/nwn/nwnprc/trunk/tlk/prc8_consortium.tlk.xml @@ -72975,4 +72975,4 @@ Use: Activated</entry> <entry id="77190" lang="en" sex="m">Spellcasting isn't required to take the Talon of Tiamat prestige class. If you currently have an arcane spellcasting, shadowcasting or invoking class, do not pick this marker feat.</entry> <entry id="77191" lang="en" sex="m">Spellcasting isn't required to take the Dragonsong Lyrist prestige class. If you currently have an arcane spellcasting or shadowcasting class, do not pick this marker feat.</entry> <entry id="77192" lang="en" sex="m">Spellcasting isn't required to take the Ollam prestige class. If you currently have an arcane spellcasting or shadowcasting class, do not pick this marker feat.</entry> -</tlk> +</tlk> \ No newline at end of file