Further file organization
Further file organization
This commit is contained in:
280
nwn/nwnprc/trunk/include/shd_mysthook.nss
Normal file
280
nwn/nwnprc/trunk/include/shd_mysthook.nss
Normal file
@@ -0,0 +1,280 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Shadowcasting Mystery Hook File.
|
||||
//:: shd_mysthook.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
|
||||
This file acts as a hub for all code that
|
||||
is hooked into the mystery scripts for Shadowcasting
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Stratovarius
|
||||
//:: Created On: 7-2-2019
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "x2_inc_spellhook"
|
||||
#include "prc_inc_spells"
|
||||
#include "inc_utility"
|
||||
#include "prc_inc_itmrstr"
|
||||
|
||||
// This function holds all functions that are supposed to run before the actual
|
||||
// spellscript gets run. If this functions returns FALSE, the spell is aborted
|
||||
// and the spellscript will not run
|
||||
int ShadPreMystCastCode();
|
||||
|
||||
// Does the counterspelling for Warp Spell,
|
||||
// and the storing of the spell for later use
|
||||
int WarpMyst(object oCaster, int nMyst)
|
||||
{
|
||||
int nWarp = GetLocalInt(oCaster, "WarpSpell");
|
||||
// If Warp Spell isn't set, just keep going
|
||||
if (!nWarp) return TRUE;
|
||||
|
||||
object oShadow = GetLocalObject(oCaster, "WarpSpell"); // The one who cast Warp Spell
|
||||
|
||||
DeleteLocalInt(oCaster, "WarpSpell");
|
||||
DeleteLocalObject(oCaster, "WarpSpell");
|
||||
|
||||
int nLevel = GetShadowcasterLevel(oCaster);
|
||||
if (d20() + nWarp > d20() + nLevel) // Won the caster level check
|
||||
{
|
||||
// Set a marker on the Shadowcaster
|
||||
SetLocalInt(oShadow, "WarpSpellSuccess", TRUE);
|
||||
FloatingTextStringOnCreature("You have successfully warped your opponent's "+GetMysteryName(nMyst), oShadow, FALSE);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SOUL_TRAP), oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FloatingTextStringOnCreature("Your warp spell has failed", oShadow, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Stores the spell for use with Echo Spell
|
||||
void EchoMyst(object oCaster, int nMyst)
|
||||
{
|
||||
int nEcho = GetLocalInt(oCaster, "EchoSpell");
|
||||
// If Echo Spell isn't set, just skip
|
||||
if (nEcho)
|
||||
{
|
||||
object oShadow = GetLocalObject(oCaster, "EchoSpell"); // The one who cast Echo Spell
|
||||
SetLocalInt(oShadow, "EchoedSpell", nMyst);
|
||||
FloatingTextStringOnCreature("You have echoed " + GetMysteryName(nMyst) + " and have one round to cast it", oShadow, FALSE);
|
||||
DelayCommand(9.0, DeleteLocalInt(oShadow, "EchoedSpell"));
|
||||
DeleteLocalInt(oCaster, "EchoSpell");
|
||||
DeleteLocalObject(oCaster, "EchoSpell");
|
||||
}
|
||||
}
|
||||
|
||||
int MysterySpellFailure(object oShadow, int nMystId, int nMystLevel, int nClass)
|
||||
{
|
||||
// Mysteries of both types ignore arcane spell failure
|
||||
if (GetIsMysterySupernatural(oShadow, nMystId, nClass) || GetIsMysterySLA(oShadow, nMystId, nClass))
|
||||
return TRUE;
|
||||
|
||||
int nASF = GetArcaneSpellFailure(oShadow);
|
||||
|
||||
if(Random(100) < nASF)
|
||||
{
|
||||
int nFail = TRUE;
|
||||
// Still spell helps
|
||||
if((GetHasFeat(FEAT_EPIC_AUTOMATIC_STILL_SPELL_1, oShadow) && nMystLevel <= 3)
|
||||
|| (GetHasFeat(FEAT_EPIC_AUTOMATIC_STILL_SPELL_2, oShadow) && nMystLevel <= 6)
|
||||
|| (GetHasFeat(FEAT_EPIC_AUTOMATIC_STILL_SPELL_3, oShadow) && nMystLevel <= 9))
|
||||
{
|
||||
nFail = FALSE;
|
||||
}
|
||||
if(nFail)
|
||||
{
|
||||
//52946 = Spell failed due to arcane spell failure!
|
||||
FloatingTextStrRefOnCreature(52946, oShadow, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int ShadowTime(object oCaster, object oTarget, int bSpellIsHostile)
|
||||
{
|
||||
// PnP Timestop
|
||||
if(GetPRCSwitch(PRC_TIMESTOP_NO_HOSTILE))
|
||||
{
|
||||
if(GetHasSpellEffect(SPELL_TIME_STOP, oCaster)
|
||||
|| GetHasSpellEffect(4032, oCaster) //epic spell: Greater Timestop
|
||||
|| GetHasSpellEffect(14236, oCaster) //psionic power: Temporal Acceleration
|
||||
|| GetHasSpellEffect(18428, oCaster)) //Mystery MYST_SHADOW_TIME
|
||||
{
|
||||
if(!GetIsObjectValid(oTarget)
|
||||
|| oTarget != oCaster
|
||||
|| bSpellIsHostile)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// if FALSE is returned by this function, the spell will not be cast
|
||||
// the order in which the functions are called here DOES MATTER, changing it
|
||||
// WILL break the crafting subsystems
|
||||
//------------------------------------------------------------------------------
|
||||
int ShadPreMystCastCode()
|
||||
{
|
||||
object oShadow = OBJECT_SELF;
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
int nMystID = PRCGetSpellId();
|
||||
int nMystLevel = GetMysteryLevel(oShadow);
|
||||
int nShadowcastingClass = GetShadowcastingClass(oShadow);
|
||||
int bMystIsHostile = Get2DACache("spells", "HostileSetting", nMystID) == "1";
|
||||
|
||||
int nContinue = !ExecuteScriptAndReturnInt("prespellcode",oShadow);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Break any spell require maintaining concentration
|
||||
//---------------------------------------------------------------------------
|
||||
X2BreakConcentrationSpells();
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Check for PRC spell effects
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue)
|
||||
nContinue = PRCSpellEffects(oShadow, oTarget, nMystID, nMystLevel, nShadowcastingClass, bMystIsHostile, -1);
|
||||
|
||||
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #1: " + IntToString(nContinue));
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Run Arcane Spell Failure
|
||||
//---------------------------------------------------------------------------
|
||||
if (nContinue)
|
||||
nContinue = MysterySpellFailure(oShadow, nMystID, nMystLevel, nShadowcastingClass);
|
||||
|
||||
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #2: " + IntToString(nContinue));
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Run Shadow Time
|
||||
//---------------------------------------------------------------------------
|
||||
if (nContinue)
|
||||
nContinue = ShadowTime(oShadow, oTarget, bMystIsHostile);
|
||||
|
||||
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #3: " + IntToString(nContinue));
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Run Grappling Concentration Check
|
||||
//---------------------------------------------------------------------------
|
||||
if (nContinue)
|
||||
nContinue = GrappleConc(oShadow, nMystLevel);
|
||||
|
||||
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #4: " + IntToString(nContinue));
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// This stuff is only interesting for player characters we assume that use
|
||||
// magic device always works and NPCs don't use the crafting feats or
|
||||
// sequencers anyway. Thus, any NON PC spellcaster always exits this script
|
||||
// with TRUE (unless they are DM possessed or in the Wild Magic Area in
|
||||
// Chapter 2 of Hordes of the Underdark.
|
||||
//---------------------------------------------------------------------------
|
||||
if(!GetIsPC(oShadow)
|
||||
&& !GetPRCSwitch(PRC_NPC_HAS_PC_SPELLCASTING))
|
||||
{
|
||||
if(!GetIsDMPossessed(oShadow) && !GetLocalInt(GetArea(oShadow), "X2_L_WILD_MAGIC"))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Run use magic device skill check
|
||||
//---------------------------------------------------------------------------
|
||||
if (nContinue)
|
||||
{
|
||||
nContinue = X2UseMagicDeviceCheck(oShadow);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// run any user defined spellscript here
|
||||
//-----------------------------------------------------------------------
|
||||
if (nContinue)
|
||||
{
|
||||
nContinue = X2RunUserDefinedSpellScript();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Check for the new restricted itemproperties
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue
|
||||
&& GetIsObjectValid(GetSpellCastItem())
|
||||
&& !CheckPRCLimitations(GetSpellCastItem(), oShadow))
|
||||
{
|
||||
SendMessageToPC(oShadow, "You cannot use "+GetName(GetSpellCastItem()));
|
||||
nContinue = FALSE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Warp Spell
|
||||
//---------------------------------------------------------------------------
|
||||
if (nContinue)
|
||||
{
|
||||
nContinue = WarpMyst(oShadow, nMystID);
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #5: " + IntToString(nContinue));
|
||||
|
||||
EchoMyst(oShadow, nMystID);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// The following code is only of interest if an item was targeted
|
||||
//---------------------------------------------------------------------------
|
||||
if (GetIsObjectValid(oTarget) && GetObjectType(oTarget) == OBJECT_TYPE_ITEM)
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Check if spell was used to trigger item creation feat
|
||||
//-----------------------------------------------------------------------
|
||||
if (nContinue) {
|
||||
nContinue = !ExecuteScriptAndReturnInt("x2_pc_craft", oShadow);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// * Execute item OnSpellCast At routing script if activated
|
||||
//-----------------------------------------------------------------------
|
||||
if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS) == TRUE)
|
||||
{
|
||||
SetUserDefinedItemEventNumber(X2_ITEM_EVENT_SPELLCAST_AT);
|
||||
int nRet = ExecuteScriptAndReturnInt(GetUserDefinedItemEventScriptName(oTarget), oShadow);
|
||||
if (nRet == X2_EXECUTE_SCRIPT_END)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Prevent any spell that has no special coding to handle targetting of items
|
||||
// from being cast on items. We do this because we can not predict how
|
||||
// all the hundreds spells in NWN will react when cast on items
|
||||
//-----------------------------------------------------------------------
|
||||
if (nContinue) {
|
||||
nContinue = X2CastOnItemWasAllowed(oTarget);
|
||||
}
|
||||
}
|
||||
|
||||
//Cleaning spell variables used for holding the charge
|
||||
if(!GetLocalInt(oShadow, "PRC_SPELL_EVENT"))
|
||||
{
|
||||
DeleteLocalInt(oShadow, "PRC_SPELL_CHARGE_COUNT");
|
||||
DeleteLocalInt(oShadow, "PRC_SPELL_CHARGE_SPELLID");
|
||||
DeleteLocalObject(oShadow, "PRC_SPELL_CONC_TARGET");
|
||||
DeleteLocalInt(oShadow, "PRC_SPELL_METAMAGIC");
|
||||
DeleteLocalManifestation(oShadow, "PRC_POWER_HOLD_MANIFESTATION");
|
||||
DeleteLocalMystery(oShadow, "MYST_HOLD_MYST");
|
||||
}
|
||||
else if(GetLocalInt(oShadow, "PRC_SPELL_CHARGE_SPELLID") != PRCGetSpellId())
|
||||
{ //Sanity check, in case something goes wrong with the action queue
|
||||
DeleteLocalInt(oShadow, "PRC_SPELL_EVENT");
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #6: " + IntToString(nContinue));
|
||||
return nContinue;
|
||||
}
|
Reference in New Issue
Block a user