generated from Jaysyn/ModuleTemplate
2025/12/23 Update
Hooked up new GUI module event. Updated PRC8 includes.
This commit is contained in:
@@ -36,18 +36,7 @@ string Get2DACache(string s2DA, string sColumn, int nRow)
|
||||
s2DA = GetStringLowerCase(s2DA);
|
||||
sColumn = GetStringLowerCase(sColumn);
|
||||
|
||||
string s = Get2DAString(s2DA, sColumn, nRow);
|
||||
return s == "****" ? "" : s;
|
||||
}
|
||||
|
||||
|
||||
/*string Get2DACache(string s2DA, string sColumn, int nRow)
|
||||
{
|
||||
//lower case the 2da and column
|
||||
s2DA = GetStringLowerCase(s2DA);
|
||||
sColumn = GetStringLowerCase(sColumn);
|
||||
|
||||
//get the chest that contains the cache
|
||||
/*//get the chest that contains the cache
|
||||
object oCacheWP = GetObjectByTag("Bioware2DACache");
|
||||
//if no chest, use HEARTOFCHAOS in limbo as a location to make a new one
|
||||
if (!GetIsObjectValid(oCacheWP))
|
||||
@@ -135,10 +124,10 @@ string Get2DACache(string s2DA, string sColumn, int nRow)
|
||||
(s == "" ? "****" : s) ); // this sets the stored string to "****" if s is an empty string (else stores s)
|
||||
if(DEBUG_GET2DACACHE) DoDebug("Get2DACache: Missing from cache: " + s2DA + "|" + sColumn + "|" + IntToString(nRow));
|
||||
}
|
||||
//if(DEBUG_GET2DACACHE) PrintString("Get2DACache: Returned value is '" + s + "'");
|
||||
//if(DEBUG_GET2DACACHE) PrintString("Get2DACache: Returned value is '" + s + "'");*/
|
||||
string s = Get2DAString(s2DA, sColumn, nRow);
|
||||
return s == "****" ? "" : s;
|
||||
}*/
|
||||
}
|
||||
|
||||
string GetBiowareDBName()
|
||||
{
|
||||
|
||||
@@ -18,100 +18,16 @@
|
||||
//////////////////////////////////////////////////
|
||||
/* Include section */
|
||||
//////////////////////////////////////////////////
|
||||
#include "utl_i_sqlocals"
|
||||
|
||||
#include "inc_2dacache"
|
||||
|
||||
|
||||
void PRC_BuildSpellIDIndex();
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function defintions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Build the SpellID ? RealSpellID index for all classes
|
||||
* Stores results directly in SQLite using utl_i_sqlocals.
|
||||
*/
|
||||
void PRC_BuildSpellIDIndex()
|
||||
{
|
||||
object oMod = GetModule();
|
||||
int nRow;
|
||||
int nFileEnd;
|
||||
string s2DA;
|
||||
string sSpellID, sRealSpellID;
|
||||
int nSpellID, nRealSpellID;
|
||||
|
||||
int nIndex = 0;
|
||||
while (nIndex <= 30)
|
||||
{
|
||||
switch(nIndex)
|
||||
{
|
||||
case 0: s2DA = "cls_psipw_psion"; break;
|
||||
case 1: s2DA = "cls_psipw_psywar"; break;
|
||||
case 2: s2DA = "cls_psipw_wilder"; break;
|
||||
case 3: s2DA = "cls_psipw_foz"; break;
|
||||
case 4: s2DA = "cls_psipw_warmnd"; break;
|
||||
case 5: s2DA = "cls_true_utter"; break;
|
||||
case 6: s2DA = "cls_move_crusdr"; break;
|
||||
case 7: s2DA = "cls_move_swdsge"; break;
|
||||
case 8: s2DA = "cls_move_warbld"; break;
|
||||
case 9: s2DA = "cls_inv_dfa"; break;
|
||||
case 10: s2DA = "cls_inv_drgshm"; break;
|
||||
case 11: s2DA = "cls_inv_warlok"; break;
|
||||
case 12: s2DA = "cls_spell_archv"; break;
|
||||
case 13: s2DA = "cls_spell_bard"; break;
|
||||
case 14: s2DA = "cls_spell_beguil"; break;
|
||||
case 15: s2DA = "cls_spell_dnecro"; break;
|
||||
case 16: s2DA = "cls_spell_duskbl"; break;
|
||||
case 17: s2DA = "cls_spell_favsol"; break;
|
||||
case 18: s2DA = "cls_spell_harper"; break;
|
||||
case 19: s2DA = "cls_spell_hexbl"; break;
|
||||
case 20: s2DA = "cls_spell_justww"; break;
|
||||
case 21: s2DA = "cls_spell_sorc"; break;
|
||||
case 22: s2DA = "cls_spell_schord"; break;
|
||||
case 23: s2DA = "cls_spell_suel"; break;
|
||||
case 24: s2DA = "cls_spell_vigil"; break;
|
||||
case 25: s2DA = "cls_spell_wrmage"; break;
|
||||
case 26: s2DA = "cls_spell_kngtwv"; break;
|
||||
case 27: s2DA = "cls_psipw_psyrog"; break;
|
||||
case 28: s2DA = "cls_myst_shdcst"; break;
|
||||
case 29: s2DA = "cls_myst_shdsmt"; break;
|
||||
case 30: s2DA = "cls_spell_sharss"; break;
|
||||
}
|
||||
|
||||
nRow = 0;
|
||||
nFileEnd = PRCGetDynamicFileEnd(s2DA);
|
||||
while (nRow < nFileEnd)
|
||||
{
|
||||
sSpellID = Get2DACache(s2DA, "SpellID", nRow);
|
||||
sRealSpellID = Get2DACache(s2DA, "RealSpellID", nRow);
|
||||
|
||||
if (sSpellID != "" && sSpellID != "****" && sRealSpellID != "" && sRealSpellID != "****")
|
||||
{
|
||||
nSpellID = StringToInt(sSpellID);
|
||||
nRealSpellID = StringToInt(sRealSpellID);
|
||||
string sKey = "PRC_GetRowFromSpellID_" + IntToString(nSpellID);
|
||||
SetLocalInt(oMod, sKey, nRealSpellID);
|
||||
|
||||
if(DEBUG) DoDebug("PRC_BuildSpellIDIndex: Adding SpellID " + sSpellID + " -> RealSpellID " + sRealSpellID);
|
||||
}
|
||||
|
||||
nRow++;
|
||||
}
|
||||
|
||||
nIndex++;
|
||||
}
|
||||
|
||||
if (DEBUG) DoDebug("PRC_BuildSpellIDIndex: SpellID -> RealSpellID index cached in SQLite.");
|
||||
}
|
||||
|
||||
void Cache_Done()
|
||||
{
|
||||
WriteTimestampedLogEntry("2da caching complete");
|
||||
|
||||
// Build the persistent SpellID ? Row index mapping
|
||||
PRC_BuildSpellIDIndex();
|
||||
}
|
||||
|
||||
void Cache_Class_Feat(int nClass, int nRow = 0)
|
||||
@@ -444,5 +360,3 @@ void Cache_2da_data()
|
||||
Cache_Appearance();
|
||||
}
|
||||
|
||||
//:: test void
|
||||
//:: void main (){}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
//PRC8 Token pre-fix = 161838
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Constant definitions */
|
||||
@@ -21,23 +22,23 @@ const int DYNCONV_EXITED = -2;
|
||||
const int DYNCONV_ABORTED = -3;
|
||||
const int DYNCONV_SETUP_STAGE = -1;
|
||||
|
||||
const int DYNCONV_TOKEN_HEADER = 99;
|
||||
const int DYNCONV_TOKEN_REPLY_0 = 100;
|
||||
const int DYNCONV_TOKEN_REPLY_1 = 101;
|
||||
const int DYNCONV_TOKEN_REPLY_2 = 102;
|
||||
const int DYNCONV_TOKEN_REPLY_3 = 103;
|
||||
const int DYNCONV_TOKEN_REPLY_4 = 104;
|
||||
const int DYNCONV_TOKEN_REPLY_5 = 105;
|
||||
const int DYNCONV_TOKEN_REPLY_6 = 106;
|
||||
const int DYNCONV_TOKEN_REPLY_7 = 107;
|
||||
const int DYNCONV_TOKEN_REPLY_8 = 108;
|
||||
const int DYNCONV_TOKEN_REPLY_9 = 109;
|
||||
const int DYNCONV_TOKEN_EXIT = 110;
|
||||
const int DYNCONV_TOKEN_WAIT = 111;
|
||||
const int DYNCONV_TOKEN_NEXT = 112;
|
||||
const int DYNCONV_TOKEN_PREV = 113;
|
||||
const int DYNCONV_MIN_TOKEN = 99;
|
||||
const int DYNCONV_MAX_TOKEN = 113;
|
||||
const int DYNCONV_TOKEN_HEADER = 16183899;
|
||||
const int DYNCONV_TOKEN_REPLY_0 = 161838100;
|
||||
const int DYNCONV_TOKEN_REPLY_1 = 161838101;
|
||||
const int DYNCONV_TOKEN_REPLY_2 = 161838102;
|
||||
const int DYNCONV_TOKEN_REPLY_3 = 161838103;
|
||||
const int DYNCONV_TOKEN_REPLY_4 = 161838104;
|
||||
const int DYNCONV_TOKEN_REPLY_5 = 161838105;
|
||||
const int DYNCONV_TOKEN_REPLY_6 = 161838106;
|
||||
const int DYNCONV_TOKEN_REPLY_7 = 161838107;
|
||||
const int DYNCONV_TOKEN_REPLY_8 = 161838108;
|
||||
const int DYNCONV_TOKEN_REPLY_9 = 161838109;
|
||||
const int DYNCONV_TOKEN_EXIT = 161838110;
|
||||
const int DYNCONV_TOKEN_WAIT = 161838111;
|
||||
const int DYNCONV_TOKEN_NEXT = 161838112;
|
||||
const int DYNCONV_TOKEN_PREV = 161838113;
|
||||
const int DYNCONV_MIN_TOKEN = 16183899;
|
||||
const int DYNCONV_MAX_TOKEN = 161838113;
|
||||
|
||||
const int DYNCONV_STRREF_PLEASE_WAIT = 16824202; // "Please wait"
|
||||
const int DYNCONV_STRREF_PREVIOUS = 16824203; // "Previous"
|
||||
@@ -477,9 +478,28 @@ void _DynConvInternal_ExitedConvo(object oPC, int bAbort)
|
||||
DeleteLocalInt(oPC, DYNCONV_STAGE);
|
||||
DeleteLocalString(oPC, DYNCONV_SCRIPT);
|
||||
DeleteLocalString(oPC, "DynConv_HeaderText");
|
||||
int i;
|
||||
for(i = DYNCONV_MIN_TOKEN; i <= DYNCONV_MAX_TOKEN; i++)
|
||||
DeleteLocalString(oPC, GetTokenIDString(i));
|
||||
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_HEADER));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_0));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_1));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_2));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_3));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_4));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_5));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_6));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_7));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_8));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_9));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_EXIT));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_WAIT));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_NEXT));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_PREV));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_MIN_TOKEN));
|
||||
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_MAX_TOKEN));
|
||||
|
||||
//int i;
|
||||
//for(i = DYNCONV_MIN_TOKEN; i <= DYNCONV_MAX_TOKEN; i++)
|
||||
//DeleteLocalString(oPC, GetTokenIDString(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ int GetSpellFromAbrev(string sAbrev);
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#include "inc_utility"
|
||||
//#include "inc_epicspelldef"
|
||||
#include "inc_epicspells"
|
||||
|
||||
// SEED FUNCTIONS
|
||||
|
||||
|
||||
@@ -303,11 +303,18 @@ int GetIsEpicShaman(object oPC)
|
||||
&& GetAbilityScore(oPC, ABILITY_WISDOM) > 18;
|
||||
}
|
||||
|
||||
int GetIsEpicSorcerer(object oPC)
|
||||
int GetIsEpicSorcerer(object oPC)
|
||||
{
|
||||
return GetHitDice(oPC) >= 21
|
||||
&& GetCasterLvl(CLASS_TYPE_SORCERER, oPC) > 17
|
||||
&& GetAbilityScore(oPC, ABILITY_CHARISMA) > 18;
|
||||
}
|
||||
|
||||
/* int GetIsEpicSorcerer(object oPC)
|
||||
{
|
||||
return GetPrCAdjustedCasterLevel(CLASS_TYPE_SORCERER, oPC, FALSE) > 17
|
||||
&& GetAbilityScore(oPC, ABILITY_CHARISMA) > 18;
|
||||
}
|
||||
} */
|
||||
|
||||
int GetIsEpicSublimeChord(object oPC)
|
||||
{
|
||||
|
||||
481
src/include/inc_infusion.nss
Normal file
481
src/include/inc_infusion.nss
Normal file
@@ -0,0 +1,481 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: ;-. ,-. ,-. ,-.
|
||||
//:: | ) | ) / ( )
|
||||
//:: |-' |-< | ;-:
|
||||
//:: | | \ \ ( )
|
||||
//:: ' ' ' `-' `-'
|
||||
//::///////////////////////////////////////////////
|
||||
//::
|
||||
/*
|
||||
Script: inc_infusion
|
||||
Author: Jaysyn
|
||||
Created: 2025-08-11 17:01:26
|
||||
|
||||
Description:
|
||||
Contains most functions related to the Create
|
||||
Infusion feat.
|
||||
|
||||
*/
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
#include "prc_inc_spells"
|
||||
|
||||
int GetMaxDivineSpellLevel(object oCaster, int nClass);
|
||||
int GetCastSpellCasterLevelFromItem(object oItem, int nSpellID);
|
||||
int GetIsClassSpell(object oCaster, int nSpellID, int nClass);
|
||||
int GetHasSpellOnClassList(object oCaster, int nSpellID);
|
||||
void InfusionSecondSave(object oUser, int nDC);
|
||||
|
||||
/**
|
||||
* @brief Finds the class index for which the given spell is available to the specified caster.
|
||||
*
|
||||
* This function iterates through all possible classes and returns the first class
|
||||
* index for which the specified spell is on the caster's spell list.
|
||||
*
|
||||
* @param oCaster The creature object to check.
|
||||
* @param nSpellID The spell ID to find the class for.
|
||||
*
|
||||
* @return The class index that has the spell on its class spell list for the caster,
|
||||
* or -1 if no matching class is found.
|
||||
*/
|
||||
int FindSpellCastingClass(object oCaster, int nSpellID)
|
||||
{
|
||||
int i = 0;
|
||||
int nClassFound = -1;
|
||||
int nClass;
|
||||
|
||||
// Only loop through caster's classes
|
||||
for (i = 0; i <= 8; i++)
|
||||
{
|
||||
nClass = GetClassByPosition(i, oCaster);
|
||||
if (nClass == CLASS_TYPE_INVALID) continue;
|
||||
|
||||
if (GetIsClassSpell(oCaster, nSpellID, nClass))
|
||||
{
|
||||
nClassFound = nClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nClassFound;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Performs validation checks to determine if the caster can use a spell infusion from the specified item.
|
||||
*
|
||||
* This function verifies that the item is a valid infused herb, checks the caster's relevant class and ability scores,
|
||||
* confirms the caster is a divine spellcaster with the necessary caster level, and ensures the spell is on the caster's class spell list.
|
||||
*
|
||||
* @param oCaster The creature attempting to use the infusion.
|
||||
* @param oItem The infused herb item containing the spell.
|
||||
* @param nSpellID The spell ID of the infusion spell being cast.
|
||||
*
|
||||
* @return TRUE if all infusion use checks pass and the caster can use the infusion; FALSE otherwise.
|
||||
*/
|
||||
int DoInfusionUseChecks(object oCaster, object oItem, int nSpellID)
|
||||
{
|
||||
int bPnPHerbs = GetPRCSwitch(PRC_CREATE_INFUSION_OPTIONAL_HERBS);
|
||||
|
||||
if(GetBaseItemType(oItem) != BASE_ITEM_INFUSED_HERB)
|
||||
{
|
||||
FloatingTextStringOnCreature("Not casting from an Infused Herb", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int nItemSpellLvl = GetCastSpellCasterLevelFromItem(oItem, nSpellID);
|
||||
if (bPnPHerbs && nItemSpellLvl == -1)
|
||||
{
|
||||
FloatingTextStringOnCreature("Item has no spellcaster level.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// **CRITICAL: Find the correct class that actually has the spell on its list**
|
||||
int nClassCaster = FindSpellCastingClass(oCaster, nSpellID);
|
||||
|
||||
if(DEBUG) DoDebug("nClassCaster is: " + IntToString(nClassCaster) + ".");
|
||||
|
||||
// Check for valid class
|
||||
if (nClassCaster == -1)
|
||||
{
|
||||
FloatingTextStringOnCreature("No valid class found for this spell.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(GetMaxDivineSpellLevel(oCaster, nClassCaster) < 1 )
|
||||
{
|
||||
FloatingTextStringOnCreature("You must be a divine spellcaster to activate an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must have spell on class list - (This will also double-check via the class)
|
||||
if (!GetHasSpellOnClassList(oCaster, nSpellID))
|
||||
{
|
||||
FloatingTextStringOnCreature("You must have a spell on one of your class spell lists to cast it from an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must meet ability requirement: Ability score >= 10 + spell level
|
||||
int nSpellLevel = PRCGetSpellLevelForClass(nSpellID, nClassCaster);
|
||||
int nClassAbility = GetAbilityScoreForClass(nClassCaster, oCaster);
|
||||
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nClassCaster is "+IntToString(nClassCaster)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: Class nSpellLevel is "+IntToString(nSpellLevel)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nClassAbility is "+IntToString(nClassAbility)+".");
|
||||
|
||||
if (nClassAbility < 10 + nSpellLevel)
|
||||
{
|
||||
FloatingTextStringOnCreature("You must meet ability score requirement to cast spell from infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must have a divine caster level at least equal to infusion's caster level
|
||||
int nDivineLvl = GetPrCAdjustedCasterLevelByType(TYPE_DIVINE, oCaster);
|
||||
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nDivineLvl is "+IntToString(nDivineLvl)+".");
|
||||
|
||||
if (nDivineLvl < nItemSpellLvl)
|
||||
{
|
||||
FloatingTextStringOnCreature("Your divine caster level is too low to cast this spell from an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* int DoInfusionUseChecks(object oCaster, object oItem, int nSpellID)
|
||||
{
|
||||
int bPnPHerbs = GetPRCSwitch(PRC_CREATE_INFUSION_OPTIONAL_HERBS);
|
||||
|
||||
if(GetBaseItemType(oItem) != BASE_ITEM_INFUSED_HERB)
|
||||
{
|
||||
FloatingTextStringOnCreature("Not casting from an Infused Herb", oCaster);
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
int nItemSpellLvl = GetCastSpellCasterLevelFromItem(oItem, nSpellID);
|
||||
if (bPnPHerbs && nItemSpellLvl == -1)
|
||||
{
|
||||
FloatingTextStringOnCreature("Item has no spellcaster level.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Find relevant class for the spell
|
||||
int nClassCaster = FindSpellCastingClass(oCaster, nSpellID);
|
||||
|
||||
if(DEBUG) DoDebug("nClassCaster is: "+IntToString(nClassCaster)+".");
|
||||
|
||||
if(GetMaxDivineSpellLevel(oCaster, nClassCaster) < 1 )
|
||||
{
|
||||
FloatingTextStringOnCreature("You must be a divine spellcaster to activate an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must have spell on class list
|
||||
if (!GetHasSpellOnClassList(oCaster, nSpellID))
|
||||
{
|
||||
FloatingTextStringOnCreature("You must have a spell on one of your class spell lists to cast it from an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must meet ability requirement: Ability score >= 10 + spell level
|
||||
int nSpellLevel = PRCGetSpellLevelForClass(nSpellID, nClassCaster);
|
||||
int nClassAbility = GetAbilityScoreForClass(nClassCaster, oCaster);
|
||||
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nClassCaster is "+IntToString(nClassCaster)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: Class nSpellLevel is "+IntToString(nSpellLevel)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nClassAbility is "+IntToString(nClassAbility)+".");
|
||||
|
||||
if (nClassAbility < 10 + nSpellLevel)
|
||||
{
|
||||
FloatingTextStringOnCreature("You must meet ability score requirement to cast spell from infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must have a divine caster level at least equal to infusion's caster level
|
||||
int nDivineLvl = GetPrCAdjustedCasterLevelByType(TYPE_DIVINE, oCaster);
|
||||
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nDivineLvl is "+IntToString(nDivineLvl)+".");
|
||||
|
||||
if (nDivineLvl < nItemSpellLvl)
|
||||
{
|
||||
FloatingTextStringOnCreature("Your divine caster level is too low to cast this spell from an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* @brief Retrieves the maximum divine spell level known by the caster for a given class.
|
||||
*
|
||||
* This function checks the caster's local integers named "PRC_DivSpell1" through "PRC_DivSpell9"
|
||||
* in descending order to determine the highest divine spell level available.
|
||||
* It returns the highest spell level for which the corresponding local int is false (zero).
|
||||
*
|
||||
* @param oCaster The creature whose divine spell levels are being checked.
|
||||
* @param nClass The class index for which to check the divine spell level (currently unused).
|
||||
*
|
||||
* @return The highest divine spell level known by the caster (1 to 9).
|
||||
*/
|
||||
int GetMaxDivineSpellLevel(object oCaster, int nClass)
|
||||
{
|
||||
int i = 9;
|
||||
for (i; i > 0; i--)
|
||||
{
|
||||
if(!GetLocalInt(oCaster, "PRC_DivSpell"+IntToString(i)))
|
||||
return i;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the spell school of an herb based on its resref by looking it up in the craft_infusion.2da file.
|
||||
*
|
||||
* This function searches the "craft_infusion" 2DA for a row matching the herb's resref.
|
||||
* If found, it returns the corresponding spell school as an integer constant.
|
||||
* If not found or the SpellSchool column is missing/invalid, it returns -1.
|
||||
*
|
||||
* @param oHerb The herb object to check.
|
||||
*
|
||||
* @return The spell school constant corresponding to the herb's infusion spell school,
|
||||
* or -1 if the herb is invalid, not found, or the data is missing.
|
||||
*/
|
||||
int GetHerbsSpellSchool(object oHerb)
|
||||
{
|
||||
if (!GetIsObjectValid(oHerb)) return -1;
|
||||
|
||||
string sResref = GetResRef(oHerb);
|
||||
int nRow = 0;
|
||||
string sRowResref;
|
||||
|
||||
while (nRow < 200)
|
||||
{
|
||||
sRowResref = Get2DACache("craft_infusion", "Resref", nRow);
|
||||
if (sRowResref == "") break;
|
||||
if (sRowResref == sResref)
|
||||
{
|
||||
string sHerbSpellSchool = Get2DAString("craft_infusion", "SpellSchool", nRow);
|
||||
|
||||
if (sHerbSpellSchool == "A") return SPELL_SCHOOL_ABJURATION;
|
||||
else if (sHerbSpellSchool == "C") return SPELL_SCHOOL_CONJURATION;
|
||||
else if (sHerbSpellSchool == "D") return SPELL_SCHOOL_DIVINATION;
|
||||
else if (sHerbSpellSchool == "E") return SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (sHerbSpellSchool == "V") return SPELL_SCHOOL_EVOCATION;
|
||||
else if (sHerbSpellSchool == "I") return SPELL_SCHOOL_ILLUSION;
|
||||
else if (sHerbSpellSchool == "N") return SPELL_SCHOOL_NECROMANCY;
|
||||
else if (sHerbSpellSchool == "T") return SPELL_SCHOOL_TRANSMUTATION;
|
||||
else return SPELL_SCHOOL_GENERAL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
nRow++;
|
||||
}
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the infusion spell level of an herb by matching its resref in the craft_infusion.2da file.
|
||||
*
|
||||
* This function searches the "craft_infusion" 2DA for a row matching the herb's resref.
|
||||
* If found, it returns the spell level from the SpellLevel column as an integer.
|
||||
* If not found or the column is missing, it returns -1.
|
||||
*
|
||||
* @param oHerb The herb object whose infusion spell level is to be retrieved.
|
||||
*
|
||||
* @return The spell level as an integer if found, or -1 if the herb is invalid, not found, or the column is missing.
|
||||
*/
|
||||
int GetHerbsInfusionSpellLevel(object oHerb)
|
||||
{
|
||||
if (!GetIsObjectValid(oHerb)) return -1;
|
||||
|
||||
string sResref = GetResRef(oHerb);
|
||||
int nRow = 0;
|
||||
string sRowResref;
|
||||
|
||||
// Brute-force loop <20> adjust limit if your 2DA has more than 500 rows
|
||||
while (nRow < 200)
|
||||
{
|
||||
sRowResref = Get2DACache("craft_infusion", "Resref", nRow);
|
||||
if (sRowResref == "") break; // End of valid rows
|
||||
if (sRowResref == sResref)
|
||||
{
|
||||
string sSpellLevelStr = Get2DAString("craft_infusion", "SpellLevel", nRow);
|
||||
return StringToInt(sSpellLevelStr);
|
||||
}
|
||||
nRow++;
|
||||
}
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the caster level of a specific cast-spell item property from an item.
|
||||
*
|
||||
* This function iterates through the item properties of the given item, searching for an
|
||||
* ITEM_PROPERTY_CAST_SPELL_CASTER_LEVEL property that matches the specified spell ID.
|
||||
* If found, it returns the caster level value stored in the item property.
|
||||
*
|
||||
* @param oItem The item object to check.
|
||||
* @param nSpellID The spell ID to match against the item property.
|
||||
*
|
||||
* @return The caster level associated with the matching cast-spell item property,
|
||||
* or -1 if no matching property is found.
|
||||
*/
|
||||
int GetCastSpellCasterLevelFromItem(object oItem, int nSpellID)
|
||||
{
|
||||
int nFoundCL = -1;
|
||||
|
||||
itemproperty ip = GetFirstItemProperty(oItem);
|
||||
while (GetIsItemPropertyValid(ip))
|
||||
{
|
||||
int nType = GetItemPropertyType(ip);
|
||||
|
||||
// First preference: PRC's CASTER_LEVEL itemprop
|
||||
if (nType == ITEM_PROPERTY_CAST_SPELL_CASTER_LEVEL)
|
||||
{
|
||||
int nSubType = GetItemPropertySubType(ip);
|
||||
string sSpellIDStr = Get2DAString("iprp_spells", "SpellIndex", nSubType);
|
||||
int nSubSpellID = StringToInt(sSpellIDStr);
|
||||
|
||||
if (nSubSpellID == nSpellID)
|
||||
{
|
||||
return GetItemPropertyCostTableValue(ip); // Found exact CL
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: vanilla CAST_SPELL property
|
||||
if (nType == ITEM_PROPERTY_CAST_SPELL && nFoundCL == -1)
|
||||
{
|
||||
int nSubType = GetItemPropertySubType(ip);
|
||||
string sSpellIDStr = Get2DAString("iprp_spells", "SpellIndex", nSubType);
|
||||
int nSubSpellID = StringToInt(sSpellIDStr);
|
||||
|
||||
if (nSubSpellID == nSpellID)
|
||||
{
|
||||
// Vanilla uses CostTableValue for *number of uses*, not CL,
|
||||
// so we<77>ll assume default caster level = spell level * 2 - 1
|
||||
int nSpellLevel = StringToInt(Get2DAString("spells", "Innate", nSubSpellID));
|
||||
nFoundCL = nSpellLevel * 2 - 1; // default NWN caster level rule
|
||||
}
|
||||
}
|
||||
|
||||
ip = GetNextItemProperty(oItem);
|
||||
}
|
||||
|
||||
return nFoundCL; // -1 if not found
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Checks if a given spell ID is present on the specified class's spell list for the caster.
|
||||
*
|
||||
* This function determines the spell level of the spell for the given class using PRCGetSpellLevelForClass.
|
||||
* If the spell level is -1, the spell is not on the class's spell list.
|
||||
* Otherwise, the spell is considered to be on the class spell list.
|
||||
*
|
||||
* @param oCaster The creature object casting or querying the spell.
|
||||
* @param nSpellID The spell ID to check.
|
||||
* @param nClass The class index to check the spell list against.
|
||||
*
|
||||
* @return TRUE if the spell is on the class's spell list; FALSE otherwise.
|
||||
*/
|
||||
int GetIsClassSpell(object oCaster, int nSpellID, int nClass)
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetIsClassSpell: nSpellID is: "+IntToString(nSpellID)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetIsClassSpell: nClass is: "+IntToString(nClass)+".");
|
||||
|
||||
int nSpellLevel = PRCGetSpellLevelForClass(nSpellID, nClass);
|
||||
if (nSpellLevel == -1)
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetIsClassSpell: SpellLevel is "+IntToString(nSpellLevel)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetIsClassSpell: Spell "+IntToString(nSpellID)+" is not in spelllist of "+IntToString(nClass)+".");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the caster has the specified spell on any of their class spell lists.
|
||||
*
|
||||
* This function iterates through all classes the caster has (up to position 8),
|
||||
* and returns TRUE if the spell is found on any class's spell list.
|
||||
*
|
||||
* @param oCaster The creature object to check.
|
||||
* @param nSpellID The spell ID to search for.
|
||||
*
|
||||
* @return TRUE if the spell is present on at least one of the caster's class spell lists;
|
||||
* FALSE otherwise.
|
||||
*/
|
||||
int GetHasSpellOnClassList(object oCaster, int nSpellID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= 8; i++)
|
||||
{
|
||||
int nClass = GetClassByPosition(i, oCaster);
|
||||
if (nClass == CLASS_TYPE_INVALID) continue;
|
||||
|
||||
if (GetIsClassSpell(oCaster, nSpellID, nClass))
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetHasSpellOnClassList: Class spell found.");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetHasSpellOnClassList: Class spell not found.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a poison nausea effect to the user when infusion use fails.
|
||||
*
|
||||
* This function performs an immediate Fortitude saving throw against poison DC based on infusion caster level.
|
||||
* If the user fails and is not immune to poison, an infusion nausea effect is applied, replacing any existing one.
|
||||
* A second saving throw is scheduled after 1 minute to attempt to remove the effect.
|
||||
*
|
||||
* @param oUser The creature who used the infusion and may be poisoned.
|
||||
* @param nInfusionCL The caster level of the infusion used, affecting the DC of the saving throw.
|
||||
*/
|
||||
void ApplyInfusionPoison(object oUser, int nInfusionCL)
|
||||
{
|
||||
int nDC = 10 + (nInfusionCL / 2);
|
||||
int bImmune = GetIsImmune(oUser, IMMUNITY_TYPE_POISON);
|
||||
|
||||
// First save immediately
|
||||
if (!bImmune && !PRCMySavingThrow(SAVING_THROW_FORT, oUser, nDC, SAVING_THROW_TYPE_POISON))
|
||||
{
|
||||
// Remove existing infusion poison nausea effect before applying new
|
||||
effect eOld = GetFirstEffect(oUser);
|
||||
while (GetIsEffectValid(eOld))
|
||||
{
|
||||
if (GetEffectTag(eOld) == "INFUSION_POISON_TAG")
|
||||
{
|
||||
RemoveEffect(oUser, eOld);
|
||||
break; // Assuming only one effect with this tag
|
||||
}
|
||||
eOld = GetNextEffect(oUser);
|
||||
}
|
||||
|
||||
effect eNausea = EffectNausea(oUser, 60.0f);
|
||||
|
||||
TagEffect(eNausea, "INFUSION_POISON_TAG");
|
||||
FloatingTextStringOnCreature("The infusion has made you nauseous.", oUser);
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eNausea, oUser, RoundsToSeconds(10));
|
||||
}
|
||||
|
||||
// Second save 1 minute later
|
||||
if (!bImmune)
|
||||
{
|
||||
DelayCommand(60.0, InfusionSecondSave(oUser, nDC));
|
||||
}
|
||||
}
|
||||
|
||||
void InfusionSecondSave(object oUser, int nDC)
|
||||
{
|
||||
if (!PRCMySavingThrow(SAVING_THROW_FORT, oUser, nDC, SAVING_THROW_TYPE_POISON))
|
||||
{
|
||||
FloatingTextStringOnCreature("The infusion has made you nauseous.", oUser);
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectNausea(oUser, 60.0f), oUser, RoundsToSeconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
//:: void main (){}
|
||||
@@ -1643,7 +1643,60 @@ int GetIsMagicItem(object oItem)
|
||||
int FeatToIprop(int nFeat)
|
||||
{
|
||||
switch(nFeat)
|
||||
{//: Weapon Focus
|
||||
{
|
||||
//:: Weapon Proficiencies
|
||||
case FEAT_WEAPON_PROFICIENCY_SHORTSWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SHORTSWORD;
|
||||
case FEAT_WEAPON_PROFICIENCY_LONGSWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LONGSWORD;
|
||||
case FEAT_WEAPON_PROFICIENCY_BATTLEAXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_BATTLEAXE;
|
||||
case FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD;
|
||||
case FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL;
|
||||
case FEAT_WEAPON_PROFICIENCY_WARHAMMER: return IP_CONST_FEAT_WEAPON_PROFICIENCY_WARHAMMER;
|
||||
case FEAT_WEAPON_PROFICIENCY_LONGBOW: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LONGBOW;
|
||||
case FEAT_WEAPON_PROFICIENCY_LIGHT_MACE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_MACE;
|
||||
case FEAT_WEAPON_PROFICIENCY_HALBERD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HALBERD;
|
||||
case FEAT_WEAPON_PROFICIENCY_SHORTBOW: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SHORTBOW;
|
||||
case FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD;
|
||||
case FEAT_WEAPON_PROFICIENCY_GREATSWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_GREATSWORD;
|
||||
case FEAT_WEAPON_PROFICIENCY_GREATAXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_GREATAXE;
|
||||
case FEAT_WEAPON_PROFICIENCY_DART: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DART;
|
||||
case FEAT_WEAPON_PROFICIENCY_DIRE_MACE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DIRE_MACE;
|
||||
case FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE;
|
||||
case FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL;
|
||||
case FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER;
|
||||
case FEAT_WEAPON_PROFICIENCY_HANDAXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HANDAXE;
|
||||
case FEAT_WEAPON_PROFICIENCY_KAMA: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KAMA;
|
||||
case FEAT_WEAPON_PROFICIENCY_KATANA: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KATANA;
|
||||
case FEAT_WEAPON_PROFICIENCY_KUKRI: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KUKRI;
|
||||
case FEAT_WEAPON_PROFICIENCY_MORNINGSTAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_MORNINGSTAR;
|
||||
case FEAT_WEAPON_PROFICIENCY_RAPIER: return IP_CONST_FEAT_WEAPON_PROFICIENCY_RAPIER;
|
||||
case FEAT_WEAPON_PROFICIENCY_SCIMITAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SCIMITAR;
|
||||
case FEAT_WEAPON_PROFICIENCY_SCYTHE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SCYTHE;
|
||||
case FEAT_WEAPON_PROFICIENCY_SHORTSPEAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SHORTSPEAR;
|
||||
case FEAT_WEAPON_PROFICIENCY_SHURIKEN: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SHURIKEN;
|
||||
case FEAT_WEAPON_PROFICIENCY_SICKLE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SICKLE;
|
||||
case FEAT_WEAPON_PROFICIENCY_SLING: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SLING;
|
||||
case FEAT_WEAPON_PROFICIENCY_THROWING_AXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_THROWING_AXE;
|
||||
case FEAT_WEAPON_PROFICIENCY_TRIDENT: return IP_CONST_FEAT_WEAPON_PROFICIENCY_TRIDENT;
|
||||
case FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE;
|
||||
case FEAT_WEAPON_PROFICIENCY_WHIP: return IP_CONST_FEAT_WEAPON_PROFICIENCY_WHIP;
|
||||
case FEAT_WEAPON_PROFICIENCY_ELVEN_LIGHTBLADE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_ELVEN_LIGHTBLADE;
|
||||
case FEAT_WEAPON_PROFICIENCY_ELVEN_THINBLADE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_ELVEN_THINBLADE;
|
||||
case FEAT_WEAPON_PROFICIENCY_ELVEN_COURTBLADE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_ELVEN_COURTBLADE;
|
||||
case FEAT_WEAPON_PROFICIENCY_LIGHT_LANCE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_LANCE;
|
||||
case FEAT_WEAPON_PROFICIENCY_HEAVY_PICK: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_PICK;
|
||||
case FEAT_WEAPON_PROFICIENCY_LIGHT_PICK: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_PICK;
|
||||
case FEAT_WEAPON_PROFICIENCY_SAI: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SAI;
|
||||
case FEAT_WEAPON_PROFICIENCY_NUNCHAKU: return IP_CONST_FEAT_WEAPON_PROFICIENCY_NUNCHAKU;
|
||||
case FEAT_WEAPON_PROFICIENCY_FALCHION: return IP_CONST_FEAT_WEAPON_PROFICIENCY_FALCHION;
|
||||
case FEAT_WEAPON_PROFICIENCY_SAP: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SAP;
|
||||
case FEAT_WEAPON_PROFICIENCY_KATAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KATAR;
|
||||
case FEAT_WEAPON_PROFICIENCY_HEAVY_MACE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_MACE;
|
||||
case FEAT_WEAPON_PROFICIENCY_MAUL: return IP_CONST_FEAT_WEAPON_PROFICIENCY_MAUL;
|
||||
case FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR;
|
||||
case FEAT_WEAPON_PROFICIENCY_GOAD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_GOAD;
|
||||
case FEAT_WEAPON_PROFICIENCY_EAGLE_CLAW: return IP_CONST_FEAT_WEAPON_PROFICIENCY_EAGLE_CLAW;
|
||||
|
||||
//: Weapon Focus
|
||||
case FEAT_WEAPON_FOCUS_BASTARD_SWORD: return IP_CONST_FEAT_WEAPON_FOCUS_BASTARD_SWORD;
|
||||
case FEAT_WEAPON_FOCUS_BATTLE_AXE: return IP_CONST_FEAT_WEAPON_FOCUS_BATTLE_AXE;
|
||||
case FEAT_WEAPON_FOCUS_CLUB: return IP_CONST_FEAT_WEAPON_FOCUS_CLUB;
|
||||
|
||||
@@ -104,81 +104,8 @@ string GetAMSDefinitionFileName(int nClass);
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
object _inc_lookups_GetCacheObject(string sTag)
|
||||
{
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Looking for waypoint with tag: " + sTag);
|
||||
object oWP = GetObjectByTag(sTag);
|
||||
if(GetIsObjectValid(oWP))
|
||||
{
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Found existing waypoint: " + sTag);
|
||||
return oWP;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Waypoint not found, creating new token...");
|
||||
|
||||
object oChest = GetObjectByTag("Bioware2DACache");
|
||||
if(!GetIsObjectValid(oChest))
|
||||
{
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Bioware2DACache object not found, creating near HEARTOFCHAOS...");
|
||||
oChest = CreateObject(OBJECT_TYPE_CREATURE, "prc_2da_cache",
|
||||
GetLocation(GetObjectByTag("HEARTOFCHAOS")), FALSE, "Bioware2DACache");
|
||||
}
|
||||
|
||||
if(!GetIsObjectValid(oChest))
|
||||
{
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Failed, creating Bioware2DACache at starting location...");
|
||||
oChest = CreateObject(OBJECT_TYPE_CREATURE, "prc_2da_cache",
|
||||
GetStartingLocation(), FALSE, "Bioware2DACache");
|
||||
}
|
||||
|
||||
if(!GetIsObjectValid(oChest))
|
||||
{
|
||||
DoDebug("_inc_lookups_GetCacheObject: ERROR - Could not create Bioware2DACache!");
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
int nContainer = 0;
|
||||
string sContainerName = "Bio2DACacheTokenContainer_Lkup_";
|
||||
object oContainer = GetObjectByTag(sContainerName + IntToString(nContainer));
|
||||
|
||||
if(GetIsObjectValid(oContainer))
|
||||
{
|
||||
nContainer = GetLocalInt(oContainer, "ContainerCount");
|
||||
oContainer = GetObjectByTag(sContainerName + IntToString(nContainer));
|
||||
if(GetLocalInt(oContainer, "NumTokensInside") >= 34)
|
||||
{
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Container full, creating new container...");
|
||||
oContainer = OBJECT_INVALID;
|
||||
++nContainer;
|
||||
}
|
||||
}
|
||||
|
||||
if(!GetIsObjectValid(oContainer))
|
||||
{
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Creating container: " + sContainerName + IntToString(nContainer));
|
||||
oContainer = CreateObject(OBJECT_TYPE_ITEM, "nw_it_contain001", GetLocation(oChest), FALSE, sContainerName + IntToString(nContainer));
|
||||
DestroyObject(oContainer);
|
||||
oContainer = CopyObject(oContainer, GetLocation(oChest), oChest, sContainerName + IntToString(nContainer));
|
||||
if(nContainer)
|
||||
SetLocalInt(GetObjectByTag(sContainerName + "0"), "ContainerCount", nContainer);
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Creating token: " + sTag);
|
||||
oWP = CreateItemOnObject("hidetoken", oContainer, 1, sTag);
|
||||
SetLocalInt(oContainer, "NumTokensInside", GetLocalInt(oContainer, "NumTokensInside") + 1);
|
||||
|
||||
if(!GetIsObjectValid(oWP))
|
||||
{
|
||||
DoDebug("_inc_lookups_GetCacheObject: ERROR - Failed to create lookup storage token for " + sTag);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("_inc_lookups_GetCacheObject: Successfully created token: " + sTag);
|
||||
return oWP;
|
||||
}
|
||||
|
||||
|
||||
/* object _inc_lookups_GetCacheObject(string sTag)
|
||||
{
|
||||
object oWP = GetObjectByTag(sTag);
|
||||
if(!GetIsObjectValid(oWP))
|
||||
@@ -244,7 +171,6 @@ object _inc_lookups_GetCacheObject(string sTag)
|
||||
|
||||
return oWP;
|
||||
}
|
||||
*/
|
||||
|
||||
void SetLkupStage(int nStage, object oModule, int nClass, string sFile)
|
||||
{
|
||||
@@ -316,25 +242,27 @@ void SetupLookupStage(object oMod, int n)
|
||||
case 11: SetLkupStage(n, oMod, CLASS_TYPE_DRAGON_SHAMAN, "cls_inv_drgshm"); break;
|
||||
case 12: SetLkupStage(n, oMod, CLASS_TYPE_WARLOCK, "cls_inv_warlok"); break;
|
||||
case 13: SetLkupStage(n, oMod, CLASS_TYPE_ARCHIVIST, "cls_spell_archv"); break;
|
||||
//case 14: SetLkupStage(n, oMod, CLASS_TYPE_ASSASSIN, "cls_spell_asasin"); break;
|
||||
case 15: SetLkupStage(n, oMod, CLASS_TYPE_BARD, "cls_spell_bard"); break;
|
||||
case 16: SetLkupStage(n, oMod, CLASS_TYPE_BEGUILER, "cls_spell_beguil"); break;
|
||||
case 17: SetLkupStage(n, oMod, CLASS_TYPE_DREAD_NECROMANCER, "cls_spell_dnecro"); break;
|
||||
case 18: SetLkupStage(n, oMod, CLASS_TYPE_DUSKBLADE, "cls_spell_duskbl"); break;
|
||||
case 19: SetLkupStage(n, oMod, CLASS_TYPE_FAVOURED_SOUL, "cls_spell_favsol"); break;
|
||||
case 20: SetLkupStage(n, oMod, CLASS_TYPE_HARPER, "cls_spell_harper"); break;
|
||||
case 21: SetLkupStage(n, oMod, CLASS_TYPE_HEXBLADE, "cls_spell_hexbl"); break;
|
||||
case 22: SetLkupStage(n, oMod, CLASS_TYPE_JUSTICEWW, "cls_spell_justww"); break;
|
||||
case 23: SetLkupStage(n, oMod, CLASS_TYPE_SORCERER, "cls_spell_sorc"); break;
|
||||
case 24: SetLkupStage(n, oMod, CLASS_TYPE_SUBLIME_CHORD, "cls_spell_schord"); break;
|
||||
case 25: SetLkupStage(n, oMod, CLASS_TYPE_SUEL_ARCHANAMACH, "cls_spell_suel"); break;
|
||||
case 26: SetLkupStage(n, oMod, CLASS_TYPE_VIGILANT, "cls_spell_vigil"); break;
|
||||
case 27: SetLkupStage(n, oMod, CLASS_TYPE_WARMAGE, "cls_spell_wrmage"); break;
|
||||
case 28: SetLkupStage(n, oMod, CLASS_TYPE_KNIGHT_WEAVE, "cls_spell_kngtwv"); break;
|
||||
case 29: SetLkupStage(n, oMod, CLASS_TYPE_PSYCHIC_ROGUE, "cls_psipw_psyrog"); break;
|
||||
case 30: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWCASTER, "cls_myst_shdcst"); break;
|
||||
case 31: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWSMITH, "cls_myst_shdsmt"); break;
|
||||
case 32: SetLkupStage(n, oMod, CLASS_TYPE_CELEBRANT_SHARESS, "cls_spell_sharss"); break;
|
||||
case 14: SetLkupStage(n, oMod, CLASS_TYPE_BARD, "cls_spell_bard"); break;
|
||||
case 15: SetLkupStage(n, oMod, CLASS_TYPE_BEGUILER, "cls_spell_beguil"); break;
|
||||
case 16: SetLkupStage(n, oMod, CLASS_TYPE_DREAD_NECROMANCER, "cls_spell_dnecro"); break;
|
||||
case 17: SetLkupStage(n, oMod, CLASS_TYPE_DUSKBLADE, "cls_spell_duskbl"); break;
|
||||
case 18: SetLkupStage(n, oMod, CLASS_TYPE_FAVOURED_SOUL, "cls_spell_favsol"); break;
|
||||
case 19: SetLkupStage(n, oMod, CLASS_TYPE_HARPER, "cls_spell_harper"); break;
|
||||
case 20: SetLkupStage(n, oMod, CLASS_TYPE_HEXBLADE, "cls_spell_hexbl"); break;
|
||||
case 21: SetLkupStage(n, oMod, CLASS_TYPE_JUSTICEWW, "cls_spell_justww"); break;
|
||||
case 22: SetLkupStage(n, oMod, CLASS_TYPE_SORCERER, "cls_spell_sorc"); break;
|
||||
case 23: SetLkupStage(n, oMod, CLASS_TYPE_SUBLIME_CHORD, "cls_spell_schord"); break;
|
||||
case 24: SetLkupStage(n, oMod, CLASS_TYPE_SUEL_ARCHANAMACH, "cls_spell_suel"); break;
|
||||
case 25: SetLkupStage(n, oMod, CLASS_TYPE_VIGILANT, "cls_spell_vigil"); break;
|
||||
case 26: SetLkupStage(n, oMod, CLASS_TYPE_WARMAGE, "cls_spell_wrmage"); break;
|
||||
case 27: SetLkupStage(n, oMod, CLASS_TYPE_KNIGHT_WEAVE, "cls_spell_kngtwv"); break;
|
||||
case 28: SetLkupStage(n, oMod, CLASS_TYPE_PSYCHIC_ROGUE, "cls_psipw_psyrog"); break;
|
||||
case 29: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWCASTER, "cls_myst_shdcst"); break;
|
||||
case 30: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWSMITH, "cls_myst_shdsmt"); break;
|
||||
case 31: SetLkupStage(n, oMod, CLASS_TYPE_CELEBRANT_SHARESS, "cls_spell_sharss"); break;
|
||||
|
||||
//:: These were all moved to the Bioware spellbooks -Jaysyn
|
||||
//case 14: SetLkupStage(n, oMod, CLASS_TYPE_ASSASSIN, "cls_spell_asasin"); break;
|
||||
//case 46: SetLkupStage(n, oMod, CLASS_TYPE_CULTIST_SHATTERED_PEAK, "cls_spell_cultst"); break;
|
||||
//case 40: SetLkupStage(n, oMod, CLASS_TYPE_NENTYAR_HUNTER, "cls_spell_hunter"); break;
|
||||
//case 28: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWLORD, "cls_spell_tfshad"); break;
|
||||
@@ -598,49 +526,13 @@ int GetClassFeatFromPower(int nPowerID, int nClass)
|
||||
|
||||
int SpellToSpellbookID(int nSpell)
|
||||
{
|
||||
// Fetch the lookup object
|
||||
object oWP = GetObjectByTag("PRC_GetRowFromSpellID");
|
||||
|
||||
// Sanity check for the object
|
||||
if(oWP == OBJECT_INVALID)
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_lookup >> SpellToSpellbookID: Lookup object PRC_GetRowFromSpellID is INVALID!");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_lookup >> SpellToSpellbookID: Object valid: TRUE");
|
||||
}
|
||||
|
||||
// Attempt to retrieve the local int for this spell
|
||||
string sKey = IntToString(nSpell);
|
||||
int nOutSpellID = GetLocalInt(oWP, sKey);
|
||||
|
||||
if(DEBUG) DoDebug("inc_lookup >> SpellToSpellbookID: Looking up key: " + sKey);
|
||||
if(DEBUG) DoDebug("inc_lookup >> SpellToSpellbookID: Retrieved value: " + IntToString(nOutSpellID));
|
||||
|
||||
// Handle missing values
|
||||
int nOutSpellID = GetLocalInt(oWP, /*"PRC_GetRowFromSpellID_" + */IntToString(nSpell));
|
||||
if(nOutSpellID == 0)
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_lookup >> SpellToSpellbookID: No value found for spell, returning -1");
|
||||
nOutSpellID = -1;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("inc_lookup >> SpellToSpellbookID: Final nOutSpellID: " + IntToString(nOutSpellID));
|
||||
|
||||
return nOutSpellID;
|
||||
}
|
||||
|
||||
|
||||
/* int SpellToSpellbookID(int nSpell)
|
||||
{
|
||||
object oWP = GetObjectByTag("PRC_GetRowFromSpellID");
|
||||
int nOutSpellID = GetLocalInt(oWP, /*"PRC_GetRowFromSpellID_" + *///IntToString(nSpell));
|
||||
/* if(nOutSpellID == 0)
|
||||
nOutSpellID = -1;
|
||||
if(DEBUG) DoDebug("inc_lookup >> SpellToSpellbookID: (nSpell: " + IntToString(nSpell) + ") = nOutSpellID: " + IntToString(nOutSpellID));
|
||||
return nOutSpellID;
|
||||
} */
|
||||
}
|
||||
|
||||
int RealSpellToSpellbookID(int nClass, int nSpell)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@ Add class to GetCasterLvl() in prc_inc_spells
|
||||
Add Practiced Spellcaster feat to feat.2da and to PracticedSpellcasting() in prc_inc_castlvl
|
||||
Run the assemble_spellbooks.bat file
|
||||
Make the prc_* scripts in newspellbook. The filenames can be found under the spell entries for the class in spells.2da.
|
||||
Update the fileends for all relevant files in inc_switch_setup
|
||||
Delete prc_data in the \database\ folder before testing new spells.
|
||||
|
||||
Spont:
|
||||
Make cls_spgn_*.2da
|
||||
@@ -41,6 +43,8 @@ Add class to prc_amagsys_gain if(CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, Mi
|
||||
Add class to ExecuteScript("prc_amagsys_gain", oPC) list in EvalPRCFeats in prc_inc_function
|
||||
Run the assemble_spellbooks.bat file
|
||||
Make the prc_* scripts in newspellbook
|
||||
Update the fileends for all relevant files in inc_switch_setup
|
||||
Delete prc_data in the \database\ folder before testing new spells.
|
||||
|
||||
prc_classes.2da entry:
|
||||
Label - name for the class
|
||||
@@ -104,11 +108,10 @@ void ProcessPreparedSpellLevel(object oPC, int nClass, int nSpellLevel, int nLev
|
||||
//#include "prc_effect_inc" //access via prc_inc_core
|
||||
//#include "inc_lookups" //access via prc_inc_core
|
||||
#include "prc_inc_core"
|
||||
#include "inc_sp_gain_mem" //providing child access to prc_inc_core
|
||||
//Must load in this order.
|
||||
#include "inc_sp_gain_mem"
|
||||
//#include "prc_inc_castlvl" //access via prc_inc_core
|
||||
//#include "prc_inc_descrptr" //access via prc_inc_core
|
||||
|
||||
#include "inc_item_props"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
@@ -1618,6 +1621,3 @@ void DoCleanUp(int nMetamagic)
|
||||
DeleteLocalInt(OBJECT_SELF, "NSB_SpellLevel");
|
||||
DeleteLocalInt(OBJECT_SELF, "NSB_SpellbookID");
|
||||
}
|
||||
|
||||
//:: Test Void
|
||||
//:: void main (){}
|
||||
@@ -7,8 +7,11 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
//:: Levels up an NPC according to variables set on NPC.
|
||||
void LevelUpSummon(object oSummon, int iTargetLvl);
|
||||
|
||||
// Get the master of oAssociate.
|
||||
object GetMasterNPC(object oAssociate=OBJECT_SELF);
|
||||
object GetMasterNPC(object oAssociate0 = OBJECT_SELF);
|
||||
|
||||
// Returns the associate type of the specified creature.
|
||||
// - Returns ASSOCIATE_TYPE_NONE if the creature is not the associate of anyone.
|
||||
@@ -75,7 +78,6 @@ void DestroySummon(object oSummon)
|
||||
DestroyObject(oSummon);
|
||||
}
|
||||
|
||||
|
||||
object CreateLocalNPC(object oMaster,int nAssociateType,string sTemplate,location loc,int Nth=1,string sTag="")
|
||||
{
|
||||
object oSummon=CreateObject(OBJECT_TYPE_CREATURE,sTemplate,loc,FALSE,sTag);
|
||||
@@ -111,7 +113,7 @@ object CreateLocalNextNPC(object oMaster,int nAssociateType,string sTemplate,loc
|
||||
SetLocalObject(oMaster, IntToString(nAssociateType)+"oHench"+IntToString(nCount), oSummon);
|
||||
SetLocalInt(oSummon, "iAssocNth", nCount);
|
||||
|
||||
SetAssociateState(NW_ASC_HAVE_MASTER,TRUE,oSummon);
|
||||
SetAssociateState(NW_ASC_HAVE_MASTER, TRUE, oSummon);
|
||||
SetAssociateState(NW_ASC_DISTANCE_2_METERS);
|
||||
SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE);
|
||||
SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE);
|
||||
@@ -122,6 +124,7 @@ object CreateLocalNextNPC(object oMaster,int nAssociateType,string sTemplate,loc
|
||||
return oSummon;
|
||||
|
||||
}
|
||||
|
||||
object GetMasterNPC(object oAssociate=OBJECT_SELF)
|
||||
{
|
||||
object oMaster = GetLocalObject(oAssociate, "oMaster");
|
||||
@@ -220,4 +223,173 @@ int GetAssociateHealMasterNPC()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Levels up a summoned creature based on its master's total casting level,
|
||||
* while respecting configured HD limits and multiclass transition rules.
|
||||
* Should only be called on the NPC onSpawn event.
|
||||
*
|
||||
* This function:
|
||||
* - Retrieves the master<65>s total casting level and clamps it to the creature<72>s
|
||||
* minimum and maximum HD (iMinHD, iMaxHD).
|
||||
* - Repeatedly calls LevelUpHenchman() until the creature reaches that level,
|
||||
* switching classes when the creature's stored "ClassXStart" thresholds are met.
|
||||
*
|
||||
* Local variables recognized on the summoned creature:
|
||||
*
|
||||
* | Variable Name | Purpose |
|
||||
* |-----------------|-------------------------------------------------------------|
|
||||
* | iMinHD | Minimum HD allowed |
|
||||
* | iMaxHD | Maximum HD allowed |
|
||||
* | Class2Start | Level to begin second class progression |
|
||||
* | Class2 | Class type for second progression |
|
||||
* | Class2Package | Package for second progression |
|
||||
* | Class3Start | Level to begin third class progression |
|
||||
* | Class3 | Class type for third progression |
|
||||
* | Class3Package | Package for third progression |
|
||||
* | Class4Start | Level to begin fourth class progression |
|
||||
* | Class4 | Class type for fourth progression |
|
||||
* | Class4Package | Package for fourth progression |
|
||||
*
|
||||
* Behavior notes:
|
||||
* - Leveling continues until the creature reaches the master<65>s effective
|
||||
* casting level (bounded by iMinHD/iMaxHD).
|
||||
* - If LevelUpHenchman() returns 0, the creature shouts a failure message.
|
||||
* - CLASS_TYPE_INVALID causes the creature to level in its current class.
|
||||
*
|
||||
* @param oCreature The summoned creature being leveled. Defaults to OBJECT_SELF.
|
||||
*
|
||||
* @see LevelUpHenchman
|
||||
* @see GetLocalInt
|
||||
* @see GetHitDice
|
||||
*/
|
||||
void LevelUpSummon(object oSummon, int iTargetLvl)
|
||||
{
|
||||
int nCurrentHD = GetHitDice(oSummon);
|
||||
int iNewHD = nCurrentHD;
|
||||
|
||||
// Read multiclassing info from locals
|
||||
int iClass2Start = GetLocalInt(oSummon, "Class2Start");
|
||||
int iClass2 = GetLocalInt(oSummon, "Class2");
|
||||
int iClass2Package = GetLocalInt(oSummon, "Class2Package");
|
||||
|
||||
int iClass3Start = GetLocalInt(oSummon, "Class3Start");
|
||||
int iClass3 = GetLocalInt(oSummon, "Class3");
|
||||
int iClass3Package = GetLocalInt(oSummon, "Class3Package");
|
||||
|
||||
int iClass4Start = GetLocalInt(oSummon, "Class4Start");
|
||||
int iClass4 = GetLocalInt(oSummon, "Class4");
|
||||
int iClass4Package = GetLocalInt(oSummon, "Class4Package");
|
||||
|
||||
int iClass; // current class to level
|
||||
int iPackage; // package to use
|
||||
|
||||
// Main leveling loop
|
||||
while (nCurrentHD < iTargetLvl && nCurrentHD > 0)
|
||||
{
|
||||
// Determine which class and package to use
|
||||
if (iClass4Start != 0 && nCurrentHD >= iClass4Start)
|
||||
{
|
||||
iClass = iClass4;
|
||||
iPackage = iClass4Package;
|
||||
}
|
||||
else if (iClass3Start != 0 && nCurrentHD >= iClass3Start)
|
||||
{
|
||||
iClass = iClass3;
|
||||
iPackage = iClass3Package;
|
||||
}
|
||||
else if (iClass2Start != 0 && nCurrentHD >= iClass2Start)
|
||||
{
|
||||
iClass = iClass2;
|
||||
iPackage = iClass2Package;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Base class (first class in the sheet)
|
||||
iClass = CLASS_TYPE_INVALID; // keeps current
|
||||
iPackage = PACKAGE_INVALID;
|
||||
}
|
||||
|
||||
// Level up one HD
|
||||
iNewHD = LevelUpHenchman(oSummon, iClass, TRUE, iPackage);
|
||||
|
||||
if (iNewHD == 0)
|
||||
{
|
||||
SpeakString(GetName(oSummon) + " failed to level properly!", TALKVOLUME_SHOUT);
|
||||
break;
|
||||
}
|
||||
|
||||
nCurrentHD = iNewHD;
|
||||
}
|
||||
|
||||
// Force the creature to rest to memorize spells
|
||||
// PRCForceRest(oSummon);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* void LevelUpSummon(object oSummon, int iTargetLvl)
|
||||
{
|
||||
//get the default hit dice of the summon
|
||||
int nDefaultHD = GetHitDice(oSummon);
|
||||
|
||||
if (DEBUG) DoDebug("inc_npc >> LevelUpSummon: nDefaultHD = " +IntToString(nDefaultHD)+".");
|
||||
|
||||
if (DEBUG) DoDebug("inc_npc >> LevelUpSummon: iTargetLvl = " +IntToString(iTargetLvl)+".");
|
||||
|
||||
//get the multiclassing variables to see if we need to change classes from its base class
|
||||
int iClass2Start = GetLocalInt(oSummon, "Class2Start");
|
||||
int iClass2 = GetLocalInt(oSummon, "Class2");
|
||||
int iClass2Package = GetLocalInt(oSummon, "Class2Package");
|
||||
|
||||
int iClass3Start = GetLocalInt(oSummon, "Class3Start");
|
||||
int iClass3 = GetLocalInt(oSummon, "Class3");
|
||||
int iClass3Package = GetLocalInt(oSummon, "Class3Package");
|
||||
|
||||
int iClass4Start = GetLocalInt(oSummon, "Class4Start");
|
||||
int iClass4 = GetLocalInt(oSummon, "Class4");
|
||||
int iClass4Package = GetLocalInt(oSummon, "Class4Package");
|
||||
|
||||
//check for zero cause thats an error
|
||||
//if creatures are not leveling then best bet is they are not legal creatures
|
||||
while( (nDefaultHD < iTargetLvl) && (nDefaultHD > 0) )
|
||||
{
|
||||
//check the multiclassing numbers to change classes
|
||||
if( (iClass4Start != 0) && (nDefaultHD >= iClass4Start) )
|
||||
{
|
||||
//level up using the new class and Packageage
|
||||
nDefaultHD = LevelUpHenchman(oSummon, iClass4 ,TRUE, iClass4Package);
|
||||
|
||||
if(nDefaultHD == 0)
|
||||
SpeakString(GetName(oSummon) + " Failed on fourth class", TALKVOLUME_SHOUT);
|
||||
}
|
||||
else if( (iClass3Start != 0) && (nDefaultHD >= iClass3Start) )
|
||||
{
|
||||
//level up using the new class and Packageage
|
||||
nDefaultHD = LevelUpHenchman(oSummon, iClass3 ,TRUE, iClass3Package);
|
||||
|
||||
if(nDefaultHD == 0)
|
||||
SpeakString(GetName(oSummon) + " Failed on third class", TALKVOLUME_SHOUT);
|
||||
}
|
||||
else if( (iClass2Start != 0) && (nDefaultHD >= iClass2Start) )
|
||||
{
|
||||
//level up using the new class and Packageage
|
||||
nDefaultHD = LevelUpHenchman(oSummon, iClass2 ,TRUE, iClass2Package);
|
||||
|
||||
if(nDefaultHD == 0)
|
||||
SpeakString(GetName(oSummon) + " Failed on second class", TALKVOLUME_SHOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
//just level up using the class it already has
|
||||
nDefaultHD = LevelUpHenchman(oSummon, CLASS_TYPE_INVALID ,TRUE);
|
||||
|
||||
if(nDefaultHD == 0)
|
||||
SpeakString(GetName(oSummon) + " Failed to level properly", TALKVOLUME_SHOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
//:: void main() {}
|
||||
@@ -3433,6 +3433,7 @@ int PrimoGetWeaponSize(object oItem)
|
||||
case BASE_ITEM_LIGHTFLAIL:
|
||||
case BASE_ITEM_KATANA:
|
||||
case BASE_ITEM_MAGICSTAFF:
|
||||
case BASE_ITEM_CRAFTED_SCEPTER:
|
||||
case BASE_ITEM_LONGSWORD:
|
||||
case BASE_ITEM_TRIDENT:
|
||||
case BASE_ITEM_MORNINGSTAR:
|
||||
|
||||
@@ -30,6 +30,7 @@ int GetDamageFromConstant(int nIPConst);
|
||||
void DoFrostRend(object oTarget, object oAttacker, object oWeapon);
|
||||
|
||||
#include "moi_inc_moifunc"
|
||||
#include "prc_inc_combat"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function defintions */
|
||||
|
||||
@@ -17,9 +17,6 @@ Created: May 1, 2008
|
||||
|
||||
//:: Updated for .35 by Jaysyn 2023/03/11
|
||||
|
||||
//:: Test Void
|
||||
//void main (){}
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Constants
|
||||
//:://////////////////////////////////////////////
|
||||
@@ -63,6 +60,14 @@ string GetMetaMagicString(int nMetaMagic);
|
||||
int GetMetaMagicFromFeat(int nFeat);
|
||||
int GetMetaMagicOfCaster(object oPC = OBJECT_SELF);
|
||||
|
||||
string GetFileForClass(int nClass);
|
||||
int GetSpellslotLevel(int nClass, object oPC);
|
||||
int GetSpellKnownMaxCount(int nLevel, int nSpellLevel, int nClass, object oPC);
|
||||
int GetSpellbookTypeForClass(int nClass);
|
||||
|
||||
#include "inc_pers_array"
|
||||
#include "inc_2dacache"
|
||||
|
||||
// name of the new spellbook file (cls_spell_*)
|
||||
string GetNSBDefinitionFileName(int nClass)
|
||||
{
|
||||
|
||||
@@ -44,6 +44,7 @@ void CreateSwitchNameArray();
|
||||
|
||||
#include "prc_inc_array" // Needs direct include instead of inc_utility
|
||||
#include "prc_inc_switch"
|
||||
#include "inc_2dacache"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
@@ -221,9 +222,9 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_bard", 144);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_beguil", 142);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_blkgrd", 47);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_dnecro", 137);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_dnecro", 138);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_duskbl", 69);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_favsol", 290);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_favsol", 300);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_harper", 35);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_healer", 77);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spcr_hexbl", 73);
|
||||
@@ -251,9 +252,9 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_bard", 169);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_beguil", 119);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_blkgrd", 163);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_dnecro", 134);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_dnecro", 135);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_duskbl", 84);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_favsol", 363);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_favsol", 373);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_harper", 21);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_healer", 271);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_hexbl", 79);
|
||||
@@ -267,7 +268,7 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_sod", 110);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_sohei", 131);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_sol", 114);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_sorc", 541);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_sorc", 550);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_suel", 160);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_templ", 95);
|
||||
SetPRCSwitch("PRC_FILE_END_cls_spell_tfshad", 70);
|
||||
@@ -335,7 +336,7 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_craft_golem", 40);
|
||||
SetPRCSwitch("PRC_FILE_END_craft_ring", 41);
|
||||
SetPRCSwitch("PRC_FILE_END_craft_weapon", 46);
|
||||
SetPRCSwitch("PRC_FILE_END_craft_wondrous", 115);
|
||||
SetPRCSwitch("PRC_FILE_END_craft_wondrous", 131);
|
||||
SetPRCSwitch("PRC_FILE_END_creaturesize", 5);
|
||||
SetPRCSwitch("PRC_FILE_END_creaturespeed", 8);
|
||||
SetPRCSwitch("PRC_FILE_END_crtemplates", 10);
|
||||
@@ -355,7 +356,7 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_des_crft_poison", 100);
|
||||
SetPRCSwitch("PRC_FILE_END_des_crft_props", 27);
|
||||
SetPRCSwitch("PRC_FILE_END_des_crft_scroll", 3999);
|
||||
SetPRCSwitch("PRC_FILE_END_des_crft_spells", 19348);
|
||||
SetPRCSwitch("PRC_FILE_END_des_crft_spells", 20000);
|
||||
SetPRCSwitch("PRC_FILE_END_des_crft_weapon", 29);
|
||||
SetPRCSwitch("PRC_FILE_END_des_cutconvdur", 26);
|
||||
SetPRCSwitch("PRC_FILE_END_des_feat2item", 1000);
|
||||
@@ -408,7 +409,7 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_ammocost", 15);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_ammotype", 2);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_amount", 4);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_aoe", 7);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_aoe", 8);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_arcspell", 19);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_base1", -1);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_bladecost", 5);
|
||||
@@ -423,15 +424,15 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_damvulcost", 7);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_decvalue1", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_decvalue2", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_feats", 24819);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_feats", 26999);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_immuncost", 7);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_immunity", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_incvalue1", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_incvalue2", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_kitcost", 50);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_lightcost", 4);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_matcost", 77);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_material", 77);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_matcost", 145);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_material", 145);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_maxpp", 8);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_meleecost", 20);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_metamagic", 6);
|
||||
@@ -458,11 +459,11 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_soakcost", 50);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_speed_dec", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_speed_enh", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_spellcost", 243);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_spellcost", 298);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_spellcstr", 42);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_spelllvcost", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_spelllvlimm", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_spells", 1456);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_spells", 1552);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_spellshl", 7);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_srcost", 99);
|
||||
SetPRCSwitch("PRC_FILE_END_iprp_staminacost", -1);
|
||||
@@ -492,9 +493,9 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_itmwizwands", 38);
|
||||
SetPRCSwitch("PRC_FILE_END_keymap", 70);
|
||||
SetPRCSwitch("PRC_FILE_END_lightcolor", 32);
|
||||
SetPRCSwitch("PRC_FILE_END_loadhints", 88);
|
||||
SetPRCSwitch("PRC_FILE_END_loadhints", 101);
|
||||
SetPRCSwitch("PRC_FILE_END_loadscreens", 259);
|
||||
SetPRCSwitch("PRC_FILE_END_masterfeats", 113);
|
||||
SetPRCSwitch("PRC_FILE_END_masterfeats", 125);
|
||||
SetPRCSwitch("PRC_FILE_END_materialcomp", 200);
|
||||
SetPRCSwitch("PRC_FILE_END_metamagic", 6);
|
||||
SetPRCSwitch("PRC_FILE_END_namefilter", 3);
|
||||
@@ -767,7 +768,7 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_soundset", 453);
|
||||
SetPRCSwitch("PRC_FILE_END_soundsettype", 4);
|
||||
SetPRCSwitch("PRC_FILE_END_soundtypes", 1);
|
||||
SetPRCSwitch("PRC_FILE_END_spells", 19348);
|
||||
SetPRCSwitch("PRC_FILE_END_spells", 19400);
|
||||
//SetPRCSwitch("PRC_FILE_END_spellschools", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_statescripts", 35);
|
||||
SetPRCSwitch("PRC_FILE_END_stringtokens", 92);
|
||||
@@ -866,6 +867,31 @@ void CreateSwitchNameArray()
|
||||
//if you add more switches, add them to this list
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DEBUG);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_COMBAT_DEBUG);
|
||||
|
||||
//craft
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_CRAFT);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MULTIPLIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MAX);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MIN);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BREW_POTION_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_SCRIBE_SCROLL_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_WAND_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_ROD_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_STAFF_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_BASE_ITEMS);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_MAXLEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_SCRIBESCROLL_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_MAXLEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CREATEINFUSION_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_ARBITRARY);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_COST_SCALE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_TIME_SCALE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_OPTIONAL_HERBS);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_SCEPTER_CASTER_LEVEL);
|
||||
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_MATERIAL_COMPONENTS);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_COMPONENTS_SHOP);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PNP_TRUESEEING);
|
||||
@@ -876,6 +902,8 @@ void CreateSwitchNameArray()
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_HARM);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_NEUTRALIZE_POISON);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_REMOVE_DISEASE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIO_UNLEARN);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_UNLEARN_SPELL_MAXNR);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TIMESTOP_BIOWARE_DURATION);
|
||||
@@ -994,7 +1022,7 @@ void CreateSwitchNameArray()
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_USES_PER_WEAPON_POISON_COUNT);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_USES_PER_WEAPON_POISON_DIE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_POISON_ALLOW_CLEAN_IN_EQUIP);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_POISON_USE_INGREDIENST);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_POISON_USE_INGREDIENTS);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PSI_ASTRAL_CONSTRUCT_USE_2DA);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PNP_RAPID_METABOLISM);
|
||||
@@ -1058,31 +1086,31 @@ void CreateSwitchNameArray()
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_LETOSCRIPT_UNICORN_SQL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_LETOSCRIPT_GETNEWESTBIC);
|
||||
|
||||
//craft
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_CRAFT);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MULTIPLIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MAX);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MIN);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BREW_POTION_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_SCRIBE_SCROLL_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_WAND_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_ROD_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_STAFF_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_BASE_ITEMS);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_MAXLEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_SCRIBESCROLL_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_MAXLEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CREATEINFUSION_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_ARBITRARY);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_COST_SCALE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_TIME_SCALE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_CASTER_LEVEL);
|
||||
|
||||
//spells
|
||||
|
||||
//shifter
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_USECR);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_HUGE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_LARGE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_MEDIUM);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_SMALL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_TINY);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OUTSIDER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ELEMENTAL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_CONSTRUCT);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_UNDEAD);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_DRAGON);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ABERRATION);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OOZE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MAGICALBEAST);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_GIANT);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_VERMIN);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_BEAST);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ANIMAL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MONSTROUSHUMANOID);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_HUMANOID);
|
||||
|
||||
//general
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "prc_inc_clsfunc"
|
||||
#include "prc_inc_sp_tch"
|
||||
|
||||
int GetBlastDamageDices(object oInvoker, int nInvokerLevel)
|
||||
{
|
||||
|
||||
@@ -135,6 +135,9 @@ int GetHasInvocation(int nInvocation, object oCreature = OBJECT_SELF);
|
||||
/* Includes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
int GetPrimaryInvocationClass(object oCreature = OBJECT_SELF);
|
||||
int GetInvocationPRCLevels(object oCaster);
|
||||
|
||||
#include "inc_item_props"
|
||||
#include "prc_x2_itemprop"
|
||||
#include "inc_lookups"
|
||||
|
||||
@@ -123,7 +123,7 @@ void DeleteLocalInvocation(object oObject, string sName);
|
||||
/* Includes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
//#include "inv_inc_invfunc" //Access in parent
|
||||
#include "inv_inc_invfunc" //Access in parent
|
||||
#include "prc_spellf_inc"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
@@ -77,6 +77,15 @@ int PreInvocationCastCode()
|
||||
|
||||
int nContinue = !ExecuteScriptAndReturnInt("prespellcode", oInvoker);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Block forsakers from using invocations
|
||||
//---------------------------------------------------------------------------
|
||||
if(GetLevelByClass(CLASS_TYPE_FORSAKER, oInvoker) > 0)
|
||||
{
|
||||
SendMessageToPC(oInvoker, "Forsakers cannot use invocations.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Break any spell require maintaining concentration
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -168,3 +177,4 @@ int PreInvocationCastCode()
|
||||
return nContinue;
|
||||
}
|
||||
|
||||
//:: void main (){}
|
||||
@@ -1170,7 +1170,10 @@ int GetMaxEssentiaCapacityFeat(object oMeldshaper)
|
||||
{
|
||||
int nMax = 1; // Always can invest one
|
||||
int nHD = GetHitDice(oMeldshaper);
|
||||
if (nHD >= 31) nMax = 5;
|
||||
if (nHD >= 61) nMax = 8;
|
||||
else if (nHD >= 51) nMax = 7;
|
||||
else if (nHD >= 41) nMax = 6;
|
||||
else if (nHD >= 31) nMax = 5;
|
||||
else if (nHD >= 18) nMax = 4;
|
||||
else if (nHD >= 12) nMax = 3;
|
||||
else if (nHD >= 6) nMax = 2;
|
||||
|
||||
623
src/include/nw_inc_gff.nss
Normal file
623
src/include/nw_inc_gff.nss
Normal file
@@ -0,0 +1,623 @@
|
||||
// This is a helper library for advanced use: It allows constructing arbitrary gff data.
|
||||
// You can then spawn your object via JsonToObject().
|
||||
//
|
||||
// The data format is the same as https://github.com/niv/neverwinter.nim@1.4.3+.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// json j = GffCreateObject(OBJECT_TYPE_ITEM);
|
||||
// j = GffAddInt(j, "BaseItem", BASE_ITEM_BELT);
|
||||
// j = GffAddInt(j, "ModelPart1", 12);
|
||||
// j = GffAddLocString(j, "LocalizedName", "hi!");
|
||||
// object belt = JsonToObject(j, GetLocation(OBJECT_SELF));
|
||||
|
||||
|
||||
const string GFF_FIELD_TYPE_STRUCT = "struct";
|
||||
const string GFF_FIELD_TYPE_LIST = "list";
|
||||
const string GFF_FIELD_TYPE_BYTE = "byte";
|
||||
const string GFF_FIELD_TYPE_CHAR = "char";
|
||||
const string GFF_FIELD_TYPE_WORD = "word";
|
||||
const string GFF_FIELD_TYPE_SHORT = "short";
|
||||
const string GFF_FIELD_TYPE_DWORD = "dword";
|
||||
const string GFF_FIELD_TYPE_INT = "int";
|
||||
const string GFF_FIELD_TYPE_DWORD64 = "dword64";
|
||||
const string GFF_FIELD_TYPE_INT64 = "int64";
|
||||
const string GFF_FIELD_TYPE_FLOAT = "float";
|
||||
const string GFF_FIELD_TYPE_DOUBLE = "double";
|
||||
const string GFF_FIELD_TYPE_RESREF = "resref";
|
||||
const string GFF_FIELD_TYPE_STRING = "cexostring";
|
||||
const string GFF_FIELD_TYPE_LOC_STRING = "cexolocstring";
|
||||
|
||||
|
||||
// Create a empty object of the given type. You need to manually fill in all
|
||||
// GFF data with GffAddXXX. This will require understanding of the GFF file format
|
||||
// and what data fields each object type requires.
|
||||
json GffCreateObject(int nObjectType);
|
||||
// Create a combined area format(CAF) object. You need to manually create the ARE and GIT objects with their required data fields.
|
||||
json GffCreateArea(json jARE, json jGIT);
|
||||
|
||||
// Returns the OBJECT_TYPE_* of jGff.
|
||||
// Note: Will return 0 for invalid object types, including areas.
|
||||
int GffGetObjectType(json jGff);
|
||||
// Returns TRUE if jGff is a combined area format(CAF) object.
|
||||
int GffGetIsArea(json jGff);
|
||||
|
||||
// Returns TRUE if a field named sLabel of sType exists in jGff.
|
||||
// * sLabel: Can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// * sType: An optional GFF_FIELD_TYPE_*, leave empty to check if sLabel exists regardless of type.
|
||||
int GffGetFieldExists(json jGff, string sLabel, string sType = "");
|
||||
|
||||
|
||||
// Add a new field, will overwrite any existing fields with the same label even if the type is different.
|
||||
// Returns a json null value on error with GetJsonError() filled in.
|
||||
//
|
||||
// sLabel can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// For example, to add the tag of an area to an empty combined area format(CAF) object you can do the following:
|
||||
// json jArea = GffCreateArea(JsonObject(), JsonObject());
|
||||
// jArea = GffAddString(jArea, "ARE/value/Tag", "AREA_TAG");
|
||||
|
||||
json GffAddStruct(json jGff, string sLabel, json jStruct, int nType = -1);
|
||||
json GffAddList(json jGff, string sLabel, json jList);
|
||||
json GffAddByte(json jGff, string sLabel, int v);
|
||||
json GffAddChar(json jGff, string sLabel, int v);
|
||||
json GffAddWord(json jGff, string sLabel, int v);
|
||||
json GffAddShort(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffAddDword(json jGff, string sLabel, int v);
|
||||
json GffAddInt(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffAddDword64(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffAddInt64(json jGff, string sLabel, int v);
|
||||
json GffAddFloat(json jGff, string sLabel, float v);
|
||||
// Note: Only data of type float will fit, because that's all that NWScript supports.
|
||||
json GffAddDouble(json jGff, string sLabel, float v);
|
||||
json GffAddResRef(json jGff, string sLabel, string v);
|
||||
json GffAddString(json jGff, string sLabel, string v);
|
||||
json GffAddLocString(json jGff, string sLabel, string v, int nStrRef = -1);
|
||||
|
||||
|
||||
// Replace a field, the type must match and the field must exist.
|
||||
// Returns a json null value on error with GetJsonError() filled in.
|
||||
//
|
||||
// sLabel can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// For example, to replace the name of an area in a combined area format(CAF) object you can do the following:
|
||||
// json jArea = ObjectToStruct(GetFirstArea());
|
||||
// jArea = GffReplaceLocString(jArea, "ARE/value/Name", "New Area Name");
|
||||
|
||||
json GffReplaceStruct(json jGff, string sLabel, json jStruct);
|
||||
json GffReplaceList(json jGff, string sLabel, json jList);
|
||||
json GffReplaceByte(json jGff, string sLabel, int v);
|
||||
json GffReplaceChar(json jGff, string sLabel, int v);
|
||||
json GffReplaceWord(json jGff, string sLabel, int v);
|
||||
json GffReplaceShort(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffReplaceDword(json jGff, string sLabel, int v);
|
||||
json GffReplaceInt(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffReplaceDword64(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffReplaceInt64(json jGff, string sLabel, int v);
|
||||
json GffReplaceFloat(json jGff, string sLabel, float v);
|
||||
// Note: Only data of type float will fit, because that's all that NWScript supports.
|
||||
json GffReplaceDouble(json jGff, string sLabel, float v);
|
||||
json GffReplaceResRef(json jGff, string sLabel, string v);
|
||||
json GffReplaceString(json jGff, string sLabel, string v);
|
||||
json GffReplaceLocString(json jGff, string sLabel, string v, int nStrRef = -1);
|
||||
|
||||
|
||||
// Remove a field, the type must match and the field must exist.
|
||||
// Returns a json null value on error with GetJsonError() filled in.
|
||||
//
|
||||
// sLabel can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// For example, to remove all placeables from an area in a combined area format(CAF) object you can do the following:
|
||||
// json jArea = ObjectToStruct(GetFirstArea());
|
||||
// jArea = GffRemoveList(jArea, "GIT/value/Placeable List");
|
||||
|
||||
json GffRemoveStruct(json jGff, string sLabel);
|
||||
json GffRemoveList(json jGff, string sLabel);
|
||||
json GffRemoveByte(json jGff, string sLabel);
|
||||
json GffRemoveChar(json jGff, string sLabel);
|
||||
json GffRemoveWord(json jGff, string sLabel);
|
||||
json GffRemoveShort(json jGff, string sLabel);
|
||||
json GffRemoveDword(json jGff, string sLabel);
|
||||
json GffRemoveInt(json jGff, string sLabel);
|
||||
json GffRemoveDword64(json jGff, string sLabel);
|
||||
json GffRemoveInt64(json jGff, string sLabel);
|
||||
json GffRemoveFloat(json jGff, string sLabel);
|
||||
json GffRemoveDouble(json jGff, string sLabel);
|
||||
json GffRemoveResRef(json jGff, string sLabel);
|
||||
json GffRemoveString(json jGff, string sLabel);
|
||||
json GffRemoveLocString(json jGff, string sLabel);
|
||||
|
||||
|
||||
// Get a field's value as json object.
|
||||
// Returns a json null value on error with GetJsonError() filled in.
|
||||
//
|
||||
// Note: Json types do not implicitly convert between types, this means you cannot convert a JsonInt to a string with JsonGetString(), etc.
|
||||
// You may need to check the type with JsonGetType() and then do the appropriate cast yourself.
|
||||
// For GffGet*() functions the json type returned is noted in the function description.
|
||||
//
|
||||
// Example:
|
||||
// INCORRECT: string s = JsonGetString(GffGetInt());
|
||||
// CORRECT: string s = IntToString(JsonGetInt(GffGetInt()));
|
||||
//
|
||||
// sLabel can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// For example, to get the resref of an area in a combined area format(CAF) object you can do the following:
|
||||
// json jResRef = GffGetResRef(ObjectToStruct(GetFirstArea()), "ARE/value/ResRef");
|
||||
// if (jResRef != JsonNull())
|
||||
// {
|
||||
// string sResRef = JsonGetString(jResRef);
|
||||
// }
|
||||
// else
|
||||
// WriteTimestampedLogEntry("Failed to get area ResRef: " + JsonGetError(jResRef));
|
||||
|
||||
// Returns the struct as JsonObject() on success.
|
||||
json GffGetStruct(json jGff, string sLabel);
|
||||
// Returns a JsonArray() with all the list elements on success.
|
||||
json GffGetList(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetByte(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetChar(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetWord(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetShort(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetDword(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetInt(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetDword64(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetInt64(json jGff, string sLabel);
|
||||
// Returns a JsonFloat() on success.
|
||||
json GffGetFloat(json jGff, string sLabel);
|
||||
// Returns a JsonFloat() on success.
|
||||
json GffGetDouble(json jGff, string sLabel);
|
||||
// Returns a JsonString() on success.
|
||||
json GffGetResRef(json jGff, string sLabel);
|
||||
// Returns a JsonString() on success.
|
||||
json GffGetString(json jGff, string sLabel);
|
||||
// Returns a JsonObject() on success.
|
||||
// Key "0" will have a JsonString() with the string, if set.
|
||||
// Key "id" will have a JsonInt() with the strref, if set.
|
||||
json GffGetLocString(json jGff, string sLabel);
|
||||
|
||||
|
||||
// *** Internal Helper Functions
|
||||
json AddPatchOperation(json jPatchArray, string sOp, string sPath, json jValue)
|
||||
{
|
||||
json jOperation = JsonObject();
|
||||
jOperation = JsonObjectSet(jOperation, "op", JsonString(sOp));
|
||||
jOperation = JsonObjectSet(jOperation, "path", JsonString(sPath));
|
||||
jOperation = JsonObjectSet(jOperation, "value", jValue);
|
||||
return JsonArrayInsert(jPatchArray, jOperation);
|
||||
}
|
||||
|
||||
json GffAddField(json jGff, string sLabel, string sType, json jValue, int nType = -1)
|
||||
{
|
||||
json jField = JsonObject();
|
||||
jField = JsonObjectSet(jField, "type", JsonString(sType));
|
||||
jField = JsonObjectSet(jField, "value", jValue);
|
||||
if (sType == GFF_FIELD_TYPE_STRUCT && nType != -1)
|
||||
jField = JsonObjectSet(jField, "__struct_id", JsonInt(nType));
|
||||
|
||||
return JsonPatch(jGff, AddPatchOperation(JsonArray(), "add", "/" + sLabel, jField));
|
||||
}
|
||||
|
||||
json GffReplaceField(json jGff, string sLabel, string sType, json jValue)
|
||||
{
|
||||
json jPatch = JsonArray();
|
||||
jPatch = AddPatchOperation(jPatch, "test", "/" + sLabel + "/type", JsonString(sType));
|
||||
jPatch = AddPatchOperation(jPatch, "replace", "/" + sLabel + "/value", jValue);
|
||||
return JsonPatch(jGff, jPatch);
|
||||
}
|
||||
|
||||
json GffRemoveField(json jGff, string sLabel, string sType)
|
||||
{
|
||||
json jPatch = JsonArray();
|
||||
jPatch = AddPatchOperation(jPatch, "test", "/" + sLabel + "/type", JsonString(sType));
|
||||
jPatch = AddPatchOperation(jPatch, "remove", "/" + sLabel, JsonNull());
|
||||
return JsonPatch(jGff, jPatch);
|
||||
}
|
||||
|
||||
json GffGetFieldType(json jGff, string sLabel)
|
||||
{
|
||||
return JsonPointer(jGff, "/" + sLabel + "/type");
|
||||
}
|
||||
|
||||
json GffGetFieldValue(json jGff, string sLabel)
|
||||
{
|
||||
return JsonPointer(jGff, "/" + sLabel + "/value");
|
||||
}
|
||||
|
||||
json GffGetField(json jGff, string sLabel, string sType)
|
||||
{
|
||||
json jType = GffGetFieldType(jGff, sLabel);
|
||||
if (jType == JsonNull())
|
||||
return jType;
|
||||
else if (jType != JsonString(sType))
|
||||
return JsonNull("field type does not match");
|
||||
else
|
||||
return GffGetFieldValue(jGff, sLabel);
|
||||
}
|
||||
|
||||
json GffLocString(string v, int nStrRef = -1)
|
||||
{
|
||||
json jLocString = JsonObject();
|
||||
if (v != "")
|
||||
jLocString = JsonObjectSet(jLocString, "0", JsonString(v)); // english/any
|
||||
if (nStrRef != -1)
|
||||
jLocString = JsonObjectSet(jLocString, "id", JsonInt(nStrRef));
|
||||
|
||||
return jLocString;
|
||||
}
|
||||
//***
|
||||
|
||||
json GffCreateObject(int nObjectType)
|
||||
{
|
||||
string ot;
|
||||
if (nObjectType == OBJECT_TYPE_CREATURE) ot = "UTC ";
|
||||
else if (nObjectType == OBJECT_TYPE_ITEM) ot = "UTI ";
|
||||
else if (nObjectType == OBJECT_TYPE_TRIGGER) ot = "UTT ";
|
||||
else if (nObjectType == OBJECT_TYPE_DOOR) ot = "UTD ";
|
||||
else if (nObjectType == OBJECT_TYPE_WAYPOINT) ot = "UTW ";
|
||||
else if (nObjectType == OBJECT_TYPE_PLACEABLE) ot = "UTP ";
|
||||
else if (nObjectType == OBJECT_TYPE_STORE) ot = "UTM ";
|
||||
else if (nObjectType == OBJECT_TYPE_ENCOUNTER) ot = "UTE ";
|
||||
|
||||
if (ot == "") return JsonNull("invalid object type");
|
||||
|
||||
json ret = JsonObject();
|
||||
ret = JsonObjectSet(ret, "__data_type", JsonString(ot));
|
||||
return ret;
|
||||
}
|
||||
|
||||
json GffCreateArea(json jARE, json jGIT)
|
||||
{
|
||||
json jCAF = JsonObject();
|
||||
jCAF = JsonObjectSet(jCAF, "__data_type", JsonString("CAF "));
|
||||
jCAF = GffAddStruct(jCAF, "ARE", jARE, 0);
|
||||
jCAF = GffAddStruct(jCAF, "GIT", jGIT, 1);
|
||||
return jCAF;
|
||||
}
|
||||
|
||||
|
||||
int GffGetObjectType(json jGff)
|
||||
{
|
||||
json jDataType = JsonObjectGet(jGff, "__data_type");
|
||||
if (jDataType == JsonNull())
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
string sObjectType = JsonGetString(jDataType);
|
||||
|
||||
if (sObjectType == "UTC ") return OBJECT_TYPE_CREATURE;
|
||||
else if (sObjectType == "UTI ") return OBJECT_TYPE_ITEM;
|
||||
else if (sObjectType == "UTT ") return OBJECT_TYPE_TRIGGER;
|
||||
else if (sObjectType == "UTD ") return OBJECT_TYPE_DOOR;
|
||||
else if (sObjectType == "UTW ") return OBJECT_TYPE_WAYPOINT;
|
||||
else if (sObjectType == "UTP ") return OBJECT_TYPE_PLACEABLE;
|
||||
else if (sObjectType == "UTM ") return OBJECT_TYPE_STORE;
|
||||
else if (sObjectType == "UTE ") return OBJECT_TYPE_ENCOUNTER;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GffGetIsArea(json jGff)
|
||||
{
|
||||
return JsonObjectGet(jGff, "__data_type") == JsonString("CAF ");
|
||||
}
|
||||
|
||||
int GffGetFieldExists(json jGff, string sLabel, string sType = "")
|
||||
{
|
||||
json jFieldType = GffGetFieldType(jGff, sLabel);
|
||||
return sType == "" ? jFieldType != JsonNull() : jFieldType == JsonString(sType);
|
||||
}
|
||||
|
||||
|
||||
json GffAddStruct(json jGff, string sLabel, json jStruct, int nType = -1)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_STRUCT, jStruct, nType);
|
||||
}
|
||||
|
||||
json GffAddList(json jGff, string sLabel, json jList)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_LIST, jList);
|
||||
}
|
||||
|
||||
json GffAddByte(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_BYTE, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddChar(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_CHAR, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddWord(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_WORD, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddShort(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_SHORT, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddDword(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_DWORD, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddInt(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_INT, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddDword64(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_DWORD64, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddInt64(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_INT64, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddFloat(json jGff, string sLabel, float v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_FLOAT, JsonFloat(v));
|
||||
}
|
||||
|
||||
json GffAddDouble(json jGff, string sLabel, float v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_DOUBLE, JsonFloat(v));
|
||||
}
|
||||
|
||||
json GffAddResRef(json jGff, string sLabel, string v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_RESREF, JsonString(v));
|
||||
}
|
||||
|
||||
json GffAddString(json jGff, string sLabel, string v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_STRING, JsonString(v));
|
||||
}
|
||||
|
||||
json GffAddLocString(json jGff, string sLabel, string v, int nStrRef = -1)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_LOC_STRING, GffLocString(v, nStrRef));
|
||||
}
|
||||
|
||||
|
||||
json GffReplaceStruct(json jGff, string sLabel, json jStruct)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_STRUCT, jStruct);
|
||||
}
|
||||
|
||||
json GffReplaceList(json jGff, string sLabel, json jList)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_LIST, jList);
|
||||
}
|
||||
|
||||
json GffReplaceByte(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_BYTE, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceChar(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_CHAR, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceWord(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_WORD, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceShort(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_SHORT, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceDword(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_DWORD, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceInt(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_INT, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceDword64(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_DWORD64, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceInt64(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_INT64, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceFloat(json jGff, string sLabel, float v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_FLOAT, JsonFloat(v));
|
||||
}
|
||||
|
||||
json GffReplaceDouble(json jGff, string sLabel, float v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_DOUBLE, JsonFloat(v));
|
||||
}
|
||||
|
||||
json GffReplaceResRef(json jGff, string sLabel, string v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_RESREF, JsonString(v));
|
||||
}
|
||||
|
||||
json GffReplaceString(json jGff, string sLabel, string v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_STRING, JsonString(v));
|
||||
}
|
||||
|
||||
json GffReplaceLocString(json jGff, string sLabel, string v, int nStrRef = -1)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_LOC_STRING, GffLocString(v, nStrRef));
|
||||
}
|
||||
|
||||
|
||||
json GffRemoveStruct(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_STRUCT);
|
||||
}
|
||||
|
||||
json GffRemoveList(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_LIST);
|
||||
}
|
||||
|
||||
json GffRemoveByte(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_BYTE);
|
||||
}
|
||||
|
||||
json GffRemoveChar(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_CHAR);
|
||||
}
|
||||
|
||||
json GffRemoveWord(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_WORD);
|
||||
}
|
||||
|
||||
json GffRemoveShort(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_SHORT);
|
||||
}
|
||||
|
||||
json GffRemoveDword(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_DWORD);
|
||||
}
|
||||
|
||||
json GffRemoveInt(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_INT);
|
||||
}
|
||||
|
||||
json GffRemoveDword64(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_DWORD64);
|
||||
}
|
||||
|
||||
json GffRemoveInt64(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_INT64);
|
||||
}
|
||||
|
||||
json GffRemoveFloat(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
json GffRemoveDouble(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
json GffRemoveResRef(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_RESREF);
|
||||
}
|
||||
|
||||
json GffRemoveString(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_STRING);
|
||||
}
|
||||
|
||||
json GffRemoveLocString(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_LOC_STRING);
|
||||
}
|
||||
|
||||
|
||||
json GffGetStruct(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_STRUCT);
|
||||
}
|
||||
|
||||
json GffGetList(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_LIST);
|
||||
}
|
||||
|
||||
json GffGetByte(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_BYTE);
|
||||
}
|
||||
|
||||
json GffGetChar(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_CHAR);
|
||||
}
|
||||
|
||||
json GffGetWord(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_WORD);
|
||||
}
|
||||
|
||||
json GffGetShort(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_SHORT);
|
||||
}
|
||||
|
||||
json GffGetDword(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_DWORD);
|
||||
}
|
||||
|
||||
json GffGetInt(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_INT);
|
||||
}
|
||||
|
||||
json GffGetDword64(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_DWORD64);
|
||||
}
|
||||
|
||||
json GffGetInt64(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_INT64);
|
||||
}
|
||||
|
||||
json GffGetFloat(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
json GffGetDouble(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
json GffGetResRef(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_RESREF);
|
||||
}
|
||||
|
||||
json GffGetString(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_STRING);
|
||||
}
|
||||
|
||||
json GffGetLocString(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_LOC_STRING);
|
||||
}
|
||||
@@ -10,9 +10,586 @@ void ShifterCheck(object oPC);
|
||||
#include "pnp_shft_main"
|
||||
#include "prc_inc_shifting"
|
||||
|
||||
//::////////////////Begin Werewolf//////////////////
|
||||
const string PRC_PNP_SHIFTING = "PRC_Shift";
|
||||
|
||||
////////////////Begin Werewolf//////////////////
|
||||
void LycanthropePoly(object oPC, int nPoly)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
|
||||
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
|
||||
|
||||
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
|
||||
|
||||
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
|
||||
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
|
||||
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
|
||||
|
||||
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
|
||||
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
|
||||
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
|
||||
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
|
||||
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
|
||||
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
|
||||
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
|
||||
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
|
||||
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
|
||||
|
||||
if (GetIsObjectValid(oShield))
|
||||
{
|
||||
int nShieldType = GetBaseItemType(oShield);
|
||||
if (nShieldType != BASE_ITEM_LARGESHIELD &&
|
||||
nShieldType != BASE_ITEM_SMALLSHIELD &&
|
||||
nShieldType != BASE_ITEM_TOWERSHIELD)
|
||||
{
|
||||
oShield = OBJECT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
ShifterCheck(oPC);
|
||||
ClearAllActions();
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
|
||||
|
||||
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
|
||||
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
|
||||
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
|
||||
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
|
||||
|
||||
//:: Weapon & Armor merge block
|
||||
object oMergeWeaponSource = OBJECT_INVALID;
|
||||
object oMergeArmorSource = OBJECT_INVALID;
|
||||
|
||||
//:: Determine Weapon Merge Source
|
||||
if (bWeapon)
|
||||
{
|
||||
if (bMonkGloves)
|
||||
{
|
||||
if (GetIsObjectValid(oGlovesOld))
|
||||
oMergeWeaponSource = oGlovesOld;
|
||||
}
|
||||
else
|
||||
{
|
||||
//:: Always attempt to merge melee weapon to creature weapon
|
||||
oMergeWeaponSource = oWeaponOld; // even if empty, ensures proper state
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//:: Weapon not requested, but arms-slot allowed monk gloves can merge via armor branch
|
||||
if (bMonkGloves && bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
|
||||
oMergeWeaponSource = oGlovesOld;
|
||||
}
|
||||
|
||||
//:: Determine Armor Merge Source
|
||||
if (bArmor && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (!bMonkGloves)
|
||||
{
|
||||
if (bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
|
||||
oMergeArmorSource = oGlovesOld;
|
||||
|
||||
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
|
||||
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
|
||||
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
|
||||
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
|
||||
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
|
||||
}
|
||||
}
|
||||
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
|
||||
{
|
||||
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
|
||||
}
|
||||
|
||||
//:: Apply Weapon Merge
|
||||
if (GetIsObjectValid(oMergeWeaponSource) || bWeapon)
|
||||
{
|
||||
//:: Always attempt to merge weapon properties even if source is OBJECT_INVALID
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewBite, TRUE);
|
||||
}
|
||||
|
||||
//:: Apply Armor Merge
|
||||
if (GetIsObjectValid(oMergeArmorSource))
|
||||
{
|
||||
if (GetIsObjectValid(oArmorNew)) IPWildShapeCopyItemProperties(oMergeArmorSource, oArmorNew);
|
||||
}
|
||||
|
||||
//:: General item merge block
|
||||
if (bItems && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
|
||||
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
|
||||
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
|
||||
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
|
||||
}
|
||||
}
|
||||
//::////////////////End Werewolf//////////////////
|
||||
|
||||
|
||||
/* //::////////////////Begin Werewolf//////////////////
|
||||
const string PRC_PNP_SHIFTING = "PRC_Shift";
|
||||
|
||||
void LycanthropePoly(object oPC, int nPoly)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
|
||||
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
|
||||
|
||||
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
|
||||
|
||||
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
|
||||
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
|
||||
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
|
||||
|
||||
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
|
||||
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
|
||||
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
|
||||
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
|
||||
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
|
||||
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
|
||||
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
|
||||
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
|
||||
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
|
||||
|
||||
if (GetIsObjectValid(oShield))
|
||||
{
|
||||
int nShieldType = GetBaseItemType(oShield);
|
||||
if (nShieldType != BASE_ITEM_LARGESHIELD &&
|
||||
nShieldType != BASE_ITEM_SMALLSHIELD &&
|
||||
nShieldType != BASE_ITEM_TOWERSHIELD)
|
||||
{
|
||||
oShield = OBJECT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
ShifterCheck(oPC);
|
||||
ClearAllActions();
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
|
||||
|
||||
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
|
||||
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
|
||||
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
|
||||
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
|
||||
|
||||
//:: Weapon & Armor merge block
|
||||
object oMergeWeaponSource = OBJECT_INVALID;
|
||||
object oMergeArmorSource = OBJECT_INVALID;
|
||||
|
||||
// ---- Determine Weapon Merge Source ----
|
||||
if (bWeapon)
|
||||
{
|
||||
if (bMonkGloves)
|
||||
{
|
||||
if (GetIsObjectValid(oGlovesOld))
|
||||
oMergeWeaponSource = oGlovesOld;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponOld))
|
||||
oMergeWeaponSource = oWeaponOld;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bMonkGloves && bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
|
||||
oMergeWeaponSource = oGlovesOld;
|
||||
}
|
||||
|
||||
// ---- Determine Armor Merge Source ----
|
||||
if (bArmor && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (!bMonkGloves)
|
||||
{
|
||||
if (bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
|
||||
oMergeArmorSource = oGlovesOld;
|
||||
|
||||
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
|
||||
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
|
||||
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
|
||||
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
|
||||
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
|
||||
}
|
||||
}
|
||||
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
|
||||
{
|
||||
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
|
||||
}
|
||||
|
||||
// ---- Apply Weapon Merge ----
|
||||
if (GetIsObjectValid(oMergeWeaponSource))
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewBite, TRUE);
|
||||
}
|
||||
|
||||
// ---- Apply Armor Merge ----
|
||||
if (GetIsObjectValid(oMergeArmorSource))
|
||||
{
|
||||
if (GetIsObjectValid(oArmorNew)) IPWildShapeCopyItemProperties(oMergeArmorSource, oArmorNew);
|
||||
}
|
||||
|
||||
//:: General item merge block
|
||||
if (bItems && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
|
||||
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
|
||||
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
|
||||
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
|
||||
}
|
||||
}
|
||||
//::////////////////End Werewolf////////////////// */
|
||||
|
||||
|
||||
/* //::////////////////Begin Werewolf//////////////////
|
||||
const string PRC_PNP_SHIFTING = "PRC_Shift";
|
||||
|
||||
void LycanthropePoly(object oPC, int nPoly)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
|
||||
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
|
||||
|
||||
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
|
||||
|
||||
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
|
||||
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
|
||||
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
|
||||
|
||||
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
|
||||
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
|
||||
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
|
||||
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
|
||||
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
|
||||
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
|
||||
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
|
||||
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
|
||||
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
|
||||
|
||||
if (GetIsObjectValid(oShield))
|
||||
{
|
||||
int nShieldType = GetBaseItemType(oShield);
|
||||
if (nShieldType != BASE_ITEM_LARGESHIELD &&
|
||||
nShieldType != BASE_ITEM_SMALLSHIELD &&
|
||||
nShieldType != BASE_ITEM_TOWERSHIELD)
|
||||
{
|
||||
oShield = OBJECT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
ShifterCheck(oPC);
|
||||
ClearAllActions();
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
|
||||
|
||||
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
|
||||
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
|
||||
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
|
||||
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
|
||||
|
||||
//:: Weapon merge block
|
||||
if (bWeapon)
|
||||
{
|
||||
object oMergeSource = OBJECT_INVALID;
|
||||
|
||||
// Priority: monk gloves override if worn and arms-slot not allowed
|
||||
if (bMonkGloves && !bArmsSlotAllowed)
|
||||
{
|
||||
if (GetIsObjectValid(oGlovesOld))
|
||||
oMergeSource = oGlovesOld;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise use main-hand weapon if it exists
|
||||
if (GetIsObjectValid(oWeaponOld))
|
||||
oMergeSource = oWeaponOld;
|
||||
}
|
||||
|
||||
// Apply merge to creature weapons if we have a source
|
||||
if (GetIsObjectValid(oMergeSource))
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oMergeSource, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oMergeSource, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oMergeSource, oWeaponNewBite, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
//:: Armor merge block
|
||||
if (bArmor && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
|
||||
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
|
||||
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
|
||||
|
||||
// Arms-slot allowed -> apply gloves & bracers to creature weapons
|
||||
if (bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
|
||||
{
|
||||
if (DEBUG) DoDebug("LycanthropePoly: Arms-slot allowed -> applying gloves/bracers to creature weapons from armor branch.");
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
|
||||
}
|
||||
}
|
||||
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
|
||||
{
|
||||
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
|
||||
}
|
||||
|
||||
//:: General item merge block
|
||||
if (bItems && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
|
||||
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
|
||||
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
|
||||
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
|
||||
}
|
||||
}
|
||||
//::////////////////End Werewolf//////////////////
|
||||
*/
|
||||
|
||||
/* //::////////////////Begin Werewolf//////////////////
|
||||
const string PRC_PNP_SHIFTING = "PRC_Shift";
|
||||
|
||||
void LycanthropePoly(object oPC, int nPoly)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
|
||||
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
|
||||
|
||||
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
|
||||
|
||||
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
|
||||
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
|
||||
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
|
||||
|
||||
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
|
||||
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
|
||||
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
|
||||
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
|
||||
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
|
||||
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
|
||||
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
|
||||
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
|
||||
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
|
||||
|
||||
if (GetIsObjectValid(oShield))
|
||||
{
|
||||
int nShieldType = GetBaseItemType(oShield);
|
||||
if (nShieldType != BASE_ITEM_LARGESHIELD &&
|
||||
nShieldType != BASE_ITEM_SMALLSHIELD &&
|
||||
nShieldType != BASE_ITEM_TOWERSHIELD)
|
||||
{
|
||||
oShield = OBJECT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
ShifterCheck(oPC);
|
||||
ClearAllActions();
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
|
||||
|
||||
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
|
||||
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
|
||||
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
|
||||
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
|
||||
|
||||
//:: Weapon merge block
|
||||
//:: Only blocked if monk gloves are equipped AND arms-slot merge is NOT allowed
|
||||
if (bWeapon && !bMonkGloves)
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponOld))
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewBite, TRUE);
|
||||
}
|
||||
}
|
||||
else if (bWeapon && bMonkGloves && !bArmsSlotAllowed)
|
||||
{
|
||||
if (DEBUG) DoDebug("LycanthropePoly: Monk gloves overriding weapon merge (arms slot NOT allowed).");
|
||||
if (GetIsObjectValid(oGlovesOld))
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//:: Armor merge block
|
||||
//:: Apply armor and gloves (if arms-slot allowed)
|
||||
|
||||
if (bArmor && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
|
||||
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
|
||||
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
|
||||
|
||||
if (bArmsSlotAllowed && bMonkGloves && GetIsObjectValid(oGlovesOld))
|
||||
{
|
||||
if (DEBUG) DoDebug("LycanthropePoly: Arms-slot allowed -> applying gloves to creature weapons from armor branch.");
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
|
||||
}
|
||||
}
|
||||
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
|
||||
{
|
||||
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
|
||||
}
|
||||
|
||||
//:: General item merge block
|
||||
if (bItems && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
|
||||
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
|
||||
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
|
||||
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
|
||||
}
|
||||
}
|
||||
//::////////////////End Werewolf////////////////// */
|
||||
|
||||
|
||||
/* //::////////////////Begin Werewolf//////////////////
|
||||
const string PRC_PNP_SHIFTING = "PRC_Shift";
|
||||
|
||||
void LycanthropePoly(object oPC, int nPoly)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
|
||||
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
|
||||
|
||||
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
|
||||
|
||||
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
|
||||
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
|
||||
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
|
||||
|
||||
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
|
||||
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
|
||||
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
|
||||
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
|
||||
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
|
||||
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
|
||||
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
|
||||
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
|
||||
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
|
||||
|
||||
if (GetIsObjectValid(oShield))
|
||||
{
|
||||
int nShieldType = GetBaseItemType(oShield);
|
||||
if (nShieldType != BASE_ITEM_LARGESHIELD &&
|
||||
nShieldType != BASE_ITEM_SMALLSHIELD &&
|
||||
nShieldType != BASE_ITEM_TOWERSHIELD)
|
||||
{
|
||||
oShield = OBJECT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
ShifterCheck(oPC);
|
||||
ClearAllActions();
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
|
||||
|
||||
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
|
||||
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
|
||||
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
|
||||
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
|
||||
|
||||
//:: Weapon merge block
|
||||
//:: Only blocked if monk gloves are equipped AND arms-slot merge is NOT allowed
|
||||
if (bWeapon && !bMonkGloves)
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponOld))
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewBite, TRUE);
|
||||
}
|
||||
}
|
||||
else if (bWeapon && bMonkGloves && !bArmsSlotAllowed)
|
||||
{
|
||||
if (DEBUG) DoDebug("LycanthropePoly: Monk gloves overriding weapon merge (arms slot NOT allowed).");
|
||||
if (GetIsObjectValid(oGlovesOld))
|
||||
{
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//:: Armor merge block
|
||||
//:: Apply armor and gloves (if arms-slot allowed)
|
||||
|
||||
if (bArmor && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
|
||||
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
|
||||
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
|
||||
|
||||
if (bArmsSlotAllowed && bMonkGloves && GetIsObjectValid(oGlovesOld))
|
||||
{
|
||||
if (DEBUG) DoDebug("LycanthropePoly: Arms-slot allowed -> applying gloves to creature weapons from armor branch.");
|
||||
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
|
||||
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
|
||||
}
|
||||
}
|
||||
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
|
||||
{
|
||||
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
|
||||
}
|
||||
|
||||
//:: General item merge block
|
||||
if (bItems && GetIsObjectValid(oArmorNew))
|
||||
{
|
||||
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
|
||||
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
|
||||
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
|
||||
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
|
||||
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
|
||||
}
|
||||
}
|
||||
//::////////////////End Werewolf////////////////// */
|
||||
|
||||
|
||||
/* ////////////////Begin Werewolf//////////////////
|
||||
|
||||
void LycanthropePoly(object oPC, int nPoly)
|
||||
{
|
||||
@@ -84,7 +661,7 @@ void LycanthropePoly(object oPC, int nPoly)
|
||||
|
||||
}
|
||||
|
||||
////////////////End Werewolf//////////////////
|
||||
////////////////End Werewolf////////////////// */
|
||||
|
||||
void ShifterCheck(object oPC)
|
||||
{
|
||||
@@ -246,4 +823,6 @@ void DoTail(object oPC, int nTailType)
|
||||
SetCreatureTailType(nTailType, oPC);
|
||||
//override any stored default appearance
|
||||
SetPersistantLocalInt(oPC, "AppearanceStoredTail", nTailType);
|
||||
}
|
||||
}
|
||||
|
||||
//::void main (){}
|
||||
@@ -54,11 +54,11 @@ int SPGetPenetrAOE(object oCaster = OBJECT_SELF, int nCasterLvl = 0);
|
||||
/* Includes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
//#include "prc_inc_spells"
|
||||
#include "prc_inc_spells"
|
||||
//#include "prc_alterations"
|
||||
//#include "prcsp_archmaginc"
|
||||
//#include "prc_inc_racial"
|
||||
|
||||
#include "inc_2dacache"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
|
||||
@@ -444,6 +444,7 @@ int Get2DALineFromItemprop(string sFile, itemproperty ip, object oItem)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEM_PROPERTY_ECHOBLADE: return 46; break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@@ -1529,7 +1530,12 @@ void ApplyItemProps(object oItem, string sFile, int nLine)
|
||||
break; //no more itemprops, no gaps, assuming no errors
|
||||
}
|
||||
if(sFile != "craft_weapon" && sFile != "craft_armour")
|
||||
SetName(oItem, GetStringByStrRef(StringToInt(Get2DACache(sFile, "Name", nLine))));
|
||||
{
|
||||
SetName(oItem, GetStringByStrRef(StringToInt(Get2DACache(sFile, "Name", nLine))));
|
||||
string sDescRef = Get2DACache(sFile, "CraftedDescription", nLine);
|
||||
if(sDescRef != "")
|
||||
SetDescription(oItem, GetStringByStrRef(StringToInt(sDescRef)));
|
||||
}
|
||||
}
|
||||
|
||||
//Partly ripped off the lexicon :P
|
||||
@@ -1620,7 +1626,8 @@ string GetCrafting2DA(object oItem)
|
||||
(nBase == BASE_ITEM_BOOTS) ||
|
||||
(nBase == BASE_ITEM_GLOVES) ||
|
||||
(nBase == BASE_ITEM_BRACER) ||
|
||||
(nBase == BASE_ITEM_CLOAK))
|
||||
(nBase == BASE_ITEM_CLOAK) ||
|
||||
(nBase == BASE_ITEM_CRAFTED_VIAL))
|
||||
)
|
||||
return "craft_wondrous";
|
||||
|
||||
@@ -1657,19 +1664,28 @@ int GetCraftingFeat(object oItem)
|
||||
if(nBase == BASE_ITEM_RING) return FEAT_FORGE_RING;
|
||||
|
||||
//routing bioware feats through this convo
|
||||
if((nBase == BASE_ITEM_CRAFTED_SCEPTER) ||
|
||||
(nBase == BASE_ITEM_CRAFTED_SCEPTER)
|
||||
)
|
||||
return FEAT_CRAFT_SCEPTER;
|
||||
|
||||
if((nBase == BASE_ITEM_MAGICROD) ||
|
||||
(nBase == BASE_ITEM_CRAFTED_ROD)
|
||||
)
|
||||
return FEAT_CRAFT_ROD;
|
||||
|
||||
if((nBase == BASE_ITEM_MAGICSTAFF) ||
|
||||
(nBase == BASE_ITEM_CRAFTED_STAFF)
|
||||
)
|
||||
return FEAT_CRAFT_STAFF;
|
||||
|
||||
if((nBase == BASE_ITEM_MAGICWAND) ||
|
||||
(nBase == BASE_ITEM_BLANK_WAND)
|
||||
)
|
||||
return FEAT_CRAFT_WAND;
|
||||
|
||||
if(nBase == BASE_ITEM_BLANK_POTION) return FEAT_BREW_POTION;
|
||||
|
||||
if(nBase == BASE_ITEM_BLANK_SCROLL) return FEAT_SCRIBE_SCROLL;
|
||||
|
||||
if(((nBase == BASE_ITEM_HELMET) ||
|
||||
@@ -1678,7 +1694,8 @@ int GetCraftingFeat(object oItem)
|
||||
(nBase == BASE_ITEM_BOOTS) ||
|
||||
(nBase == BASE_ITEM_GLOVES) ||
|
||||
(nBase == BASE_ITEM_BRACER) ||
|
||||
(nBase == BASE_ITEM_CLOAK))
|
||||
(nBase == BASE_ITEM_CLOAK) ||
|
||||
(nBase == BASE_ITEM_CRAFTED_VIAL))
|
||||
)
|
||||
return FEAT_CRAFT_WONDROUS;
|
||||
|
||||
|
||||
@@ -75,10 +75,11 @@ void DeathlessFrenzyCheck(object oTarget);
|
||||
// * PRC Version of a Bioware function to disable include loops
|
||||
void PRCRemoveSpellEffects(int nSpell_ID, object oCaster, object oTarget);
|
||||
|
||||
|
||||
/**
|
||||
* Target is immune to gaze attacks
|
||||
*
|
||||
* @return the Dazzle effect
|
||||
* @return the Gaze Immunity effect
|
||||
*/
|
||||
effect EffectGazeImmune();
|
||||
|
||||
@@ -89,6 +90,9 @@ effect EffectGazeImmune();
|
||||
*/
|
||||
effect EffectDazzle();
|
||||
|
||||
//ebonfowl: adding this function to check if a target is already shaken
|
||||
int GetIsShaken(object oTarget);
|
||||
|
||||
/**
|
||||
* Shaken effect: -2 to attack, all skills and saving throws
|
||||
*
|
||||
@@ -177,14 +181,11 @@ effect EffectAbilityBasedSkillIncrease(int iAbility, int iIncrease = 1);
|
||||
*/
|
||||
effect EffectAbilityBasedSkillDecrease(int iAbility, int iDecrease = 1);
|
||||
|
||||
//ebonfowl: adding this function to check if a target is already shaken
|
||||
int GetIsShaken(object oTarget);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Include section */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#include "prc_inc_castlvl" // get prc_racial_const, prc_inc_nwscript, prc_inc_newip
|
||||
#include "inc_epicspelldef"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
@@ -268,6 +269,8 @@ object GetObjectToApplyNewEffect(string sTag, object oPC, int nStripEffects = TR
|
||||
SetCreatureAppearanceType(oWP, APPEARANCE_TYPE_INVISIBLE_HUMAN_MALE);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectVisualEffect(VFX_DUR_CUTSCENE_INVISIBILITY), oWP);
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectCutsceneGhost(), oWP);
|
||||
AssignCommand(oWP, ActionUseSkill(SKILL_HIDE, oWP));
|
||||
|
||||
}
|
||||
//remove previous effects
|
||||
if(nStripEffects)
|
||||
@@ -746,7 +749,6 @@ effect EffectImmunityMiscAll()
|
||||
//:: Immunity to all gaze attacks
|
||||
effect EffectGazeImmune()
|
||||
{
|
||||
effect eBlank;
|
||||
|
||||
effect eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CHARM);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CONFUSION);
|
||||
@@ -768,6 +770,23 @@ effect EffectGazeImmune()
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
//:: Immunity to all perification attacks
|
||||
effect EffectPetrificationImmune()
|
||||
{
|
||||
effect eReturn = EffectSpellImmunity(SPELLABILITY_TOUCH_PETRIFY);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_BREATH_PETRIFY);
|
||||
eReturn = EffectSpellImmunity(SPELL_FLESH_TO_STONE);
|
||||
eReturn = EffectSpellImmunity(SPELL_STONEHOLD);
|
||||
eReturn = EffectSpellImmunity(SPELL_EPIC_A_STONE);
|
||||
eReturn = EffectSpellImmunity(POWER_CRYSTALLIZE);
|
||||
eReturn = EffectSpellImmunity(MELD_BASILISK_MASK);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_PETRIFY);
|
||||
|
||||
eReturn = TagEffect(eReturn, "PRCPetrificationImmune");
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
int GetIsShaken(object oTarget)
|
||||
{
|
||||
effect eEffect = GetFirstEffect(oTarget);
|
||||
@@ -785,5 +804,11 @@ int GetIsShaken(object oTarget)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Forward declarations for size change effects
|
||||
// Implementations are in prc_inc_size
|
||||
effect EffectSizeChange(object oTarget, int nObjectType, int bEnlarge, int nChanges);
|
||||
void DelayedSetVisualTransform(int nExpectedGeneration, object oTarget, int nTransform, float fValue);
|
||||
void DelaySetVisualTransform(float fDelay, object oTarget, string sGenerationName, int nTransform, float fValue);
|
||||
|
||||
//:: Test void
|
||||
//:: void main() {}
|
||||
//::void main() {}
|
||||
@@ -4,6 +4,11 @@
|
||||
//:: PRC Options Conversation
|
||||
const int FEAT_OPTIONS_CONVERSATION = 2285;
|
||||
|
||||
//;; Builder Feats
|
||||
const int FEAT_ARCHETYPAL_FORM = 2918;
|
||||
const int FEAT_INTRINSIC_ARMOR = 25990;
|
||||
const int FEAT_INTRINSIC_WEAPON = 25991;
|
||||
|
||||
//:: Missing Bioware Feats
|
||||
const int FEAT_EPIC_PLANAR_TURNING = 854;
|
||||
|
||||
@@ -219,6 +224,9 @@ const int FEAT_MAGICAL_ARTISAN_CREATE_INFUSION = 25961;
|
||||
const int FEAT_PLANT_DEFIANCE = 25992;
|
||||
const int FEAT_PLANT_CONTROL = 25993;
|
||||
|
||||
//:: Lost Empires of Faerun feats
|
||||
const int FEAT_CRAFT_SCEPTER = 25962;
|
||||
const int FEAT_MAGICAL_ARTISAN_CRAFT_SCEPTER = 25963;
|
||||
|
||||
//:: Racial Feats
|
||||
const int FEAT_WEMIC_JUMP_8 = 4518;
|
||||
@@ -1314,6 +1322,7 @@ const int FEAT_SOMATIC_WEAPONRY = 5186;
|
||||
|
||||
// Forgotten Realms Campaign Setting
|
||||
const int FEAT_INSCRIBE_RUNE = 2462;
|
||||
const int EPIC_FEAT_INSCRIBE_EPIC_RUNES = 2549;
|
||||
|
||||
// Miniature Handbook
|
||||
const int FEAT_SHIELDMATE = 3258;
|
||||
@@ -3726,6 +3735,9 @@ const int FEAT_EPIC_ARTIFICER = 4072;
|
||||
//////////////// END INFUSIONS /////////////////
|
||||
//////////////////////////////////////////////////*/
|
||||
|
||||
//:: Monk
|
||||
const int FEAT_MONK_ABUNDANT_STEP = 2351;
|
||||
|
||||
//Justice of Weald and Woe
|
||||
const int FEAT_LUCKY_SHOT = 24021;
|
||||
|
||||
@@ -6275,6 +6287,7 @@ const int FEAT_DSONG_SPELLCASTING_NONE = 19592;
|
||||
const int FEAT_OLLAM_SPELLCASTING_NONE = 19593;
|
||||
|
||||
//:: PRC8 Hidden Talent Feats
|
||||
const int FEAT_HIDDEN_TALENT = 25900;
|
||||
const int FEAT_HIDDEN_TALENT_BIOFEEDBACK = 25901;
|
||||
const int FEAT_HIDDEN_TALENT_BITE_WOLF = 25902;
|
||||
const int FEAT_HIDDEN_TALENT_BOLT = 25903;
|
||||
|
||||
@@ -400,5 +400,4 @@ int GetBestAvailableSpell(object oTarget)
|
||||
if(nBestSpell == 99999) nBestSpell = GetBestL1Spell(oTarget, nBestSpell);
|
||||
if(nBestSpell == 99999) nBestSpell = GetBestL0Spell(oTarget, nBestSpell);
|
||||
return nBestSpell;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -124,6 +124,8 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#include "prc_alterations"
|
||||
#include "prcsp_archmaginc"
|
||||
#include "prc_inc_spells"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
|
||||
@@ -3859,7 +3859,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_ARCHIVIST, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_ARCHIVIST, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_ARCHIVIST, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
|
||||
@@ -4193,7 +4196,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_CLERIC, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_CLERIC, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_CLERIC, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
|
||||
@@ -4309,9 +4315,12 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_DRUID, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster); */
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_DRUID, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_DRUID, oCaster))
|
||||
/* if(GetHasFeat(FEAT_BFZ_SPELLCASTING_DRUID, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_BFZ, oCaster + 1) / 2 */
|
||||
|
||||
// if(GetHasFeat(FEAT_BRIMSTONE_SPEAKER_SPELLCASTING_DRUID, oCaster))
|
||||
@@ -4421,7 +4430,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_FAVOURED_SOUL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_FAVOURED_SOUL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_FAVOURED_SOUL, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
|
||||
@@ -4534,7 +4546,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster); */
|
||||
|
||||
/* if(GetHasFeat(FEAT_BFZ_SPELLCASTING_HEALER, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2; */
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2; */
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_HEALER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BRIMSTONE_SPEAKER_SPELLCASTING_HEALER, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BRIMSTONE_SPEAKER, oCaster) + 1) / 2;
|
||||
@@ -4641,7 +4656,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_JUSTICEWW, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_JOWAW, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_JUSTICEWW, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
|
||||
@@ -4742,6 +4760,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
|
||||
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_KNIGHT_CHALICE, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_KOTC, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_KNIGHT_CHALICE, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
@@ -4849,6 +4870,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
|
||||
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_KNIGHT_MIDDLECIRCLE, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_KOTMC, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_KNIGHT_MIDDLECIRCLE, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
@@ -4962,6 +4986,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
|
||||
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_NENTYAR_HUNTER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_NENTYAR_HUNTER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_NENTYAR_HUNTER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster); */
|
||||
@@ -5164,6 +5191,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
|
||||
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_PALADIN, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_PALADIN, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_PALADIN, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
@@ -5272,7 +5302,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_RANGER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_RANGER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_RANGER, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
|
||||
@@ -5385,7 +5418,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_OASHAMAN, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_OASHAMAN, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_OASHAMAN, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
|
||||
@@ -5599,7 +5635,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_SOHEI, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_SOHEI, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_SOHEI, oCaster))
|
||||
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
|
||||
@@ -5704,6 +5743,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
|
||||
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_SOL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_SOL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_SOL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
|
||||
|
||||
@@ -16,6 +16,7 @@ Command summary:
|
||||
*/
|
||||
|
||||
#include "prc_inc_chat"
|
||||
#include "inc_persist_loca"
|
||||
|
||||
const string CMD_POWER_ATTACK = "pow-erattack";
|
||||
|
||||
|
||||
@@ -380,6 +380,7 @@ int Vile_Feat(int iTypeWeap)
|
||||
case BASE_ITEM_BASTARDSWORD: return GetHasFeat(FEAT_VILE_MARTIAL_BASTARDSWORD);
|
||||
case BASE_ITEM_BATTLEAXE: return GetHasFeat(FEAT_VILE_MARTIAL_BATTLEAXE);
|
||||
case BASE_ITEM_CLUB: return GetHasFeat(FEAT_VILE_MARTIAL_CLUB);
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return GetHasFeat(FEAT_VILE_MARTIAL_CLUB);
|
||||
case BASE_ITEM_DAGGER: return GetHasFeat(FEAT_VILE_MARTIAL_DAGGER);
|
||||
case BASE_ITEM_DART: return GetHasFeat(FEAT_VILE_MARTIAL_DART);
|
||||
case BASE_ITEM_DIREMACE: return GetHasFeat(FEAT_VILE_MARTIAL_DIREMACE);
|
||||
@@ -426,7 +427,7 @@ int Vile_Feat(int iTypeWeap)
|
||||
GetHasFeat(FEAT_VILE_MARTIAL_RAPIER) ||
|
||||
GetHasFeat(FEAT_VILE_MARTIAL_ELVEN_THINBLADE));
|
||||
|
||||
case BASE_ITEM_ELVEN_COURTBLADE: return GetHasFeat(FEAT_VILE_MARTIAL_GREATSWORD ||
|
||||
case BASE_ITEM_ELVEN_COURTBLADE: return (GetHasFeat(FEAT_VILE_MARTIAL_GREATSWORD) ||
|
||||
GetHasFeat(FEAT_VILE_MARTIAL_ELVEN_COURTBLADE));
|
||||
|
||||
case BASE_ITEM_DOUBLE_SCIMITAR: return GetHasFeat(FEAT_VILE_MARTIAL_DBL_SCIMITAR);
|
||||
@@ -461,6 +462,7 @@ int GetSanctifedMartialFeat(int iTypeWeap)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_SANCTIFY_MARTIAL_BASTARDSWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_SANCTIFY_MARTIAL_BATTLEAXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_SANCTIFY_MARTIAL_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_SANCTIFY_MARTIAL_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_SANCTIFY_MARTIAL_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_SANCTIFY_MARTIAL_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_SANCTIFY_MARTIAL_DIREMACE;
|
||||
@@ -535,6 +537,7 @@ int Sanctify_Feat(int iTypeWeap)
|
||||
case BASE_ITEM_BASTARDSWORD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_BASTARDSWORD);
|
||||
case BASE_ITEM_BATTLEAXE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_BATTLEAXE);
|
||||
case BASE_ITEM_CLUB: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_CLUB);
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_CLUB);
|
||||
case BASE_ITEM_DAGGER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DAGGER);
|
||||
case BASE_ITEM_DART: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DART);
|
||||
case BASE_ITEM_DIREMACE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DIREMACE);
|
||||
|
||||
@@ -1082,7 +1082,7 @@ int GetIsTwoHandedMeleeWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_HEAVYFLAIL: return TRUE;
|
||||
case BASE_ITEM_SCYTHE: return TRUE;
|
||||
case BASE_ITEM_QUARTERSTAFF: return TRUE;
|
||||
case BASE_ITEM_MAGICSTAFF: return TRUE;
|
||||
//case BASE_ITEM_MAGICSTAFF: return TRUE;
|
||||
case BASE_ITEM_ELVEN_COURTBLADE: return TRUE;
|
||||
case BASE_ITEM_MAUL: return TRUE;
|
||||
case BASE_ITEM_FALCHION: return TRUE;
|
||||
@@ -1141,8 +1141,8 @@ int GetIsSimpleWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_CSLSHPRCWEAP: return 1;
|
||||
case BASE_ITEM_GLOVES: return 1;
|
||||
case BASE_ITEM_BRACER: return 1;
|
||||
|
||||
case BASE_ITEM_CLUB: return 2;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return 1;
|
||||
|
||||
case BASE_ITEM_DAGGER: return 2;
|
||||
case BASE_ITEM_LIGHTMACE: return 2;
|
||||
case BASE_ITEM_SICKLE: return 2;
|
||||
@@ -1279,6 +1279,19 @@ struct WeaponFeat GetAllFeatsOfWeaponType(int iWeaponType)
|
||||
sFeat.VileMartialStrike = FEAT_VILE_MARTIAL_CLUB;
|
||||
break;
|
||||
}
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: {
|
||||
sFeat.Focus = FEAT_WEAPON_FOCUS_CLUB;
|
||||
sFeat.Specialization = FEAT_WEAPON_SPECIALIZATION_CLUB;
|
||||
sFeat.EpicFocus = FEAT_EPIC_WEAPON_FOCUS_CLUB;
|
||||
sFeat.EpicSpecialization = FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB;
|
||||
sFeat.ImprovedCritical = FEAT_IMPROVED_CRITICAL_CLUB;
|
||||
sFeat.OverwhelmingCritical = FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB;
|
||||
sFeat.DevastatingCritical = FEAT_EPIC_DEVASTATING_CRITICAL_CLUB;
|
||||
sFeat.WeaponOfChoice = FEAT_WEAPON_OF_CHOICE_CLUB;
|
||||
sFeat.SanctifyMartialStrike = FEAT_SANCTIFY_MARTIAL_CLUB;
|
||||
sFeat.VileMartialStrike = FEAT_VILE_MARTIAL_CLUB;
|
||||
break;
|
||||
}
|
||||
case BASE_ITEM_DAGGER: {
|
||||
sFeat.Focus = FEAT_WEAPON_FOCUS_DAGGER;
|
||||
sFeat.Specialization = FEAT_WEAPON_SPECIALIZATION_DAGGER;
|
||||
@@ -8090,7 +8103,12 @@ void AttackLoopLogic(object oDefender, object oAttacker,
|
||||
if (DEBUG) DoDebug("entered AttackLoopLogic: bFirstAttack = " + IntToString(bFirstAttack) + ", cleave = " + IntToString(bIsCleaveAttack) + ", current action = " + GetActionName(iAction));
|
||||
if (DEBUG) DoDebug("AttackLoopLogic: iMainAttacks = " + IntToString(iMainAttacks) + ", iOffHandAttacks = " + IntToString(iOffHandAttacks) + ", iBonusAttacks = " + IntToString(iBonusAttacks));
|
||||
|
||||
int bIsRangedAttack = sAttackVars.bIsRangedWeapon || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED;
|
||||
//int bIsRangedAttack = sAttackVars.bIsRangedWeapon || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED;
|
||||
|
||||
int bIsRangedAttack = sAttackVars.bIsRangedWeapon ||
|
||||
sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL ||
|
||||
sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED ||
|
||||
GetLocalInt(oAttacker, "WhirlingBlade");
|
||||
|
||||
// check for valid target etc., but only if it is not a cleave or circle kick (in this case we checked all of this before)
|
||||
if (!bIsCleaveAttack)
|
||||
|
||||
@@ -273,6 +273,7 @@ void TigerBlooded(object oInitiator, object oTarget);
|
||||
|
||||
#include "prc_inc_combat"
|
||||
#include "prc_inc_sp_tch"
|
||||
#include "prc_feat_const"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
@@ -1321,7 +1322,29 @@ int DoTrip(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TRUE,
|
||||
DelayCommand(0.0, PerformAttack(oTarget, oPC, eNone, 0.0, 0, 0, 0, "Improved Trip Free Attack Hit", "Improved Trip Free Attack Miss"));
|
||||
}
|
||||
}
|
||||
else // If you fail, enemy gets a counter trip attempt, using Strength
|
||||
else // If you fail, enemy gets a counter trip attempt, using Strength
|
||||
{
|
||||
if(!nCounterTrip)
|
||||
{
|
||||
nTargetStat = GetAbilityModifier(ABILITY_STRENGTH, oTarget) + GetCombatMoveCheckBonus(oTarget, COMBAT_MOVE_TRIP, FALSE, TRUE);
|
||||
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
|
||||
// Roll counter trip attempt
|
||||
nTargetCheck = nTargetStat + nTargetBonus + d20();
|
||||
nPCCheck = nPCStat + nPCBonus + d20();
|
||||
// If counters aren't allowed, don't knock em down
|
||||
// Its down here to allow the text message to go through
|
||||
SendMessageToPC(oPC, "Enemy Counter Trip Check: "+IntToString(nPCCheck)+" vs "+IntToString(nTargetCheck));
|
||||
|
||||
SetLocalInt(oPC, "TripDifference", nTargetCheck - nPCCheck);
|
||||
DelayCommand(2.0, DeleteLocalInt(oPC, "TripDifference"));
|
||||
}
|
||||
if (nTargetCheck >= nPCCheck && nCounterTrip)
|
||||
{
|
||||
// Knock em down
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectKnockdown()), oPC, 6.0);
|
||||
}
|
||||
}
|
||||
/* else // If you fail, enemy gets a counter trip attempt, using Strength
|
||||
{
|
||||
nTargetStat = GetAbilityModifier(ABILITY_STRENGTH, oTarget) + GetCombatMoveCheckBonus(oTarget, COMBAT_MOVE_TRIP, FALSE, TRUE);
|
||||
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
|
||||
@@ -1338,7 +1361,7 @@ int DoTrip(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TRUE,
|
||||
}
|
||||
SetLocalInt(oPC, "TripDifference", nTargetCheck - nPCCheck);
|
||||
DelayCommand(2.0, DeleteLocalInt(oPC, "TripDifference"));
|
||||
}
|
||||
} */
|
||||
}
|
||||
else
|
||||
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
|
||||
@@ -1941,10 +1964,21 @@ void TigerBlooded(object oInitiator, object oTarget)
|
||||
int DoDisarm(object oPC, object oTarget, int nExtraBonus = 0, int nGenerateAoO = TRUE, int nCounter = TRUE)
|
||||
{
|
||||
object oTargetWep = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
|
||||
int bNoDisarm = GetHasFeat(FEAT_INTRINSIC_WEAPON, oTarget);
|
||||
|
||||
string sName = GetName(oTarget);
|
||||
|
||||
if(bNoDisarm)
|
||||
{
|
||||
FloatingTextStringOnCreature(sName+" is wielding an intrinsic weapon", oPC, FALSE);
|
||||
AssignCommand(oPC, ActionAttack(oTarget));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetIsObjectValid(oTargetWep) || GetPlotFlag(oTargetWep) || (!GetIsCreatureDisarmable(oTarget) && !GetPRCSwitch(PRC_PNP_DISARM)) || GetLocalInt(oTarget, "TigerFangDisarm"))
|
||||
{
|
||||
FloatingTextStringOnCreature("Target is not a legal target", oPC, FALSE);
|
||||
FloatingTextStringOnCreature(sName+" is not a legal target", oPC, FALSE);
|
||||
AssignCommand(oPC, ActionAttack(oTarget));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ const int METAMAGIC_QUICKEN_LEVEL = 4;
|
||||
#include "prc_inc_damage"
|
||||
#include "prc_inc_sb_const" // Spell Book Constants
|
||||
#include "x0_i0_position"
|
||||
#include "inc_newspellbook"
|
||||
|
||||
/*
|
||||
access to prc_inc_nwscript via prc_inc_damage
|
||||
@@ -410,6 +411,8 @@ int PRCGetSpellLevelForClass(int nSpell, int nClass)
|
||||
sSpellLevel = Get2DACache("spells", "Cleric", nSpell);
|
||||
else if (nClass == CLASS_TYPE_BARD)
|
||||
sSpellLevel = Get2DACache("spells", "Bard", nSpell);
|
||||
else if (nClass == CLASS_TYPE_ASSASSIN)
|
||||
sSpellLevel = Get2DACache("spells", "Assassin", nSpell);
|
||||
else if (nClass == CLASS_TYPE_CULTIST_SHATTERED_PEAK)
|
||||
sSpellLevel = Get2DACache("spells", "Cultist", nSpell);
|
||||
else if (nClass == CLASS_TYPE_NENTYAR_HUNTER)
|
||||
|
||||
@@ -169,8 +169,8 @@ int GetSubschoolFlags(int nSpellID);
|
||||
/* Includes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#include "inc_2dacache" // already has access via inc_utility
|
||||
//#include "inc_utility"
|
||||
#include "inc_2dacache"
|
||||
#include "inc_utility"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
|
||||
@@ -49,6 +49,8 @@ const int BRILLIANCE_SLOT_3 = 3919;
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
//////////////////////////////////////////////////
|
||||
void TriggerInspiration(object oPC, int nCombat);
|
||||
|
||||
|
||||
void PrepareArcDilSpell(object oPC, int nSpell)
|
||||
{
|
||||
@@ -188,7 +190,8 @@ void SetInspiration(object oPC)
|
||||
for(i = FEAT_FONT_INSPIRATION_1; i <= FEAT_FONT_INSPIRATION_10; i++)
|
||||
if(GetHasFeat(i, oPC)) nFont++;
|
||||
|
||||
nInspiration += nFont * (1 + nFont + 1) / 2;
|
||||
//nInspiration += nFont * (1 + nFont + 1) / 2;
|
||||
nInspiration += nFont * (nFont + 1) / 2;
|
||||
SetLocalInt(oPC, "InspirationPool", nInspiration);
|
||||
FloatingTextStringOnCreature("Encounter begins with "+IntToString(nInspiration)+" inspiration", oPC, FALSE);
|
||||
}
|
||||
@@ -201,6 +204,8 @@ void ClearInspiration(object oPC)
|
||||
|
||||
int ExpendInspiration(object oPC, int nCost)
|
||||
{
|
||||
if (nCost <= 0) return FALSE;
|
||||
|
||||
int nInspiration = GetLocalInt(oPC, "InspirationPool");
|
||||
if (nInspiration >= nCost)
|
||||
{
|
||||
@@ -261,6 +266,21 @@ void FactotumTriggerAbil(object oPC, int nAbil)
|
||||
IPSafeAddItemProperty(oSkin, ipIP, 60.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
||||
}
|
||||
|
||||
void TriggerInspiration(object oPC, int nCombat)
|
||||
{
|
||||
SetLocalInt(oPC, "InspirationHBRunning", TRUE);
|
||||
DelayCommand(0.249, DeleteLocalInt(oPC, "InspirationHBRunning"));
|
||||
int nCurrent = GetIsInCombat(oPC);
|
||||
// We just entered combat
|
||||
if (nCurrent == TRUE && nCombat == FALSE)
|
||||
SetInspiration(oPC);
|
||||
else if (nCurrent == FALSE && nCombat == TRUE) // Just left combat
|
||||
ClearInspiration(oPC);
|
||||
|
||||
DelayCommand(0.25, TriggerInspiration(oPC, nCurrent));
|
||||
}
|
||||
|
||||
|
||||
/*void AddCunningBrillianceAbility(object oPC, int nAbil)
|
||||
{
|
||||
if (DEBUG) DoDebug("AddCunningBrillianceAbility "+IntToString(nAbil));
|
||||
|
||||
@@ -23,11 +23,14 @@ const int FEAT_TYPE_IMPROVED_CRITICAL = 5;
|
||||
const int FEAT_TYPE_OVERWHELMING_CRITICAL = 6;
|
||||
const int FEAT_TYPE_DEVASTATING_CRITICAL = 7;
|
||||
const int FEAT_TYPE_WEAPON_OF_CHOICE = 8;
|
||||
const int FEAT_TYPE_WEAPON_PROFICIENCY = 9;
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function prototypes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
int GetProficiencyFeatOfWeaponType(int iWeaponType);
|
||||
|
||||
/**
|
||||
* Returns the appropriate weapon feat given a weapon type.
|
||||
*
|
||||
@@ -210,10 +213,86 @@ int GetFeatOfWeaponType(int iWeaponType, int iFeatType)
|
||||
case FEAT_TYPE_OVERWHELMING_CRITICAL: return GetOverwhelmingCriticalFeatOfWeaponType(iWeaponType);
|
||||
case FEAT_TYPE_DEVASTATING_CRITICAL: return GetDevastatingCriticalFeatOfWeaponType(iWeaponType);
|
||||
case FEAT_TYPE_WEAPON_OF_CHOICE: return GetWeaponOfChoiceFeatOfWeaponType(iWeaponType);
|
||||
case FEAT_TYPE_WEAPON_PROFICIENCY: return GetProficiencyFeatOfWeaponType(iWeaponType);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GetProficiencyFeatOfWeaponType(int iWeaponType)
|
||||
{
|
||||
switch(iWeaponType)
|
||||
{
|
||||
case BASE_ITEM_CBLUDGWEAPON:
|
||||
case BASE_ITEM_CPIERCWEAPON:
|
||||
case BASE_ITEM_CSLASHWEAPON:
|
||||
case BASE_ITEM_CSLSHPRCWEAP: return FEAT_WEAPON_PROFICIENCY_CREATURE;
|
||||
case BASE_ITEM_INVALID: return FEAT_IMPROVED_UNARMED_STRIKE;
|
||||
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_WEAPON_PROFICIENCY_BATTLEAXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_WEAPON_PROFICIENCY_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_WEAPON_PROFICIENCY_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_WEAPON_PROFICIENCY_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_WEAPON_PROFICIENCY_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_WEAPON_PROFICIENCY_DIRE_MACE;
|
||||
case BASE_ITEM_DOUBLEAXE: return FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE;
|
||||
case BASE_ITEM_DWARVENWARAXE: return FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE;
|
||||
case BASE_ITEM_GREATAXE: return FEAT_WEAPON_PROFICIENCY_GREATAXE;
|
||||
case BASE_ITEM_GREATSWORD: return FEAT_WEAPON_PROFICIENCY_GREATSWORD;
|
||||
case BASE_ITEM_HALBERD: return FEAT_WEAPON_PROFICIENCY_HALBERD;
|
||||
case BASE_ITEM_HANDAXE: return FEAT_WEAPON_PROFICIENCY_HANDAXE;
|
||||
case BASE_ITEM_HEAVYCROSSBOW: return FEAT_WEAPON_PROFICIENCY_HEAVY_XBOW;
|
||||
case BASE_ITEM_HEAVYFLAIL: return FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL;
|
||||
case BASE_ITEM_KAMA: return FEAT_WEAPON_PROFICIENCY_KAMA;
|
||||
case BASE_ITEM_KATANA: return FEAT_WEAPON_PROFICIENCY_KATANA;
|
||||
case BASE_ITEM_KUKRI: return FEAT_WEAPON_PROFICIENCY_KUKRI;
|
||||
case BASE_ITEM_LIGHTCROSSBOW: return FEAT_WEAPON_PROFICIENCY_LIGHT_XBOW;
|
||||
case BASE_ITEM_LIGHTFLAIL: return FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL;
|
||||
case BASE_ITEM_LIGHTHAMMER: return FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER;
|
||||
case BASE_ITEM_LIGHTMACE: return FEAT_WEAPON_PROFICIENCY_LIGHT_MACE;
|
||||
case BASE_ITEM_LONGBOW: return FEAT_WEAPON_PROFICIENCY_LONGBOW;
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_WEAPON_PROFICIENCY_LONGSWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_WEAPON_PROFICIENCY_MORNINGSTAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_WEAPON_PROFICIENCY_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_WEAPON_PROFICIENCY_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_WEAPON_PROFICIENCY_SCYTHE;
|
||||
case BASE_ITEM_SHORTBOW: return FEAT_WEAPON_PROFICIENCY_SHORTBOW;
|
||||
case BASE_ITEM_SHORTSPEAR: return FEAT_WEAPON_PROFICIENCY_SHORTSPEAR;
|
||||
case BASE_ITEM_SHORTSWORD: return FEAT_WEAPON_PROFICIENCY_SHORTSWORD;
|
||||
case BASE_ITEM_SHURIKEN: return FEAT_WEAPON_PROFICIENCY_SHURIKEN;
|
||||
case BASE_ITEM_SICKLE: return FEAT_WEAPON_PROFICIENCY_SICKLE;
|
||||
case BASE_ITEM_SLING: return FEAT_WEAPON_PROFICIENCY_SLING;
|
||||
case BASE_ITEM_THROWINGAXE: return FEAT_WEAPON_PROFICIENCY_THROWING_AXE;
|
||||
case BASE_ITEM_TRIDENT: return FEAT_WEAPON_PROFICIENCY_TRIDENT;
|
||||
case BASE_ITEM_TWOBLADEDSWORD: return FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD;
|
||||
case BASE_ITEM_WARHAMMER: return FEAT_WEAPON_PROFICIENCY_WARHAMMER;
|
||||
case BASE_ITEM_WHIP: return FEAT_WEAPON_PROFICIENCY_WHIP;
|
||||
|
||||
//:: new item types
|
||||
case BASE_ITEM_DOUBLE_SCIMITAR: return FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR;
|
||||
case BASE_ITEM_EAGLE_CLAW: return FEAT_WEAPON_PROFICIENCY_EAGLE_CLAW;
|
||||
case BASE_ITEM_ELVEN_COURTBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_COURTBLADE;
|
||||
case BASE_ITEM_ELVEN_LIGHTBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_LIGHTBLADE;
|
||||
case BASE_ITEM_ELVEN_THINBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_THINBLADE;
|
||||
case BASE_ITEM_FALCHION: return FEAT_WEAPON_PROFICIENCY_FALCHION;
|
||||
case BASE_ITEM_GOAD: return FEAT_WEAPON_PROFICIENCY_GOAD;
|
||||
case BASE_ITEM_HEAVY_MACE: return FEAT_WEAPON_PROFICIENCY_HEAVY_MACE;
|
||||
case BASE_ITEM_HEAVY_PICK: return FEAT_WEAPON_PROFICIENCY_HEAVY_PICK;
|
||||
case BASE_ITEM_KATAR: return FEAT_WEAPON_PROFICIENCY_KATAR;
|
||||
case BASE_ITEM_LIGHT_LANCE: return FEAT_WEAPON_PROFICIENCY_LIGHT_LANCE;
|
||||
case BASE_ITEM_LIGHT_PICK: return FEAT_WEAPON_PROFICIENCY_LIGHT_PICK;
|
||||
case BASE_ITEM_MAUL: return FEAT_WEAPON_PROFICIENCY_MAUL;
|
||||
case BASE_ITEM_NUNCHAKU: return FEAT_WEAPON_PROFICIENCY_NUNCHAKU;
|
||||
case BASE_ITEM_SAI: return FEAT_WEAPON_PROFICIENCY_SAI;
|
||||
case BASE_ITEM_SAP: return FEAT_WEAPON_PROFICIENCY_SAP;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int GetFocusFeatOfWeaponType(int iWeaponType)
|
||||
{
|
||||
switch(iWeaponType)
|
||||
@@ -226,6 +305,7 @@ int GetFocusFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_WEAPON_FOCUS_BASTARD_SWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_WEAPON_FOCUS_BATTLE_AXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_WEAPON_FOCUS_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_WEAPON_FOCUS_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_WEAPON_FOCUS_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_WEAPON_FOCUS_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_WEAPON_FOCUS_DIRE_MACE;
|
||||
@@ -297,6 +377,7 @@ int GetSpecializationFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_WEAPON_SPECIALIZATION_BASTARD_SWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_WEAPON_SPECIALIZATION_BATTLE_AXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_WEAPON_SPECIALIZATION_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_WEAPON_SPECIALIZATION_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_WEAPON_SPECIALIZATION_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_WEAPON_SPECIALIZATION_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_WEAPON_SPECIALIZATION_DIRE_MACE;
|
||||
@@ -368,6 +449,7 @@ int GetEpicFocusFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_EPIC_WEAPON_FOCUS_BASTARDSWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_EPIC_WEAPON_FOCUS_BATTLEAXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_EPIC_WEAPON_FOCUS_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_EPIC_WEAPON_FOCUS_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_EPIC_WEAPON_FOCUS_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_EPIC_WEAPON_FOCUS_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_EPIC_WEAPON_FOCUS_DIREMACE;
|
||||
@@ -439,6 +521,7 @@ int GetEpicSpecializationFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_EPIC_WEAPON_SPECIALIZATION_BASTARDSWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_EPIC_WEAPON_SPECIALIZATION_BATTLEAXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_EPIC_WEAPON_SPECIALIZATION_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_EPIC_WEAPON_SPECIALIZATION_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_EPIC_WEAPON_SPECIALIZATION_DIREMACE;
|
||||
@@ -510,6 +593,7 @@ int GetImprovedCriticalFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_IMPROVED_CRITICAL_BASTARD_SWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_IMPROVED_CRITICAL_BATTLE_AXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_IMPROVED_CRITICAL_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_IMPROVED_CRITICAL_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_IMPROVED_CRITICAL_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_IMPROVED_CRITICAL_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_IMPROVED_CRITICAL_DIRE_MACE;
|
||||
@@ -581,6 +665,7 @@ int GetOverwhelmingCriticalFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_EPIC_OVERWHELMING_CRITICAL_BASTARDSWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_EPIC_OVERWHELMING_CRITICAL_BATTLEAXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_EPIC_OVERWHELMING_CRITICAL_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_EPIC_OVERWHELMING_CRITICAL_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_EPIC_OVERWHELMING_CRITICAL_DIREMACE;
|
||||
@@ -652,6 +737,7 @@ int GetDevastatingCriticalFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_EPIC_DEVASTATING_CRITICAL_BASTARDSWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_EPIC_DEVASTATING_CRITICAL_BATTLEAXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_EPIC_DEVASTATING_CRITICAL_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_EPIC_DEVASTATING_CRITICAL_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_EPIC_DEVASTATING_CRITICAL_DAGGER;
|
||||
case BASE_ITEM_DART: return FEAT_EPIC_DEVASTATING_CRITICAL_DART;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_EPIC_DEVASTATING_CRITICAL_DIREMACE;
|
||||
@@ -718,6 +804,7 @@ int GetWeaponOfChoiceFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_BASTARDSWORD: return FEAT_WEAPON_OF_CHOICE_BASTARDSWORD;
|
||||
case BASE_ITEM_BATTLEAXE: return FEAT_WEAPON_OF_CHOICE_BATTLEAXE;
|
||||
case BASE_ITEM_CLUB: return FEAT_WEAPON_OF_CHOICE_CLUB;
|
||||
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_WEAPON_OF_CHOICE_CLUB;
|
||||
case BASE_ITEM_DAGGER: return FEAT_WEAPON_OF_CHOICE_DAGGER;
|
||||
case BASE_ITEM_DIREMACE: return FEAT_WEAPON_OF_CHOICE_DIREMACE;
|
||||
case BASE_ITEM_DOUBLEAXE: return FEAT_WEAPON_OF_CHOICE_DOUBLEAXE;
|
||||
@@ -844,4 +931,6 @@ int PRCLargeWeaponCheck(int iBaseType, int nSize)
|
||||
}
|
||||
}
|
||||
return sTest != "" && sTest != IntToString(nSize);
|
||||
}
|
||||
}
|
||||
|
||||
//::void main(){}
|
||||
@@ -109,7 +109,7 @@ void SetupCharacterData(object oPC)
|
||||
case CLASS_TYPE_ARCANE_DUELIST: sScript = "prc_arcduel"; break;
|
||||
case CLASS_TYPE_ARCHIVIST: sScript = "prc_archivist"; iData |= 0x01; break;
|
||||
case CLASS_TYPE_ASSASSIN: break;
|
||||
//case CLASS_TYPE_BAELNORN: sScript = "prc_baelnorn"; break;
|
||||
//case CLASS_TYPE_BAELNORN: sScript = "prc_baelnorn"; break;
|
||||
case CLASS_TYPE_BARD: iData |= 0x07; break;
|
||||
case CLASS_TYPE_BATTLESMITH: sScript = "prc_battlesmith"; break;
|
||||
case CLASS_TYPE_BEGUILER: iData |= 0x03; break;
|
||||
@@ -431,7 +431,7 @@ void EvalPRCFeats(object oPC)
|
||||
ExecuteScript("moi_events", oPC);
|
||||
|
||||
if (GetIsBinder(oPC))
|
||||
ExecuteScript("bnd_events", oPC);
|
||||
ExecuteScript("bnd_events", oPC);
|
||||
|
||||
// check if character with crafting feat has appropriate base item in her inventory
|
||||
// x - moved from prc_onhb_indiv.nss
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "prc_feat_const"
|
||||
#include "inc_item_props"
|
||||
#include "prc_inc_spells"
|
||||
|
||||
const string BRUTAL_STRIKE_MODE_VAR = "PRC_BRUTAL_STRIKE_MODE";
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ void CheckForPnPHolyAvenger(object oItem);
|
||||
|
||||
#include "inc_utility"
|
||||
#include "prc_inc_newip"
|
||||
#include "prc_inc_castlvl"
|
||||
#include "inc_newspellbook"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
1993
src/include/prc_inc_json.nss
Normal file
1993
src/include/prc_inc_json.nss
Normal file
File diff suppressed because it is too large
Load Diff
@@ -430,8 +430,8 @@ string GetMaterialName( int iMaterialType, int bLowerCase = FALSE)
|
||||
case IP_MATERIAL_ROPE_GIANT_HAIR: sName = IP_MATERIAL_NAME_ROPE_GIANT_HAIR; break;
|
||||
case IP_MATERIAL_OBSIDIAN: sName = IP_MATERIAL_NAME_OBSIDIAN; break;
|
||||
case IP_MATERIAL_BAMBOO: sName = IP_MATERIAL_NAME_BAMBOO; break;
|
||||
case IP_MATERIAL_POTTERY: sName = IP_MATERIAL_NAME_POTTERY; break;
|
||||
case IP_MATERIAL_GLASSTEEL: sName = IP_MATERIAL_NAME_GLASSTEEL; break;
|
||||
case IP_MATERIAL_POTTERY: sName = IP_MATERIAL_NAME_POTTERY; break;
|
||||
case IP_MATERIAL_GLASSTEEL: sName = IP_MATERIAL_NAME_GLASSTEEL; break;
|
||||
case IP_MATERIAL_HERB: sName = IP_MATERIAL_NAME_HERB; break;
|
||||
|
||||
default: return "";
|
||||
|
||||
@@ -1,9 +1,68 @@
|
||||
//:: prc_inc_nat_hb
|
||||
//::
|
||||
//:: void main(){}
|
||||
|
||||
|
||||
void DoNaturalWeaponHB(object oPC = OBJECT_SELF);
|
||||
|
||||
#include "prc_inc_combat"
|
||||
#include "prc_inc_template"
|
||||
|
||||
object GetProperTarget(object oPC, object oTarget)
|
||||
/**
|
||||
* Finds a valid enemy target in melee range when the original target is invalid.
|
||||
* Now includes input validation, LOS checks, configurable radius, and target priority.
|
||||
*
|
||||
* @param oPC The creature seeking a new target
|
||||
* @param oTarget The original (invalid) target
|
||||
* @param fRadius Search radius in meters (optional, defaults to melee range)
|
||||
* @return A valid enemy target or OBJECT_INVALID if none found
|
||||
*/
|
||||
object GetProperTarget(object oPC, object oTarget, float fRadius = MELEE_RANGE_METERS)
|
||||
{
|
||||
// Input validation
|
||||
if(!GetIsObjectValid(oPC))
|
||||
{
|
||||
DoDebug("GetProperTarget(): Invalid oPC parameter");
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
// Use target list system for better target selection
|
||||
PurgeTargetList(oPC);
|
||||
|
||||
location lPC = GetLocation(oPC);
|
||||
object oTest = MyFirstObjectInShape(SHAPE_SPHERE, fRadius, lPC, TRUE, OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(GetIsObjectValid(oTest))
|
||||
{
|
||||
// Basic validation checks
|
||||
if(oTest != oPC && // Not self
|
||||
GetIsEnemy(oPC, oTest) && // Is enemy
|
||||
GetIsInMeleeRange(oPC, oTest) && // In melee range
|
||||
!GetIsDead(oTest) && // Is alive
|
||||
LineOfSightObject(oPC, oTest)) // Has line of sight
|
||||
{
|
||||
// Add to target list with priority based on distance (nearest first)
|
||||
AddToTargetList(oTest, oPC, INSERTION_BIAS_DISTANCE, FALSE);
|
||||
}
|
||||
|
||||
oTest = MyNextObjectInShape(SHAPE_SPHERE, fRadius, lPC, TRUE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
|
||||
// Get the highest priority target (nearest enemy)
|
||||
object oBestTarget = GetTargetListHead(oPC);
|
||||
PurgeTargetList(oPC);
|
||||
|
||||
if(GetIsObjectValid(oBestTarget))
|
||||
{
|
||||
DoDebug("GetProperTarget(): Selected target " + GetName(oBestTarget) +
|
||||
" for " + GetName(oPC));
|
||||
return oBestTarget;
|
||||
}
|
||||
|
||||
// No valid target found
|
||||
DoDebug("GetProperTarget(): No valid target found for " + GetName(oPC));
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
/* object GetProperTarget(object oPC, object oTarget)
|
||||
{
|
||||
location lTarget = GetLocation(oPC);
|
||||
// Use the function to get the closest creature as a target
|
||||
@@ -21,7 +80,7 @@ object GetProperTarget(object oPC, object oTarget)
|
||||
}
|
||||
|
||||
return oTarget;
|
||||
}
|
||||
} */
|
||||
|
||||
void DoNaturalAttack(object oWeapon)
|
||||
{
|
||||
@@ -289,59 +348,72 @@ void DoOverflowOnhandAttack(int nAttackMod)
|
||||
);
|
||||
}
|
||||
|
||||
void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
|
||||
/* void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
|
||||
{
|
||||
//not in combat, abort
|
||||
if(!GetIsInCombat(oPC))
|
||||
return;
|
||||
|
||||
// if(DEBUG) DoDebug("entered DoNaturalWeaponHB");
|
||||
if(DEBUG) DoDebug("prc_inc_nat_hb: entered DoNaturalWeaponHB");
|
||||
|
||||
float fDelay = 0.1 + IntToFloat(Random(10))/100.0;
|
||||
|
||||
//no natural weapons, abort
|
||||
//in a different form, abort for now fix it later
|
||||
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
|
||||
&& !GetIsPolyMorphedOrShifted(oPC))
|
||||
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
|
||||
&& !GetIsPolyMorphedOrShifted(oPC))
|
||||
{
|
||||
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creature has natural secondary weapons");
|
||||
UpdateSecondaryWeaponSizes(oPC);
|
||||
int i;
|
||||
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
|
||||
{
|
||||
// DoDebug("DoNaturalWeaponHB: creature has natural secondary weapons");
|
||||
UpdateSecondaryWeaponSizes(oPC);
|
||||
int i;
|
||||
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
|
||||
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
|
||||
if(sResRef != "")
|
||||
{
|
||||
//get the resref to use
|
||||
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
|
||||
//if null, move to next
|
||||
if(sResRef != "")
|
||||
// Get stored weapon object, or create if doesn't exist
|
||||
object oWeapon = GetLocalObject(oPC, "NAT_SEC_WEAP_" + sResRef);
|
||||
|
||||
if(!GetIsObjectValid(oWeapon))
|
||||
{
|
||||
//get the created item
|
||||
object oWeapon = GetObjectByTag(sResRef);
|
||||
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creating and storing creature weapon " + sResRef);
|
||||
oWeapon = CreateItemOnObject(sResRef, oPC);
|
||||
|
||||
if(!GetIsObjectValid(oWeapon))
|
||||
{
|
||||
object oLimbo = GetObjectByTag("HEARTOFCHAOS");
|
||||
location lLimbo = GetLocation(oLimbo);
|
||||
if(!GetIsObjectValid(oLimbo))
|
||||
lLimbo = GetStartingLocation();
|
||||
oWeapon = CreateObject(OBJECT_TYPE_ITEM, sResRef, lLimbo);
|
||||
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: ERROR - CreateItemOnObject FAILED for " + sResRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: SUCCESS - weapon created, tag=" + GetTag(oWeapon) + ", name=" + GetName(oWeapon));
|
||||
SetIdentified(oWeapon, TRUE);
|
||||
SetLocalObject(oPC, "NAT_SEC_WEAP_" + sResRef, oWeapon);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: using stored creature weapon object");
|
||||
}
|
||||
|
||||
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
|
||||
//do the attack within a delay
|
||||
/*
|
||||
// motu99: commented this out; AssignCommand ist not needed, because OBJECT_SELF is oPC - using AssignCommand will only degrade performance
|
||||
AssignCommand(oPC, DelayCommand(fDelay, DoNaturalAttack(oWeapon)));
|
||||
*/
|
||||
|
||||
// Double-check validity before scheduling
|
||||
if(GetIsObjectValid(oWeapon))
|
||||
{
|
||||
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
|
||||
DelayCommand(fDelay, DoNaturalAttack(oWeapon));
|
||||
|
||||
//calculate the delay to use next time
|
||||
fDelay += 2.05;
|
||||
if(fDelay > 6.0)
|
||||
fDelay -= 6.0;
|
||||
fDelay -= 6.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: ERROR - weapon object is INVALID, cannot schedule attack");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int iMod = 5; // motu99: added check for monk weapon
|
||||
if(GetHasMonkWeaponEquipped(oPC)) iMod = 3;
|
||||
@@ -357,10 +429,10 @@ void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
|
||||
for(i = 0; i < nOverflowAttackCount; i++)
|
||||
{
|
||||
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted overflow attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
|
||||
/*
|
||||
|
||||
// motu99: see comment above why this is commented out
|
||||
AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
|
||||
*/
|
||||
//AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
|
||||
|
||||
DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty));
|
||||
|
||||
//calculate the delay to use
|
||||
@@ -399,6 +471,128 @@ void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
|
||||
{
|
||||
//not in combat, abort
|
||||
if(!GetIsInCombat(oPC))
|
||||
return;
|
||||
|
||||
if(DEBUG) DoDebug("prc_inc_nat_hb: entered DoNaturalWeaponHB");
|
||||
|
||||
float fDelay = 0.1 + IntToFloat(Random(10))/100.0;
|
||||
|
||||
//no natural weapons, abort
|
||||
//in a different form, abort for now fix it later
|
||||
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
|
||||
&& !GetIsPolyMorphedOrShifted(oPC))
|
||||
{
|
||||
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creature has natural secondary weapons");
|
||||
UpdateSecondaryWeaponSizes(oPC);
|
||||
int i;
|
||||
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
|
||||
{
|
||||
//get the resref to use
|
||||
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
|
||||
//if null, move to next
|
||||
if(sResRef != "")
|
||||
{
|
||||
//get the created item
|
||||
object oWeapon = GetObjectByTag(sResRef);
|
||||
if(!GetIsObjectValid(oWeapon))
|
||||
{
|
||||
object oLimbo = GetObjectByTag("HEARTOFCHAOS");
|
||||
location lLimbo = GetLocation(oLimbo);
|
||||
if(!GetIsObjectValid(oLimbo))
|
||||
lLimbo = GetStartingLocation();
|
||||
oWeapon = CreateObject(OBJECT_TYPE_ITEM, sResRef, lLimbo);
|
||||
DoDebug(PRC_TEXT_WHITE + "prc_inc_nat_hb >> DoNaturalWeaponHB: creature weapon object found!!!");
|
||||
}
|
||||
|
||||
// Check for enhancements after creating the weapon object
|
||||
int nEnhance = GetLocalInt(oPC, "PRC_NAT_WEAPON_ENHANCE");
|
||||
if(nEnhance > 0)
|
||||
{
|
||||
|
||||
DoDebug(PRC_TEXT_WHITE + "prc_inc_nat_hb >> DoNaturalWeaponHB: Applying enhancement.");
|
||||
float fDuration = GetLocalFloat(oPC, "PRC_NAT_WEAPON_ENH_DUR");
|
||||
IPSafeAddItemProperty(oWeapon, ItemPropertyEnhancementBonus(nEnhance), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
|
||||
//do the attack within a delay
|
||||
// motu99: commented this out; AssignCommand ist not needed, because OBJECT_SELF is oPC - using AssignCommand will only degrade performance
|
||||
//AssignCommand(oPC, DelayCommand(fDelay, DoNaturalAttack(oWeapon)));
|
||||
|
||||
DelayCommand(fDelay, DoNaturalAttack(oWeapon));
|
||||
|
||||
//calculate the delay to use next time
|
||||
fDelay += 2.05;
|
||||
if(fDelay > 6.0)
|
||||
fDelay -= 6.0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int iMod = 5; // motu99: added check for monk weapon
|
||||
if(GetHasMonkWeaponEquipped(oPC)) iMod = 3;
|
||||
|
||||
// check for overflow (main hand) attacks
|
||||
int nOverflowAttackCount = GetLocalInt(oPC, "OverflowBaseAttackCount");
|
||||
if(nOverflowAttackCount)
|
||||
{
|
||||
int i;
|
||||
// the first overflow attack would be the seventh main hand attack, at an AB of -30
|
||||
int nAttackPenalty = -6 * iMod; // -30 for normal bab, -18 for monks
|
||||
// DoDebug("DoNaturalWeaponHB(): number of scripted overflow attacks: "+IntToString(nOverflowAttackCount));
|
||||
for(i = 0; i < nOverflowAttackCount; i++)
|
||||
{
|
||||
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted overflow attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
|
||||
|
||||
// motu99: see comment above why this is commented out
|
||||
// AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
|
||||
|
||||
DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty));
|
||||
|
||||
//calculate the delay to use
|
||||
fDelay += 2.05;
|
||||
if(fDelay > 6.0)
|
||||
fDelay -= 6.0;
|
||||
//calculate new attack penalty
|
||||
nAttackPenalty -= iMod; // motu99: usually -5, for monks -3 (unarmed or kama)
|
||||
}
|
||||
}
|
||||
|
||||
// motu99: this is only here for debugging in order to test PerformAttackRound()
|
||||
// must be deleted after debugging!!!
|
||||
//if (GetPRCSwitch(PRC_PNP_TRUESEEING)) DelayCommand(0.01, DoOffhandAttackRound());
|
||||
|
||||
|
||||
// check for overflow offhand attacks
|
||||
int nOffhandAttackCount = GetLocalInt(oPC, "OffhandOverflowAttackCount");
|
||||
// if (DEBUG) DoDebug("DoNaturalWeaponHB: number of scripted offhand attacks = "+IntToString(nOffhandAttackCount));
|
||||
if(nOffhandAttackCount)
|
||||
{
|
||||
int i;
|
||||
int nAttackPenalty = -2 * iMod; // offhand attacks always come at -5 per additional attack (but for monks we assume -3)
|
||||
for(i = 0; i < nOffhandAttackCount; i++)
|
||||
{
|
||||
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted offhand attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
|
||||
|
||||
DelayCommand(fDelay, DoOffhandAttack(nAttackPenalty));
|
||||
|
||||
//calculate the delay to use
|
||||
fDelay += 2.05;
|
||||
if(fDelay > 6.0)
|
||||
fDelay -= 6.0;
|
||||
//calculate new attack penalty
|
||||
nAttackPenalty -= iMod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* motu99's test functions. Not actually used by PRC scripts
|
||||
|
||||
@@ -277,6 +277,32 @@ void ClearNaturalWeapons(object oPC)
|
||||
array_delete(oPC, ARRAY_NAT_PRI_WEAP_ATTACKS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a natural primary weapon to a creature (PC/NPC).
|
||||
*
|
||||
* This function manages a creature's natural primary weapons by storing their
|
||||
* resource references and attack counts in persistent arrays. If the weapon
|
||||
* being added is the first natural weapon, it may automatically become the
|
||||
* creature's active primary natural weapon, unless the creature is a Monk or
|
||||
* Brawler. Optionally, the weapon can be forced to become the active primary
|
||||
* weapon regardless of class.
|
||||
*
|
||||
* @param oPC The creature object to which the natural weapon will be added.
|
||||
* @param sResRef The resource reference string of the natural weapon.
|
||||
* @param nCount (Optional) The number of attacks this natural weapon provides.
|
||||
* Default is 1.
|
||||
* @param nForceUse (Optional) If TRUE, forces this weapon to become the active
|
||||
* primary natural weapon regardless of the creature's class.
|
||||
* Default is FALSE.
|
||||
*
|
||||
* @details
|
||||
* - Creates persistent arrays for weapon references and attack counts if they
|
||||
* do not already exist.
|
||||
* - Checks if the weapon is already present to avoid duplicates.
|
||||
* - Adds the weapon and attack count to the arrays.
|
||||
* - Sets the primary natural weapon index to this weapon if it is the first
|
||||
* natural weapon added, unless the creature is a Monk or Brawler.
|
||||
*/
|
||||
void AddNaturalPrimaryWeapon(object oPC, string sResRef, int nCount = 1, int nForceUse = FALSE)
|
||||
{
|
||||
int nFirstNaturalWeapon = FALSE;
|
||||
|
||||
@@ -572,7 +572,10 @@ int GetMaxEssentiaCapacity(object oMeldshaper, int nClass, int nMeld)
|
||||
{
|
||||
int nMax = 1; // Always can invest one
|
||||
int nHD = GetHitDice(oMeldshaper);
|
||||
if (nHD >= 31) nMax = 5;
|
||||
if (nHD >= 61) nMax = 8;
|
||||
else if (nHD >= 51) nMax = 7;
|
||||
else if (nHD >= 41) nMax = 6;
|
||||
else if (nHD >= 31) nMax = 5;
|
||||
else if (nHD >= 18) nMax = 4;
|
||||
else if (nHD >= 12) nMax = 3;
|
||||
else if (nHD >= 6) nMax = 2;
|
||||
|
||||
@@ -1370,7 +1370,9 @@ void _prc_inc_shifting_ShiftIntoTemplateAux(object oShifter, int nShifterType, o
|
||||
if(GetIsObjectValid(oShifterCWpR)) MyDestroyObject(oShifterCWpR);
|
||||
if(GetIsObjectValid(oShifterCWpL)) MyDestroyObject(oShifterCWpL);
|
||||
if(GetIsObjectValid(oShifterCWpB)) MyDestroyObject(oShifterCWpB);
|
||||
oShifterCWpR = oShifterCWpL = oShifterCWpR = OBJECT_INVALID;
|
||||
oShifterCWpR = OBJECT_INVALID;
|
||||
oShifterCWpL = OBJECT_INVALID;
|
||||
oShifterCWpB = OBJECT_INVALID;
|
||||
|
||||
// Copy the template's weapons and assign equipping
|
||||
|
||||
|
||||
154
src/include/prc_inc_size.nss
Normal file
154
src/include/prc_inc_size.nss
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "prc_inc_util"
|
||||
#include "prc_inc_spells"
|
||||
#include "prc_inc_function"
|
||||
|
||||
// Wrapper function for delayed visual transform with generation tracking
|
||||
void DelayedSetVisualTransform(int nExpectedGeneration, object oTarget, int nTransform, float fValue)
|
||||
{
|
||||
// Read current generation at execution time, not when scheduled
|
||||
if (nExpectedGeneration != GetLocalInt(oTarget, "PRC_SIZE_GENERATION"))
|
||||
{
|
||||
// Generation has changed, don't apply the transform
|
||||
return;
|
||||
}
|
||||
SetObjectVisualTransform(oTarget, nTransform, fValue);
|
||||
}
|
||||
|
||||
// Main wrapper function that handles generation tracking
|
||||
void DelaySetVisualTransform(float fDelay, object oTarget, string sGenerationName, int nTransform, float fValue)
|
||||
{
|
||||
int nExpectedGeneration = GetLocalInt(oTarget, sGenerationName);
|
||||
DelayCommand(fDelay, DelayedSetVisualTransform(nExpectedGeneration, oTarget, nTransform, fValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a size change effect that can enlarge or reduce a creature
|
||||
*
|
||||
* @param oTarget Object to affect
|
||||
* @param nObjectType Object type filter (OBJECT_TYPE_CREATURE, etc.)
|
||||
* @param bEnlarge TRUE to enlarge, FALSE to reduce
|
||||
* @param nChanges Number of size categories to change (0 = reset to original)
|
||||
* @return The size change effect
|
||||
*/
|
||||
|
||||
effect EffectSizeChange(object oTarget, int nObjectType, int bEnlarge, int nChanges)
|
||||
{
|
||||
effect eBlank;
|
||||
|
||||
// Increment generation for any size change
|
||||
int nGeneration = PRC_NextGeneration(GetLocalInt(oTarget, "PRC_SIZE_GENERATION"));
|
||||
SetLocalInt(oTarget, "PRC_SIZE_GENERATION", nGeneration);
|
||||
|
||||
// Store original size if not already stored - READ ACTUAL CURRENT SCALE
|
||||
if(GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE") == 0.0f)
|
||||
{
|
||||
float fCurrentScale = GetObjectVisualTransform(oTarget, OBJECT_VISUAL_TRANSFORM_SCALE);
|
||||
SetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE", fCurrentScale);
|
||||
}
|
||||
|
||||
// Reset to original size
|
||||
if(nChanges == 0)
|
||||
{
|
||||
float fOriginalSize = GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE");
|
||||
DelaySetVisualTransform(0.0f, oTarget, "PRC_SIZE_GENERATION", OBJECT_VISUAL_TRANSFORM_SCALE, fOriginalSize);
|
||||
// DON'T delete PRC_ORIGINAL_SIZE here - keep it for future casts
|
||||
return eBlank;
|
||||
}
|
||||
|
||||
// Get the original scale
|
||||
float fOriginalScale = GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE");
|
||||
|
||||
// Calculate scale factor relative to original size
|
||||
float fScale = fOriginalScale;
|
||||
if(bEnlarge)
|
||||
fScale = fOriginalScale * pow(1.5f, IntToFloat(nChanges));
|
||||
else
|
||||
fScale = fOriginalScale * pow(0.5f, IntToFloat(nChanges));
|
||||
|
||||
// Create the effect link with sanctuary VFX
|
||||
effect eReturn = EffectLinkEffects(EffectVisualEffect(VFX_DUR_SANCTUARY),
|
||||
EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE));
|
||||
|
||||
if(bEnlarge)
|
||||
{
|
||||
eReturn = EffectLinkEffects(eReturn, EffectAttackDecrease(nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_DEXTERITY, 2 * nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectAbilityIncrease(ABILITY_STRENGTH, 2 * nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectACDecrease(nChanges));
|
||||
eReturn = TagEffect(eReturn, "PRC_SIZE_INCREASE");
|
||||
}
|
||||
else
|
||||
{
|
||||
eReturn = EffectLinkEffects(eReturn, EffectAttackIncrease(nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectAbilityIncrease(ABILITY_DEXTERITY, 2 * nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_STRENGTH, 2 * nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectACIncrease(nChanges));
|
||||
eReturn = TagEffect(eReturn, "PRC_SIZE_DECREASE");
|
||||
}
|
||||
|
||||
// Apply visual transform using wrapper
|
||||
DelaySetVisualTransform(0.0f, oTarget, "PRC_SIZE_GENERATION", OBJECT_VISUAL_TRANSFORM_SCALE, fScale);
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* effect EffectSizeChange(object oTarget, int nObjectType, int bEnlarge, int nChanges)
|
||||
{
|
||||
effect eBlank;
|
||||
|
||||
// Increment generation for any size change
|
||||
int nGeneration = PRC_NextGeneration(GetLocalInt(oTarget, "PRC_SIZE_GENERATION"));
|
||||
SetLocalInt(oTarget, "PRC_SIZE_GENERATION", nGeneration);
|
||||
|
||||
// Store original size if not already stored (fixed check)
|
||||
if(GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE") == 0.0f)
|
||||
{
|
||||
SetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE", 1.0f);
|
||||
}
|
||||
|
||||
// Reset to original size
|
||||
if(nChanges == 0)
|
||||
{
|
||||
float fOriginalSize = GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE");
|
||||
DelaySetVisualTransform(0.0f, oTarget, "PRC_SIZE_GENERATION", OBJECT_VISUAL_TRANSFORM_SCALE, fOriginalSize);
|
||||
DeleteLocalFloat(oTarget, "PRC_ORIGINAL_SIZE");
|
||||
return eBlank;
|
||||
}
|
||||
|
||||
// Calculate scale factor using pow() for multi-step changes
|
||||
float fScale = 1.0f;
|
||||
if(bEnlarge)
|
||||
fScale = pow(1.5f, IntToFloat(nChanges)); // 1.5, 2.25, 3.375...
|
||||
else
|
||||
fScale = pow(0.5f, IntToFloat(nChanges)); // 0.5, 0.25, 0.125...
|
||||
|
||||
// Create the effect link based on enlarge/reduce
|
||||
effect eReturn;
|
||||
if(bEnlarge)
|
||||
{
|
||||
eReturn = EffectLinkEffects(EffectAttackDecrease(nChanges),
|
||||
EffectAbilityDecrease(ABILITY_DEXTERITY, 2 * nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectAbilityIncrease(ABILITY_STRENGTH, 2 * nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectACDecrease(nChanges));
|
||||
eReturn = TagEffect(eReturn, "PRC_SIZE_INCREASE");
|
||||
}
|
||||
else
|
||||
{
|
||||
eReturn = EffectLinkEffects(EffectAttackIncrease(nChanges),
|
||||
EffectAbilityIncrease(ABILITY_DEXTERITY, 2 * nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_STRENGTH, 2 * nChanges));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectACIncrease(nChanges));
|
||||
eReturn = TagEffect(eReturn, "PRC_SIZE_DECREASE");
|
||||
}
|
||||
|
||||
// Apply visual transform using wrapper
|
||||
DelaySetVisualTransform(0.0f, oTarget, "PRC_SIZE_GENERATION", OBJECT_VISUAL_TRANSFORM_SCALE, fScale);
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
*/
|
||||
|
||||
//:: void main(){}
|
||||
@@ -363,8 +363,11 @@ int PRCIsFlying(object oCreature)
|
||||
bFlying = TRUE;
|
||||
}
|
||||
if(!bFlying
|
||||
&& ((nWings > 0 && nWings < 79) || nWings == 90))//CEP and Project Q wing models
|
||||
bFlying = TRUE;
|
||||
&& ((nWings > 0 && nWings < 79)
|
||||
|| (nWings > 1959 && nWings < 1962)
|
||||
|| (nWings > 1962 && nWings < 1966)
|
||||
|| nWings == 90))//CEP and Project Q wing models
|
||||
bFlying = TRUE;
|
||||
|
||||
if (GetHasSpellEffect(MOVE_SH_BALANCE_SKY, oCreature))
|
||||
bFlying = TRUE;
|
||||
|
||||
@@ -385,10 +385,10 @@ const int TYPE_DIVINE = -2;
|
||||
// Returns TRUE if nSpellID is a subradial spell, FALSE otherwise
|
||||
int GetIsSubradialSpell(int nSpellID)
|
||||
{
|
||||
string sMaster = Get2DAString("spells", "Master", nSpellID);
|
||||
string sMaster = Get2DACache("spells", "Master", nSpellID);
|
||||
|
||||
// A subradial will have a numeric master ID here, not ****
|
||||
if (sMaster != "****")
|
||||
// If the Master column is numeric, this spell is a subradial of that master
|
||||
if (sMaster != "" && sMaster != "****")
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1011,11 +1011,16 @@ int PRCMySavingThrow(int nSavingThrow, object oTarget, int nDC, int nSaveType =
|
||||
// Plague Resistant gives a +4 bonus on disease saves
|
||||
if(GetHasFeat(FEAT_PLAGUE_RESISTANT, oTarget))
|
||||
nDC -= 4;
|
||||
// Racial +2 vs disease saves
|
||||
if(GetHasFeat(FEAT_RACE_HARDINESS_VS_DISEASE, oTarget))
|
||||
nDC -= 2;
|
||||
// +4/+2 bonus on saves against disease, done here
|
||||
if(GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oTarget) > 13)
|
||||
nDC -= 4;
|
||||
else if(GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oTarget) > 3)
|
||||
nDC -= 2;
|
||||
|
||||
|
||||
}
|
||||
else if(nSaveType == SAVING_THROW_TYPE_POISON)
|
||||
{
|
||||
|
||||
@@ -70,13 +70,13 @@
|
||||
43 PRC_CRAFTING_BASE_ITEMS int 1
|
||||
44 PRC_XP_USE_SIMPLE_LA int 1
|
||||
45 PRC_XP_USE_SIMPLE_RACIAL_HD int 1
|
||||
46 PRC_CREATE_INFUSION_CASTER_LEVEL int 1
|
||||
47 PRC_CREATE_INFUSION_OPTIONAL_HERBS int 0
|
||||
46 PRC_CREATE_INFUSION_CASTER_LEVEL int 1
|
||||
47 PRC_CREATE_INFUSION_OPTIONAL_HERBS int 0
|
||||
*/
|
||||
|
||||
/* This variable MUST be updated with every new version of the PRC!!! */
|
||||
|
||||
const string PRC_VERSION = "PRC 3.9.0";
|
||||
const string PRC_VERSION = "PRC8 4.76";
|
||||
|
||||
/* This variable MUST be updated every time 'assemble_spellbooks.bat' is run!!! */
|
||||
|
||||
@@ -91,11 +91,11 @@
|
||||
* This allows material components in NWN through the materialcomp.2da
|
||||
* Just put the SpellID and UTC resref in, MINUS the .utc on the end.
|
||||
* This also requires the names of the items, formatted like so ("" included): "Object Name"
|
||||
*
|
||||
*
|
||||
* Set switch to 2 to activate this
|
||||
* Deducts gold instead of requiring material components
|
||||
* Put the gold value in the Cost column
|
||||
|
||||
|
||||
* Set switch to 3 to activate both at the same time
|
||||
* WARNING: This will slow spellcasting down due to 2da reads and inventory loops
|
||||
*/
|
||||
@@ -129,7 +129,7 @@ const string PRC_BIOWARE_NEUTRALIZE_POISON = "PRC_BIOWARE_NEUTRALIZE_P
|
||||
/** Remove the cap PRC added to this spell */
|
||||
const string PRC_BIOWARE_REMOVE_DISEASE = "PRC_BIOWARE_REMOVE_DISEASE";
|
||||
|
||||
/**
|
||||
/**
|
||||
* This replaces the 3.0 Spell Focus bonuses with the 3.5 edition ones
|
||||
*/
|
||||
const string PRC_35_SPELL_FOCUS = "PRC_35_SPELL_FOCUS";
|
||||
@@ -263,8 +263,8 @@ const string PRC_165_DEATH_IMMUNITY = "PRC_165_DEATH_IMMUNITY";
|
||||
|
||||
/*
|
||||
* PRC_ACTIVATE_MAX_SPELL_DC_CAP: activate a max cap on DC casted by creature/player
|
||||
* PRC_SET_MAX_SPELL_DC_CAP: the max value ex: 99
|
||||
*
|
||||
* PRC_SET_MAX_SPELL_DC_CAP: the max value ex: 99
|
||||
*
|
||||
*/
|
||||
const string PRC_ACTIVATE_MAX_SPELL_DC_CAP = "PRC_ACTIVATE_MAX_SPELL_DC_CAP";
|
||||
const string PRC_SET_MAX_SPELL_DC_CAP = "PRC_SET_MAX_SPELL_DC_CAP";
|
||||
@@ -291,8 +291,8 @@ const string PRC_DC_BASE_OVERRIDE = "PRC_DC_BASE_OVERRIDE";
|
||||
const string PRC_DC_ADJUSTMENT = "PRC_DC_ADJUSTMENT";
|
||||
|
||||
/*
|
||||
* By default when calculating caster level for characters with PrCs, the highest class rule will
|
||||
* be used (ie. Bard 2/Wizard 4/Elemental Savant 6 - Wizard is the highest arcane class so levels
|
||||
* By default when calculating caster level for characters with PrCs, the highest class rule will
|
||||
* be used (ie. Bard 2/Wizard 4/Elemental Savant 6 - Wizard is the highest arcane class so levels
|
||||
* form PrC will be added to that class, and the caster level will be 2 for Bard and 10 for Wizard).
|
||||
* When this is set, the first class rule will be used (with the same character caster level would
|
||||
* be 8 for Bard and 4 for Wizard).
|
||||
@@ -572,12 +572,12 @@ const string PRC_SOUL_EATER_MAX_SLAVES = "PRC_SOUL_EATER_MAX_SLAVES";
|
||||
* For the Psionic Slayer prestige class, this switch limits the Favored Enemy selection
|
||||
* to the Aberration racial type.
|
||||
*
|
||||
* This switch is provided to allow builders to more closely represent the Pen and Paper
|
||||
* This switch is provided to allow builders to more closely represent the Pen and Paper
|
||||
* Illithid Slayer class, instead of the broader Open Game License "Slayer" class.
|
||||
*
|
||||
* Type: Int
|
||||
* Type: Int
|
||||
* Values: 0 [Default] (Favored Enemy racial type is not limited)
|
||||
* 1 (Favored Enemy race is limited to Aberration only)
|
||||
* 1 (Favored Enemy race is limited to Aberration only)
|
||||
*/
|
||||
const string PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY = "PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY";
|
||||
|
||||
@@ -585,20 +585,20 @@ const string PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY = "PRC_PSIONIC_S
|
||||
* For the Psionic Slayer prestige class, this switch requires a character to make a "kill"
|
||||
* of a specific type of creature before the class becomes available.
|
||||
*
|
||||
* Use of this switch requires that the module builder add a "Psionic Slayer Kill Token"
|
||||
* (included in the PRC Items) to the designated creature.
|
||||
* Use of this switch requires that the module builder add a "Psionic Slayer Kill Token"
|
||||
* (included in the PRC Items) to the designated creature.
|
||||
*
|
||||
* Alternately, a script or item can be made that will run the script "prc_psysly_killt"
|
||||
* Alternately, a script or item can be made that will run the script "prc_psysly_killt"
|
||||
* on the PC. This script will set the flag that allows the target PC to take the Psionic Slayer Class.
|
||||
* Example code:
|
||||
* ExecuteScript("prc_psysly_killt", oPC); // Where oPC is an player charcter object
|
||||
* Example code:
|
||||
* ExecuteScript("prc_psysly_killt", oPC); // Where oPC is an player charcter object
|
||||
*
|
||||
* This switch is provided to allow builders to more closely represent the Pen and Paper
|
||||
* This switch is provided to allow builders to more closely represent the Pen and Paper
|
||||
* Illithid Slayer class, instead of the broader Open Game License "Slayer" class.
|
||||
*
|
||||
* Type: Int
|
||||
* Type: Int
|
||||
* Values: 0 [Default] (Kill Token / Script NOT required for taking the Psionic Slayer Class)
|
||||
* 1 (Kill Token / Script REQUIRED before the Psionic Slayer Class is available to take)
|
||||
* 1 (Kill Token / Script REQUIRED before the Psionic Slayer Class is available to take)
|
||||
*/
|
||||
const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN";
|
||||
|
||||
@@ -607,19 +607,19 @@ const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_R
|
||||
* By default the Werewolf class uses the Bioware Polymorph effect to perfrom its
|
||||
* Hybrid Form Shapchange.
|
||||
*
|
||||
* This switch allows the Werewolf class to be toggled to use the PRC Shifter
|
||||
* Shapchange code instead.
|
||||
* This switch allows the Werewolf class to be toggled to use the PRC Shifter
|
||||
* Shapchange code instead.
|
||||
*
|
||||
* Type: Int
|
||||
* Type: Int
|
||||
* Values: 0 [Default] (Werewolf Hybrid Shapchange uses Bioware Polymorph)
|
||||
* 1 (Werewolf Hybrid Shapchange uses PRC Shifter shape change code)
|
||||
* 1 (Werewolf Hybrid Shapchange uses PRC Shifter shape change code)
|
||||
*/
|
||||
const string PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE = "PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE";
|
||||
const string PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE = "PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE";
|
||||
|
||||
/**
|
||||
* Sets the max bonus for the PnP Shifter shifting systems
|
||||
*
|
||||
* Type: Int
|
||||
* Type: Int
|
||||
* Values: any greater than 0
|
||||
*/
|
||||
const string PRC_PNP_SHIFTER_BONUS = "PRC_PNP_SHIFTER_BONUS";
|
||||
@@ -783,7 +783,7 @@ const string PRC_STAFF_CASTER_LEVEL = "PRC_STAFF_CASTER_LEVEL";
|
||||
/**
|
||||
* [DEFUNCT]
|
||||
* A wand must be equipped before it can cast a spell
|
||||
*
|
||||
*
|
||||
* Any value above 0 turns off the requirement to have a wand equipped to use it
|
||||
*
|
||||
* This switch is defunct, wands must *always* be equipped to use them.
|
||||
@@ -931,7 +931,7 @@ const string PRC_PNP_FAMILIAR_FEEDING = "PRC_PNP_FAMILIAR_FEEDING
|
||||
|
||||
/**
|
||||
* Use PRC henchmen-familiars instead of BioWare's - this will allow
|
||||
* new classes to have familiars, but summoned creatures will no longer
|
||||
* new classes to have familiars, but summoned creatures will no longer
|
||||
* be 'true' familiars (ie. can't possess PRC familiar)
|
||||
*/
|
||||
const string PRC_FAMILIARS = "PRC_FAMILIARS";
|
||||
@@ -1114,7 +1114,7 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
|
||||
* Disable registration of custom cohorts
|
||||
*/
|
||||
const string PRC_DISABLE_REGISTER_COHORTS = "PRC_DISABLE_REGISTER_COHORTS";
|
||||
|
||||
|
||||
/*
|
||||
* Disable cohorts starting with gear
|
||||
*/
|
||||
@@ -1144,19 +1144,19 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
|
||||
* Medium armor is a 25% speed reduction, Heavy is a 33% reduction
|
||||
*/
|
||||
const string PRC_PNP_ARMOR_SPEED = "PRC_PNP_ARMOR_SPEED";
|
||||
|
||||
|
||||
/*
|
||||
* Applies a 99% speed boost when out of combat
|
||||
* Warning that it will likely cause PCs to be overly speedy when combat starts
|
||||
* Potential problem causer
|
||||
*/
|
||||
const string PRC_FAST_TRAVEL_SPEED = "PRC_FAST_TRAVEL_SPEED";
|
||||
|
||||
|
||||
/*
|
||||
* Applys a Discipline bonus equal to BAB to all characters if turned on
|
||||
* Bonus only applies to characters with 0 ranks in Discipline
|
||||
*/
|
||||
const string PRC_PNP_KNOCKDOWN = "PRC_PNP_KNOCKDOWN";
|
||||
const string PRC_PNP_KNOCKDOWN = "PRC_PNP_KNOCKDOWN";
|
||||
|
||||
/*
|
||||
* by Bioware rules, PCs have approximatly a 7th faster movement than NPCs
|
||||
@@ -1204,8 +1204,11 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
|
||||
*/
|
||||
const string PRC_APPEARNCE_CHANGE_DISABLE = "PRC_APPEARNCE_CHANGE_DISABLE";
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Allow "Monk" gloves to merge with a creature weapons when Wildshaped.
|
||||
* Will also merge bracers with creature hides when Wildshaped.
|
||||
*/
|
||||
const string PRC_WILDSHAPE_ALLOWS_ARMS_SLOT = "PRC_WILDSHAPE_ALLOWS_ARMS_SLOT";
|
||||
|
||||
/******************************************************************************\
|
||||
* Death/Bleeding system *
|
||||
@@ -1223,7 +1226,7 @@ const string PRC_PNP_DEATH_ENABLE = "PRC_PNP_DEATH_ENA
|
||||
* if FALSE, dont bleed just die
|
||||
* By PnP this would be 1 round, or 6 seconds
|
||||
*/
|
||||
const string PRC_DEATH_OR_BLEED = "PRC_DEATH_OR_BLEED";
|
||||
const string PRC_DEATH_OR_BLEED = "PRC_DEATH_OR_BLEED";
|
||||
|
||||
/*
|
||||
* Damage when bleeding
|
||||
@@ -1316,7 +1319,7 @@ const string PRC_ACP_DELAY = "PRC_ACP_DELAY";
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* File End switches
|
||||
* File End switches
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
@@ -1490,10 +1493,10 @@ const string PRC_POISON_IS_FOOD_SCRIPT_NAME = "PRC_POISON_IS_FOOD_SCRIP
|
||||
const string PRC_POISON_ALLOW_CLEAN_IN_EQUIP = "PRC_POISON_ALLOW_CLEAN_IN_EQUIP";
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Default: crafting requires only gold and xp
|
||||
*/
|
||||
const string PRC_CRAFT_POISON_USE_INGREDIENST = "PRC_CRAFT_POISON_USE_INGREDIENST";
|
||||
const string PRC_CRAFT_POISON_USE_INGREDIENTS = "PRC_CRAFT_POISON_USE_INGREDIENTS";
|
||||
|
||||
/******************************************************************************\
|
||||
* PRGT system switches *
|
||||
@@ -1542,10 +1545,10 @@ const string PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD = "PRC_PSI_ASTRAL_CONSTRUCT
|
||||
|
||||
/**
|
||||
* If this is set, The Astral Seed power will attempt to use the provided string as
|
||||
* the ResRef to create the Astral Seed object instead of the of the phylactery
|
||||
* the ResRef to create the Astral Seed object instead of the of the phylactery
|
||||
* ResRef("x2_plc_phylact").
|
||||
* May be used by builders to create an object that CAN be destroyed, or has other traits,
|
||||
* as desired.
|
||||
* as desired.
|
||||
* Type: String
|
||||
* Values: "" [Default] (Blank, or not set: Use default phylactery ResRef for Astral Seed)
|
||||
* STRING (Entered String will be used as the ResRef of created Astral Seed object)
|
||||
@@ -1553,14 +1556,14 @@ const string PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD = "PRC_PSI_ASTRAL_CONSTRUCT
|
||||
const string PRC_PSI_ASTRAL_SEED_RESREF = "PRC_PSI_ASTRAL_SEED_RESREF";
|
||||
|
||||
/**
|
||||
* By default the Astral Seed power respawns the player, and then makes them immobile for
|
||||
* By default the Astral Seed power respawns the player, and then makes them immobile for
|
||||
* 24-game-hours.
|
||||
* If this switch is set, it will adjust the imobility time period; shortening it, lengthing it, or
|
||||
* If this switch is set, it will adjust the imobility time period; shortening it, lengthing it, or
|
||||
* effectively eliminating it.
|
||||
* Type: Int
|
||||
* Values: 0 [Default] (Not set: Use default 24 hour duration)
|
||||
* -1 (Any negative value will result in a fixed duratoion of 2 seconds, which effectively eliminates the wait period)
|
||||
* 1 (Any potitive value: multiply duration by the value provided and then divide result by 1000.
|
||||
* 1 (Any potitive value: multiply duration by the value provided and then divide result by 1000.
|
||||
* Values less than 1000 will shorten the duration, values higher than 1000 will lengthen it.)
|
||||
*/
|
||||
const string PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000 = "PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000";
|
||||
@@ -1571,7 +1574,7 @@ const string PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000 = "PRC_PSI_ASTRAL_SE
|
||||
* If this flag is set, the XP loss is completely eliminated. The standard PRC event hook script
|
||||
* of "prc_pw_astralseed" may be used to script any additional effects to occure upon Astral Seed
|
||||
* respawning, including scripting specific XP loss amount.
|
||||
* Type: Int
|
||||
* Type: Int
|
||||
* Values: 0 [Default] (Not set: lose 1 level worth of XP upon Astral Seed respawn)
|
||||
* 1 (Any potitive value: Remove all XP loss from Astral Seed respawn)
|
||||
*/
|
||||
@@ -1908,7 +1911,7 @@ const string PRC_CRAFT_TIMER_MAX = "PRC_CRAFT_TIMER_MAX";
|
||||
*/
|
||||
const string PRC_CRAFT_TIMER_MIN = "PRC_CRAFT_TIMER_MIN";
|
||||
|
||||
/**
|
||||
/*
|
||||
* These three switches modify Bioware crafting so that the items produced have the
|
||||
* casterlevel of the spellcaster who created them. Normally under Bioware, it is possible
|
||||
* for a level 3 caster to produce level 9 items and for a level 40 caster to only produce
|
||||
@@ -1955,16 +1958,21 @@ const string PRC_CRAFT_ROD_CASTER_LEVEL = "PRC_CRAFT_ROD_CASTER_LEVE
|
||||
const string PRC_CRAFT_STAFF_CASTER_LEVEL = "PRC_CRAFT_STAFF_CASTER_LEVEL";
|
||||
|
||||
/*
|
||||
* As above, except it applies to herbal infusions
|
||||
* As above, except it applies to scepters
|
||||
*/
|
||||
const string PRC_CREATE_INFUSION_CASTER_LEVEL = "PRC_CREATE_INFUSION_CASTER_LEVEL";
|
||||
const string PRC_CRAFT_SCEPTER_CASTER_LEVEL = "PRC_CRAFT_SCEPTER_CASTER_LEVEL";
|
||||
|
||||
/*
|
||||
* Builder's Option: Enables the optional PnP herbs for creating infusions.
|
||||
* As above, except it applies to herbal infusions
|
||||
*/
|
||||
const string PRC_CREATE_INFUSION_CASTER_LEVEL = "PRC_CREATE_INFUSION_CASTER_LEVEL";
|
||||
|
||||
/*
|
||||
* Builder's Option: Enables the optional PnP herbs for creating infusions.
|
||||
* Each herb is keyed to a spell circle level & spell school as shown on pg. 33
|
||||
* of the Master's of the Wild sourcebook.
|
||||
*/
|
||||
const string PRC_CREATE_INFUSION_OPTIONAL_HERBS = "PRC_CREATE_INFUSION_OPTIONAL_HERBS";
|
||||
const string PRC_CREATE_INFUSION_OPTIONAL_HERBS = "PRC_CREATE_INFUSION_OPTIONAL_HERBS";
|
||||
|
||||
/*
|
||||
* Characters with a crafting feat always have the appropriate base item in their inventory
|
||||
@@ -2015,6 +2023,13 @@ const string PRC_X2_CRAFTWAND_COSTMODIFIER = "PRC_X2_CRAFTWAND_COSTMO
|
||||
*/
|
||||
const string PRC_X2_CRAFTROD_COSTMODIFIER = "PRC_X2_CRAFTROD_COSTMODIFIER";
|
||||
|
||||
/*
|
||||
* cost modifier of spells crafted into scepters
|
||||
* note that adding a second spell costs 75%
|
||||
* defaults to 750
|
||||
*/
|
||||
const string PRC_X2_CRAFTSCEPTER_COSTMODIFIER = "PRC_X2_CRAFTSCEPTER_COSTMODIFIER";
|
||||
|
||||
/*
|
||||
* cost modifier of spells crafted into staffs
|
||||
* note that adding a second spell costs 75% and 3 or more costs 50%
|
||||
@@ -2342,7 +2357,7 @@ const string PRC_XP_GIVE_XP_TO_NPCS = "PRC_XP_GIVE_XP_TO_NPCS";
|
||||
/**
|
||||
* Setting this switch will turn off the messages about being too far awy to gain XP
|
||||
*/
|
||||
const string PRC_XP_DISABLE_SPAM = "PRC_XP_DISABLE_SPAM";
|
||||
const string PRC_XP_DISABLE_SPAM = "PRC_XP_DISABLE_SPAM";
|
||||
|
||||
/**
|
||||
* PCs must be in the same area as the CR to gain XP.
|
||||
@@ -2901,13 +2916,13 @@ const string PRC_PERFECTED_MAP_MULTIPLIER = "PRC_PERFECTED_MAP_MULTIP
|
||||
\******************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets how many seconds it takes to contact a vestige.
|
||||
* Sets how many seconds it takes to contact a vestige.
|
||||
* Any number less than 6 is ignored
|
||||
*/
|
||||
const string PRC_CONTACT_VESTIGE_TIMER = "PRC_CONTACT_VESTIGE_TIMER";
|
||||
|
||||
/**
|
||||
* Sets how many seconds it takes to bind a vestige.
|
||||
* Sets how many seconds it takes to bind a vestige.
|
||||
* Any number less than 12 is ignored
|
||||
*/
|
||||
const string PRC_BIND_VESTIGE_TIMER = "PRC_BIND_VESTIGE_TIMER";
|
||||
@@ -2941,6 +2956,20 @@ const string PRC_PW_SECURITY_CD_CHECK = "PRC_PW_SECURITY_CD_CHECK";
|
||||
*/
|
||||
const string PRC_DEBUG = "PRC_DEBUG";
|
||||
|
||||
/******************************************************************************\
|
||||
* Duration NUI Switches *
|
||||
\******************************************************************************/
|
||||
|
||||
/**
|
||||
* Toggles allowing player to remove friendly PC spells on player through Duration NUI
|
||||
* instead of just their own spells.
|
||||
*/
|
||||
const string PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS = "PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS";
|
||||
/**
|
||||
* Toggles allowing players to see the duration of hostile spells on them.
|
||||
*/
|
||||
const string PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS = "PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_spell_const"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function prototypes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
@@ -91,6 +91,107 @@ float DamageAvg(int iDamage);
|
||||
/* Function defintions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
// StepDie: increases a damage die by 'nSteps' steps according to d20 SRD progression
|
||||
// Increment the unarmed damage by nSteps
|
||||
int StepDie(int nDamage, int nSteps)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nSteps; i++)
|
||||
{
|
||||
switch (nDamage)
|
||||
{
|
||||
// 1-dice increments
|
||||
case IP_CONST_MONSTERDAMAGE_1d2: nDamage = IP_CONST_MONSTERDAMAGE_1d3; break;
|
||||
case IP_CONST_MONSTERDAMAGE_1d3: nDamage = IP_CONST_MONSTERDAMAGE_1d4; break;
|
||||
case IP_CONST_MONSTERDAMAGE_1d4: nDamage = IP_CONST_MONSTERDAMAGE_1d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_1d6: nDamage = IP_CONST_MONSTERDAMAGE_1d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_1d8: nDamage = IP_CONST_MONSTERDAMAGE_1d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_1d10: nDamage = IP_CONST_MONSTERDAMAGE_1d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_1d12: nDamage = IP_CONST_MONSTERDAMAGE_2d8; break;
|
||||
|
||||
// 2-dice increments
|
||||
//case IP_CONST_MONSTERDAMAGE_2d3: nDamage = IP_CONST_MONSTERDAMAGE_2d4; break;
|
||||
case IP_CONST_MONSTERDAMAGE_2d4: nDamage = IP_CONST_MONSTERDAMAGE_2d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_2d6: nDamage = IP_CONST_MONSTERDAMAGE_2d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_2d8: nDamage = IP_CONST_MONSTERDAMAGE_2d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_2d10: nDamage = IP_CONST_MONSTERDAMAGE_2d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_2d12: nDamage = IP_CONST_MONSTERDAMAGE_3d10; break;
|
||||
|
||||
// 3-dice increments
|
||||
case IP_CONST_MONSTERDAMAGE_3d4: nDamage = IP_CONST_MONSTERDAMAGE_3d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_3d6: nDamage = IP_CONST_MONSTERDAMAGE_3d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_3d8: nDamage = IP_CONST_MONSTERDAMAGE_3d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_3d10: nDamage = IP_CONST_MONSTERDAMAGE_3d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_3d12: nDamage = IP_CONST_MONSTERDAMAGE_4d8; break;
|
||||
|
||||
// 4-dice increments
|
||||
case IP_CONST_MONSTERDAMAGE_4d4: nDamage = IP_CONST_MONSTERDAMAGE_4d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_4d6: nDamage = IP_CONST_MONSTERDAMAGE_4d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_4d8: nDamage = IP_CONST_MONSTERDAMAGE_4d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_4d10: nDamage = IP_CONST_MONSTERDAMAGE_4d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_4d12: nDamage = IP_CONST_MONSTERDAMAGE_5d8; break;
|
||||
|
||||
// 5-dice increments
|
||||
case IP_CONST_MONSTERDAMAGE_5d4: nDamage = IP_CONST_MONSTERDAMAGE_5d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_5d6: nDamage = IP_CONST_MONSTERDAMAGE_5d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_5d8: nDamage = IP_CONST_MONSTERDAMAGE_5d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_5d10: nDamage = IP_CONST_MONSTERDAMAGE_5d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_5d12: nDamage = IP_CONST_MONSTERDAMAGE_6d10; break;
|
||||
|
||||
// 6-dice increments
|
||||
//case IP_CONST_MONSTERDAMAGE_6d4: nDamage = IP_CONST_MONSTERDAMAGE_6d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_6d6: nDamage = IP_CONST_MONSTERDAMAGE_6d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_6d8: nDamage = IP_CONST_MONSTERDAMAGE_6d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_6d10: nDamage = IP_CONST_MONSTERDAMAGE_6d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_6d12: nDamage = IP_CONST_MONSTERDAMAGE_7d10; break;
|
||||
|
||||
// 7-dice increments
|
||||
case IP_CONST_MONSTERDAMAGE_7d4: nDamage = IP_CONST_MONSTERDAMAGE_7d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_7d6: nDamage = IP_CONST_MONSTERDAMAGE_7d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_7d8: nDamage = IP_CONST_MONSTERDAMAGE_7d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_7d10: nDamage = IP_CONST_MONSTERDAMAGE_7d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_7d12: nDamage = IP_CONST_MONSTERDAMAGE_9d10; break;
|
||||
|
||||
// 8-dice increments
|
||||
//case IP_CONST_MONSTERDAMAGE_8d4: nDamage = IP_CONST_MONSTERDAMAGE_8d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_8d6: nDamage = IP_CONST_MONSTERDAMAGE_8d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_8d8: nDamage = IP_CONST_MONSTERDAMAGE_8d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_8d10: nDamage = IP_CONST_MONSTERDAMAGE_8d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_8d12: nDamage = IP_CONST_MONSTERDAMAGE_10d10; break;
|
||||
|
||||
// 9-dice increments
|
||||
//case IP_CONST_MONSTERDAMAGE_9d4: nDamage = IP_CONST_MONSTERDAMAGE_9d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_9d6: nDamage = IP_CONST_MONSTERDAMAGE_9d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_9d8: nDamage = IP_CONST_MONSTERDAMAGE_9d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_9d10: nDamage = IP_CONST_MONSTERDAMAGE_9d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_9d12: nDamage = IP_CONST_MONSTERDAMAGE_6d20; break;
|
||||
|
||||
// 10-dice increments
|
||||
//case IP_CONST_MONSTERDAMAGE_10d4: nDamage = IP_CONST_MONSTERDAMAGE_10d6; break;
|
||||
case IP_CONST_MONSTERDAMAGE_10d6: nDamage = IP_CONST_MONSTERDAMAGE_10d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_10d8: nDamage = IP_CONST_MONSTERDAMAGE_10d10; break;
|
||||
case IP_CONST_MONSTERDAMAGE_10d10: nDamage = IP_CONST_MONSTERDAMAGE_10d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_10d12: nDamage = IP_CONST_MONSTERDAMAGE_7d20; break;
|
||||
|
||||
// d20 increments
|
||||
case IP_CONST_MONSTERDAMAGE_1d20: nDamage = IP_CONST_MONSTERDAMAGE_3d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_2d20: nDamage = IP_CONST_MONSTERDAMAGE_4d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_3d20: nDamage = IP_CONST_MONSTERDAMAGE_8d8; break;
|
||||
case IP_CONST_MONSTERDAMAGE_4d20: nDamage = IP_CONST_MONSTERDAMAGE_8d12; break;
|
||||
case IP_CONST_MONSTERDAMAGE_5d20: nDamage = IP_CONST_MONSTERDAMAGE_9d12; break; //:: Everything breaks down here
|
||||
case IP_CONST_MONSTERDAMAGE_6d20: nDamage = IP_CONST_MONSTERDAMAGE_1d20; break;
|
||||
case IP_CONST_MONSTERDAMAGE_7d20: nDamage = IP_CONST_MONSTERDAMAGE_8d20; break;
|
||||
case IP_CONST_MONSTERDAMAGE_8d20: nDamage = IP_CONST_MONSTERDAMAGE_9d20; break;
|
||||
case IP_CONST_MONSTERDAMAGE_9d20: nDamage = IP_CONST_MONSTERDAMAGE_10d20; break;
|
||||
|
||||
default: break; // top tier or unknown
|
||||
}
|
||||
}
|
||||
|
||||
return nDamage;
|
||||
}
|
||||
|
||||
|
||||
// Clean up any extras in the inventory.
|
||||
void CleanExtraFists(object oCreature)
|
||||
{
|
||||
@@ -168,12 +269,169 @@ void ApplyUnarmedAttackEffects(object oCreature)
|
||||
}
|
||||
|
||||
// Determines the amount of damage a character can do.
|
||||
// IoDM: +1 dice at level 4, +2 dice at level 8
|
||||
// IoDM: +1 die at level 4, +2 dice at level 8
|
||||
// Sacred Fist: Levels add to monk levels, or stand alone as monk levels.
|
||||
// Shou: 1d6 at level 1, 1d8 at level 2, 1d10 at level 3, 2d6 at level 5
|
||||
// Monk: 1d6 at level 1, 1d8 at level 4, 1d10 at level 8, 2d6 at level 12, 2d8 at level 16, 2d10 at level 20
|
||||
// Frostrager: 1d6 at level 1, 1d8 at level 4
|
||||
int FindUnarmedDamage(object oCreature)
|
||||
{
|
||||
int iDamage = 0;
|
||||
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
|
||||
int iShou = GetLevelByClass(CLASS_TYPE_SHOU, oCreature);
|
||||
int iBrawler = GetLevelByClass(CLASS_TYPE_BRAWLER, oCreature);
|
||||
int iSacredFist = GetLevelByClass(CLASS_TYPE_SACREDFIST, oCreature);
|
||||
int iEnlightenedFist = GetLevelByClass(CLASS_TYPE_ENLIGHTENEDFIST, oCreature);
|
||||
int iHenshin = GetLevelByClass(CLASS_TYPE_HENSHIN_MYSTIC, oCreature);
|
||||
int iZuoken = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oCreature);
|
||||
int iShadowSunNinja = GetLevelByClass(CLASS_TYPE_SHADOW_SUN_NINJA, oCreature);
|
||||
int iFrost = GetLevelByClass(CLASS_TYPE_FROSTRAGER, oCreature);
|
||||
int iAscetic = GetLevelByClass(CLASS_TYPE_NINJA, oCreature);
|
||||
int iRonove = 0;
|
||||
int iMonkDamage = 1;
|
||||
int iShouDamage = 1;
|
||||
int iBrawlerDamage = 1;
|
||||
int iFrostDamage = 1;
|
||||
int iSUSDamage = 1;
|
||||
int iDieIncrease = 0;
|
||||
int iSize;
|
||||
|
||||
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature))
|
||||
iRonove = GetLocalInt(oCreature, "RonovesFists");
|
||||
|
||||
//:: Determine creature size
|
||||
if( GetIsPolyMorphedOrShifted(oCreature) || GetPRCSwitch(PRC_APPEARANCE_SIZE))
|
||||
{
|
||||
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
iSize = 5; // medium
|
||||
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
|
||||
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
|
||||
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
|
||||
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
|
||||
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
|
||||
if (iSize < 1) iSize = 1;
|
||||
if (iSize > 9) iSize = 9;
|
||||
}
|
||||
|
||||
// Sacred Fist code break protection
|
||||
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
|
||||
|
||||
// Combine monk-like levels
|
||||
iMonk += iSacredFist + iHenshin + iEnlightenedFist + iShou + iZuoken + iShadowSunNinja;
|
||||
|
||||
// Superior Unarmed Strike
|
||||
if (GetHasFeat(FEAT_SUPERIOR_UNARMED_STRIKE, oCreature))
|
||||
{
|
||||
iMonk += 4;
|
||||
int nHD = GetHitDice(oCreature);
|
||||
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
|
||||
else if (nHD >= 12) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d10;
|
||||
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
||||
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
||||
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
|
||||
}
|
||||
|
||||
// Ascetic Stalker
|
||||
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
|
||||
iMonk += iAscetic;
|
||||
|
||||
// Cap monk progression
|
||||
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE)) iMonk = 16;
|
||||
else if (iMonk > 20) iMonk = 20;
|
||||
|
||||
// Ronove replacement
|
||||
if (iRonove > iMonk) iMonk = iRonove;
|
||||
|
||||
// Monk damage calculation (2DA row)
|
||||
if (iMonk > 0) iMonkDamage = iMonk / 4 + 3;
|
||||
if (iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
|
||||
iMonkDamage = 8;
|
||||
|
||||
// Shou Disciple base damage
|
||||
if (iShou > 0)
|
||||
{
|
||||
int nRow;
|
||||
if (iShou == 1) nRow = 3;
|
||||
else if (iShou == 2) nRow = 4;
|
||||
else if (iShou == 3) nRow = 5;
|
||||
else if (iShou == 4) nRow = 5;
|
||||
else if (iShou == 5) nRow = 6;
|
||||
else nRow = 3;
|
||||
|
||||
if (nRow > 6) nRow = 6;
|
||||
|
||||
iShouDamage = StringToInt(Get2DACache("unarmed_dmg", "size" + IntToString(iSize), nRow));
|
||||
}
|
||||
|
||||
// Frostrager
|
||||
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
||||
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
||||
|
||||
// Brawler
|
||||
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3;
|
||||
if (iBrawler >= 36) iBrawlerDamage += 2;
|
||||
|
||||
// Armor/shield penalties
|
||||
if (iMonkDamage > 1)
|
||||
{
|
||||
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
||||
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
|
||||
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
|
||||
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
|
||||
if (GetBaseAC(oArmor) > 0 || bShieldEq)
|
||||
iMonkDamage = 1;
|
||||
}
|
||||
|
||||
if (iShouDamage > 1)
|
||||
{
|
||||
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
||||
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
|
||||
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
|
||||
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
|
||||
if (GetBaseAC(oArmor) > 3 || bShieldEq)
|
||||
iShouDamage = 1;
|
||||
}
|
||||
|
||||
// Determine IoDM die increase
|
||||
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
|
||||
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
|
||||
|
||||
// Lookup monk damage in 2DA
|
||||
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
|
||||
|
||||
// 3.0e monk special cases
|
||||
if (iSize <= 5 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
|
||||
{
|
||||
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d6) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d12;
|
||||
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d10) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d20;
|
||||
}
|
||||
|
||||
// Apply IoDM die increase last, after 2DA lookups
|
||||
if (iMonkDamage > 0) iMonkDamage = StepDie(iMonkDamage, iDieIncrease);
|
||||
if (iShouDamage > 0) iShouDamage = StepDie(iShouDamage, iDieIncrease);
|
||||
if (iBrawlerDamage > 0) iBrawlerDamage = StepDie(iBrawlerDamage, iDieIncrease);
|
||||
if (iFrostDamage > 0) iFrostDamage = StepDie(iFrostDamage, iDieIncrease);
|
||||
if (iSUSDamage > 0) iSUSDamage = StepDie(iSUSDamage, iDieIncrease);
|
||||
|
||||
// Select best damage
|
||||
iDamage = iMonkDamage;
|
||||
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
|
||||
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
|
||||
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
|
||||
iDamage = (DamageAvg(iBrawlerDamage) > DamageAvg(iDamage)) ? iBrawlerDamage : iDamage;
|
||||
|
||||
if (DEBUG) DoDebug("prc_inc_unarmed: iDamage "+IntToString(iDamage));
|
||||
|
||||
return iDamage;
|
||||
}
|
||||
|
||||
|
||||
/* int FindUnarmedDamage(object oCreature)
|
||||
{
|
||||
int iDamage = 0;
|
||||
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
|
||||
@@ -195,36 +453,30 @@ int FindUnarmedDamage(object oCreature)
|
||||
int iDieIncrease = 0;
|
||||
int iSize;
|
||||
|
||||
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature)) iRonove = GetLocalInt(oCreature, "RonovesFists");
|
||||
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature))
|
||||
iRonove = GetLocalInt(oCreature, "RonovesFists");
|
||||
|
||||
// if the creature is shifted, use model size
|
||||
// otherwise, we want to stick to what the feats say they "should" be.
|
||||
// No making pixies with Dragon Appearance for "huge" fist damage.
|
||||
if( GetIsPolyMorphedOrShifted(oCreature)
|
||||
|| GetPRCSwitch(PRC_APPEARANCE_SIZE))
|
||||
// Determine creature size
|
||||
if( GetIsPolyMorphedOrShifted(oCreature) || GetPRCSwitch(PRC_APPEARANCE_SIZE))
|
||||
{
|
||||
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5; // medium is size 5 for us
|
||||
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine creature size by feats.
|
||||
iSize = 5; // medium is size 5 for us
|
||||
iSize = 5; // medium
|
||||
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
|
||||
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
|
||||
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
|
||||
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
|
||||
// include size changes
|
||||
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
|
||||
// cap if needed
|
||||
if (iSize < 1) iSize = 1;
|
||||
if (iSize > 9) iSize = 9;
|
||||
}
|
||||
|
||||
// Sacred Fist cannot add their levels if they've broken their code.
|
||||
// Sacred Fist code break protection
|
||||
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
|
||||
|
||||
// several classes add their levels to the monk class,
|
||||
// or use monk progression if the character has no monk levels
|
||||
// Combine monk-like levels
|
||||
iMonk += iSacredFist + iHenshin + iEnlightenedFist + iShou + iZuoken + iShadowSunNinja;
|
||||
|
||||
// Superior Unarmed Strike
|
||||
@@ -232,49 +484,66 @@ int FindUnarmedDamage(object oCreature)
|
||||
{
|
||||
iMonk += 4;
|
||||
int nHD = GetHitDice(oCreature);
|
||||
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
|
||||
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
|
||||
else if (nHD >= 12) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d10;
|
||||
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
||||
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
||||
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
|
||||
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
||||
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
||||
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
|
||||
}
|
||||
|
||||
// Ascetic Stalker
|
||||
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
|
||||
iMonk += iAscetic;
|
||||
|
||||
// In 3.0e, Monk progression stops after level 16:
|
||||
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE) ) iMonk = 16;
|
||||
// in 3.5e, monk progression stops at 20.
|
||||
else if(iMonk > 20) iMonk = 20;
|
||||
// Cap monk progression
|
||||
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE)) iMonk = 16;
|
||||
else if (iMonk > 20) iMonk = 20;
|
||||
|
||||
// Ronove is in place of monk, does not stack
|
||||
// Ronove replacement
|
||||
if (iRonove > iMonk) iMonk = iRonove;
|
||||
|
||||
// monks damage progesses every four levels, starts at 1d6
|
||||
if (iMonk > 0)
|
||||
iMonkDamage = iMonk / 4 + 3;
|
||||
// Monk damage calculation
|
||||
if (iMonk > 0) iMonkDamage = iMonk / 4 + 3;
|
||||
|
||||
// For medium monks in 3.0e skip 2d8 and go to 1d20
|
||||
if(iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE) ) iMonkDamage = 8;
|
||||
if(iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
|
||||
iMonkDamage = 8;
|
||||
|
||||
// Shou Disciple either adds its level to existing class or does its own damage, depending
|
||||
// on which is better. Here we will determine how much damage the Shou Disciple does
|
||||
// without stacking.
|
||||
if (iShou > 0) iShouDamage = iShou + 2; // Lv. 1: 1d6, Lv. 2: 1d8, Lv. 3: 1d10
|
||||
if (iShou > 3) iShouDamage--; // Lv. 4: 1d10, Lv. 5: 2d6
|
||||
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
|
||||
|
||||
// Frostrager does not stack with other damage types
|
||||
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6; // Lv. 1: 1d6
|
||||
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8; // Lv. 3: 1d8
|
||||
//if (iShou > 0) iShouDamage = iShou + 2; // Lv. 1: 1d6, Lv. 2: 1d8, Lv. 3: 1d10
|
||||
//if (iShou > 3) iShouDamage--; // Lv. 4: 1d10, Lv. 5: 2d6
|
||||
//iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
|
||||
|
||||
if (iShou > 0)
|
||||
{
|
||||
// Determine 2DA row for Shou progression
|
||||
int nRow;
|
||||
if (iShou == 1) nRow = 3; // monk1
|
||||
else if (iShou == 2) nRow = 4; // monk2
|
||||
else if (iShou == 3) nRow = 5; // monk3
|
||||
else if (iShou == 4) nRow = 6; // monk4
|
||||
else if (iShou == 5) nRow = 7; // monk5
|
||||
else if (iShou == 6) nRow = 8; // monk6
|
||||
else if (iShou == 7) nRow = 9; // monk7
|
||||
else nRow = 10; // monk8+
|
||||
|
||||
nRow += iDieIncrease;
|
||||
if (nRow > 10) nRow = 10; // clamp to max row
|
||||
|
||||
// Brawler follows monk progression except for the last one (3d8)
|
||||
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3; // 1d6, 1d8, 1d10, 2d6, 2d8, 2d10
|
||||
if (iBrawler >= 36) iBrawlerDamage += 2; // 3d8
|
||||
// Lookup damage in unarmed_damage.2da using size column
|
||||
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), nRow));
|
||||
}
|
||||
|
||||
// Monks and monk-like classes deal no additional damage when wearing any armor, at
|
||||
// least in NWN. This is to reflect that. No shields too.
|
||||
// Frostrager
|
||||
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
||||
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
||||
|
||||
// Brawler
|
||||
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3;
|
||||
if (iBrawler >= 36) iBrawlerDamage += 2;
|
||||
|
||||
// Armor/shield penalties
|
||||
if (iMonkDamage > 1)
|
||||
{
|
||||
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
|
||||
@@ -284,13 +553,10 @@ int FindUnarmedDamage(object oCreature)
|
||||
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
|
||||
|
||||
if (GetBaseAC(oArmor) > 0 || bShieldEq)
|
||||
{
|
||||
iMonkDamage = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Shou Disciples can wear light armor
|
||||
if (iShouDamage > 1)
|
||||
if (iShouDamage > 1)
|
||||
{
|
||||
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
||||
@@ -299,53 +565,31 @@ int FindUnarmedDamage(object oCreature)
|
||||
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
|
||||
|
||||
if (GetBaseAC(oArmor) > 3 || bShieldEq)
|
||||
{
|
||||
iShouDamage = 1;
|
||||
}
|
||||
iShouDamage = 1;
|
||||
}
|
||||
|
||||
// For Initiate of Draconic Mysteries
|
||||
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
|
||||
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
|
||||
|
||||
//:: Expansion / Compression powers
|
||||
int nExpansion = GetLocalInt(oCreature, "PRC_Power_Expansion_SizeIncrease");
|
||||
int nCompression = GetLocalInt(oCreature, "PRC_Power_Compression_SizeReduction");
|
||||
|
||||
if (nExpansion)
|
||||
{
|
||||
iSize += nExpansion;
|
||||
}
|
||||
|
||||
if (nCompression)
|
||||
{
|
||||
iSize -= nCompression;
|
||||
}
|
||||
// IoDM die increase
|
||||
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease += 2;
|
||||
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease += 1;
|
||||
|
||||
iMonkDamage += iDieIncrease;
|
||||
iShouDamage += iDieIncrease;
|
||||
iBrawlerDamage += iDieIncrease;
|
||||
iFrostDamage += iDieIncrease;
|
||||
iSUSDamage += iDieIncrease;
|
||||
|
||||
//FloatingTextStringOnCreature("prc_inc_unarmed: Size is: "+IntToString(iSize)+".", oCreature);
|
||||
//FloatingTextStringOnCreature("prc_inc_unarmed: Pre 2DA Lookup >> iMonkDamage = "+IntToString(iMonkDamage)+".", oCreature);
|
||||
|
||||
// now, read the damage from the table in unarmed_dmg.2da
|
||||
// Lookup final monk damage in 2DA
|
||||
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
|
||||
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
|
||||
|
||||
//FloatingTextStringOnCreature("prc_inc_unarmed: Post 2DA Lookup >> iMonkDamage = "+IntToString(iMonkDamage)+".", oCreature);
|
||||
|
||||
// Medium+ monks have some special values on the table in 3.0:
|
||||
// 3.0e monk special cases
|
||||
if (iSize >= 5 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
|
||||
{
|
||||
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d6) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d12;
|
||||
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d10) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d20;
|
||||
}
|
||||
|
||||
// Select best damage
|
||||
iDamage = iMonkDamage;
|
||||
// Future unarmed classes: if you do your own damage, add in "comparisons" below here.
|
||||
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
|
||||
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
|
||||
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
|
||||
@@ -354,6 +598,8 @@ int FindUnarmedDamage(object oCreature)
|
||||
|
||||
return iDamage;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Adds appropriate feats to the skin. Stolen from SoulTaker + expanded with overwhelming/devastating critical.
|
||||
void UnarmedFeats(object oCreature)
|
||||
@@ -426,13 +672,13 @@ void UnarmedFists(object oCreature)
|
||||
|
||||
// Sacred Fists who break their code get no benefits.
|
||||
if (GetHasFeat(FEAT_SF_CODE,oCreature)) iSacFist = 0;
|
||||
|
||||
|
||||
// The monk adds all these classes.
|
||||
int iMonkEq = iMonk + iShou + iSacFist + iHenshin + iZuoken + iShadowSunNinja;
|
||||
|
||||
int iMonkEq = iMonk + iShou + iSacFist + iHenshin + iZuoken + iShadowSunNinja;
|
||||
|
||||
// Ascetic Stalker
|
||||
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
|
||||
iMonkEq += iAscetic;
|
||||
iMonkEq += iAscetic;
|
||||
|
||||
// Determine the type of damage the character should do.
|
||||
string sWeapType;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Weapon Restriction System Include
|
||||
//:: prc_inc_restwpn.nss
|
||||
//:: prc_inc_wpnrest.nss
|
||||
//::///////////////////////////////////////////////
|
||||
/*
|
||||
Functions to support PnP Weapon Proficiency and
|
||||
@@ -15,6 +15,56 @@
|
||||
#include "inc_item_props"
|
||||
#include "prc_x2_itemprop"
|
||||
|
||||
//:: Detects if "monk" gloves are being equipped & set a
|
||||
//:: variable if TRUE for use with other functions
|
||||
void DetectMonkGloveEquip(object oItem)
|
||||
{
|
||||
int nItemType = GetBaseItemType(oItem);
|
||||
|
||||
object oPC = GetItemPossessor(oItem);
|
||||
if (!GetIsObjectValid(oItem))
|
||||
{
|
||||
if (DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloveEquip(): Unable to determine item possessor");
|
||||
return;
|
||||
}
|
||||
|
||||
if(nItemType != BASE_ITEM_GLOVES && nItemType != BASE_ITEM_BRACER) {return;}
|
||||
|
||||
else if (nItemType == BASE_ITEM_BRACER)
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloveEquip(): Bracer found!");
|
||||
DeleteLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemproperty ipG = GetFirstItemProperty(oItem);
|
||||
|
||||
while(GetIsItemPropertyValid(ipG))
|
||||
{
|
||||
int nTypeG = GetItemPropertyType(ipG);
|
||||
|
||||
// Damage related properties we care about
|
||||
if(nTypeG == ITEM_PROPERTY_DAMAGE_BONUS
|
||||
|| nTypeG == ITEM_PROPERTY_ATTACK_BONUS
|
||||
|| nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP
|
||||
|| nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|
||||
|| nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT)
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloves(): Monk gloves found!");
|
||||
SetLocalInt(oPC, "WEARING_MONK_GLOVES", 1);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloves(): Monk gloves not found! You should never see this.");
|
||||
DeleteLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All of the following functions use the following parameters:
|
||||
*
|
||||
@@ -23,6 +73,69 @@
|
||||
* @param nHand The hand the weapon is wielded in. In the form of
|
||||
* ATTACK_BONUS_ONHAND or ATTACK_BONUS_OFFHAND.
|
||||
*/
|
||||
//:: returns TRUE if the wielded weapon works with the Swashbuckler's class abilities.
|
||||
int GetHasSwashbucklerWeapon(object oPC)
|
||||
{
|
||||
object oWeap = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
if (!GetIsObjectValid(oWeap)) return FALSE;
|
||||
|
||||
int nType = GetBaseItemType(oWeap);
|
||||
|
||||
switch (nType)
|
||||
{
|
||||
case BASE_ITEM_DAGGER:
|
||||
case BASE_ITEM_KATAR:
|
||||
case BASE_ITEM_HANDAXE:
|
||||
case BASE_ITEM_KAMA:
|
||||
case BASE_ITEM_KUKRI:
|
||||
case BASE_ITEM_LIGHTHAMMER:
|
||||
case BASE_ITEM_LIGHTMACE:
|
||||
case BASE_ITEM_LIGHT_PICK:
|
||||
case BASE_ITEM_RAPIER:
|
||||
case BASE_ITEM_SHORTSWORD:
|
||||
case BASE_ITEM_SICKLE:
|
||||
case BASE_ITEM_WHIP:
|
||||
case BASE_ITEM_SAI:
|
||||
case BASE_ITEM_SAP:
|
||||
case BASE_ITEM_NUNCHAKU:
|
||||
case BASE_ITEM_GOAD:
|
||||
case BASE_ITEM_ELVEN_LIGHTBLADE:
|
||||
case BASE_ITEM_ELVEN_THINBLADE:
|
||||
case BASE_ITEM_EAGLE_CLAW:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Iaijutsu Master allows katana
|
||||
if (GetLevelByClass(CLASS_TYPE_IAIJUTSU_MASTER, oPC) > 0)
|
||||
{
|
||||
if (nType == BASE_ITEM_KATANA) return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//:: returns TRUE if the wielded weapon works with the Champion of Corellon's Elegant Strike.
|
||||
int GetHasCorellonWeapon(object oPC)
|
||||
{
|
||||
object oWeap = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
if (!GetIsObjectValid(oWeap)) return FALSE;
|
||||
|
||||
int nType = GetBaseItemType(oWeap);
|
||||
|
||||
switch (nType)
|
||||
{
|
||||
case BASE_ITEM_SCIMITAR:
|
||||
case BASE_ITEM_LONGSWORD:
|
||||
case BASE_ITEM_RAPIER:
|
||||
case BASE_ITEM_ELVEN_COURTBLADE:
|
||||
case BASE_ITEM_ELVEN_LIGHTBLADE:
|
||||
case BASE_ITEM_ELVEN_THINBLADE:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void DoRacialEquip(object oPC, int nBaseType);
|
||||
|
||||
//return if PC has proficiency in an item
|
||||
@@ -763,6 +876,7 @@ int IsMeleeWeapon(int nBaseItemType)
|
||||
case BASE_ITEM_CLOAK:
|
||||
case BASE_ITEM_CRAFTED_ROD:
|
||||
case BASE_ITEM_CRAFTED_STAFF:
|
||||
case BASE_ITEM_CRAFTED_SCEPTER:
|
||||
case BASE_ITEM_CRAFTMATERIALMED:
|
||||
case BASE_ITEM_CRAFTMATERIALSML:
|
||||
case BASE_ITEM_CREATUREITEM:
|
||||
|
||||
@@ -262,7 +262,7 @@ const int IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_LANCE = 4638;
|
||||
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_PICK = 4639;
|
||||
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_PICK = 4640;
|
||||
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_SAI = 4641;
|
||||
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_NUNCHUKU = 4642;
|
||||
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_NUNCHAKU = 4642;
|
||||
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_FALCHION = 4643;
|
||||
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_SAP = 4644;
|
||||
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_KATAR = 4645;
|
||||
|
||||
@@ -29,8 +29,8 @@ const int BASE_ITEM_CRAFTED_STAFF = 201;
|
||||
const int BASE_ITEM_ELVEN_LIGHTBLADE = 202;
|
||||
const int BASE_ITEM_ELVEN_THINBLADE = 203;
|
||||
const int BASE_ITEM_ELVEN_COURTBLADE = 204;
|
||||
const int BASE_ITEM_CRAFT_SCEPTER = 249;
|
||||
const int BASE_ITEM_MAGIC_SCEPTER = 250;
|
||||
const int BASE_ITEM_CRAFTED_SCEPTER = 249;
|
||||
const int BASE_ITEM_CRAFTED_VIAL = 250;
|
||||
const int BASE_ITEM_MUNDANE_HERB = 252;
|
||||
const int BASE_ITEM_INFUSED_HERB = 253;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "psi_inc_psifunc"
|
||||
#include "inc_lookups"
|
||||
#include "nw_inc_nui"
|
||||
#include "tob_inc_tobfunc"
|
||||
|
||||
//
|
||||
// GetCurrentSpellLevel
|
||||
@@ -153,8 +154,53 @@ json GreyOutButton(json jButton, float w, float h);
|
||||
//
|
||||
json CreateGreyOutRectangle(float w, float h);
|
||||
|
||||
//
|
||||
// GetTrueClassType
|
||||
// Gets the true class Id for a provided class Id, mostly for RHD and for
|
||||
// ToB prestige classes
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int classId
|
||||
//
|
||||
// Returns:
|
||||
// int the true classId based off nClass
|
||||
//
|
||||
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF);
|
||||
|
||||
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0);
|
||||
|
||||
void CallSpellUnlevelScript(object oPC, int nClass, int nLevel);
|
||||
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF);
|
||||
void RemoveIPFeat(object oPC, int ipFeatID);
|
||||
|
||||
void CallSpellUnlevelScript(object oPC, int nClass, int nLevel)
|
||||
{
|
||||
SetScriptParam("UnLevel_ClassChoice", IntToString(nClass));
|
||||
SetScriptParam("UnLevel_LevelChoice", IntToString(nLevel));
|
||||
ExecuteScript("prc_unlvl_script", oPC);
|
||||
}
|
||||
|
||||
void RemoveIPFeat(object oPC, int ipFeatID)
|
||||
{
|
||||
object oSkin = GetPCSkin(oPC);
|
||||
itemproperty ipTest = GetFirstItemProperty(oSkin);
|
||||
while(GetIsItemPropertyValid(ipTest))
|
||||
{
|
||||
// Check if the itemproperty is a bonus feat that has been marked for removal
|
||||
if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_BONUS_FEAT)
|
||||
{
|
||||
if (GetItemPropertySubType(ipTest) == ipFeatID)
|
||||
{
|
||||
if(DEBUG) DoDebug("_ManeuverRecurseRemoveArray(): Removing bonus feat itemproperty:\n" + DebugIProp2Str(ipTest));
|
||||
// If so, remove it
|
||||
RemoveItemProperty(oSkin, ipTest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ipTest = GetNextItemProperty(oSkin);
|
||||
}
|
||||
}
|
||||
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||
{
|
||||
@@ -401,6 +447,9 @@ json GetSpellIcon(int spellId,int featId=0,int nClass=0)
|
||||
|
||||
// the FeatID holds the accurate spell icon, not the SpellID
|
||||
int nFeatID = StringToInt(Get2DACache("spells", "FeatID", spellId));
|
||||
// however if no featId was found use the spell's icon instead
|
||||
if (!nFeatID)
|
||||
return JsonString(Get2DACache("spells", "IconResRef", spellId));
|
||||
|
||||
return JsonString(Get2DACache("feat", "Icon", nFeatID));
|
||||
}
|
||||
@@ -528,3 +577,39 @@ void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF)
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR);
|
||||
}
|
||||
|
||||
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF)
|
||||
{
|
||||
if (nClass == CLASS_TYPE_JADE_PHOENIX_MAGE
|
||||
|| nClass == CLASS_TYPE_MASTER_OF_NINE
|
||||
|| nClass == CLASS_TYPE_DEEPSTONE_SENTINEL
|
||||
|| nClass == CLASS_TYPE_BLOODCLAW_MASTER
|
||||
|| nClass == CLASS_TYPE_RUBY_VINDICATOR
|
||||
|| nClass == CLASS_TYPE_ETERNAL_BLADE
|
||||
|| nClass == CLASS_TYPE_SHADOW_SUN_NINJA)
|
||||
{
|
||||
int trueClass = GetPrimaryBladeMagicClass(oPC);
|
||||
return trueClass;
|
||||
}
|
||||
|
||||
if ((nClass == CLASS_TYPE_SHAPECHANGER
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|
||||
|| (nClass == CLASS_TYPE_OUTSIDER
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|
||||
|| (nClass == CLASS_TYPE_ABERRATION
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
|
||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
|
||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_HOBGOBLIN_WARSOUL)
|
||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
|
||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT))
|
||||
return CLASS_TYPE_SORCERER;
|
||||
if (nClass == CLASS_TYPE_FEY
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
|
||||
return CLASS_TYPE_BARD;
|
||||
|
||||
return nClass;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,3 +156,16 @@ const string NUI_SPELL_DESCRIPTION_CLASSID_VAR = "NUISpellDescriptionClassID";
|
||||
const string NUI_SPELL_DESCRIPTION_SPELLID_VAR = "NUISpellDescriptionSpellID";
|
||||
const string NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR = "NUISpellDescriptionRealSpellID";
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// //
|
||||
// Spell Duration NUI //
|
||||
// //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
const string DURATION_NUI_WINDOW_ID = "DurationNUI";
|
||||
const string NUI_DURATION_MANUALLY_OPENED_PARAM = "DurationNUIManuallyOpenedParam";
|
||||
const string NUI_DURATION_NO_LOOP_PARAM = "DurationNUINoLoopParam";
|
||||
const string NUI_DURATION_TRACKED_SPELLS = "durationNUI_trackedSpellList";
|
||||
const string NUI_SPELL_DURATION_BASE_BIND = "durationNUI_durationSpellId";
|
||||
const string NUI_SPELL_DURATION_SPELLID_BASE_CANCEL_BUTTON = "NuiDurationCancelButtonSpellID";
|
||||
|
||||
@@ -98,21 +98,9 @@ void OpenNUILevelUpWindow(int nClass, object oPC=OBJECT_SELF);
|
||||
//
|
||||
// CloseNUILevelUpWindow
|
||||
// Closes the NUI Level Up Window if its open
|
||||
// setting reset to 1 will make it clear the entire cache as if the NUI was never opened
|
||||
//
|
||||
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF);
|
||||
|
||||
//
|
||||
// GetTrueClassType
|
||||
// Gets the true class Id for a provided class Id, mostly for RHD and for
|
||||
// ToB prestige classes
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int classId
|
||||
//
|
||||
// Returns:
|
||||
// int the true classId based off nClass
|
||||
//
|
||||
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF);
|
||||
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF, int reset=0);
|
||||
|
||||
//
|
||||
// GetRemainingSpellChoices
|
||||
@@ -432,7 +420,7 @@ json GetChosenReplaceListObject(object oPC=OBJECT_SELF);
|
||||
// Returns:
|
||||
// int:Boolean TRUE if the spell is a expanded knowledge spell, FALSE otherwise
|
||||
//
|
||||
int IsExpKnowledgePower(int nClass, int spellbookId);
|
||||
int IsExpKnowledgePower(int nClass, int spellbookId, object oPC=OBJECT_SELF);
|
||||
|
||||
//
|
||||
// GetExpKnowledgePowerListRequired
|
||||
@@ -782,7 +770,7 @@ int IsClassAllowedToUseLevelUpNUI(int nClass)
|
||||
return TRUE;
|
||||
|
||||
if (nClass == CLASS_TYPE_ARCHIVIST)
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -861,7 +849,7 @@ void AddSpellToChosenList(int nClass, int spellbookId, int spellCircle, object o
|
||||
// if the power is a expanded knowledge than we immediatly add it to the
|
||||
// extra list, otherwise check to make sure we have made all choices in our
|
||||
// base list first before adding it to the extra list.
|
||||
if (IsExpKnowledgePower(nClass, spellbookId)
|
||||
if (IsExpKnowledgePower(nClass, spellbookId, oPC)
|
||||
|| GetRemainingPowerChoices(nClass, spellCircle, oPC, FALSE) == 0)
|
||||
{
|
||||
string sFile = GetClassSpellbookFile(nClass);
|
||||
@@ -1061,53 +1049,20 @@ void OpenNUILevelUpWindow(int nClass, object oPC=OBJECT_SELF)
|
||||
// figure out what the true base class is (mostly true for RHD)
|
||||
int chosenClass = GetTrueClassType(nClass, oPC);
|
||||
SetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CLASS_VAR, chosenClass);
|
||||
|
||||
ExecuteScript("prc_nui_lv_view", oPC);
|
||||
}
|
||||
|
||||
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF)
|
||||
{
|
||||
if (nClass == CLASS_TYPE_JADE_PHOENIX_MAGE
|
||||
|| nClass == CLASS_TYPE_MASTER_OF_NINE
|
||||
|| nClass == CLASS_TYPE_DEEPSTONE_SENTINEL
|
||||
|| nClass == CLASS_TYPE_BLOODCLAW_MASTER
|
||||
|| nClass == CLASS_TYPE_RUBY_VINDICATOR
|
||||
|| nClass == CLASS_TYPE_ETERNAL_BLADE
|
||||
|| nClass == CLASS_TYPE_SHADOW_SUN_NINJA)
|
||||
{
|
||||
int trueClass = GetPrimaryBladeMagicClass(oPC);
|
||||
return trueClass;
|
||||
}
|
||||
|
||||
if ((nClass == CLASS_TYPE_SHAPECHANGER
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|
||||
|| (nClass == CLASS_TYPE_OUTSIDER
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|
||||
|| (nClass == CLASS_TYPE_ABERRATION
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
|
||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
|
||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_HOBGOBLIN_WARSOUL)
|
||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
|
||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT))
|
||||
return CLASS_TYPE_SORCERER;
|
||||
if (nClass == CLASS_TYPE_FEY
|
||||
&& GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
|
||||
return CLASS_TYPE_BARD;
|
||||
|
||||
return nClass;
|
||||
}
|
||||
|
||||
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF)
|
||||
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF, int reset=0)
|
||||
{
|
||||
int currentClass = GetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||
// if we are refreshing the NUI but not finished we need to clear some caching done
|
||||
// to save computation time as they will need to be reprocessed.
|
||||
DeleteLocalJson(oPC, NUI_LEVEL_UP_DISCIPLINE_INFO_VAR + IntToString(currentClass));
|
||||
SetLocalInt(oPC, NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR, -20);
|
||||
if (reset)
|
||||
{
|
||||
ClearLevelUpNUICaches(currentClass, oPC);
|
||||
}
|
||||
int nPreviousToken = NuiFindWindow(oPC, NUI_LEVEL_UP_WINDOW_ID);
|
||||
if (nPreviousToken != 0)
|
||||
{
|
||||
@@ -1126,7 +1081,7 @@ int ShouldSpellButtonBeEnabled(int nClass, int circleLevel, int spellbookId, obj
|
||||
|
||||
// if its an expanded knowledge choice and we have already made all our
|
||||
// exp knowledge choices then it needs to be disabled.
|
||||
if (IsExpKnowledgePower(nClass, spellbookId))
|
||||
if (IsExpKnowledgePower(nClass, spellbookId, oPC))
|
||||
{
|
||||
int remainingExp = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC)
|
||||
+ GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
||||
@@ -1540,7 +1495,7 @@ int GetRemainingSpellChoices(int nClass, int circleLevel, object oPC=OBJECT_SELF
|
||||
totalSpellsKnown = GetSpellKnownMaxCount(casterLevel, circleLevel, nClass, oPC);
|
||||
// Favoured Soul has more 0 choices than there are spells for some reason
|
||||
if (nClass == CLASS_TYPE_FAVOURED_SOUL && circleLevel == 0 && totalSpellsKnown > 6)
|
||||
totalSpellsKnown = 6;
|
||||
totalSpellsKnown = 7;
|
||||
|
||||
// logic for spont casters
|
||||
json selectedCircle = JsonObjectGet(chosenSpells, IntToString(circleLevel));
|
||||
@@ -1554,6 +1509,7 @@ int GetRemainingSpellChoices(int nClass, int circleLevel, object oPC=OBJECT_SELF
|
||||
|
||||
if (chosenCircle == circleLevel)
|
||||
SetLocalInt(oPC, NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR, remainingChoices);
|
||||
if (DEBUG) DoDebug("Remaining spell choices is " + IntToString(remainingChoices));
|
||||
return remainingChoices;
|
||||
}
|
||||
|
||||
@@ -1566,10 +1522,6 @@ void FinishLevelUp(int nClass, object oPC=OBJECT_SELF)
|
||||
int nLevel = GetLevelByClass(nClass, oPC);
|
||||
SetPersistantLocalInt(oPC, "LastSpellGainLevel", nLevel);
|
||||
}
|
||||
if (GetIsBladeMagicClass(nClass))
|
||||
{
|
||||
DeletePersistantLocalInt(oPC, "AllowedDisciplines");
|
||||
}
|
||||
ClearLevelUpNUICaches(nClass, oPC);
|
||||
}
|
||||
|
||||
@@ -1668,11 +1620,13 @@ void RemoveSpells(int nClass, object oPC=OBJECT_SELF)
|
||||
{
|
||||
string sFile = GetClassSpellbookFile(nClass);
|
||||
string sSpellBook = GetSpellsKnown_Array(nClass);
|
||||
string spellsAtLevelList = "SpellsKnown_" + IntToString(nClass) + "_AtLevel" + IntToString(GetHitDice(oPC));
|
||||
// remove the spell from the spellbook
|
||||
array_extract_int(oPC, sSpellBook, nSpellbookID);
|
||||
array_extract_int(oPC, spellsAtLevelList, nSpellbookID);
|
||||
// wipe the spell from the player
|
||||
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||
WipeSpellFromHide(ipFeatID, oPC);
|
||||
RemoveIPFeat(oPC, ipFeatID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1783,6 +1737,7 @@ void LearnSpells(int nClass, object oPC=OBJECT_SELF)
|
||||
|
||||
// get location of persistant storage on the hide
|
||||
string sSpellbook = GetSpellsKnown_Array(nClass, nSpellLevel);
|
||||
if (DEBUG) DoDebug("Adding spell " + IntToString(nSpellbookID) + "to " + sSpellbook);
|
||||
//object oToken = GetHideToken(oPC);
|
||||
|
||||
// Create spells known persistant array if it is missing
|
||||
@@ -1793,13 +1748,25 @@ void LearnSpells(int nClass, object oPC=OBJECT_SELF)
|
||||
nSize = 0;
|
||||
}
|
||||
|
||||
string spellsAtLevelList = "SpellsKnown_" + IntToString(nClass) + "_AtLevel" + IntToString(GetHitDice(oPC));
|
||||
int spellsAtLevelSize = persistant_array_get_size(oPC, spellsAtLevelList);
|
||||
if (spellsAtLevelSize < 0)
|
||||
{
|
||||
persistant_array_create(oPC, spellsAtLevelList);
|
||||
spellsAtLevelSize = 0;
|
||||
}
|
||||
// set the list of spells learned at this level
|
||||
string sFile = GetClassSpellbookFile(nClass);
|
||||
int spellId = StringToInt(Get2DACache(sFile, "SpellID", nSpellbookID));
|
||||
persistant_array_set_int(oPC, spellsAtLevelList, spellsAtLevelSize, spellId);
|
||||
if (DEBUG) DoDebug("Adding spells to array " + spellsAtLevelList);
|
||||
|
||||
// Mark the spell as known (e.g. add it to the end of oPCs spellbook)
|
||||
persistant_array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
|
||||
|
||||
if (nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||
{
|
||||
// add spell
|
||||
string sFile = GetClassSpellbookFile(nClass);
|
||||
string sArrayName = "NewSpellbookMem_" + IntToString(nClass);
|
||||
int featId = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||||
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||
@@ -1979,7 +1946,7 @@ void RemoveSpellKnown(int nClass, int spellbookId, object oPC=OBJECT_SELF, int n
|
||||
//if we could not find the spell here, something went wrong
|
||||
if (persistant_array_extract_int(oPC, sTestArray, spellID) < 0)
|
||||
{
|
||||
SendMessageToPC(oPC, "Could not find spellID " + IntToString(spellID) + " in the class's spellbook!");
|
||||
if (DEBUG) DoDebug("Could not find spellID " + IntToString(spellID) + " in the class's spellbook!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2006,10 +1973,7 @@ void RemoveSpellKnown(int nClass, int spellbookId, object oPC=OBJECT_SELF, int n
|
||||
|
||||
// remove spell from player
|
||||
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", spellbookId));
|
||||
itemproperty ipFeat = PRCItemPropertyBonusFeat(ipFeatID);
|
||||
object oSkin = GetPCSkin(oPC);
|
||||
RemoveItemProperty(oSkin, ipFeat);
|
||||
CheckAndRemoveFeat(oSkin, ipFeat);
|
||||
RemoveIPFeat(oPC, ipFeatID);
|
||||
}
|
||||
|
||||
json GetSpellIDsKnown(int nClass, object oPC=OBJECT_SELF, int nList=0)
|
||||
@@ -2092,7 +2056,7 @@ string ReasonForDisabledSpell(int nClass, int spellbookId, object oPC=OBJECT_SEL
|
||||
|
||||
// if its an expanded knowledge choice and we have already made all our
|
||||
// exp knowledge choices then it needs to be disabled.
|
||||
if (IsExpKnowledgePower(nClass, spellbookId))
|
||||
if (IsExpKnowledgePower(nClass, spellbookId, oPC))
|
||||
{
|
||||
int remainingExp = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC)
|
||||
+ GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
||||
@@ -2326,11 +2290,15 @@ json GetChosenReplaceListObject(object oPC=OBJECT_SELF)
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
int IsExpKnowledgePower(int nClass, int spellbookId)
|
||||
int IsExpKnowledgePower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
|
||||
{
|
||||
string sFile = GetClassSpellbookFile(nClass);
|
||||
int isExp = StringToInt(Get2DACache(sFile, "Exp", spellbookId));
|
||||
return isExp;
|
||||
if (isExp)
|
||||
return TRUE;
|
||||
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
||||
int isOuterDomain = (featId) ? !CheckPowerPrereqs(featId, oPC) : FALSE;
|
||||
return isOuterDomain;
|
||||
}
|
||||
|
||||
json GetCurrentPowerList(object oPC=OBJECT_SELF)
|
||||
@@ -2350,12 +2318,8 @@ int ShouldAddPower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
|
||||
string sFile = GetClassSpellbookFile(nClass);
|
||||
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
||||
int isExp = StringToInt(Get2DACache(sFile, "Exp", spellbookId));
|
||||
// if you don't have the prereqs for a power then don't add it. Specific for
|
||||
// psions
|
||||
if (!CheckPowerPrereqs(featId, oPC))
|
||||
return FALSE;
|
||||
// if the power is a expanded knowledge power
|
||||
if (isExp)
|
||||
if (!CheckPowerPrereqs(featId, oPC) || isExp)
|
||||
{
|
||||
// and we have a expanded knowledge choice left to make then show
|
||||
// the button
|
||||
@@ -2364,10 +2328,12 @@ int ShouldAddPower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
|
||||
int currentCircle = GetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR);
|
||||
|
||||
int choicesLeft = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC);
|
||||
if (DEBUG) DoDebug("You still have " + IntToString(choicesLeft) + " expanded power choices left!");
|
||||
if (choicesLeft && (currentCircle <= (maxLevel-1)))
|
||||
addPower = TRUE;
|
||||
choicesLeft = GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
||||
if (choicesLeft)
|
||||
if (DEBUG) DoDebug("You still have " + IntToString(choicesLeft) + " epic expanded power choices left!");
|
||||
if (choicesLeft && (currentCircle <= (maxLevel-1)))
|
||||
addPower = TRUE;
|
||||
// otherwise don't show the button.
|
||||
return addPower;
|
||||
@@ -2387,7 +2353,7 @@ void LearnPowers(int nClass, object oPC=OBJECT_SELF)
|
||||
int nSpellbookID = JsonGetInt(JsonArrayGet(powerList, i));
|
||||
// get the expanded knowledge list we are adding to if any
|
||||
int expKnow = GetExpKnowledgePowerListRequired(nClass, nSpellbookID, oPC);
|
||||
AddPowerKnown(oPC, nClass, nSpellbookID, TRUE, GetManifesterLevel(oPC, nClass, TRUE), expKnow);
|
||||
AddPowerKnown(oPC, nClass, nSpellbookID, TRUE, GetHitDice(oPC), expKnow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2573,7 +2539,8 @@ int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_S
|
||||
json chosenDisc = JsonObjectGet(discInfo, discipline);
|
||||
if (chosenDisc != JsonNull())
|
||||
{
|
||||
int nManCount = JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)));
|
||||
int nManCount = (JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)))
|
||||
+ JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE))));
|
||||
if (nManCount >= prereqs)
|
||||
return TRUE;
|
||||
}
|
||||
@@ -3169,13 +3136,18 @@ json GetInvokerKnownListObject(int nClass, object oPC=OBJECT_SELF)
|
||||
}
|
||||
|
||||
SetLocalJson(oPC, NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR + IntToString(nClass), knownObject);
|
||||
if (DEBUG) DoDebug("Printing json representation of allowed invocations for class " + IntToString(nClass));
|
||||
if (DEBUG) DoDebug(JsonDump(knownObject, 2));
|
||||
return knownObject;
|
||||
}
|
||||
|
||||
int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJECT_SELF, int extra=TRUE)
|
||||
{
|
||||
if (DEBUG) DoDebug ("Getting remaining invocation choices at " + IntToString(chosenCircle) + " circle");
|
||||
int remaining = 0;
|
||||
int nLevel = GetInvokerLevel(oPC, nClass);
|
||||
if (nClass == CLASS_TYPE_DRAGON_SHAMAN) nLevel = GetLevelByClass(nClass, oPC);
|
||||
if (DEBUG) DoDebug("Invoker level is " + IntToString(nLevel));
|
||||
|
||||
json knownObject = GetInvokerKnownListObject(nClass, oPC);
|
||||
json chosenInv = GetChosenSpellListObject(nClass, oPC);
|
||||
@@ -3203,8 +3175,10 @@ int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJEC
|
||||
currentChosen += 1;
|
||||
}
|
||||
}
|
||||
if (DEBUG) DoDebug(IntToString(currentChosen) + " incantations chosen at " + IntToString(chosenCircle) + " circle");
|
||||
|
||||
int allowedAtCircle = JsonGetInt(JsonObjectGet(currentLevelKnown, IntToString(i)));
|
||||
if (DEBUG) DoDebug(IntToString(allowedAtCircle) + " incantations allowed at " + IntToString(chosenCircle) + " circle");
|
||||
|
||||
remaining = (allowedAtCircle - currentChosen + remaining);
|
||||
// if the circle is below the chosen circle and we have a positive remaining,
|
||||
|
||||
@@ -28,11 +28,17 @@ void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int re
|
||||
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0)
|
||||
{
|
||||
// look for existing window and destroy
|
||||
int nPreviousToken = NuiFindWindow(OBJECT_SELF, NUI_SPELL_DESCRIPTION_WINDOW_ID);
|
||||
int nPreviousToken = NuiFindWindow(oPlayer, NUI_SPELL_DESCRIPTION_WINDOW_ID);
|
||||
if(nPreviousToken != 0)
|
||||
{
|
||||
NuiDestroy(oPlayer, nPreviousToken);
|
||||
}
|
||||
|
||||
/* int nPreviousToken = NuiFindWindow(OBJECT_SELF, NUI_SPELL_DESCRIPTION_WINDOW_ID);
|
||||
if(nPreviousToken != 0)
|
||||
{
|
||||
NuiDestroy(OBJECT_SELF, nPreviousToken);
|
||||
}
|
||||
} */
|
||||
|
||||
// in order of accuracy for names it goes RealSpellID > SpellID > FeatID
|
||||
string spellName;
|
||||
|
||||
@@ -180,6 +180,24 @@ void RunImpactScript(object oPC, int nSpellID, int nEventType)
|
||||
DeleteLocalInt(oPC, PRC_SPELLID_OVERRIDE);
|
||||
}
|
||||
|
||||
//Returns true if the spell is one of the repair spells
|
||||
int IsRepair(int nSpellID)
|
||||
{
|
||||
return ((nSpellID >= SPELL_REPAIR_MINOR_DAMAGE) && (nSpellID <= SPELL_REPAIR_CRITICAL_DAMAGE));
|
||||
}
|
||||
|
||||
//Returns true if the spell is one of the mass repair spells
|
||||
int IsMassRepair(int nSpellID)
|
||||
{
|
||||
return ((nSpellID >= SPELL_MASS_REPAIR_LIGHT_DAMAGE) && (nSpellID <= SPELL_MASS_REPAIR_CRITICAL_DAMAGE));
|
||||
}
|
||||
|
||||
//Returns true if the spell is one of the mass inflict damage spells
|
||||
int IsMassInflictDamage(int nSpellID)
|
||||
{
|
||||
return ((nSpellID >= SPELL_MASS_INFLICT_LIGHT_DAMAGE) && (nSpellID <= SPELL_MASS_INFLICT_CRITICAL_DAMAGE));
|
||||
}
|
||||
|
||||
//Returns true if the spell is one of the cure spells
|
||||
int IsCure(int nSpellID)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,9 @@ const int SPELL_BLACKLIGHT = 2091;
|
||||
const int SPELL_BARD_SONG = 411;
|
||||
const int SPELL_BARD_CURSE_SONG = 644;
|
||||
|
||||
//:: Monk
|
||||
const int SPELL_MONK_ABUNDANT_STEP = 17986;
|
||||
|
||||
//:: Epic Level Handbook
|
||||
const int SPELL_EPIC_SWARM_OF_ARROWS = 17996;
|
||||
|
||||
@@ -1359,8 +1362,27 @@ const int SPELL_SUMMON_NATURES_ALLY_9_ARANEA = 17085;
|
||||
const int SPELL_CHASING_PERFECTION = 2479;
|
||||
|
||||
//:: Spell Compendium Spells
|
||||
const int SPELL_SPIRIT_WORM = 17248;
|
||||
const int SPELL_FORCE_MISSILES = 2480;
|
||||
const int SPELL_FORCE_MISSILES = 2480;
|
||||
const int SPELL_REPAIR_MINOR_DAMAGE = 17094;
|
||||
const int SPELL_REPAIR_LIGHT_DAMAGE = 17095;
|
||||
const int SPELL_REPAIR_MODERATE_DAMAGE = 17096;
|
||||
const int SPELL_REPAIR_SERIOUS_DAMAGE = 17097;
|
||||
const int SPELL_REPAIR_CRITICAL_DAMAGE = 17098;
|
||||
const int SPELL_INFLICT_LIGHT_DAMAGE = 17100;
|
||||
const int SPELL_INFLICT_MODERATE_DAMAGE = 17101;
|
||||
const int SPELL_INFLICT_SERIOUS_DAMAGE = 17102;
|
||||
const int SPELL_INFLICT_CRITICAL_DAMAGE = 17103;
|
||||
const int SPELL_SPIRIT_WORM = 17248;
|
||||
|
||||
//:: Races of Eberron
|
||||
const int SPELL_MASS_REPAIR_LIGHT_DAMAGE = 17105;
|
||||
const int SPELL_MASS_REPAIR_MODERATE_DAMAGE = 17106;
|
||||
const int SPELL_MASS_REPAIR_SERIOUS_DAMAGE = 17107;
|
||||
const int SPELL_MASS_REPAIR_CRITICAL_DAMAGE = 17108;
|
||||
const int SPELL_MASS_INFLICT_LIGHT_DAMAGE = 17110;
|
||||
const int SPELL_MASS_INFLICT_MODERATE_DAMAGE = 17111;
|
||||
const int SPELL_MASS_INFLICT_SERIOUS_DAMAGE = 17112;
|
||||
const int SPELL_MASS_INFLICT_CRITICAL_DAMAGE = 17113;
|
||||
|
||||
//:: Masters of the Wild Spells
|
||||
const int SPELL_FORESTFOLD = 17090;
|
||||
@@ -1392,6 +1414,10 @@ const int SPELL_FOT_LEONALS_ROAR = 17993;
|
||||
const int SPELL_FOT_LIONS_SWIFTNESS = 17994;
|
||||
const int SPELL_FAVORED_OF_THE_COMPANIONS = 17995;
|
||||
|
||||
//:: Magic Item Compendium
|
||||
const int SPELL_AROMA_OF_CURDLED_DEATH = 17987;
|
||||
const int SPELL_ELIXIR_OF_THE_BEETLE = 17987;
|
||||
|
||||
//x
|
||||
const int SPELL_TENSERS_FLOATING_DISK = 3849;
|
||||
const int SPELL_WOLFSKIN = 3850;
|
||||
|
||||
@@ -487,7 +487,8 @@ void SpellfireChargeItem(object oPC, object oItem)
|
||||
AddSpellfireLevels(oPC, nNewCharges - 50);
|
||||
nNewCharges = 50;
|
||||
}
|
||||
SetItemCharges(oItem, nCharges + nExpend);
|
||||
//SetItemCharges(oItem, nCharges + nExpend);
|
||||
SetItemCharges(oItem, nNewCharges);
|
||||
//Assuming 50 is the maximum
|
||||
//refunding excess charges
|
||||
}
|
||||
|
||||
@@ -47,12 +47,10 @@ int GetWeaponFocusFeatItemProperty(int nFeatNumber)
|
||||
if(nItemProperty != -1) return nItemProperty;
|
||||
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_TRIDENT, IP_CONST_FEAT_WEAPON_FOCUS_TRIDENT);
|
||||
if(nItemProperty != -1) return nItemProperty;
|
||||
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_LIGHT_LANCE, IP_CONST_FEAT_WEAPON_FOCUS_GOAD);
|
||||
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_EAGLE_CLAW, IP_CONST_FEAT_WEAPON_FOCUS_GOAD);
|
||||
if(nItemProperty != -1) return nItemProperty;
|
||||
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_LIGHTBLADE, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_LIGHTBLADE);
|
||||
if(nItemProperty != -1) return nItemProperty;
|
||||
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_EAGLE_CLAW, IP_CONST_FEAT_WEAPON_FOCUS_EAGLE_CLAW);
|
||||
if(nItemProperty != -1) return nItemProperty;
|
||||
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_THINBLADE, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_THINBLADE);
|
||||
if(nItemProperty != -1) return nItemProperty;
|
||||
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_COURTBLADE, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_COURTBLADE);
|
||||
|
||||
@@ -61,6 +61,7 @@ const int X2_CI_CRAFTROD_EPIC_FEAT_ID = 3490;
|
||||
const int X2_CI_CRAFTSTAFF_FEAT_ID = 2928;
|
||||
const int X2_CI_CRAFTSTAFF_EPIC_FEAT_ID = 3491;
|
||||
const int X2_CI_CREATEINFUSION_FEAT_ID = 25960;
|
||||
const int X2_CI_CRAFTSCEPTER_FEAT_ID = 25962;
|
||||
|
||||
const string X2_CI_BREWPOTION_NEWITEM_RESREF = "x2_it_pcpotion"; // ResRef for new potion item
|
||||
const string X2_CI_SCRIBESCROLL_NEWITEM_RESREF = "x2_it_pcscroll"; // ResRef for new scroll item
|
||||
@@ -276,6 +277,7 @@ int CIGetIsCraftFeatBaseItem(object oItem)
|
||||
nBt == BASE_ITEM_BLANK_WAND ||
|
||||
nBt == BASE_ITEM_CRAFTED_ROD ||
|
||||
nBt == BASE_ITEM_CRAFTED_STAFF ||
|
||||
nBt == BASE_ITEM_CRAFTED_SCEPTER ||
|
||||
nBt == BASE_ITEM_MUNDANE_HERB)
|
||||
return TRUE;
|
||||
else
|
||||
@@ -302,7 +304,7 @@ object CICraftBrewPotion(object oCreator, int nSpellID )
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
/* //just a tad retarded, don't you think? other crafting feats are not similarly restricted
|
||||
/* //just a tad silly, don't you think? other crafting feats are not similarly restricted
|
||||
//Uses per day
|
||||
int nUsesAllowed;
|
||||
|
||||
@@ -529,6 +531,7 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
|
||||
case CLASS_TYPE_WIZARD:
|
||||
case CLASS_TYPE_SORCERER: sClass = "Wiz_Sorc"; break;
|
||||
case CLASS_TYPE_CLERIC:
|
||||
case CLASS_TYPE_OCULAR:
|
||||
case CLASS_TYPE_UR_PRIEST: sClass = "Cleric"; break;
|
||||
case CLASS_TYPE_PALADIN: sClass = "Paladin"; break;
|
||||
case CLASS_TYPE_DRUID:
|
||||
@@ -709,6 +712,7 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
|
||||
return oTarget;
|
||||
}
|
||||
*/
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Returns TRUE if the player used the last spell to brew a potion
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -864,7 +868,6 @@ These dont work as IPs since they are hardcoded */
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Returns TRUE if the player used the last spell to create a scroll
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -1132,6 +1135,169 @@ These dont work as IPs since they are hardcoded */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Returns TRUE if the player used the last spell to craft a scepter
|
||||
// -----------------------------------------------------------------------------
|
||||
int CICraftCheckCraftScepter(object oSpellTarget, object oCaster, int nSpellID = 0)
|
||||
{
|
||||
|
||||
if(nSpellID == 0) nSpellID = PRCGetSpellId();
|
||||
int nCasterLevel = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
|
||||
int bSuccess = TRUE;
|
||||
int nCount = 0;
|
||||
itemproperty ip = GetFirstItemProperty(oSpellTarget);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
|
||||
while(GetIsItemPropertyValid(ip))
|
||||
{
|
||||
if(GetItemPropertyType(ip) == ITEM_PROPERTY_CAST_SPELL)
|
||||
nCount++;
|
||||
ip = GetNextItemProperty(oSpellTarget);
|
||||
}
|
||||
if(nCount >= 2) //:: Scepters are limited to two spells
|
||||
{
|
||||
FloatingTextStringOnCreature("* Failure - Too many castspell itemproperties *", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
if(!GetHasFeat(X2_CI_CRAFTSCEPTER_FEAT_ID, oCaster))
|
||||
{
|
||||
FloatingTextStrRefOnCreature(40487, oCaster); // Item Creation Failed - Don't know how to create that type of item
|
||||
return TRUE; // tried item creation but do not know how to do it
|
||||
}
|
||||
if(CIGetIsSpellRestrictedFromCraftFeat(nSpellID, X2_CI_CRAFTSCEPTER_FEAT_ID))
|
||||
{
|
||||
FloatingTextStrRefOnCreature(16829169, oCaster); // can not be used with this feat
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Get the base spell level (circle) before metamagic adjustments
|
||||
int nBaseLevel = CIGetSpellInnateLevel(nSpellID, TRUE);
|
||||
|
||||
// Check if spell circle is 7th level or lower
|
||||
if (nBaseLevel > 7)
|
||||
{
|
||||
//FloatingTextStrRefOnCreature(83623, oCaster); // Spell level too high
|
||||
FloatingTextStringOnCreature("* Failure - scepters can not hold spells higher than level 7", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int nLevel = nBaseLevel;
|
||||
|
||||
if(GetPRCSwitch(PRC_CRAFT_SCEPTER_CASTER_LEVEL))
|
||||
{
|
||||
switch(nMetaMagic)
|
||||
{
|
||||
case METAMAGIC_EMPOWER:
|
||||
nLevel += 2;
|
||||
break;
|
||||
case METAMAGIC_EXTEND:
|
||||
nLevel += 1;
|
||||
break;
|
||||
case METAMAGIC_MAXIMIZE:
|
||||
nLevel += 3;
|
||||
break;
|
||||
/* case METAMAGIC_QUICKEN:
|
||||
nLevel += 1;
|
||||
break;
|
||||
case METAMAGIC_SILENT:
|
||||
nLevel += 5;
|
||||
break;
|
||||
case METAMAGIC_STILL:
|
||||
nLevel += 6;
|
||||
break;
|
||||
These dont work as IPs since they are hardcoded */
|
||||
}
|
||||
}
|
||||
|
||||
int nCostMod = GetPRCSwitch(PRC_X2_CRAFTSCEPTER_COSTMODIFIER);
|
||||
if(!nCostMod) nCostMod = 750;
|
||||
int nLvlRow = IPGetIPConstCastSpellFromSpellID(nSpellID);
|
||||
int nCLevel = StringToInt(Get2DACache("iprp_spells","CasterLvl",nLvlRow));
|
||||
int nCost = CIGetCraftGPCost(nLevel, nCostMod, PRC_CRAFT_SCEPTER_CASTER_LEVEL);
|
||||
|
||||
//discount for second spell
|
||||
if(nCount+1 == 2)
|
||||
nCost = (nCost/2);
|
||||
|
||||
//takes epic xp costs into account
|
||||
struct craft_cost_struct costs = GetModifiedCostsFromBase(nCost, oCaster, FEAT_CRAFT_SCEPTER, (nMetaMagic > 0));
|
||||
|
||||
if(costs.nGoldCost < 1) costs.nXPCost = 1;
|
||||
if(costs.nXPCost < 1) costs.nXPCost = 1;
|
||||
//if(GetGold(oCaster) < nGoldCost) // enough gold?
|
||||
if (!GetHasGPToSpend(oCaster, costs.nGoldCost))
|
||||
{
|
||||
FloatingTextStrRefOnCreature(3786, oCaster); // Item Creation Failed - not enough gold!
|
||||
return TRUE;
|
||||
}
|
||||
int nHD = GetHitDice(oCaster);
|
||||
int nMinXPForLevel = (nHD * (nHD - 1)) * 500;
|
||||
int nNewXP = GetXP(oCaster) - costs.nXPCost;
|
||||
//if (nMinXPForLevel > nNewXP || nNewXP == 0 )
|
||||
if (!GetHasXPToSpend(oCaster, costs.nXPCost))
|
||||
{
|
||||
FloatingTextStrRefOnCreature(3785, oCaster); // Item Creation Failed - Not enough XP
|
||||
return TRUE;
|
||||
}
|
||||
//check spell emulation
|
||||
if(!CheckAlternativeCrafting(oCaster, nSpellID, costs))
|
||||
{
|
||||
FloatingTextStringOnCreature("*Crafting failed!*", oCaster, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellID);
|
||||
if (nPropID == 0 && nSpellID != 0)
|
||||
{
|
||||
FloatingTextStrRefOnCreature(84544,oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
if (nPropID != -1)
|
||||
{
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpell(nPropID,IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE),oSpellTarget);
|
||||
|
||||
if(GetPRCSwitch(PRC_CRAFT_SCEPTER_CASTER_LEVEL))
|
||||
{
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellCasterLevel(nSpellID, nCasterLevel),oSpellTarget);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellMetamagic(nSpellID, PRCGetMetaMagicFeat()),oSpellTarget);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellDC(nSpellID, PRCGetSaveDC(PRCGetSpellTargetObject(), OBJECT_SELF)),oSpellTarget);
|
||||
}
|
||||
}
|
||||
else
|
||||
bSuccess = FALSE;
|
||||
|
||||
if(bSuccess)
|
||||
{
|
||||
//TakeGoldFromCreature(nGoldCost, oCaster, TRUE);
|
||||
//SetXP(oCaster, nNewXP);
|
||||
SpendXP(oCaster, costs.nXPCost);
|
||||
SpendGP(oCaster, costs.nGoldCost);
|
||||
//DestroyObject (oSpellTarget);
|
||||
FloatingTextStrRefOnCreature(8502, oCaster); // Item Creation successful
|
||||
|
||||
//advance time here
|
||||
if(!costs.nTimeCost) costs.nTimeCost = 1;
|
||||
AdvanceTimeForPlayer(oCaster, RoundsToSeconds(costs.nTimeCost));
|
||||
string sName;
|
||||
sName = GetName(oCaster)+"'s Magic Scepter";
|
||||
SetItemCharges(oSpellTarget, 50);
|
||||
//sName = Get2DACache("spells", "Name", nID);
|
||||
//sName = "Wand of "+GetStringByStrRef(StringToInt(sName));
|
||||
SetName(oSpellTarget, sName);
|
||||
SetItemCursedFlag(oSpellTarget, FALSE);
|
||||
SetDroppableFlag(oSpellTarget, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingTextStrRefOnCreature(76417, oCaster); // Item Creation Failed
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Returns TRUE if the player used the last spell to craft a staff
|
||||
// -----------------------------------------------------------------------------
|
||||
int CICraftCheckCraftStaff(object oSpellTarget, object oCaster, int nSpellID = 0)
|
||||
{
|
||||
|
||||
@@ -1280,6 +1446,9 @@ These dont work as IPs since they are hardcoded */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Returns TRUE if the player used the last spell to craft a rod
|
||||
// -----------------------------------------------------------------------------
|
||||
int CICraftCheckCraftRod(object oSpellTarget, object oCaster, int nSpellID = 0)
|
||||
{
|
||||
|
||||
@@ -1426,6 +1595,7 @@ These dont work as IPs since they are hardcoded */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID, int nSpell = 0)
|
||||
{
|
||||
if(!GetIsObjectValid(oCaster)) oCaster = OBJECT_SELF;
|
||||
@@ -1476,6 +1646,11 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
|
||||
|
||||
if(!GetIsObjectValid(oTarget)) oTarget = PRCGetSpellTargetObject();
|
||||
int nCaster = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
|
||||
|
||||
//:: Check for Inscribe Epic Runes and cap CL at 20 if it doesn't exist.
|
||||
int bEpicRunes = GetHasFeat(EPIC_FEAT_INSCRIBE_EPIC_RUNES, oCaster);
|
||||
if (!bEpicRunes) { if(nCaster > 20) nCaster = 20; }
|
||||
|
||||
int nDC = PRCGetSaveDC(oTarget, oCaster);
|
||||
if(!nSpell) nSpell = PRCGetSpellId();
|
||||
int nSpellLevel = 0;
|
||||
@@ -1498,6 +1673,7 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
|
||||
// Minimum level.
|
||||
if (nSpellLevel == 0) nSpellLevel = 1;
|
||||
|
||||
|
||||
// This will be modified with Runecaster code later.
|
||||
int nCharges = 1;
|
||||
if (GetLocalInt(oCaster, "RuneCharges")) nCharges = nCount;
|
||||
@@ -1606,9 +1782,14 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
|
||||
// If they have this active, the bonuses are already added, so skip
|
||||
// If they don't, add the bonuses down below
|
||||
if(GetHasSpellEffect(SPELL_RUNE_CHANT))
|
||||
nRuneChant = 0;
|
||||
nRuneChant = 0;
|
||||
|
||||
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, PRCGetCasterLevel());
|
||||
//:: Check for Inscribe Epic Runes and cap CL at 20 if it doesn't exist.
|
||||
nCaster = PRCGetCasterLevel();
|
||||
|
||||
if (!bEpicRunes) { if(nCaster > 20) nCaster = 20; }
|
||||
|
||||
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, nCaster);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipLevel,oRune);
|
||||
itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpell, PRCGetMetaMagicFeat());
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ipMeta,oRune);
|
||||
@@ -1715,13 +1896,23 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
|
||||
}
|
||||
// oTarget here should be the gem. If it's not, fail.
|
||||
if(!GetIsObjectValid(oTarget)) oTarget = PRCGetSpellTargetObject();
|
||||
// Only accepts bioware gems
|
||||
if (GetStringLeft(GetResRef(oTarget), 5) == "it_gem")
|
||||
// Only accepts bioware gems & Craftable Natural Resources gems, but not gem dust.
|
||||
int bIsBioGem = (GetStringLeft(GetResRef(oTarget), 5) == "it_gem");
|
||||
int bIsCNRGem = (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem");
|
||||
int bIsDust = (GetStringLeft(GetResRef(oTarget), 10) == "cnrgemdust");
|
||||
|
||||
if (!(bIsBioGem || bIsCNRGem) || bIsDust)
|
||||
{
|
||||
FloatingTextStringOnCreature("Spell target is not a valid gem.", oCaster, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* if ((GetStringLeft(GetResRef(oTarget), 5) == "it_gem") || (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem") && (GetStringLeft(GetResRef(oTarget), 10) != "cnrgemdust"))
|
||||
{
|
||||
FloatingTextStringOnCreature("Spell target is not a valid gem.", oCaster, FALSE);
|
||||
// And out we go
|
||||
return TRUE;
|
||||
}
|
||||
} */
|
||||
|
||||
int nCaster = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
|
||||
int nDC = PRCGetSaveDC(oTarget, oCaster);
|
||||
@@ -2117,6 +2308,13 @@ int CIGetSpellWasUsedForItemCreation(object oSpellTarget)
|
||||
// -------------------------------------------------
|
||||
nRet = CICraftCheckCraftStaff(oSpellTarget,oCaster);
|
||||
break;
|
||||
|
||||
case BASE_ITEM_CRAFTED_SCEPTER :
|
||||
// -------------------------------------------------
|
||||
// Craft Scepter
|
||||
// -------------------------------------------------
|
||||
nRet = CICraftCheckCraftScepter(oSpellTarget,oCaster);
|
||||
break;
|
||||
|
||||
case BASE_ITEM_MUNDANE_HERB :
|
||||
// -------------------------------------------------
|
||||
@@ -2916,7 +3114,12 @@ int GetMagicalArtisanFeat(int nCraftingFeat)
|
||||
{
|
||||
nReturn = FEAT_MAGICAL_ARTISAN_CREATE_INFUSION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case FEAT_CRAFT_SCEPTER:
|
||||
{
|
||||
nReturn = FEAT_MAGICAL_ARTISAN_CRAFT_SCEPTER;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(DEBUG) DoDebug("GetMagicalArtisanFeat: invalid crafting feat");
|
||||
@@ -3309,21 +3512,23 @@ object CICreateInfusion(object oCreator, int nSpellID)
|
||||
|
||||
// Keep the original spell id the engine gave us (may be a subradial)
|
||||
int nSpellOriginal = nSpellID;
|
||||
if (DEBUG) DoDebug("prc_x2_craft >> CICreateInfusion: nSpellOriginal is "+IntToString(nSpellOriginal)+".");
|
||||
|
||||
// Compute the master (one-step) if this is a subradial. Keep original intact.
|
||||
int nSpellMaster = nSpellOriginal;
|
||||
// Compute the master if this is a subradial. Keep original intact.
|
||||
int nSpellMaster = nSpellOriginal;
|
||||
if (GetIsSubradialSpell(nSpellOriginal))
|
||||
{
|
||||
nSpellMaster = GetMasterSpellFromSubradial(nSpellOriginal);
|
||||
if (DEBUG) DoDebug("CICreateInfusion: detected subradial " + IntToString(nSpellOriginal) + " master -> " + IntToString(nSpellMaster));
|
||||
}
|
||||
if (DEBUG) DoDebug("prc_x2_craft >> CICreateInfusion: nSpellMaster is "+IntToString(nSpellMaster)+".");
|
||||
|
||||
// Try to find an iprp_spells row for the original subradial first (preferred).
|
||||
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellOriginal);
|
||||
int nSpellUsedForIP = nSpellOriginal;
|
||||
|
||||
// If not found for original, fall back to the master/base spell.
|
||||
if (nPropID < 0)
|
||||
if (nPropID < 0)
|
||||
{
|
||||
if (DEBUG) DoDebug("CICreateInfusion: no iprp row for original " + IntToString(nSpellOriginal) + ", trying master " + IntToString(nSpellMaster));
|
||||
nPropID = IPGetIPConstCastSpellFromSpellID(nSpellMaster);
|
||||
|
||||
@@ -20,9 +20,6 @@
|
||||
//:: Last Update: 2003-10-07
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
//:: Test void
|
||||
//:: void main (){}
|
||||
|
||||
//Changed by primogenitor to include CEP itemtypes
|
||||
|
||||
// * The tag of the ip work container, a placeable which has to be set into each
|
||||
@@ -697,6 +694,7 @@ if(nItem == BASE_ITEM_BASTARDSWORD
|
||||
|| nItem == BASE_ITEM_SICKLE
|
||||
|| nItem == BASE_ITEM_TWOBLADEDSWORD
|
||||
|| nItem == BASE_ITEM_CLUB
|
||||
|| nItem == BASE_ITEM_CRAFTED_SCEPTER
|
||||
|| nItem == BASE_ITEM_DAGGER
|
||||
|| nItem == BASE_ITEM_DIREMACE
|
||||
|| nItem == BASE_ITEM_HEAVYFLAIL
|
||||
@@ -729,6 +727,7 @@ if(nItem == BASE_ITEM_BASTARDSWORD
|
||||
|| nItem == BASE_ITEM_ELVEN_THINBLADE
|
||||
|| nItem == BASE_ITEM_ELVEN_COURTBLADE
|
||||
|| nItem == BASE_ITEM_CRAFTED_STAFF
|
||||
|| nItem == BASE_ITEM_CRAFTED_SCEPTER
|
||||
|| nItem == 300 //CEP Trident
|
||||
|| nItem == 303 //CEP Sai
|
||||
|| nItem == 304 //CEP nunchaku
|
||||
@@ -1612,31 +1611,140 @@ int IPGetDamageBonusConstantFromNumber(int nNumber)
|
||||
// oOld - Item equipped before polymorphing (source for item props)
|
||||
// oNew - Item equipped after polymorphing (target for item props)
|
||||
// bWeapon - Must be set TRUE when oOld is a weapon.
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE)
|
||||
{
|
||||
if (GetIsObjectValid(oOld) && GetIsObjectValid(oNew))
|
||||
{
|
||||
itemproperty ip = GetFirstItemProperty(oOld);
|
||||
while (GetIsItemPropertyValid(ip))
|
||||
{
|
||||
if (bWeapon)
|
||||
{
|
||||
if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) )
|
||||
{
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
|
||||
}
|
||||
ip = GetNextItemProperty(oOld);
|
||||
// Invalid source/target
|
||||
if (!GetIsObjectValid(oOld) || !GetIsObjectValid(oNew))
|
||||
return;
|
||||
|
||||
// Determine possessor
|
||||
object oPC = GetItemPossessor(oOld);
|
||||
if (!GetIsObjectValid(oPC))
|
||||
oPC = GetItemPossessor(oNew);
|
||||
|
||||
}
|
||||
}
|
||||
if (!GetIsObjectValid(oPC))
|
||||
{
|
||||
if (DEBUG) DoDebug("IPWS: Unable to determine item possessor");
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine glove state once
|
||||
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
|
||||
// Weapon ranged mismatch = do nothing (intent is no partial copy)
|
||||
if (bWeapon && GetWeaponRanged(oOld) != GetWeaponRanged(oNew))
|
||||
{
|
||||
if (DEBUG) DoDebug("IPWS: Weapon ranged mismatch <20> skipping all IP copy");
|
||||
return;
|
||||
}
|
||||
|
||||
// Begin property copy
|
||||
itemproperty ip = GetFirstItemProperty(oOld);
|
||||
while (GetIsItemPropertyValid(ip))
|
||||
{
|
||||
int nType = GetItemPropertyType(ip);
|
||||
|
||||
// If copying from gloves and monk gloves are active
|
||||
if (bMonkGloves
|
||||
&& (nType == ITEM_PROPERTY_DAMAGE_BONUS
|
||||
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|
||||
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP))
|
||||
{
|
||||
// Always apply glove damage IPs
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
|
||||
ip = GetNextItemProperty(oOld);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Normal weapon pass
|
||||
if (bWeapon)
|
||||
{
|
||||
// If monk gloves active ? skip ALL weapon damage IPs
|
||||
if (bMonkGloves
|
||||
&& (nType == ITEM_PROPERTY_DAMAGE_BONUS
|
||||
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|
||||
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP))
|
||||
{
|
||||
ip = GetNextItemProperty(oOld);
|
||||
continue;
|
||||
}
|
||||
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
|
||||
}
|
||||
|
||||
ip = GetNextItemProperty(oOld);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* // ----------------------------------------------------------------------------
|
||||
// GZ, Sept. 30 2003
|
||||
// Special Version of Copy Item Properties for use with greater wild shape
|
||||
// oOld - Item equipped before polymorphing (source for item props)
|
||||
// oNew - Item equipped after polymorphing (target for item props)
|
||||
// bWeapon - Must be set TRUE when oOld is a weapon.
|
||||
// ----------------------------------------------------------------------------
|
||||
void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE)
|
||||
{
|
||||
if (!GetIsObjectValid(oOld) || !GetIsObjectValid(oNew))
|
||||
return;
|
||||
|
||||
object oPC = GetItemPossessor(oOld);
|
||||
if (!GetIsObjectValid(oPC))
|
||||
{
|
||||
oPC = GetItemPossessor(oNew);
|
||||
}
|
||||
if (!GetIsObjectValid(oPC))
|
||||
{
|
||||
if (DEBUG) DoDebug("IPWS: Unable to determine item possessor");
|
||||
return;
|
||||
}
|
||||
|
||||
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
|
||||
|
||||
itemproperty ip = GetFirstItemProperty(oOld);
|
||||
while (GetIsItemPropertyValid(ip))
|
||||
{
|
||||
if (bWeapon)
|
||||
{
|
||||
// Gloves override weapon damage <20> skip weapon damage properties
|
||||
if (bMonkGloves)
|
||||
{
|
||||
int nType = GetItemPropertyType(ip);
|
||||
|
||||
// skip damage props
|
||||
if (nType == ITEM_PROPERTY_DAMAGE_BONUS
|
||||
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|
||||
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)
|
||||
{
|
||||
if (DEBUG) DoDebug("IPWS: SKIPPED weapon damage IP");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DEBUG) DoDebug("IPWS: Applied non-damage weapon IP");
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
|
||||
}
|
||||
|
||||
}
|
||||
else if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) )
|
||||
{
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
|
||||
}
|
||||
|
||||
ip = GetNextItemProperty(oOld);
|
||||
}
|
||||
} */
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Returns the current enhancement bonus of a weapon (+1 to +20), 0 if there is
|
||||
// no enhancement bonus. You can test for a specific type of enhancement bonus
|
||||
@@ -2018,4 +2126,6 @@ int IPOnHitSaveDC(int nSaveDC)
|
||||
if (nSaveDC > 26) nIPBonus = IP_CONST_ONHIT_SAVEDC_26;
|
||||
|
||||
return nIPBonus;
|
||||
} */
|
||||
} */
|
||||
|
||||
//:: void main(){}
|
||||
@@ -73,6 +73,7 @@ void SetMasteryOfElements();
|
||||
|
||||
//#include "lookup_2da_spell"
|
||||
#include "prcsp_reputation"
|
||||
#include "prc_inc_core"
|
||||
//#include "prc_inc_spells"
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "prc_ipfeat_const"
|
||||
#include "prc_feat_const"
|
||||
#include "inc_vfx_const"
|
||||
#include "prc_inc_nwscript"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
@@ -41,6 +41,8 @@ const int POWER_LIST_WARMIND = CLASS_TYPE_WARMIND;
|
||||
/* Function prototypes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
int IsHiddenTalent(object oPC = OBJECT_SELF);
|
||||
|
||||
/**
|
||||
* Attempts to use psionic focus. If the creature was focused, it
|
||||
* loses the focus. If it has Epic Psionic Focus feats, it will
|
||||
@@ -520,9 +522,9 @@ void GainPsionicFocus(object oGainee = OBJECT_SELF)
|
||||
{
|
||||
int nPsySneak = 1;
|
||||
if(GetHasFeat(FEAT_PSY_SNEAK_ATTACK_2d6, oGainee))
|
||||
nPsySneak += 2;
|
||||
nPsySneak += 1;
|
||||
if(GetHasFeat(FEAT_PSY_SNEAK_ATTACK_3d6, oGainee))
|
||||
nPsySneak += 3;
|
||||
nPsySneak += 1;
|
||||
|
||||
SetLocalInt(oGainee, "PsyRogueSneak",nPsySneak);
|
||||
DelayCommand(0.1, ExecuteScript("prc_sneak_att", oGainee));
|
||||
@@ -786,69 +788,12 @@ int GetIsPsionicCharacter(object oCreature)
|
||||
GetHasFeat(FEAT_KALASHTAR_PP, oCreature) ||
|
||||
GetHasFeat(FEAT_NATPSIONIC_1, oCreature) ||
|
||||
GetHasFeat(FEAT_NATPSIONIC_2, oCreature) ||
|
||||
GetHasFeat(FEAT_NATPSIONIC_3, oCreature)
|
||||
GetHasFeat(FEAT_NATPSIONIC_3, oCreature) ||
|
||||
IsHiddenTalent(oCreature)
|
||||
// Racial psionicity signifying feats go here
|
||||
);
|
||||
}
|
||||
|
||||
int IsHiddenTalent(object oPC = OBJECT_SELF)
|
||||
{
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC) ||
|
||||
//GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LocalCleanExtraFists(object oCreature)
|
||||
{
|
||||
int iIsCWeap, iIsEquip;
|
||||
@@ -985,6 +930,48 @@ int PracticedManifesting(object oManifester, int iManifestingClass, int iManifes
|
||||
|
||||
int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVALID, int nMaxPowerLevel = FALSE)
|
||||
{
|
||||
// Handle POWER_LIST_MISC (Hidden Talent) powers
|
||||
// Check if this is a power list call
|
||||
int nPowerType = GetLocalInt(oManifester, "PRC_UsePowerList");
|
||||
|
||||
if(nSpecificClass == CLASS_TYPE_INVALID && nPowerType == POWER_LIST_MISC)
|
||||
{
|
||||
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: CLASS_TYPE_INVALID + POWER_LIST_MISC found!");
|
||||
// Check if character has psionic class levels
|
||||
int nPsionLevel = GetLevelByClass(CLASS_TYPE_PSION, oManifester);
|
||||
int nPsywarLevel = GetLevelByClass(CLASS_TYPE_PSYWAR, oManifester);
|
||||
int nWilderLevel = GetLevelByClass(CLASS_TYPE_WILDER, oManifester);
|
||||
int nWarmindLevel = GetLevelByClass(CLASS_TYPE_WARMIND, oManifester);
|
||||
int nFistOfZuokenLevel = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oManifester);
|
||||
int nPsychicRogueLevel = GetLevelByClass(CLASS_TYPE_PSYCHIC_ROGUE, oManifester);
|
||||
|
||||
// If no psionic levels, use Charisma-based calculation (treat as 1st level)
|
||||
if(nPsionLevel + nPsywarLevel + nWilderLevel + nWarmindLevel +
|
||||
nFistOfZuokenLevel + nPsychicRogueLevel == 0)
|
||||
{
|
||||
// Hidden Talent: considered 1st-level manifester, but must have CHA 11+
|
||||
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: Hidden Talent found!");
|
||||
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
|
||||
return 1;
|
||||
else
|
||||
return 0; // Cannot manifest without CHA 11+
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: nSpecificClass=" + IntToString(nSpecificClass) +
|
||||
", nPowerType=" + IntToString(nPowerType));
|
||||
|
||||
// Has psionic levels - return highest manifester level
|
||||
int nHighest = 0;
|
||||
if(nPsionLevel > 0) nHighest = GetManifesterLevel(oManifester, CLASS_TYPE_PSION);
|
||||
if(nPsywarLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_PSYWAR));
|
||||
if(nWilderLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_WILDER));
|
||||
if(nWarmindLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_WARMIND));
|
||||
if(nFistOfZuokenLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_FIST_OF_ZUOKEN));
|
||||
if(nPsychicRogueLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_PSYCHIC_ROGUE));
|
||||
|
||||
return nHighest;
|
||||
}
|
||||
|
||||
int nLevel;
|
||||
int nAdjust = GetLocalInt(oManifester, PRC_CASTERLEVEL_ADJUSTMENT);
|
||||
nAdjust -= GetLocalInt(oManifester, "WoLManifPenalty");
|
||||
@@ -1049,17 +1036,27 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
|
||||
|
||||
DelayCommand(1.0, DeleteLocalInt(oManifester, PRC_CASTERLEVEL_OVERRIDE));
|
||||
nLevel = GetLocalInt(oManifester, PRC_CASTERLEVEL_OVERRIDE);
|
||||
}
|
||||
else if(GetManifestingClass(oManifester) != CLASS_TYPE_INVALID)
|
||||
{
|
||||
//Gets the manifesting class
|
||||
int nManifestingClass = GetManifestingClass(oManifester);
|
||||
if(DEBUG) DoDebug("Manifesting Class #2: " + IntToString(nManifestingClass), oManifester);
|
||||
nLevel = GetLevelByClass(nManifestingClass, oManifester);
|
||||
// Add levels from +ML PrCs only for the first manifesting class
|
||||
nLevel += GetPsionicPRCLevels(oManifester, nManifestingClass);
|
||||
//nLevel += nManifestingClass == GetPrimaryPsionicClass(oManifester) ? GetPsionicPRCLevels(oManifester) : 0;
|
||||
|
||||
}
|
||||
else if(GetManifestingClass(oManifester) != CLASS_TYPE_INVALID)
|
||||
{
|
||||
//Gets the manifesting class
|
||||
int nManifestingClass = GetManifestingClass(oManifester);
|
||||
if(DEBUG) DoDebug("Manifesting Class #2: " + IntToString(nManifestingClass), oManifester);
|
||||
|
||||
nLevel = GetLevelByClass(nManifestingClass, oManifester);
|
||||
// Add levels from +ML PrCs only for the first manifesting class
|
||||
nLevel += GetPsionicPRCLevels(oManifester, nManifestingClass);
|
||||
|
||||
// CHECK: If this is Hidden Talent and character has no levels, set to 1
|
||||
if(nLevel == 0 && GetLocalInt(oManifester, "PRC_UsePowerList") == TRUE &&
|
||||
GetLocalInt(oManifester, "PRC_PowerListType") == POWER_LIST_MISC)
|
||||
{
|
||||
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
|
||||
{
|
||||
if(DEBUG) DoDebug("GetManifesterLevel: Hidden Talent with no psionic levels, returning 1");
|
||||
nLevel = 1;
|
||||
}
|
||||
}
|
||||
// Psionic vestiges are tucked in here to override things.
|
||||
// This assumes that there will never be a psion with this spell effect manifesting things
|
||||
if (nManifestingClass == CLASS_TYPE_PSION && GetHasSpellEffect(VESTIGE_ARETE, oManifester) && !nMaxPowerLevel)
|
||||
@@ -1085,7 +1082,37 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
|
||||
// if(DEBUG) DoDebug("Level gotten via GetLevelByClass: " + IntToString(nLevel), oManifester);
|
||||
}
|
||||
|
||||
// If you have a primary psionic class and no manifester level yet, get levels based on that
|
||||
// If you have a primary psionic class and no manifester level yet, get levels based on that
|
||||
if (GetPrimaryPsionicClass(oManifester) && nLevel == 0)
|
||||
{
|
||||
int nClass = GetPrimaryPsionicClass(oManifester);
|
||||
nLevel = GetLevelByClass(nClass, oManifester);
|
||||
nLevel += GetPsionicPRCLevels(oManifester, nClass);
|
||||
nLevel += PracticedManifesting(oManifester, nClass, nLevel);
|
||||
}
|
||||
|
||||
// If everything else fails, check for Hidden Talent before returning 0
|
||||
if(nLevel == 0)
|
||||
{
|
||||
// Check if this is a Hidden Talent power
|
||||
if(GetLocalInt(oManifester, "PRC_UsePowerList") == POWER_LIST_MISC)
|
||||
{
|
||||
// Hidden Talent: manifester level is 1 if they have CHA 11+
|
||||
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
|
||||
{
|
||||
if(DEBUG) DoDebug("GetManifesterLevel: Hidden Talent character, returning level 1");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("Failed to get manifester level for creature " + DebugObject2Str(oManifester) + ", using first class slot");
|
||||
//else WriteTimestampedLogEntry("Failed to get manifester level for creature " + DebugObject2Str(oManifester) + ", using first class slot");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* // If you have a primary psionic class and no manifester level yet, get levels based on that
|
||||
if (GetPrimaryPsionicClass(oManifester) && nLevel == 0)
|
||||
{
|
||||
int nClass = GetPrimaryPsionicClass(oManifester);
|
||||
@@ -1102,7 +1129,7 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// The bonuses inside only apply to normal manifestation
|
||||
if(!GetLocalInt(oManifester, PRC_IS_PSILIKE))
|
||||
@@ -1665,4 +1692,225 @@ int GetMaxPowerLevel(object oManifester)
|
||||
int nMax = StringToInt(Get2DACache(sFile, "MaxPowerLevel", nLevel));
|
||||
if (DEBUG) DoDebug("GetMaxPowerLevel is "+IntToString(nMax));
|
||||
return nMax;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
/* START HIDDEN TALENT */
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
int IsHiddenTalent(object oPC = OBJECT_SELF)
|
||||
{
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC) ||
|
||||
//GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC) ||
|
||||
GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
int GetHiddenTalentPowerFromFeat(int nFeatID)
|
||||
{
|
||||
// Map Hidden Talent feats to their corresponding power IDs
|
||||
// Using the same mappings as GetIsHiddenTalentPower()
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_BIOFEEDBACK) return POWER_BIOFEEDBACK;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_BITE_WOLF) return POWER_BITE_WOLF;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_BOLT) return POWER_BOLT;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_BURST) return POWER_BURST;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_CALLTOMIND) return POWER_CALLTOMIND;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_CALL_WEAPONRY) return POWER_CALL_WEAPONRY;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_CHAMELEON) return POWER_CHAMELEON;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_CLAWS_BEAST) return POWER_CLAWS_BEAST;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_COMPRESSION) return POWER_COMPRESSION;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_CONCEALTHOUGHT) return POWER_CONCEALTHOUGHT;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_CREATESOUND) return POWER_CREATESOUND;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_CRYSTALSHARD) return POWER_CRYSTALSHARD;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_DAZE) return POWER_DAZE;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_DECELERATION) return POWER_DECELERATION;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_DEFPRECOG) return POWER_DEFPRECOG;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_DEMORALIZE) return POWER_DEMORALIZE;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_DISABLE) return POWER_DISABLE;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH)return POWER_DISSIPATINGTOUCH;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_DISTRACT) return POWER_DISTRACT;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_ELFSIGHT) return POWER_ELFSIGHT;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_EMPATHY) return POWER_EMPATHY;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_EMPTYMIND) return POWER_EMPTYMIND;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_ENTANGLE) return POWER_ENTANGLE;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_EXPANSION) return POWER_EXPANSION;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_FARHAND) return POWER_FARHAND;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_FORCESCREEN) return POWER_FORCESCREEN;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_GREASE) return POWER_GREASE;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_HAMMER) return POWER_HAMMER;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_INERTIALARMOUR) return POWER_INERTIALARMOUR;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_MATTERAGITATION) return POWER_MATTERAGITATION;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW) return POWER_METAPHYSICAL_CLAW;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON) return POWER_METAPHYSICAL_WEAPON;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_MINDTHRUST) return POWER_MINDTHRUST;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_MYLIGHT) return POWER_MYLIGHT;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_OFFPRECOG) return POWER_OFFPRECOG;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_OFFPRESC) return POWER_OFFPRESC;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_PREVENOM) return POWER_PREVENOM;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_PREVENOM_WEAPON) return POWER_PREVENOM_WEAPON;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_SKATE) return POWER_SKATE;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_STOMP) return POWER_STOMP;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_SYNESTHETE) return POWER_SYNESTHETE;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_TELEMPATHICPRO) return POWER_TELEMPATHICPRO;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_THICKSKIN) return POWER_THICKSKIN;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_VIGOR) return POWER_VIGOR;
|
||||
if(nFeatID == FEAT_HIDDEN_TALENT_GRIP_IRON) return POWER_GRIP_IRON;
|
||||
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
int GetHiddenTalentCount(object oPC = OBJECT_SELF)
|
||||
{
|
||||
int nCount = 0;
|
||||
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC)) nCount++;
|
||||
//if (GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC))nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC)) nCount++;
|
||||
if (GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC)) nCount++;
|
||||
|
||||
return nCount;
|
||||
}
|
||||
|
||||
int GetIsHiddenTalentPower(object oPC, int nPower)
|
||||
{
|
||||
// Check each Hidden Talent feat to see if it grants this power
|
||||
if(nPower == POWER_BIOFEEDBACK && GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC)) return TRUE;
|
||||
if(nPower == POWER_BITE_WOLF && GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC)) return TRUE;
|
||||
if(nPower == POWER_BOLT && GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC)) return TRUE;
|
||||
if(nPower == POWER_BURST && GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC)) return TRUE;
|
||||
if(nPower == POWER_CALLTOMIND && GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC)) return TRUE;
|
||||
if(nPower == POWER_CALL_WEAPONRY && GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC)) return TRUE;
|
||||
if(nPower == POWER_CHAMELEON && GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC)) return TRUE;
|
||||
if(nPower == POWER_CLAWS_BEAST && GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC)) return TRUE;
|
||||
if(nPower == POWER_COMPRESSION && GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC)) return TRUE;
|
||||
if(nPower == POWER_CONCEALTHOUGHT && GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC)) return TRUE;
|
||||
if(nPower == POWER_CREATESOUND && GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC)) return TRUE;
|
||||
if(nPower == POWER_CRYSTALSHARD && GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC)) return TRUE;
|
||||
if(nPower == POWER_DAZE && GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC)) return TRUE;
|
||||
if(nPower == POWER_DECELERATION && GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC)) return TRUE;
|
||||
if(nPower == POWER_DEFPRECOG && GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC)) return TRUE;
|
||||
if(nPower == POWER_DEMORALIZE && GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC)) return TRUE;
|
||||
if(nPower == POWER_DISABLE && GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC)) return TRUE;
|
||||
if(nPower == POWER_DISSIPATINGTOUCH && GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC)) return TRUE;
|
||||
if(nPower == POWER_DISTRACT && GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC)) return TRUE;
|
||||
if(nPower == POWER_ELFSIGHT && GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC)) return TRUE;
|
||||
if(nPower == POWER_EMPATHY && GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC)) return TRUE;
|
||||
if(nPower == POWER_EMPTYMIND && GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC)) return TRUE;
|
||||
//if(nPower == POWER_ENERGYRAY && GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) return TRUE;
|
||||
if(nPower == POWER_ENTANGLE && GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC)) return TRUE;
|
||||
if(nPower == POWER_EXPANSION && GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC)) return TRUE;
|
||||
if(nPower == POWER_FARHAND && GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC)) return TRUE;
|
||||
if(nPower == POWER_FORCESCREEN && GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC)) return TRUE;
|
||||
if(nPower == POWER_GREASE && GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC)) return TRUE;
|
||||
if(nPower == POWER_HAMMER && GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC)) return TRUE;
|
||||
if(nPower == POWER_INERTIALARMOUR && GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC)) return TRUE;
|
||||
if(nPower == POWER_MATTERAGITATION && GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC)) return TRUE;
|
||||
if(nPower == POWER_METAPHYSICAL_CLAW && GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC)) return TRUE;
|
||||
if(nPower == POWER_METAPHYSICAL_WEAPON && GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC)) return TRUE;
|
||||
if(nPower == POWER_MINDTHRUST && GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC)) return TRUE;
|
||||
if(nPower == POWER_MYLIGHT && GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC)) return TRUE;
|
||||
if(nPower == POWER_OFFPRECOG && GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC)) return TRUE;
|
||||
if(nPower == POWER_OFFPRESC && GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC)) return TRUE;
|
||||
if(nPower == POWER_PREVENOM && GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC)) return TRUE;
|
||||
if(nPower == POWER_PREVENOM_WEAPON && GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC)) return TRUE;
|
||||
if(nPower == POWER_SKATE && GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC)) return TRUE;
|
||||
if(nPower == POWER_STOMP && GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC)) return TRUE;
|
||||
if(nPower == POWER_SYNESTHETE && GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC)) return TRUE;
|
||||
if(nPower == POWER_TELEMPATHICPRO && GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC)) return TRUE;
|
||||
if(nPower == POWER_THICKSKIN && GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC)) return TRUE;
|
||||
if(nPower == POWER_VIGOR && GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC)) return TRUE;
|
||||
if(nPower == POWER_GRIP_IRON && GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC)) return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ object GetSplitPsionicRayTarget(struct manifestation manif, object oPrimaryTarge
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#include "psi_inc_core"
|
||||
#include "psi_inc_psifunc"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
|
||||
@@ -572,7 +572,11 @@ int GetMaxPowerCount(object oCreature, int nList)
|
||||
|
||||
int GetHasPower(int nPower, object oCreature = OBJECT_SELF)
|
||||
{
|
||||
if((GetLevelByClass(CLASS_TYPE_PSION, oCreature)
|
||||
// Check MISC list first (for Hidden Talent and similar feats)
|
||||
if(GetHasFeat(GetClassFeatFromPower(nPower, CLASS_TYPE_INVALID), oCreature))
|
||||
return TRUE;
|
||||
|
||||
if((GetLevelByClass(CLASS_TYPE_PSION, oCreature)
|
||||
&& GetHasFeat(GetClassFeatFromPower(nPower, CLASS_TYPE_PSION), oCreature)
|
||||
) ||
|
||||
(GetLevelByClass(CLASS_TYPE_PSYWAR, oCreature)
|
||||
|
||||
@@ -93,9 +93,8 @@ void GainPowerPoints(object oChar, int nGain, int bCanExceedMax = FALSE, int bIn
|
||||
* @param bInform If TRUE, runs TellCharacterPowerPointStatus() on oChar
|
||||
* after making the modification.
|
||||
*/
|
||||
/*
|
||||
void GainTemporaryPowerPoints(object oChar, int nGain, float fDuration, int bInform = TRUE);
|
||||
*/
|
||||
|
||||
/**
|
||||
* Decreases the character's current power point count by up to the given
|
||||
* amount, limited to not going below 0.
|
||||
@@ -138,8 +137,12 @@ int _GetFeatBonusPP(object oChar)
|
||||
{
|
||||
int nBonusPP = 0;
|
||||
|
||||
//:: Wild Talent & Hidden Talents
|
||||
if(GetHasFeat(FEAT_WILD_TALENT, oChar) || IsHiddenTalent())
|
||||
//:: Wild Talent
|
||||
if(GetHasFeat(FEAT_WILD_TALENT, oChar))
|
||||
nBonusPP += 2;
|
||||
|
||||
//:: Hidden Talent
|
||||
if(GetHasFeat(FEAT_HIDDEN_TALENT, oChar))
|
||||
nBonusPP += 2;
|
||||
|
||||
//:: Psionic Feats
|
||||
|
||||
@@ -40,7 +40,8 @@ void IdentifyPower(object oManifester, int nPowerId);
|
||||
|
||||
// Always access via psi_inc_psifunc.
|
||||
|
||||
//#include "psi_inc_core"
|
||||
#include "psi_inc_core"
|
||||
#include "inc_2dacache"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
|
||||
@@ -407,6 +407,8 @@ void _CleanManifestationVariables(object oManifester)
|
||||
DeleteLocalInt(oManifester, PRC_POWER_LEVEL);
|
||||
DeleteLocalInt(oManifester, PRC_IS_PSILIKE);
|
||||
DeleteLocalInt(oManifester, PRC_AUGMENT_OVERRIDE);
|
||||
DeleteLocalInt(oManifester, "PRC_UsePowerList");
|
||||
DeleteLocalInt(oManifester, "PRC_PowerListType");
|
||||
}
|
||||
|
||||
/** Internal function.
|
||||
@@ -692,10 +694,28 @@ void _UsePowerAux(object oManifester, object oMfToken, int nSpellId,
|
||||
|
||||
struct manifestation EvaluateManifestation(object oManifester, object oTarget, struct power_augment_profile pap, int nMetaPsiFlags)
|
||||
{
|
||||
/* Get some data */
|
||||
//:: Handle Hidden Talent
|
||||
int nSpellID = PRCGetSpellId();
|
||||
int bIsHiddenTalent = GetIsHiddenTalentPower(oManifester, nSpellID);
|
||||
if(bIsHiddenTalent)
|
||||
{
|
||||
SetLocalInt(oManifester, "PRC_UsePowerList", TRUE);
|
||||
SetLocalInt(oManifester, "PRC_PowerListType", POWER_LIST_MISC);
|
||||
}
|
||||
/* Get some data */
|
||||
int bIgnoreConstraints = (DEBUG) ? GetLocalInt(oManifester, PRC_DEBUG_IGNORE_CONSTRAINTS) : FALSE;
|
||||
|
||||
// Manifester-related stuff
|
||||
int nManifesterLevel = GetManifesterLevel(oManifester);
|
||||
//int nManifesterLevel = GetManifesterLevel(oManifester);
|
||||
int nManifesterLevel;
|
||||
if(bIsHiddenTalent)
|
||||
{
|
||||
nManifesterLevel = GetManifesterLevel(oManifester, CLASS_TYPE_INVALID);
|
||||
}
|
||||
else
|
||||
{
|
||||
nManifesterLevel = GetManifesterLevel(oManifester);
|
||||
}
|
||||
int nPowerLevel = GetPowerLevel(oManifester);
|
||||
int nClass = GetManifestingClass(oManifester);
|
||||
int nWildSurge = GetWildSurge(oManifester);
|
||||
@@ -714,6 +734,8 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
|
||||
manif.nManifesterLevel = nManifesterLevel;
|
||||
manif.nSpellID = PRCGetSpellId();
|
||||
|
||||
|
||||
|
||||
// Run an ability score check to see if the manifester can manifest the power at all
|
||||
if (bIsPsiLike)
|
||||
{
|
||||
@@ -767,7 +789,9 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
|
||||
//If the manifester does not have enough points before hostile modifiers, cancel power
|
||||
if(manif.nPPCost > nManifesterPP && !bIsPsiLike && !bIgnoreConstraints)
|
||||
{
|
||||
FloatingTextStrRefOnCreature(16826412, oManifester, FALSE); // "You do not have enough Power Points to manifest this power"
|
||||
// DEBUG: show why the cost over cap branch triggered
|
||||
FloatingTextStringOnCreature("DEBUG: manif.nManifesterLevel=" + IntToString(manif.nManifesterLevel) + " manif.nPPCost=" + IntToString(manif.nPPCost) +" PRC_UsePowerList=" + IntToString(GetLocalInt(manif.oManifester, "PRC_UsePowerList")), manif.oManifester, FALSE);
|
||||
FloatingTextStrRefOnCreature(16826412, oManifester, FALSE); // "You do not have enough Power Points to manifest this power"
|
||||
manif.bCanManifest = FALSE;
|
||||
}
|
||||
// The manifester has enough power points that they would be able to use the power, barring extra costs
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "prc_class_const"
|
||||
*/
|
||||
#include "prc_alterations"
|
||||
#include "prcsp_engine"
|
||||
|
||||
// Constants that dictate ResistPower results
|
||||
const int POWER_RESIST_FAIL = 1;
|
||||
|
||||
@@ -75,6 +75,15 @@ int PsiPrePowerCastCode()
|
||||
|
||||
int nContinue = !ExecuteScriptAndReturnInt("prespellcode", oManifester);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Forsakers can't use psionics
|
||||
//---------------------------------------------------------------------------
|
||||
if (nContinue && GetLevelByClass(CLASS_TYPE_FORSAKER, oManifester))
|
||||
{
|
||||
FloatingTextStringOnCreature("Forsakers cannot manifest psionic powers!", oManifester, FALSE);
|
||||
nContinue = FALSE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Break any spell require maintaining concentration
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -209,3 +218,4 @@ int PsiPrePowerCastCode()
|
||||
return nContinue;
|
||||
}
|
||||
|
||||
//:: void main (){}
|
||||
@@ -192,7 +192,8 @@ int PathFeatToIPFeat(int nFeat);
|
||||
/* Includes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "inc_lookups"
|
||||
#include "inc_pers_array"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
@@ -519,7 +520,7 @@ int GetMaxMysteryLevelLearnable(object oShadow, int nClass, int nType)
|
||||
if(DEBUG) DoDebug("GetMaxMysteryLevelLearnable nType: " + IntToString(nType));
|
||||
|
||||
// Rules Quote:
|
||||
// Within a category<72>Apprentice, Initiate, Master<65>you must have at least two mysteries of any given level
|
||||
// Within a category<72>Apprentice, Initiate, Master<65>you must have at least two mysteries of any given level
|
||||
// before you can take any mysteries of the next higher level. For instance, you must have two 1st-level
|
||||
// mysteries before you can take any 2nds, and at least two 2nds before you can take any 3rds.
|
||||
int nMaxLrn, i, nMystLevel, nCount1, nCount2;
|
||||
|
||||
@@ -210,6 +210,7 @@ int GetHasNocturnal(object oShadow, int nPath);
|
||||
#include "prc_alterations"
|
||||
#include "shd_inc_myst"
|
||||
#include "shd_inc_mystknwn"
|
||||
#include "lookup_2da_spell"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "prc_inc_spells"
|
||||
#include "inc_utility"
|
||||
#include "prc_inc_itmrstr"
|
||||
#include "shd_inc_shdfunc"
|
||||
#include "lookup_2da_spell"
|
||||
|
||||
// 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
|
||||
@@ -132,6 +134,15 @@ int ShadPreMystCastCode()
|
||||
|
||||
int nContinue = !ExecuteScriptAndReturnInt("prespellcode",oShadow);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Block forsakers from using shadowcasting
|
||||
//---------------------------------------------------------------------------
|
||||
if(GetLevelByClass(CLASS_TYPE_FORSAKER, oShadow) > 0)
|
||||
{
|
||||
SendMessageToPC(oShadow, "Forsakers cannot use the power of shadowcasting.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Break any spell require maintaining concentration
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -277,4 +288,6 @@ int ShadPreMystCastCode()
|
||||
|
||||
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #6: " + IntToString(nContinue));
|
||||
return nContinue;
|
||||
}
|
||||
}
|
||||
|
||||
//:: void main (){}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "prc_inc_spells"
|
||||
#include "inc_utility"
|
||||
#include "x2_inc_spellhook"
|
||||
#include "tob_inc_tobfunc"
|
||||
|
||||
// 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
|
||||
@@ -78,7 +79,14 @@ int PreManeuverCastCode()
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue)
|
||||
nContinue = !GetLocalInt(oInitiator, "CrusaderBreak");
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Forsakers can't use supernatural maneuvers
|
||||
//---------------------------------------------------------------------------
|
||||
if (nContinue && GetIsManeuverSupernatural(nMoveId) && GetLevelByClass(CLASS_TYPE_FORSAKER, oInitiator))
|
||||
{
|
||||
FloatingTextStringOnCreature("Forsakers cannot use supernatural maneuvers!", oInitiator, FALSE);
|
||||
nContinue = FALSE;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
// Run NullPsionicsField Check
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -109,11 +109,14 @@ int GetIsSyllable(int nSpellId);
|
||||
*/
|
||||
int DoSpellTruenameCheck(object oTrueSpeaker, object oTarget, int nPersonal = FALSE);
|
||||
|
||||
string GetNormalUtterSpellId(int nSpellId);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Includes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#include "prc_inc_spells"
|
||||
#include "true_inc_trufunc"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
|
||||
@@ -260,6 +260,7 @@ int GetCadenceCount(object oTrueSpeaker);
|
||||
#include "prc_alterations"
|
||||
#include "true_inc_utter"
|
||||
#include "true_inc_truknwn"
|
||||
#include "true_inc_truespk"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
|
||||
@@ -141,6 +141,7 @@ int GetHasUtterance(int nUtter, object oCreature = OBJECT_SELF);
|
||||
#include "inc_pers_array"
|
||||
#include "prc_inc_nwscript"
|
||||
#include "inc_lookups"
|
||||
#include "prc_x2_itemprop"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "prc_inc_spells"
|
||||
#include "inc_utility"
|
||||
#include "prc_inc_itmrstr"
|
||||
#include "true_inc_trufunc"
|
||||
|
||||
|
||||
// This function holds all functions that are supposed to run before the actual
|
||||
@@ -42,6 +43,16 @@ int TruePreUtterCastCode()
|
||||
|
||||
int nContinue = !ExecuteScriptAndReturnInt("prespellcode",oTrueSpeaker);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Block forsakers from using truenaming
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
if(GetLevelByClass(CLASS_TYPE_FORSAKER, oTrueSpeaker) > 0)
|
||||
{
|
||||
SendMessageToPC(oTrueSpeaker, "Forsakers cannot use the power of truenaming.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Break any spell require maintaining concentration
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -145,6 +145,7 @@ int PRCGetUserSpecificSpellScriptFinished();
|
||||
#include "inc_dynconv"
|
||||
#include "inc_npc"
|
||||
#include "inc_infusion"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
int Spontaneity(object oCaster, int nCastingClass, int nSpellID, int nSpellLevel)
|
||||
@@ -200,7 +201,6 @@ int Spontaneity(object oCaster, int nCastingClass, int nSpellID, int nSpellLevel
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int DruidSpontSummon(object oCaster, int nCastingClass, int nSpellID, int nSpellLevel)
|
||||
{
|
||||
if(nCastingClass != CLASS_TYPE_DRUID)
|
||||
@@ -217,14 +217,14 @@ int DruidSpontSummon(object oCaster, int nCastingClass, int nSpellID, int nSpell
|
||||
{
|
||||
case 0: return TRUE;
|
||||
case 1: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_1; break;
|
||||
case 2: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_2; break;
|
||||
case 2: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_2; break;
|
||||
case 3: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_3; break;
|
||||
case 4: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_4; break;
|
||||
case 4: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_4; break;
|
||||
case 5: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_5; break;
|
||||
case 6: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_6; break;
|
||||
case 7: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_7; break;
|
||||
case 6: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_6; break;
|
||||
case 7: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_7; break;
|
||||
case 8: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_8; break;
|
||||
case 9: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_9; break;
|
||||
case 9: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_9; break;
|
||||
}
|
||||
|
||||
//:: All SNA spells are subradial spells
|
||||
@@ -2902,7 +2902,7 @@ int WandEquipped(object oCaster, object oSpellCastItem)
|
||||
|
||||
int nType = GetBaseItemType(oSpellCastItem);
|
||||
|
||||
if(nType == BASE_ITEM_MAGICWAND || nType == BASE_ITEM_ENCHANTED_WAND) // Has to be a wand, obv
|
||||
if(nType == BASE_ITEM_MAGICWAND || nType == BASE_ITEM_ENCHANTED_WAND || nType == BASE_ITEM_CRAFTED_SCEPTER) // Has to be a wand, obv
|
||||
{
|
||||
if(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCaster) == oSpellCastItem || GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCaster) == oSpellCastItem) // Needs to be equipped
|
||||
{
|
||||
@@ -2910,7 +2910,7 @@ int WandEquipped(object oCaster, object oSpellCastItem)
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingTextStringOnCreature("You must equip a wand to cast from it.", oCaster, FALSE);
|
||||
FloatingTextStringOnCreature("You must equip this item to cast from it.", oCaster, FALSE);
|
||||
return FALSE; // It's a wand not equipped
|
||||
}
|
||||
}
|
||||
@@ -3347,6 +3347,28 @@ int X2PreSpellCastCode2()
|
||||
X2BreakConcentrationSpells();
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Herbal Infusion Use check
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue && (GetBaseItemType(oSpellCastItem) == BASE_ITEM_INFUSED_HERB))
|
||||
{
|
||||
int bIsSubradial = GetIsSubradialSpell(nSpellID);
|
||||
|
||||
if(bIsSubradial)
|
||||
{
|
||||
nSpellID = GetMasterSpellFromSubradial(nSpellID);
|
||||
}
|
||||
int nItemCL = GetCastSpellCasterLevelFromItem(oSpellCastItem, nSpellID);
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook >> X2PreSpellCastCode2: Item Spellcaster Level: "+IntToString(nItemCL)+".");
|
||||
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook >> X2PreSpellCastCode2: Herbal Infusion Found");
|
||||
if(!DoInfusionUseChecks(oCaster, oSpellCastItem, nSpellID))
|
||||
{
|
||||
ApplyInfusionPoison(oCaster, nItemCL);
|
||||
nContinue = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// No casting while using expertise
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue)
|
||||
@@ -3355,13 +3377,8 @@ int X2PreSpellCastCode2()
|
||||
SendMessageToPC(oCaster, "Combat Expertise only works with attack actions.");
|
||||
nContinue = FALSE;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
// Run Infusion use check
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue)
|
||||
nContinue = DoInfusionUseChecks(oCaster, oSpellCastItem, nSpellID);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Run Spelldance perform check
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "x0_i0_position"
|
||||
#include "X0_INC_HENAI"
|
||||
#include "x3_inc_skin"
|
||||
#include "prc_racial_const"
|
||||
|
||||
/*
|
||||
|
||||
@@ -638,7 +639,7 @@ int HorseGetMountTail(object oHorse);
|
||||
// FILE: x3_inc_horse FUNCTION: HorseGetMountFailureMessage()
|
||||
// This is a companion function to HorseGetCanBeMounted. If you need a text
|
||||
// message that explains why the horse cannot be mounted.
|
||||
string HorseGetMountFailureMessage(object oTarget,object oRider=OBJECT_INVALID);
|
||||
string HorseGetMountFailureMessage(object oHorse,object oRider=OBJECT_INVALID);
|
||||
|
||||
|
||||
// FILE: x3_inc_horse FUNCTION: HorseAddHorseMenu()
|
||||
@@ -1050,6 +1051,8 @@ void HORSE_SupportOriginalSpeed(object oRider)
|
||||
} // check to see if matches conditions
|
||||
eSearch=GetNextEffect(oRider);
|
||||
} // cycle through effects
|
||||
|
||||
|
||||
} // HORSE_SupportOriginalSpeed()
|
||||
|
||||
|
||||
|
||||
@@ -1681,7 +1681,7 @@
|
||||
},
|
||||
"Mod_OnPlrGuiEvt": {
|
||||
"type": "resref",
|
||||
"value": ""
|
||||
"value": "prc_onplayergui"
|
||||
},
|
||||
"Mod_OnPlrLvlUp": {
|
||||
"type": "resref",
|
||||
|
||||
@@ -18529,7 +18529,7 @@
|
||||
"__struct_id": 0,
|
||||
"CR": {
|
||||
"type": "float",
|
||||
"value": 17.0
|
||||
"value": 16.0
|
||||
},
|
||||
"FACTION": {
|
||||
"type": "cexostring",
|
||||
@@ -29133,7 +29133,7 @@
|
||||
"__struct_id": 0,
|
||||
"CR": {
|
||||
"type": "float",
|
||||
"value": 0.3333
|
||||
"value": 84.0
|
||||
},
|
||||
"FACTION": {
|
||||
"type": "cexostring",
|
||||
|
||||
Reference in New Issue
Block a user