PRC8/nwn/nwnprc/trunk/smp/phs_spellhook.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

269 lines
8.9 KiB
Plaintext

/*:://////////////////////////////////////////////
//:: Name Spell Hook file
//:: FileName SMP_SpellHook
//:://////////////////////////////////////////////
//:: Notes
//:://////////////////////////////////////////////
Spell hook file.
This is executed on any PC casters who cast a spell with SMP_SpellHookCheck()
at the beginning.
This has all the things like Domain spells and stuff and everything.
Affects PCs only.
Its sets the local variable "SMP_SPELLHOOK_RETURN" to TRUE if the spellhook interrupts
the spell.
//:://////////////////////////////////////////////
//:: Created By: Jasperre
//::////////////////////////////////////////////*/
#include "SMP_INC_SPLLHOOK"
#include "SMP_INC_CRAFT"
// This returns bResult
// * FALSE and stops the rest of the spell firing.
// * TRUE and the rest of the spell fires normally.
void ReturnResult(int bResult);
void main()
{
// Declare things we may, or may not use.
object oCaster = OBJECT_SELF;
object oTarget = GetSpellTargetObject();
object oSpellItem = GetSpellCastItem();
object oArea = GetArea(oCaster);
int nCasterClass = GetLastSpellCastClass();
int nSpellSaveDC = SMP_GetSpellSaveDC();
int nRoll;
string sMessage;
// Check nSpellID
int nSpellId = GetSpellId();
// Note: Get master as appropriate too.
// * Is this needed?
// int nMasterSpell = GetMaster(nSpellId);
// Get info from nSpellId
string sName = SMP_ArrayGetSpellName(nSpellId);
int nSpellLevel = SMP_ArrayGetSpellLevel(nSpellId, nCasterClass);
// DEBUG MESSAGE
SpeakString("Cast: " + sName + ". ID (Input): " + IntToString(nSpellId) + ". Target: " + GetName(oTarget) + ". Class: " + IntToString(nCasterClass));
// We MUST set the caster level for this spell onto the caster, using nSpellID.
int nCasterLevel = SMP_GetCasterLevel();
SetLocalInt(oCaster, "SMP_SPELL_CAST_BY_LEVEL_" + IntToString(nSpellId), nCasterLevel);
// We also must set the level of the spell cast
SetLocalInt(oCaster, "SMP_SPELL_CAST_SPELL_LEVEL" + IntToString(nSpellId), nSpellLevel);
// We also set the DC used, if we need it later.
SetLocalInt(oCaster, "SMP_SPELL_CAST_SPELL_SAVEDC" + IntToString(nSpellId), nSpellSaveDC);
// We also set the Metamagic used, if we need it later.
int nMetaMagic = GetMetaMagicFeat();
SetLocalInt(oCaster, "SMP_SPELL_CAST_SPELL_METAMAGIC" + IntToString(nSpellId), nMetaMagic);
/*:://////////////////////////////////////////////
Section 1: Anything that should happen whenever a spell is attempted.
----------
Basically, things which do not stop the spell from being cast, but
will be activated even if the spell fails - it is the mear action of attempting
to cast the spell (even if it is unsucessful) which this section uses.
//::////////////////////////////////////////////*/
// Concentration for spells such as Black Blade of Disaster
SMP_SpecialConcentrationChecks(oCaster);
// Check for damage via. Spell Curse and Greater Spell curse.
SMP_SpellCurseCheck(nSpellLevel, nCasterClass, oSpellItem, oCaster);
// We may turn of Expertise. Bioware setting.
if(SMP_SettingGetGlobal(SMP_SETTING_BIO_STOP_EXPERTISE_ABUSE) == TRUE)
{
SetActionMode(oCaster, ACTION_MODE_EXPERTISE, FALSE);
SetActionMode(oCaster, ACTION_MODE_IMPROVED_EXPERTISE, FALSE);
}
/*:://////////////////////////////////////////////
Section 2: Stop if the spell hook catches something
----------
If there is something that would stop the spell, such as, for example,
wild magic, an invalid target, or a fail at a blink check, it is done here.
The order is basically the "Damaging" parts first, and later, the checks
for things like "Blink" and "Divine Focus".
Uses, in each case, ReturnResult(FALSE); if it wants to stop the spell script
from firing.
//::////////////////////////////////////////////*/
// You can NOT cast a spell on another person or thing if you are in
// "Meld into Stone"
if(GetHasSpellEffect(SMP_SPELL_MELD_INTO_STONE, oCaster))
{
// Check the target
if(oTarget != oCaster)
{
// Stop the casting
FloatingTextStringOnCreature("*You cannot cast a spell onto anything but yourself if you are Melded into Stone*", oCaster, FALSE);
ReturnResult(FALSE);
return;
}
}
// Cannot cast hostile spells (any) while in timestop.
if(GetHasSpellEffect(SMP_SPELL_TIME_STOP, oCaster))
{
// Is it hositle?
if(SMP_ArrayGetIsHostile(nSpellId))
{
// Stop the casting
FloatingTextStringOnCreature("*You are unable to affect with hostile spells in timestop*", oCaster, FALSE);
ReturnResult(FALSE);
return;
}
}
// Note:
// - We automatically exit for all NPC's, only doing wild magic checks
if(!GetIsPC(oCaster))
{
ReturnResult(SMP_WildMagicAreaSurge(oArea, oCaster));
return;
}
// Make a check for explosive runes
if(SMP_ExplosiveRunes())
{
ReturnResult(FALSE);
return;
}
// Making sure they are not in time stop and casting spells against a target.
if(GetIsObjectValid(oTarget) && oTarget != oCaster)
{
if(GetHasSpellEffect(SMP_SPELL_TIME_STOP, oCaster))
{
FloatingTextStringOnCreature("*You cannot cast spells against objects other then yourself under the effects of Time Stop*", oCaster, FALSE);
ReturnResult(FALSE);
return;
}
}
// Divine Focus check
// * Must have the correct alignment-orientated relic to power spells
if(!SMP_DivineFocusCheck(sName))
{
ReturnResult(FALSE);
return;
}
// Scroll casting
if(!SMP_SpellScrollCastingCheck(nSpellId, nSpellLevel, oSpellItem, nCasterClass, oCaster))
{
ReturnResult(FALSE);
return;
}
// Clerical divine domain spell Check
// * Make sure a cleric isn't trying to cast 2 domain spells for one level.
if(!SMP_DomainSpellCheck(nSpellId, oSpellItem, nCasterClass, oCaster))
{
ReturnResult(FALSE);
return;
}
// Check use magical device
// * Check UMD, if an item is being used to cast the spell with.
if(!SMP_UMDCheck(sName, nSpellLevel, nSpellId))
{
ReturnResult(FALSE);
return;
}
// Check breaking concentration incase normal hardcoded things where overriden
// * Concentration from other sources:
// - Entanglement
if(!SMP_BreakConcentrationCheck(nSpellLevel, oCaster))
{
// Failed: We do a special VFX to show it was concentration failure
SMP_ApplyVFX(oCaster, EffectVisualEffect(SMP_VFX_FNF_SPELL_FAIL_HAND));
ReturnResult(FALSE);
return;
}
// We cannot have a sorceror or bard casting a quickened spell - we did
// warn them its against the rules.
if((nCasterClass == CLASS_TYPE_BARD ||
nCasterClass == CLASS_TYPE_SORCERER) &&
GetMetaMagicFeat() == METAMAGIC_QUICKEN)
{
SendMessageToPC(oCaster, "You cannot use the quicken metamagic feat with a bard or sorceror spell");
ReturnResult(FALSE);
return;
}
// Wild magic area + Effects.
if(!SMP_WildMagicAreaSurge(oArea, oCaster))
{
ReturnResult(FALSE);
return;
}
// Crafting checks
if(SMP_CraftASpellOntoSomething(oCaster, nSpellId, nSpellLevel, nCasterClass, nCasterLevel, oTarget))
{
// Crafting checks are sucessful, stop the spell
ReturnResult(FALSE);
return;
}
// Spell components check.
if(!SMP_SpellComponentsHookCheck(oCaster, nSpellId))
{
// Return FALSE, it failed as we do not have the components.
ReturnResult(FALSE);
return;
}
// Make sure Blink doesn't stop the spell from working (if it is a
// single target spell!)
if(GetIsObjectValid(oTarget) && GetObjectType(oTarget) == OBJECT_TYPE_CREATURE)
{
// Blink check
if(!SMP_BlinkCheck(oTarget, oCaster))
{
// Stop if the roll fails.
ReturnResult(FALSE);
return;
}
}
// NEED:
// - Check for SEQUENCER ROBES!
// Can this be cast on an item? Bioware for now...
// if(Get2DAString("crafting 2da need this string completeing", "CastOnItems", GetSpellId()) != "1")
// {
// FloatingTextStrRefOnCreature(83453, OBJECT_SELF); // not cast spell on item
// ReturnResult(FALSE);
// return;
// }
// Return TRUE if we can cast the spell
ReturnResult(TRUE);
}
// This returns bResult
// * FALSE and stops the rest of the spell firing.
// * TRUE and the rest of the spell fires normally.
void ReturnResult(int bResult)
{
SMP_Debug("HOOK RESULT:" + IntToString(bResult));
// Return value
// FALSE - stops the spell
// TRUE - fires the spell normally
SetLocalInt(OBJECT_SELF, "SMP_SPELLHOOK_RETURN", bResult);
}