594 lines
25 KiB
Plaintext
594 lines
25 KiB
Plaintext
|
//::///////////////////////////////////////////////
|
||
|
//:: Shadowcasting main include: Miscellaneous
|
||
|
//:: shd_inc_shdfunc
|
||
|
//::///////////////////////////////////////////////
|
||
|
/** @file
|
||
|
Defines various functions and other stuff that
|
||
|
do something related to Shadowcasting.
|
||
|
|
||
|
Also acts as inclusion nexus for the general
|
||
|
shadowcasting includes. In other words, don't include
|
||
|
them directly in your scripts, instead include this.
|
||
|
|
||
|
@author Stratovarius
|
||
|
@date Created - 2019.02.08
|
||
|
*/
|
||
|
//:://////////////////////////////////////////////
|
||
|
//:://////////////////////////////////////////////
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
/* Function prototypes */
|
||
|
//////////////////////////////////////////////////
|
||
|
|
||
|
/**
|
||
|
* Determines from what class's mystery list the currently being shadowcast
|
||
|
* mystery is shadowcast from.
|
||
|
*
|
||
|
* @param oShadow A creature shadowcasting a mystery at this moment
|
||
|
* @return CLASS_TYPE_* constant of the class
|
||
|
*/
|
||
|
int GetShadowcastingClass(object oShadow = OBJECT_SELF);
|
||
|
|
||
|
/**
|
||
|
* Determines the given creature's Shadowcaster level. If a class is specified,
|
||
|
* then returns the Shadowcaster level for that class. Otherwise, returns
|
||
|
* the Shadowcaster level for the currently active mystery.
|
||
|
*
|
||
|
* @param oShadow The creature whose Shadowcaster level to determine
|
||
|
* @param nSpecificClass The class to determine the creature's Shadowcaster
|
||
|
* level in.
|
||
|
* DEFAULT: CLASS_TYPE_INVALID, which means the creature's
|
||
|
* Shadowcaster level in regards to an ongoing mystery
|
||
|
* is determined instead.
|
||
|
* @return The Shadowcaster level
|
||
|
*/
|
||
|
int GetShadowcasterLevel(object oShadow = OBJECT_SELF, int nSpecificClass = CLASS_TYPE_INVALID);
|
||
|
|
||
|
/**
|
||
|
* Determines whether a given creature uses ShadowMagic.
|
||
|
* Requires either levels in a ShadowMagic-related class or
|
||
|
* natural ShadowMagic ability based on race.
|
||
|
*
|
||
|
* @param oCreature Creature to test
|
||
|
* @return TRUE if the creature can use ShadowMagics, FALSE otherwise.
|
||
|
*/
|
||
|
int GetIsShadowMagicUser(object oCreature);
|
||
|
|
||
|
/**
|
||
|
* Determines the given creature's highest unmodified Shadowcaster level among its
|
||
|
* shadowcasting classes.
|
||
|
*
|
||
|
* @param oCreature Creature whose highest Shadowcaster level to determine
|
||
|
* @return The highest unmodified Shadowcaster level the creature can have
|
||
|
*/
|
||
|
int GetHighestShadowcasterLevel(object oCreature);
|
||
|
|
||
|
/**
|
||
|
* Determines whether a given class is a ShadowMagic-related class or not.
|
||
|
*
|
||
|
* @param nClass CLASS_TYPE_* of the class to test
|
||
|
* @return TRUE if the class is a ShadowMagic-related class, FALSE otherwise
|
||
|
*/
|
||
|
int GetIsShadowMagicClass(int nClass);
|
||
|
|
||
|
/**
|
||
|
* Gets the level of the mystery being currently shadowcast or the level
|
||
|
* of the mystery ID passed to it.
|
||
|
*
|
||
|
* @param oShadow The creature currently shadowcasting a mystery
|
||
|
* @return The level of the mystery being shadowcast
|
||
|
*/
|
||
|
int GetMysteryLevel(object oShadow, int nMystId = 0);
|
||
|
|
||
|
/**
|
||
|
* Returns the name of the Path
|
||
|
*
|
||
|
* @param nPath PATH_* to name
|
||
|
*/
|
||
|
string GetPathName(int nPath);
|
||
|
|
||
|
/**
|
||
|
* Returns the Path the mystery is in
|
||
|
* @param nMystId Mystery to check
|
||
|
*
|
||
|
* @return PATH_*
|
||
|
*/
|
||
|
int GetPathByMystery(int nMystId);
|
||
|
|
||
|
/**
|
||
|
* Returns true or false if the character has Path
|
||
|
* focus in the chosen path
|
||
|
* @param oShadow Person to check
|
||
|
* @param nPath Path to check
|
||
|
*
|
||
|
* @return TRUE or FALSE
|
||
|
*/
|
||
|
int GetHasPathFocus(object oShadow, int nPath);
|
||
|
|
||
|
/**
|
||
|
* Calculates how many shadowcaster levels are gained by a given creature from
|
||
|
* it's levels in prestige classes.
|
||
|
*
|
||
|
* @param oCreature Creature to calculate added shadowcaster levels for
|
||
|
* @return The number of shadowcaster levels gained
|
||
|
*/
|
||
|
int GetShadowMagicPRCLevels(object oShadow);
|
||
|
|
||
|
/**
|
||
|
* Determines which of the character's classes is their highest or first
|
||
|
* shadowcasting class, if any. This is the one which gains shadowcaster
|
||
|
* level raise benefits from prestige classes.
|
||
|
*
|
||
|
* @param oCreature Creature whose classes to test
|
||
|
* @return CLASS_TYPE_* of the first shadowcasting class,
|
||
|
* CLASS_TYPE_INVALID if the creature does not possess any.
|
||
|
*/
|
||
|
int GetPrimaryShadowMagicClass(object oCreature = OBJECT_SELF);
|
||
|
|
||
|
/**
|
||
|
* Determines the position of a creature's first shadowcasting class, if any.
|
||
|
*
|
||
|
* @param oCreature Creature whose classes to test
|
||
|
* @return The position of the first shadowcasting class {1, 2, 3} or 0 if
|
||
|
* the creature possesses no levels in shadowcasting classes.
|
||
|
*/
|
||
|
int GetFirstShadowMagicClassPosition(object oCreature = OBJECT_SELF);
|
||
|
|
||
|
/**
|
||
|
* Returns ability score needed to Shadowcast
|
||
|
* Type 1 is score to cast, Type 2 is score for DC
|
||
|
*
|
||
|
* @param nClass The class to check
|
||
|
* @return ABILITY_*
|
||
|
*/
|
||
|
int GetShadowAbilityOfClass(int nClass, int nType);
|
||
|
|
||
|
/**
|
||
|
* Calculates the DC of the Mystery being currently shadowcast.
|
||
|
*
|
||
|
* WARNING: Return value is not defined when a mystery isn't being shadowcast.
|
||
|
*
|
||
|
*/
|
||
|
int GetShadowcasterDC(object oShadow = OBJECT_SELF);
|
||
|
|
||
|
/**
|
||
|
* Calculates the SpellPen of the Mystery being currently shadowcast.
|
||
|
* Whether a Mystery is supernatural or not is checked in EvaluateMystery
|
||
|
*
|
||
|
* Currently just a placeholder returning GetShadowcasterLevel
|
||
|
*/
|
||
|
int ShadowSRPen(object oShadow, int nShadowcasterLevel);
|
||
|
|
||
|
/**
|
||
|
* Stores a mystery structure as a set of local variables. If
|
||
|
* a structure was already stored with the same name on the same object,
|
||
|
* it is overwritten.
|
||
|
*
|
||
|
* @param oObject The object on which to store the structure
|
||
|
* @param sName The name under which to store the structure
|
||
|
* @param myst The mystery structure to store
|
||
|
*/
|
||
|
void SetLocalMystery(object oObject, string sName, struct mystery myst);
|
||
|
|
||
|
/**
|
||
|
* Retrieves a previously stored mystery structure. If no structure is stored
|
||
|
* by the given name, the structure returned is empty.
|
||
|
*
|
||
|
* @param oObject The object from which to retrieve the structure
|
||
|
* @param sName The name under which the structure is stored
|
||
|
* @return The structure built from local variables stored on oObject under sName
|
||
|
*/
|
||
|
struct mystery GetLocalMystery(object oObject, string sName);
|
||
|
|
||
|
/**
|
||
|
* Returns the boost to caster level from feats
|
||
|
*
|
||
|
* @param oShadow The caster
|
||
|
* @param nMyst The mystery being cast
|
||
|
* @return Total bonus to caster level
|
||
|
*/
|
||
|
int ShadowcastingFeats(object oShadow, int nMyst);
|
||
|
|
||
|
/**
|
||
|
* Returns the boost to DC from nocturnal caster
|
||
|
*
|
||
|
* @param oShadow The caster
|
||
|
* @param nPath The path to check for
|
||
|
* @return Total bonus to caster level
|
||
|
*/
|
||
|
int GetHasNocturnal(object oShadow, int nPath);
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
/* Includes */
|
||
|
//////////////////////////////////////////////////
|
||
|
|
||
|
#include "prc_alterations"
|
||
|
#include "shd_inc_myst"
|
||
|
#include "shd_inc_mystknwn"
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
/* Internal functions */
|
||
|
//////////////////////////////////////////////////
|
||
|
|
||
|
//////////////////////////////////////////////////
|
||
|
/* Function definitions */
|
||
|
//////////////////////////////////////////////////
|
||
|
|
||
|
int GetShadowcastingClass(object oShadow = OBJECT_SELF)
|
||
|
{
|
||
|
int nReturn = GetLocalInt(oShadow, PRC_SHADOWCASTING_CLASS) - 1;
|
||
|
//if (DEBUG) FloatingTextStringOnCreature("GetShadowcastingClass: GetShadowcastingClass value is "+IntToString(nReturn), oShadow);
|
||
|
return nReturn;
|
||
|
}
|
||
|
|
||
|
int GetShadowcasterLevel(object oShadow = OBJECT_SELF, int nSpecificClass = CLASS_TYPE_INVALID)
|
||
|
{
|
||
|
int nAdjust = GetLocalInt(oShadow, PRC_CASTERLEVEL_ADJUSTMENT);
|
||
|
int nLevel = GetLocalInt(oShadow, PRC_CASTERLEVEL_OVERRIDE);
|
||
|
int nMyst = PRCGetSpellId(); // The fact that this will return 0 sometimes is relied upon
|
||
|
if (GetIsFundamental(nMyst)) nSpecificClass = CLASS_TYPE_SHADOWCASTER;
|
||
|
|
||
|
// For when you want to assign the caster level.
|
||
|
if(nLevel)
|
||
|
{
|
||
|
if(DEBUG) SendMessageToPC(oShadow, "GetShadowcasterLevel(): Forced-level shadowcasting at level " + IntToString(nLevel));
|
||
|
//DelayCommand(1.0, DeleteLocalInt(oShadow, PRC_CASTERLEVEL_OVERRIDE));
|
||
|
return nLevel + nAdjust;
|
||
|
}
|
||
|
|
||
|
if (DEBUG) FloatingTextStringOnCreature("GetShadowcasterLevel: "+GetName(oShadow)+" is a "+IntToString(nSpecificClass), oShadow);
|
||
|
// The function user needs to know the character's Shadowcaster level in a specific class
|
||
|
// instead of whatever the character last shadowcast a mystery as
|
||
|
if(nSpecificClass != CLASS_TYPE_INVALID)
|
||
|
{
|
||
|
//if (DEBUG) FloatingTextStringOnCreature("GetShadowcasterLevel: Class is Valid", oShadow);
|
||
|
if(GetIsShadowMagicClass(nSpecificClass))
|
||
|
{
|
||
|
//if (DEBUG) FloatingTextStringOnCreature("GetShadowcasterLevel: Class is Shadow Magic Class", oShadow);
|
||
|
// Shadowcaster level is class level + prestige
|
||
|
nLevel = GetLevelByClass(nSpecificClass, oShadow);
|
||
|
if(nLevel)
|
||
|
{
|
||
|
nLevel += GetShadowMagicPRCLevels(oShadow);
|
||
|
nLevel += ShadowcastingFeats(oShadow, nMyst);
|
||
|
if (GetLocalInt(oShadow, "CaptureMagic"))
|
||
|
{
|
||
|
nLevel += GetLocalInt(oShadow, "CaptureMagic");
|
||
|
DeleteLocalInt(oShadow, "CaptureMagic");
|
||
|
}
|
||
|
if (GetLocalInt(oShadow, "EldritchDisrupt"))
|
||
|
nLevel -= 4;
|
||
|
if (GetLocalInt(oShadow, "EldritchVortex"))
|
||
|
nLevel -= 4;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if(GetShadowcastingClass(oShadow) != -1)
|
||
|
{
|
||
|
//if (DEBUG) FloatingTextStringOnCreature("GetShadowcasterLevel: GetShadowcastingClass", oShadow);
|
||
|
nLevel = GetLevelByClass(GetShadowcastingClass(oShadow), oShadow);
|
||
|
//if (DEBUG) FloatingTextStringOnCreature("GetShadowcasterLevel: GetShadowcastingClass level "+IntToString(nLevel), oShadow);
|
||
|
nLevel += GetShadowMagicPRCLevels(oShadow);
|
||
|
//if (DEBUG) FloatingTextStringOnCreature("GetShadowcasterLevel: GetShadowcastingClass prestige level "+IntToString(nLevel), oShadow);
|
||
|
nLevel += ShadowcastingFeats(oShadow, nMyst);
|
||
|
//if (DEBUG) FloatingTextStringOnCreature("GetShadowcasterLevel: GetShadowcastingClass feat level "+IntToString(nLevel), oShadow);
|
||
|
if (GetLocalInt(oShadow, "CaptureMagic"))
|
||
|
{
|
||
|
nLevel += GetLocalInt(oShadow, "CaptureMagic");
|
||
|
DeleteLocalInt(oShadow, "CaptureMagic");
|
||
|
}
|
||
|
if (GetLocalInt(oShadow, "EldritchDisrupt"))
|
||
|
nLevel -= 4;
|
||
|
if (GetLocalInt(oShadow, "EldritchVortex"))
|
||
|
nLevel -= 4;
|
||
|
}
|
||
|
|
||
|
if(DEBUG) FloatingTextStringOnCreature("Shadowcaster Level: " + IntToString(nLevel), oShadow, FALSE);
|
||
|
|
||
|
return nLevel + nAdjust;
|
||
|
}
|
||
|
|
||
|
int GetIsShadowMagicUser(object oCreature)
|
||
|
{
|
||
|
return !!(GetLevelByClass(CLASS_TYPE_SHADOWCASTER, oCreature)
|
||
|
|| GetLevelByClass(CLASS_TYPE_SHADOWSMITH, oCreature));
|
||
|
}
|
||
|
|
||
|
int GetHighestShadowcasterLevel(object oCreature)
|
||
|
{
|
||
|
return max(max(GetClassByPosition(1, oCreature) != CLASS_TYPE_INVALID ? GetShadowcasterLevel(oCreature, GetClassByPosition(1, oCreature)) : 0,
|
||
|
GetClassByPosition(2, oCreature) != CLASS_TYPE_INVALID ? GetShadowcasterLevel(oCreature, GetClassByPosition(2, oCreature)) : 0
|
||
|
),
|
||
|
GetClassByPosition(3, oCreature) != CLASS_TYPE_INVALID ? GetShadowcasterLevel(oCreature, GetClassByPosition(3, oCreature)) : 0
|
||
|
);
|
||
|
}
|
||
|
|
||
|
int GetIsShadowMagicClass(int nClass)
|
||
|
{
|
||
|
return nClass == CLASS_TYPE_SHADOWCASTER
|
||
|
|| nClass == CLASS_TYPE_SHADOWSMITH;
|
||
|
}
|
||
|
|
||
|
int GetMysteryLevel(object oShadow, int nMystId = 0)
|
||
|
{
|
||
|
if (nMystId > 0) return StringToInt(lookup_spell_innate(nMystId));
|
||
|
int nLevel = GetLocalInt(oShadow, PRC_MYSTERY_LEVEL);
|
||
|
if (nLevel > 0) return nLevel;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
string GetPathName(int nPath)
|
||
|
{
|
||
|
int nStrRef;
|
||
|
switch(nPath)
|
||
|
{
|
||
|
/* case PATH_DESERT_WIND: nStrRef = 16829714; break;
|
||
|
case PATH_DEVOTED_SPIRIT: nStrRef = 16829715; break;
|
||
|
case PATH_DIAMOND_MIND: nStrRef = 16829716; break;
|
||
|
case PATH_IRON_HEART: nStrRef = 16829717; break;
|
||
|
case PATH_SETTING_SUN: nStrRef = 16829718; break;
|
||
|
case PATH_SHADOW_HAND: nStrRef = 16829719; break;
|
||
|
case PATH_STONE_DRAGON: nStrRef = 16829720; break;
|
||
|
case PATH_TIGER_CLAW: nStrRef = 16829721; break;
|
||
|
case PATH_WHITE_RAVEN: nStrRef = 16829722; break;*/
|
||
|
}
|
||
|
return GetStringByStrRef(nStrRef);
|
||
|
}
|
||
|
|
||
|
int GetPathByMystery(int nMystId)
|
||
|
{
|
||
|
// Shadowcaster has every mystery ever, so this is just the easy way out.
|
||
|
int i = GetPowerfileIndexFromRealSpellID(nMystId);
|
||
|
string sClass = GetAMSDefinitionFileName(CLASS_TYPE_SHADOWCASTER);
|
||
|
int nReturn = StringToInt(Get2DACache(sClass, "Path", i));
|
||
|
/*if (DEBUG) DoDebug("GetPathByMystery() i "+IntToString(i));
|
||
|
if (DEBUG) DoDebug("GetPathByMystery() sClass "+sClass);
|
||
|
if (DEBUG) DoDebug("GetPathByMystery() nReturn "+IntToString(nReturn)); */
|
||
|
|
||
|
return nReturn;
|
||
|
}
|
||
|
|
||
|
int GetShadowMagicPRCLevels(object oShadow)
|
||
|
{
|
||
|
int nLevel = GetLevelByClass(CLASS_TYPE_NOCTUMANCER, oShadow);
|
||
|
|
||
|
// These two don't add at 1st level
|
||
|
if (GetLevelByClass(CLASS_TYPE_CHILD_OF_NIGHT, oShadow))
|
||
|
nLevel += GetLevelByClass(CLASS_TYPE_CHILD_OF_NIGHT, oShadow) - 1;
|
||
|
if (GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oShadow))
|
||
|
nLevel += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oShadow) - 1;
|
||
|
|
||
|
return nLevel;
|
||
|
}
|
||
|
|
||
|
int GetPrimaryShadowMagicClass(object oCreature = OBJECT_SELF)
|
||
|
{
|
||
|
int nClass = CLASS_TYPE_INVALID;
|
||
|
|
||
|
if(GetPRCSwitch(PRC_CASTERLEVEL_FIRST_CLASS_RULE))
|
||
|
{
|
||
|
int nShadowMagicPos = GetFirstShadowMagicClassPosition(oCreature);
|
||
|
if (!nShadowMagicPos) return CLASS_TYPE_INVALID; // no Blade Magic shadowcasting class
|
||
|
|
||
|
nClass = GetClassByPosition(nShadowMagicPos, oCreature);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int nClassLvl;
|
||
|
int nClass1, nClass2, nClass3;
|
||
|
int nClass1Lvl, nClass2Lvl, nClass3Lvl;
|
||
|
|
||
|
nClass1 = GetClassByPosition(1, oCreature);
|
||
|
nClass2 = GetClassByPosition(2, oCreature);
|
||
|
nClass3 = GetClassByPosition(3, oCreature);
|
||
|
if(GetIsShadowMagicClass(nClass1)) nClass1Lvl = GetLevelByClass(nClass1, oCreature);
|
||
|
if(GetIsShadowMagicClass(nClass2)) nClass2Lvl = GetLevelByClass(nClass2, oCreature);
|
||
|
if(GetIsShadowMagicClass(nClass3)) nClass3Lvl = GetLevelByClass(nClass3, oCreature);
|
||
|
|
||
|
nClass = nClass1;
|
||
|
nClassLvl = nClass1Lvl;
|
||
|
if(nClass2Lvl > nClassLvl)
|
||
|
{
|
||
|
nClass = nClass2;
|
||
|
nClassLvl = nClass2Lvl;
|
||
|
}
|
||
|
if(nClass3Lvl > nClassLvl)
|
||
|
{
|
||
|
nClass = nClass3;
|
||
|
nClassLvl = nClass3Lvl;
|
||
|
}
|
||
|
if(nClassLvl == 0)
|
||
|
nClass = CLASS_TYPE_INVALID;
|
||
|
}
|
||
|
|
||
|
return nClass;
|
||
|
}
|
||
|
|
||
|
int GetFirstShadowMagicClassPosition(object oCreature = OBJECT_SELF)
|
||
|
{
|
||
|
if (GetIsShadowMagicClass(GetClassByPosition(1, oCreature)))
|
||
|
return 1;
|
||
|
if (GetIsShadowMagicClass(GetClassByPosition(2, oCreature)))
|
||
|
return 2;
|
||
|
if (GetIsShadowMagicClass(GetClassByPosition(3, oCreature)))
|
||
|
return 3;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int GetHasPathFocus(object oShadow, int nPath)
|
||
|
{
|
||
|
//if (DEBUG) DoDebug("GetHasPathFocus() nPath "+IntToString(nPath));
|
||
|
int nFocus, nGRFocus, nReturn;
|
||
|
switch(nPath)
|
||
|
{
|
||
|
case PATH_CLOAK_SHADOWS: nFocus = FEAT_PATH_FOCUS_CLOAK_SHADOWS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_CLOAK_SHADOWS ; break;
|
||
|
case PATH_DARK_TERRAIN: nFocus = FEAT_PATH_FOCUS_DARK_TERRAIN ; nGRFocus = FEAT_GREATER_PATH_FOCUS_DARK_TERRAIN ; break;
|
||
|
case PATH_EBON_WHISPERS: nFocus = FEAT_PATH_FOCUS_EBON_WHISPERS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_EBON_WHISPERS ; break;
|
||
|
case PATH_EYES_DARKNESS: nFocus = FEAT_PATH_FOCUS_EYES_DARKNESS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_EYES_DARKNESS ; break;
|
||
|
case PATH_SHUTTERS_CLOUDS: nFocus = FEAT_PATH_FOCUS_SHUTTERS_CLOUDS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_SHUTTERS_CLOUDS ; break;
|
||
|
case PATH_TOUCH_TWILIGHT: nFocus = FEAT_PATH_FOCUS_TOUCH_TWILIGHT ; nGRFocus = FEAT_GREATER_PATH_FOCUS_TOUCH_TWILIGHT ; break;
|
||
|
case PATH_UMBRAL_MIND: nFocus = FEAT_PATH_FOCUS_UMBRAL_MIND ; nGRFocus = FEAT_GREATER_PATH_FOCUS_UMBRAL_MIND ; break;
|
||
|
case PATH_BLACK_MAGIC: nFocus = FEAT_PATH_FOCUS_BLACK_MAGIC ; nGRFocus = FEAT_GREATER_PATH_FOCUS_BLACK_MAGIC ; break;
|
||
|
case PATH_BODY_SOUL: nFocus = FEAT_PATH_FOCUS_BODY_SOUL ; nGRFocus = FEAT_GREATER_PATH_FOCUS_BODY_SOUL ; break;
|
||
|
case PATH_DARK_REFLECTIONS: nFocus = FEAT_PATH_FOCUS_DARK_REFLECTIONS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_DARK_REFLECTIONS ; break;
|
||
|
case PATH_EBON_ROADS: nFocus = FEAT_PATH_FOCUS_EBON_ROADS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_EBON_ROADS ; break;
|
||
|
case PATH_ELEMENTAL_SHADOWS: nFocus = FEAT_PATH_FOCUS_ELEMENTAL_SHADOWS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_ELEMENTAL_SHADOWS ; break;
|
||
|
case PATH_UNBINDING_SHADE: nFocus = FEAT_PATH_FOCUS_UNBINDING_SHADE ; nGRFocus = FEAT_GREATER_PATH_FOCUS_UNBINDING_SHADE ; break;
|
||
|
case PATH_VEIL_SHADOWS: nFocus = FEAT_PATH_FOCUS_VEIL_SHADOWS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_VEIL_SHADOWS ; break;
|
||
|
case PATH_BREATH_TWILIGHT: nFocus = FEAT_PATH_FOCUS_BREATH_TWILIGHT ; nGRFocus = FEAT_GREATER_PATH_FOCUS_BREATH_TWILIGHT ; break;
|
||
|
case PATH_DARK_METAMORPHOSIS: nFocus = FEAT_PATH_FOCUS_DARK_METAMORPHOSIS; nGRFocus = FEAT_GREATER_PATH_FOCUS_DARK_METAMORPHOSIS; break;
|
||
|
case PATH_EBON_WALLS: nFocus = FEAT_PATH_FOCUS_EBON_WALLS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_EBON_WALLS ; break;
|
||
|
case PATH_EYES_NIGHT_SKY: nFocus = FEAT_PATH_FOCUS_EYES_NIGHT_SKY ; nGRFocus = FEAT_GREATER_PATH_FOCUS_EYES_NIGHT_SKY ; break;
|
||
|
case PATH_HEART_SOUL: nFocus = FEAT_PATH_FOCUS_HEART_SOUL ; nGRFocus = FEAT_GREATER_PATH_FOCUS_HEART_SOUL ; break;
|
||
|
case PATH_SHADOW_CALLING: nFocus = FEAT_PATH_FOCUS_SHADOW_CALLING ; nGRFocus = FEAT_GREATER_PATH_FOCUS_SHADOW_CALLING ; break;
|
||
|
case PATH_NIGHTS_LONG_FINGERS: nFocus = FEAT_PATH_FOCUS_NIGHTS_LONG_FINGERS; nGRFocus = FEAT_GREATER_PATH_FOCUS_NIGHTS_LONG_FINGERS; break;
|
||
|
case PATH_DARKENED_ALLEYS: nFocus = FEAT_PATH_FOCUS_DARKENED_ALLEYS ; nGRFocus = FEAT_GREATER_PATH_FOCUS_DARKENED_ALLEYS ; break;
|
||
|
case PATH_SHADOWSCAPE: nFocus = FEAT_PATH_FOCUS_SHADOWSCAPE ; nGRFocus = FEAT_GREATER_PATH_FOCUS_SHADOWSCAPE ; break;
|
||
|
}
|
||
|
if(GetHasFeat(nFocus, oShadow))
|
||
|
nReturn = 1;
|
||
|
if(GetHasFeat(nGRFocus, oShadow))
|
||
|
nReturn = 2;
|
||
|
|
||
|
//if (DEBUG) DoDebug("GetHasPathFocus() nReturn "+IntToString(nReturn));
|
||
|
|
||
|
// If none of those trigger.
|
||
|
return nReturn;
|
||
|
}
|
||
|
|
||
|
int GetShadowAbilityOfClass(int nClass, int nType)
|
||
|
{
|
||
|
if (nClass == CLASS_TYPE_SHADOWSMITH) return ABILITY_INTELLIGENCE;
|
||
|
// Intelligence for max mystery known
|
||
|
if (nClass == CLASS_TYPE_SHADOWCASTER && nType == 1) return ABILITY_INTELLIGENCE;
|
||
|
// Charisma for DC
|
||
|
if (nClass == CLASS_TYPE_SHADOWCASTER && nType == 2) return ABILITY_CHARISMA;
|
||
|
|
||
|
// Technically, never gets here but the compiler does not realise that
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int GetShadowcasterDC(object oShadow = OBJECT_SELF)
|
||
|
{
|
||
|
// Things we need for DC Checks
|
||
|
int nMystId = PRCGetSpellId();
|
||
|
int nShadEvo = GetLocalInt(oShadow, "ShadowEvoking");
|
||
|
if (nShadEvo > 0)
|
||
|
nMystId = nShadEvo; // This is used to get the proper DC for Shadow Evocation mysteries
|
||
|
|
||
|
int nLevel = GetMysteryLevel(oShadow, nMystId);
|
||
|
int nClass = GetShadowcastingClass(oShadow);
|
||
|
int nShadow = GetShadowcasterLevel(oShadow);
|
||
|
int nAbi = GetAbilityModifier(GetShadowAbilityOfClass(nClass, 2), oShadow);
|
||
|
int nPath = GetPathByMystery(nMystId);
|
||
|
int nPFocus = GetHasPathFocus(oShadow, nPath);
|
||
|
int nNoct = GetHasNocturnal(oShadow, nPath);
|
||
|
nShadow -= nPFocus; // These don't count here
|
||
|
|
||
|
// DC is 10 + Mystery level + ability
|
||
|
int nDC = 10 + nLevel + nAbi;
|
||
|
|
||
|
// If total Shadowcaster level is >= 13, change the DC for level 3 and under mysteries
|
||
|
// DC is 10 + 1/2 Shadowcaster level + ability
|
||
|
if (GetIsMysterySupernatural(oShadow, nMystId, nClass))
|
||
|
nDC = 10 + nShadow/2 + nAbi;
|
||
|
|
||
|
nDC += nPFocus;
|
||
|
nDC += nNoct;// It's a 0 if it doesn't exist
|
||
|
|
||
|
return nDC;
|
||
|
}
|
||
|
|
||
|
int ShadowSRPen(object oShadow, int nShadowcasterLevel)
|
||
|
{
|
||
|
return nShadowcasterLevel;
|
||
|
}
|
||
|
|
||
|
void SetLocalMystery(object oObject, string sName, struct mystery myst)
|
||
|
{
|
||
|
//SetLocal (oObject, sName + "_", );
|
||
|
SetLocalObject(oObject, sName + "_oShadow", myst.oShadow);
|
||
|
|
||
|
SetLocalInt(oObject, sName + "_bCanMyst", myst.bCanMyst);
|
||
|
SetLocalInt(oObject, sName + "_nShadowcasterLevel", myst.nShadowcasterLevel);
|
||
|
SetLocalInt(oObject, sName + "_nMystId", myst.nMystId);
|
||
|
SetLocalInt(oObject, sName + "_nPen", myst.nPen);
|
||
|
SetLocalInt(oObject, sName + "_bIgnoreSR", myst.bIgnoreSR);
|
||
|
|
||
|
SetLocalInt(oObject, sName + "_bEmpower", myst.bEmpower);
|
||
|
SetLocalInt(oObject, sName + "_bExtend", myst.bExtend);
|
||
|
SetLocalInt(oObject, sName + "_bMaximize", myst.bMaximize);
|
||
|
SetLocalInt(oObject, sName + "_bQuicken", myst.bQuicken);
|
||
|
|
||
|
SetLocalInt(oObject, sName + "_nSaveDC", myst.nSaveDC);
|
||
|
SetLocalFloat(oObject, sName + "_fDur", myst.fDur);
|
||
|
}
|
||
|
|
||
|
struct mystery GetLocalMystery(object oObject, string sName)
|
||
|
{
|
||
|
struct mystery myst;
|
||
|
myst.oShadow = GetLocalObject(oObject, sName + "_oShadow");
|
||
|
|
||
|
myst.bCanMyst = GetLocalInt(oObject, sName + "_bCanMyst");
|
||
|
myst.nShadowcasterLevel = GetLocalInt(oObject, sName + "_nShadowcasterLevel");
|
||
|
myst.nMystId = GetLocalInt(oObject, sName + "_nMystId");
|
||
|
myst.nPen = GetLocalInt(oObject, sName + "_nPen");
|
||
|
myst.bIgnoreSR = GetLocalInt(oObject, sName + "_bIgnoreSR");
|
||
|
|
||
|
myst.bEmpower = GetLocalInt(oObject, sName + "_bEmpower");
|
||
|
myst.bExtend = GetLocalInt(oObject, sName + "_bExtend");
|
||
|
myst.bMaximize = GetLocalInt(oObject, sName + "_bMaximize");
|
||
|
myst.bQuicken = GetLocalInt(oObject, sName + "_bQuicken");
|
||
|
|
||
|
myst.nSaveDC = GetLocalInt(oObject, sName + "_nSaveDC");
|
||
|
myst.fDur = GetLocalFloat(oObject, sName + "_fDur");
|
||
|
|
||
|
return myst;
|
||
|
}
|
||
|
|
||
|
int ShadowcastingFeats(object oShadow, int nMyst)
|
||
|
{
|
||
|
int nReturn = 0;
|
||
|
int nPath = GetPathByMystery(nMyst);
|
||
|
nReturn += GetHasPathFocus(oShadow, nPath);
|
||
|
|
||
|
return nReturn;
|
||
|
}
|
||
|
|
||
|
int GetHasNocturnal(object oShadow, int nPath)
|
||
|
{
|
||
|
int nNocturnal, nReturn;
|
||
|
switch(nPath)
|
||
|
{
|
||
|
case PATH_CLOAK_SHADOWS: nNocturnal = FEAT_NOCTURNAL_CASTER_CLOAK_SHADOWS ; break;
|
||
|
case PATH_DARK_TERRAIN: nNocturnal = FEAT_NOCTURNAL_CASTER_DARK_TERRAIN ; break;
|
||
|
case PATH_EBON_WHISPERS: nNocturnal = FEAT_NOCTURNAL_CASTER_EBON_WHISPERS ; break;
|
||
|
case PATH_EYES_DARKNESS: nNocturnal = FEAT_NOCTURNAL_CASTER_EYES_DARKNESS ; break;
|
||
|
case PATH_SHUTTERS_CLOUDS: nNocturnal = FEAT_NOCTURNAL_CASTER_SHUTTERS_CLOUDS ; break;
|
||
|
case PATH_TOUCH_TWILIGHT: nNocturnal = FEAT_NOCTURNAL_CASTER_TOUCH_TWILIGHT ; break;
|
||
|
case PATH_UMBRAL_MIND: nNocturnal = FEAT_NOCTURNAL_CASTER_UMBRAL_MIND ; break;
|
||
|
case PATH_BLACK_MAGIC: nNocturnal = FEAT_NOCTURNAL_CASTER_BLACK_MAGIC ; break;
|
||
|
case PATH_BODY_SOUL: nNocturnal = FEAT_NOCTURNAL_CASTER_BODY_SOUL ; break;
|
||
|
case PATH_DARK_REFLECTIONS: nNocturnal = FEAT_NOCTURNAL_CASTER_DARK_REFLECTIONS ; break;
|
||
|
case PATH_EBON_ROADS: nNocturnal = FEAT_NOCTURNAL_CASTER_EBON_ROADS ; break;
|
||
|
case PATH_ELEMENTAL_SHADOWS: nNocturnal = FEAT_NOCTURNAL_CASTER_ELEMENTAL_SHADOWS ; break;
|
||
|
case PATH_UNBINDING_SHADE: nNocturnal = FEAT_NOCTURNAL_CASTER_UNBINDING_SHADE ; break;
|
||
|
case PATH_VEIL_SHADOWS: nNocturnal = FEAT_NOCTURNAL_CASTER_VEIL_SHADOWS ; break;
|
||
|
case PATH_BREATH_TWILIGHT: nNocturnal = FEAT_NOCTURNAL_CASTER_BREATH_TWILIGHT ; break;
|
||
|
case PATH_DARK_METAMORPHOSIS: nNocturnal = FEAT_NOCTURNAL_CASTER_DARK_METAMORPHOSIS; break;
|
||
|
case PATH_EBON_WALLS: nNocturnal = FEAT_NOCTURNAL_CASTER_EBON_WALLS ; break;
|
||
|
case PATH_EYES_NIGHT_SKY: nNocturnal = FEAT_NOCTURNAL_CASTER_EYES_NIGHT_SKY ; break;
|
||
|
case PATH_HEART_SOUL: nNocturnal = FEAT_NOCTURNAL_CASTER_HEART_SOUL ; break;
|
||
|
case PATH_SHADOW_CALLING: nNocturnal = FEAT_NOCTURNAL_CASTER_SHADOW_CALLING ; break;
|
||
|
case PATH_NIGHTS_LONG_FINGERS:nNocturnal = FEAT_NOCTURNAL_CASTER_NIGHTS_LONG_FINGERS; break;
|
||
|
case PATH_DARKENED_ALLEYS: nNocturnal = FEAT_NOCTURNAL_CASTER_DARKENED_ALLEYS ; break;
|
||
|
case PATH_SHADOWSCAPE: nNocturnal = FEAT_NOCTURNAL_CASTER_SHADOWSCAPE ; break;
|
||
|
}
|
||
|
if(GetHasFeat(nNocturnal, oShadow) && GetIsNight())
|
||
|
nReturn = 1;
|
||
|
|
||
|
// If none of those trigger.
|
||
|
return nReturn;
|
||
|
}
|