2 Commits
1.04 ... 1.06

Author SHA1 Message Date
Jaysyn904
157382e60d 2026/02/09 Update
Added and activated PRCX.
Updated PRC8 includes.
2026-02-09 08:18:11 -05:00
Jaysyn904
fde89f634f 2025/12/25 Update
Hooked up new GUI module event.
Updated PEPS.
Updated PRC8 includes
Updated nasher.cfg.
2025-12-25 20:17:20 -05:00
190 changed files with 113683 additions and 5388 deletions

View File

@@ -3,8 +3,9 @@ name = "Realms of Trinity II [PRC8]"
description = "Realms of Trinity II with PRC8 & other enhancements"
version = "2.02prc8"
url = "https://discord.gg/gZtMe894eh"
author = "Jaysyn904 <68194417+Jaysyn904@users.noreply.github.com>"
author = "Tab"
author = "Jaysyn904 <68194417+Jaysyn904@users.noreply.github.com>"
[package.sources]
include = "src/module/**/*.{nss.json}"
@@ -232,9 +233,16 @@ description = "Realms of Trinity II with PRC8 & other enhancements"
filter = "prc_nui_sc_inc.nss"
filter = "prc_nui_scd_inc.nss"
filter = "prc_nui_consts.nss"
filter = "nw_inc_nui"
filter = "nw_inc_nui.nss"
filter = "xchst_inc.nss"
filter = "nui_i_library.nss"
filter = "prc_nui_sbd_inc.nss"
filter = "prc_nui_sb_inc.nss"
filter = "prc_nui_lv_inc.nss"
filter = "prc_nui_com_inc.nss"
filter = "prc_inc_size.nss"
filter = "prc_inc_json.nss"
filter = "prc_inc_gff.nss"
filter = "inc_infusion.nss"
[target]
name = "pepshak"

View File

@@ -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()
{

View File

@@ -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 (){}

View File

@@ -4,12 +4,15 @@
//:://////////////////////////////////////////////
/** @file
@author Primogenitor
@date 2005.09.23 - Rebuilt the system - Ornedan
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
//PRC8 Token pre-fix = 161838
//////////////////////////////////////////////////
/* Constant definitions */
@@ -41,7 +44,7 @@ const int DYNCONV_STRREF_PLEASE_WAIT = 16824202; // "Please wait"
const int DYNCONV_STRREF_PREVIOUS = 16824203; // "Previous"
const int DYNCONV_STRREF_NEXT = 16824204; // "Next"
const int DYNCONV_STRREF_ABORT_CONVO = 16824212; // "Abort"
const int DYNCONV_STRREF_EXIT_CONVO = 16183878; // "Exit"
const int DYNCONV_STRREF_EXIT_CONVO = 78; // "Exit"
const string DYNCONV_SCRIPT = "DynConv_Script";
const string DYNCONV_VARIABLE = "DynConv_Var";
@@ -475,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));
}
}
}

View File

@@ -26,7 +26,7 @@ int GetSpellFromAbrev(string sAbrev);
//////////////////////////////////////////////////
#include "inc_utility"
//#include "inc_epicspelldef"
#include "inc_epicspells"
// SEED FUNCTIONS

View File

@@ -305,10 +305,17 @@ int GetIsEpicShaman(object oPC)
int GetIsEpicSorcerer(object oPC)
{
return GetPrCAdjustedCasterLevel(CLASS_TYPE_SORCERER, oPC, FALSE) > 17
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)
{
return GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oPC) > 8

View 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 (){}

View File

@@ -880,7 +880,8 @@ void SetCompositeBonusT(object oItem, string sBonus, int iVal, int iType, int iS
AddItemProperty(DURATION_TYPE_TEMPORARY, ItemPropertyAttackBonusVsSAlign(iSubType, iCurVal + iChange), oItem,9999.0);
break;
case ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP:
iCurVal = TotalAndRemoveProperty(oItem, iType, iSubType);
//iCurVal = TotalAndRemoveProperty(oItem, iType, iSubType);
iCurVal = TotalAndRemovePropertyT(oItem, iType, iSubType);
if ((iCurVal + iChange) > 20)
{
iVal -= iCurVal + iChange - 20;
@@ -888,7 +889,8 @@ void SetCompositeBonusT(object oItem, string sBonus, int iVal, int iType, int iS
iChange = 0;
}
if(iCurVal+iChange > 0)
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageBonusVsRace(iSubType, DAMAGE_TYPE_SLASHING, iCurVal + iChange), oItem);
//AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageBonusVsRace(iSubType, DAMAGE_TYPE_SLASHING, iCurVal + iChange), oItem);
AddItemProperty(DURATION_TYPE_TEMPORARY, ItemPropertyDamageBonusVsRace(iSubType, DAMAGE_TYPE_SLASHING, iCurVal + iChange), oItem);
break;
case ITEM_PROPERTY_DECREASED_ABILITY_SCORE:
iCurVal = TotalAndRemovePropertyT(oItem, iType, iSubType);

View File

@@ -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_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 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 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)
{

View File

@@ -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 (){}

View File

@@ -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);
@@ -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() {}

View File

@@ -2,21 +2,23 @@
/* Combined wrappers for both Win32 and Linux NWNX funcs */
////////////////////////////////////////////////////////////////////////////////////
#include "inc_debug"
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
// Used in OnModuleLoad event to auto-detect if NWNX_Funcs plugin is enabled
// Used in OnModuleLoad event to auto-detect if NWNX_Funcs plugin is enabled (DEFUNCT)
void PRC_Funcs_Init(object oModule);
// Sets the amount of hitpoints oObject has currently to nHP
void PRC_Funcs_SetCurrentHitPoints(object oCreature, int nHP);
// Sets the amount of hitpoints oObject can maximally have to nHP
void PRC_Funcs_SetMaxHitPoints(object oCreature, int nHP);
void PRC_Funcs_SetMaxHitPoints(object oCreature, int nHP, int nLevel = 0);
// Changes the skill ranks for nSkill on oObject by iValue
void PRC_Funcs_ModSkill(object oCreature, int nSkill, int nValue);
void PRC_Funcs_ModSkill(object oCreature, int nSkill, int nValue, int nLevel = 0);
// Sets a base ability score nAbility (ABILITY_STRENGTH, ABILITY_DEXTERITY, etc) to nValue
// The range of nValue is 3 to 255
@@ -44,17 +46,17 @@ void PRC_Funcs_SetBaseNaturalAC(object oCreature, int nValue);
int PRC_Funcs_GetBaseNaturalAC(object oCreature);
// Sets the specialist spell school of a Wizard
void PRC_Funcs_SetWizardSpecialization(object oCreature, int iSpecialization);
void PRC_Funcs_SetWizardSpecialization(object oCreature, int iSpecialization, int nClass = CLASS_TYPE_WIZARD);
// Returns the specialist spell school of a Wizard
int PRC_Funcs_GetWizardSpecialization(object oCreature);
int PRC_Funcs_GetWizardSpecialization(object oCreature, int nClass = CLASS_TYPE_WIZARD);
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
int _PRC_NWNXFuncsZero(object oObject, string sFunc) {
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
SetLocalString(oObject, sFunc, "-");
else if (nVersion == 2)
@@ -65,7 +67,7 @@ int _PRC_NWNXFuncsZero(object oObject, string sFunc) {
}
int _PRC_NWNXFuncsOne(object oObject, string sFunc, int nVal1) {
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
SetLocalString(oObject, sFunc, IntToString(nVal1));
else if (nVersion == 2)
@@ -76,7 +78,7 @@ int _PRC_NWNXFuncsOne(object oObject, string sFunc, int nVal1) {
}
int _PRC_NWNXFuncsTwo(object oObject, string sFunc, int nVal1, int nVal2) {
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
SetLocalString(oObject, sFunc, IntToString(nVal1) + " " + IntToString(nVal2));
else if (nVersion == 2)
@@ -87,7 +89,7 @@ int _PRC_NWNXFuncsTwo(object oObject, string sFunc, int nVal1, int nVal2) {
}
int _PRC_NWNXFuncsThree(object oObject, string sFunc, int nVal1, int nVal2, int nVal3) {
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
SetLocalString(oObject, sFunc, IntToString(nVal1) + " " + IntToString(nVal2) + " " + IntToString(nVal3));
else if (nVersion == 2)
@@ -98,7 +100,7 @@ int _PRC_NWNXFuncsThree(object oObject, string sFunc, int nVal1, int nVal2, int
}
int _PRC_NWNXFuncsFour(object oObject, string sFunc, int nVal1, int nVal2, int nVal3, int nVal4) {
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
SetLocalString(oObject, sFunc, IntToString(nVal1) + " " + IntToString(nVal2) + " " + IntToString(nVal3) + " " + IntToString(nVal4));
else if (nVersion == 2)
@@ -114,13 +116,13 @@ void PRC_Funcs_Init(object oModule)
string sTestVariable = "PRC_TEST_NWNX_FUNCS";
SetLocalString(oModule, sTestVariable, "1");
SetLocalString(oModule, "NWNX!FUNCS!GETHASLOCALVARIABLE", sTestVariable + " 3"); //3 is the variable type
//NOTE: don't use _PRC_NWNXFuncsX functions here; they depend on the PRC_NWNX_FUNCS that we haven't set yet
//NOTE: don't use _PRC_NWNXFuncsX functions here; they depend on the PRC_NWNXEE_ENABLED that we haven't set yet
int iTest = StringToInt(GetLocalString(oModule, "NWNX!FUNCS!GETHASLOCALVARIABLE"));
DeleteLocalString(oModule, "NWNX!FUNCS!GETHASLOCALVARIABLE");
DeleteLocalString(oModule, sTestVariable);
if (iTest)
SetLocalInt(oModule, "PRC_NWNX_FUNCS", 1); //1 == win32
SetLocalInt(oModule, "PRC_NWNXEE_ENABLED", 1); //1 == win32
else
{
//NWNX GetLocalVariableCount behaves differently for win32 and linux,
@@ -132,7 +134,7 @@ void PRC_Funcs_Init(object oModule)
//the call failed because NWNX funcs is not present.
string sFunc = "NWNX!FUNCS!GETLOCALVARIABLECOUNT";
SetLocalString(oModule, sFunc, " ");
//NOTE: don't use _PRC_NWNXFuncsX functions here; they depend on the PRC_NWNX_FUNCS that we haven't set yet
//NOTE: don't use _PRC_NWNXFuncsX functions here; they depend on the PRC_NWNXEE_ENABLED that we haven't set yet
//NOTE: the number being returned by GetLocalVariableCount() on Linux seems bogus to me (it's huge, e.g. 294,654,504),
//but it does seem to be reliably zero when NWNX funcs is not present, and so far has been reliably non-zero
//when it is present. That's all we need here.
@@ -140,50 +142,116 @@ void PRC_Funcs_Init(object oModule)
int nVariables = StringToInt(GetLocalString(oModule, sFunc));
DeleteLocalString(oModule, sFunc);
if (nVariables)
SetLocalInt(oModule, "PRC_NWNX_FUNCS", 2); //2 == linux
SetLocalInt(oModule, "PRC_NWNXEE_ENABLED", 2); //2 == linux
}
}
void PRC_Funcs_SetMaxHitPoints(object oCreature, int nHP)
void PRC_Funcs_SetMaxHitPoints(object oCreature, int nHP, int nLevel = 0)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Default to total hit dice if not provided
if (nLevel <= 0)
nLevel = GetHitDice(oCreature);
//:: Payload for NWNxEE shim
SetLocalInt(oCreature, "PRC_EE_MAXHP", nHP);
SetLocalInt(oCreature, "PRC_EE_MAXHP_LEVEL", nLevel);
//:: Fire NWNxEE shim
ExecuteScript("prcx_set_maxhp", oCreature);
}
/* void PRC_Funcs_SetMaxHitPoints(object oCreature, int nHP)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1 || nVersion == 2)
{
_PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!SETMAXHITPOINTS", nHP);
DeleteLocalString(oCreature, "NWNX!FUNCS!SETMAXHITPOINTS");
}
} */
void PRC_Funcs_ModSkill(object oCreature, int nSkill, int nValue, int nLevel = 0)
{
//:: Default to current level if not provided
if (nLevel <= 0)
nLevel = GetHitDice(oCreature);
//:: Payload for NWNxEE shim
SetLocalInt(oCreature, "PRC_EE_SKILL", nSkill);
SetLocalInt(oCreature, "PRC_EE_SKILL_DELTA", nValue);
SetLocalInt(oCreature, "PRC_EE_SKILL_LEVEL", nLevel);
//:: Fire NWNxEE shim
ExecuteScript("prcx_mod_skill", oCreature);
}
void PRC_Funcs_ModSkill(object oCreature, int nSkill, int nValue)
/* void PRC_Funcs_ModSkill(object oCreature, int nSkill, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
_PRC_NWNXFuncsThree(oCreature, "NWNX!FUNCS!SETSKILL", nSkill, nValue, 1); //The 1 is a flag specifying modify instead of set
else if (nVersion == 2)
_PRC_NWNXFuncsTwo(oCreature, "NWNX!FUNCS!MODIFYSKILLRANK", nSkill, nValue);
}
} */
void PRC_Funcs_SetAbilityScore(object oCreature, int nAbility, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Payload for NWNxEE shim
SetLocalInt(oCreature, "PRC_EE_ABILITY", nAbility);
SetLocalInt(oCreature, "PRC_EE_ABILITY_VALUE", nValue);
//:: Fire NWNxEE shim
ExecuteScript("prcx_set_ability", oCreature);
}
/* void PRC_Funcs_SetAbilityScore(object oCreature, int nAbility, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
_PRC_NWNXFuncsFour(oCreature, "NWNX!FUNCS!SETABILITYSCORE", nAbility, nValue, 0, 0); //The first 0 is a flag specifying set instead of modify
else if (nVersion == 2)
_PRC_NWNXFuncsTwo(oCreature, "NWNX!FUNCS!SETABILITYSCORE", nAbility, nValue);
}
} */
void PRC_Funcs_ModAbilityScore(object oCreature, int nAbility, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
if(DEBUG) DoDebug("============================================");
if(DEBUG) DoDebug("PRC_Funcs_ModAbiltyScore: Starting function.");
if(DEBUG) DoDebug("============================================");
//:: Payload for NWNxEE shim
SetLocalInt(oCreature, "PRC_EE_ABILITY", nAbility);
SetLocalInt(oCreature, "PRC_EE_ABILITY_DELTA", nValue);
if(DEBUG) DoDebug("PRC_Funcs_ModAbiltyScore: Variables Set");
//:: Fire NWNxEE shim
if(DEBUG) DoDebug("PRC_Funcs_ModAbiltyScore: Firing prc_mod_ability");
ExecuteScript("prcx_mod_ability", oCreature);
}
/* void PRC_Funcs_ModAbilityScore(object oCreature, int nAbility, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
_PRC_NWNXFuncsFour(oCreature, "NWNX!FUNCS!SETABILITYSCORE", nAbility, nValue, 1, 0); //The 1 is a flag specifying modify instead of set
else if (nVersion == 2)
_PRC_NWNXFuncsTwo(oCreature, "NWNX!FUNCS!MODIFYABILITYSCORE", nAbility, nValue);
}
} */
void PRC_Funcs_AddFeat(object oCreature, int nFeat, int nLevel = 0)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Payload for NWNxEE shim
SetLocalInt(oCreature, "PRC_EE_FEAT", nFeat);
SetLocalInt(oCreature, "PRC_EE_FEAT_LEVEL", nLevel);
//:: Fire NWNxEE shim
ExecuteScript("prcx_add_feat", oCreature);
}
/* void PRC_Funcs_AddFeat(object oCreature, int nFeat, int nLevel=0)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
{
if (!nLevel)
@@ -198,21 +266,88 @@ void PRC_Funcs_AddFeat(object oCreature, int nFeat, int nLevel=0)
else if(nLevel > 0)
_PRC_NWNXFuncsTwo(oCreature, "NWNX!FUNCS!ADDKNOWNFEATATLEVEL", nLevel, nFeat);
}
}
} */
/**
* @brief Determines whether a creature inherently knows a feat.
*
* This function returns TRUE only if the specified feat is an inherent
* (true) feat possessed by the creature. Bonus feats granted via
* EFFECT_TYPE_BONUS_FEAT effects are explicitly ignored.
*
* This allows reliable differentiation between permanent feats
* (e.g. class, racial, or template feats) and temporary or granted
* bonus feats applied through effects.
*
* No NWNxEE shim is required; this function operates entirely using
* stock NWScript functionality.
*
* @param oCreature The creature to check.
* @param nFeatIndex The feat constant to test.
*
* @return TRUE if the creature inherently knows the feat and does not
* possess it solely via a bonus feat effect; FALSE otherwise.
*/
int PRC_Funcs_GetFeatKnown(object oCreature, int nFeatIndex)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Check for an EffectBonusFeat with this feat ID
effect eCheck = GetFirstEffect(oCreature);
int bHasBonusFeatEffect = FALSE;
while (GetIsEffectValid(eCheck))
{
if (GetEffectType(eCheck) == EFFECT_TYPE_BONUS_FEAT && GetEffectInteger(eCheck, 0) == nFeatIndex)
{
bHasBonusFeatEffect = TRUE;
break;
}
eCheck = GetNextEffect(oCreature);
}
//;: Return TRUE only if inherent and no matching bonus feat effect
return (!bHasBonusFeatEffect && GetHasFeat(nFeatIndex, oCreature));
}
/* int PRC_Funcs_GetFeatKnown(object oCreature, int nFeatIndex)
{
//:: Payload for NWNxEE shim
SetLocalInt(oCreature, "PRC_EE_FEAT", nFeatIndex);
//:: Fire NWNxEE shim
ExecuteScript("prcx_knows_feat", oCreature);
//:: Read result
int nResult = GetLocalInt(oCreature, "PRC_EE_FEAT_RESULT");
//:: Clean up locals
DeleteLocalInt(oCreature, "PRC_EE_FEAT");
DeleteLocalInt(oCreature, "PRC_EE_FEAT_RESULT");
return nResult;
} */
/* int PRC_Funcs_GetFeatKnown(object oCreature, int nFeatIndex)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
return _PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!GETFEATKNOWN", nFeatIndex);
else if (nVersion == 2)
return _PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!GETKNOWNFEAT", nFeatIndex);
return 0;
}
} */
void PRC_Funcs_ModSavingThrowBonus(object oCreature, int nSavingThrow, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Payload for NWNxEE shim
SetLocalInt(oCreature, "PRC_EE_STYPE", nSavingThrow);
SetLocalInt(oCreature, "PRC_EE_SDELTA", nValue);
//:: Fire NWNxEE shim
ExecuteScript("prcx_mod_save", oCreature);
}
/* void PRC_Funcs_ModSavingThrowBonus(object oCreature, int nSavingThrow, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
_PRC_NWNXFuncsThree(oCreature, "NWNX!FUNCS!SETSAVINGTHROWBONUS", nSavingThrow, nValue, 1); //The 1 is a flag specifying modify instead of set
else if (nVersion == 2)
@@ -224,61 +359,133 @@ void PRC_Funcs_ModSavingThrowBonus(object oCreature, int nSavingThrow, int nValu
nNewValue = 127;
_PRC_NWNXFuncsTwo(oCreature, "NWNX!FUNCS!SETSAVINGTHROWBONUS", nSavingThrow, nNewValue);
}
}
} */
void PRC_Funcs_SetBaseNaturalAC(object oCreature, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Payload for NWNxEE shim
SetLocalInt(oCreature, "PRC_EE_BASEAC", nValue);
//:: Fire NWNxEE shim
ExecuteScript("prcx_set_ac", oCreature);
}
/* void PRC_Funcs_SetBaseNaturalAC(object oCreature, int nValue)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
_PRC_NWNXFuncsTwo(oCreature, "NWNX!FUNCS!SETBASEAC", nValue, AC_NATURAL_BONUS);
else if (nVersion == 2)
_PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!SETACNATURALBASE", nValue);
}
} */
int PRC_Funcs_GetBaseNaturalAC(object oCreature)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Fire NWNxEE shim
ExecuteScript("prcx_get_ac", oCreature);
//:: Read result
int nAC = GetLocalInt(oCreature, "PRC_EE_BASEAC_RESULT");
//:: Clean up
DeleteLocalInt(oCreature, "PRC_EE_BASEAC_RESULT");
return nAC;
}
/* int PRC_Funcs_GetBaseNaturalAC(object oCreature)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
return _PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!GETBASEAC", AC_NATURAL_BONUS);
else if (nVersion == 2)
return _PRC_NWNXFuncsZero(oCreature, "NWNX!FUNCS!GETACNATURALBASE");
return 0;
}
} */
void PRC_Funcs_SetCurrentHitPoints(object oCreature, int nHP)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Sanity check
if (nHP < 0)
nHP = 0;
//:: Set current hit points directly
//:: Was this not a native function in the past?
SetCurrentHitPoints(oCreature, nHP);
}
/* void PRC_Funcs_SetCurrentHitPoints(object oCreature, int nHP)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1 || nVersion == 2)
_PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!SETCURRENTHITPOINTS", nHP);
}
} */
void PRC_Funcs_SetCreatureSize(object oCreature, int nSize)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Pass parameters via locals
SetLocalInt(oCreature, "PRC_EE_CREATURESIZE", nSize);
//:: Fire NWNxEE shim
ExecuteScript("prcx_set_size", oCreature);
}
/* void PRC_Funcs_SetCreatureSize (object oCreature, int nSize)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1 || nVersion == 2)
_PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!SETCREATURESIZE", nSize);
}
} */
void PRC_Funcs_SetRace(object oCreature, int nRace)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
//:: Pass parameters via locals
SetLocalInt(oCreature, "PRC_EE_RACETYPE", nRace);
//:: Fire NWNxEE shim
ExecuteScript("prcx_set_race", oCreature);
}
/* void PRC_Funcs_SetRace(object oCreature, int nRace)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1)
_PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!SETRACE", nRace);
else if (nVersion == 2)
_PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!SETRACIALTYPE", nRace);
} */
void PRC_Funcs_SetWizardSpecialization(object oCreature, int iSpecialization, int nClass = CLASS_TYPE_WIZARD)
{
//:: Pass parameters via locals
SetLocalInt(oCreature, "PRC_EE_WIZCLASS", nClass);
SetLocalInt(oCreature, "PRC_EE_WIZSCHOOL", iSpecialization);
//:: Fire NWNxEE shim
ExecuteScript("prcx_set_spec", oCreature);
}
void PRC_Funcs_SetWizardSpecialization(object oCreature, int iSpecialization)
/* void PRC_Funcs_SetWizardSpecialization(object oCreature, int iSpecialization)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1 || nVersion == 2)
_PRC_NWNXFuncsOne(oCreature, "NWNX!FUNCS!SETWIZARDSPECIALIZATION", iSpecialization);
} */
//:: This is a native function now.
int PRC_Funcs_GetWizardSpecialization(object oCreature, int nClass = CLASS_TYPE_WIZARD)
{
return GetSpecialization(oCreature, nClass);
}
int PRC_Funcs_GetWizardSpecialization(object oCreature)
/* int PRC_Funcs_GetWizardSpecialization(object oCreature)
{
int nVersion = GetLocalInt(GetModule(), "PRC_NWNX_FUNCS");
int nVersion = GetLocalInt(GetModule(), "PRC_NWNXEE_ENABLED");
if (nVersion == 1 || nVersion == 2)
return _PRC_NWNXFuncsZero(oCreature, "NWNX!FUNCS!GETWIZARDSPECIALIZATION");
return 0;
}
} */
//:: void main(){}

View File

@@ -686,3 +686,16 @@ string SQLocalsPlayer_GetLastUpdated_UTC(object oPlayer, string sVarName, int nT
else
return "";
}
// Returns the current Unix timestamp (seconds since 1970-01-01)
int GetCurrentUnixTimestamp()
{
sqlquery sql = SqlPrepareQueryObject(GetModule(),
"SELECT strftime('%s','now');");
if (SqlStep(sql))
return SqlGetInt(sql, 0);
else
return 0;
}

View File

@@ -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:

View File

@@ -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 */

View File

@@ -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)
{

View File

@@ -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,33 @@ 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);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PRCX_ENABLED);
//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_SHOW_SR_CHECK_DETAILS);
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 +904,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 +1024,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,36 +1088,37 @@ 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
//PW
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_ENABLE);
// ConvoCC is unneeded now.
/* array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_ENABLE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_AVARIEL_WINGS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_FEYRI_WINGS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_AASIMAR_WINGS);
@@ -1117,7 +1148,7 @@ void CreateSwitchNameArray()
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_MAX_STAT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_SKILL_MULTIPLIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_SKILL_BONUS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_CUSTOM_EXIT_SCRIPT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CONVOCC_CUSTOM_EXIT_SCRIPT); */
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TRUENAME_CR_MULTIPLIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TRUENAME_LEVEL_BONUS);

View File

@@ -1,4 +1,5 @@
#include "prc_inc_clsfunc"
#include "prc_inc_sp_tch"
int GetBlastDamageDices(object oInvoker, int nInvokerLevel)
{

View File

@@ -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"

View File

@@ -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"
//////////////////////////////////////////////////

View File

@@ -39,8 +39,10 @@ int InvocationASFCheck(object oInvoker, int nClass)
case 1: nASF -= 5; break;//light
case 2: nASF -= 10; break;//light
case 3: nASF -= 20; break;//light
case 4: nASF -= GetHasFeat(FEAT_BATTLE_CASTER, oInvoker) ? 20 : 0; break;//medium;
case 5: nASF -= GetHasFeat(FEAT_BATTLE_CASTER, oInvoker) ? 30 : 0; break;//medium
//case 4: nASF -= GetHasFeat(FEAT_BATTLE_CASTER, oInvoker) ? 20 : 0; break; //medium;
//case 5: nASF -= GetHasFeat(FEAT_BATTLE_CASTER, oInvoker) ? 30 : 0; break; //medium
case 4: nASF = GetHasFeat(FEAT_BATTLE_CASTER, oInvoker) ? 0 : nASF; break; //medium
case 5: nASF = GetHasFeat(FEAT_BATTLE_CASTER, oInvoker) ? 0 : nASF; break; //medium;
default: break;
}
}
@@ -77,6 +79,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 +179,4 @@ int PreInvocationCastCode()
return nContinue;
}
//:: void main (){}

View File

@@ -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;

View File

@@ -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)
{
@@ -247,3 +824,5 @@ void DoTail(object oPC, int nTailType)
//override any stored default appearance
SetPersistantLocalInt(oPC, "AppearanceStoredTail", nTailType);
}
//::void main (){}

View File

@@ -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 */

View File

@@ -40,6 +40,7 @@ struct ipstruct GetIpStructFromString(string sIp);
//#include "prc_inc_listener"
#include "prc_inc_chat"
#include "prc_x2_craft"
#include "prc_inc_material"
const int NUM_MAX_PROPERTIES = 200;
const int NUM_MAX_SUBTYPES = 256;
@@ -444,6 +445,7 @@ int Get2DALineFromItemprop(string sFile, itemproperty ip, object oItem)
}
break;
}
case ITEM_PROPERTY_ECHOBLADE: return 46; break;
}
}
return -1;
@@ -1529,7 +1531,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))));
string sDescRef = Get2DACache(sFile, "CraftedDescription", nLine);
if(sDescRef != "")
SetDescription(oItem, GetStringByStrRef(StringToInt(sDescRef)));
}
}
//Partly ripped off the lexicon :P
@@ -1620,7 +1627,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 +1665,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 +1695,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;
@@ -1790,6 +1808,11 @@ int GetCraftingDC(object oItem)
void MakeMasterwork(object oItem)
{
if(GetPlotFlag(oItem)) return; //sanity check
itemproperty ip = ItemPropertyQuality(IP_CONST_QUALITY_MASTERWORK);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
int nBase = GetBaseItemType(oItem);
if((nBase == BASE_ITEM_ARMOR) ||
(nBase == BASE_ITEM_SMALLSHIELD) ||
@@ -1799,6 +1822,70 @@ void MakeMasterwork(object oItem)
{
//no armour check penalty here
if(GetItemArmourCheckPenalty(oItem) == 0) return;
ip = ItemPropertySkillBonus(SKILL_BALANCE, 1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_CLIMB, 1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_HIDE, 1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_MOVE_SILENTLY, 1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_PICK_POCKET, 1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_SET_TRAP, 1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_TUMBLE, 1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_JUMP, 1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
else if(GetWeaponType(nBase))
{
ip = ItemPropertyAttackBonus(1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
}
else if(StringToInt(Get2DACache("prc_craft_gen_it", "Type", nBase)) == PRC_CRAFT_ITEM_TYPE_AMMO)
{
ip = ItemPropertyAttackBonus(1);
ip = TagItemProperty(ip, "Quality_Masterwork");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
}
else
return;
}
/* void MakeMasterwork(object oItem)
{
if(GetPlotFlag(oItem)) return; //sanity check
int nBase = GetBaseItemType(oItem);
if((nBase == BASE_ITEM_ARMOR) ||
(nBase == BASE_ITEM_SMALLSHIELD) ||
(nBase == BASE_ITEM_LARGESHIELD) ||
(nBase == BASE_ITEM_TOWERSHIELD)
)
{
//no armour check penalty here
if(GetItemArmourCheckPenalty(oItem) == 0) return;
IPSafeAddItemProperty(oItem, ItemPropertySkillBonus(SKILL_HIDE, 1) , 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
IPSafeAddItemProperty(oItem, ItemPropertySkillBonus(SKILL_MOVE_SILENTLY, 1), 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
IPSafeAddItemProperty(oItem, ItemPropertySkillBonus(SKILL_PICK_POCKET, 1) , 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
@@ -1812,17 +1899,226 @@ void MakeMasterwork(object oItem)
}
else if(StringToInt(Get2DACache("prc_craft_gen_it", "Type", nBase)) == PRC_CRAFT_ITEM_TYPE_AMMO)
{
/*
int nDamageType = (nBase == BASE_ITEM_BULLET) ? DAMAGE_TYPE_BLUDGEONING : DAMAGE_TYPE_PIERCING;
itemproperty ip1 = ItemPropertyDamageBonus(nDamageType, IP_CONST_DAMAGEBONUS_1);
*/
//int nDamageType = (nBase == BASE_ITEM_BULLET) ? DAMAGE_TYPE_BLUDGEONING : DAMAGE_TYPE_PIERCING;
//itemproperty ip1 = ItemPropertyDamageBonus(nDamageType, IP_CONST_DAMAGEBONUS_1);
IPSafeAddItemProperty(oItem, ItemPropertyAttackBonus(1), 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
}
else
return;
}
*/
void MakeAdamantine(object oItem)
{
if(GetPlotFlag(oItem)) return; //sanity check
if(GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
{
int nBonus = 0;
switch(GetItemBaseAC(oItem))
{
case 1:
case 2:
case 3: nBonus = IP_CONST_DAMAGERESIST_1; break;
case 4:
case 5: nBonus = IP_CONST_DAMAGERESIST_2; break;
case 6:
case 7:
case 8: nBonus = IP_CONST_DAMAGERESIST_3; break;
}
if(nBonus)
{
itemproperty ip = ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_BLUDGEONING, nBonus);
ip = TagItemProperty(ip, "Material_Adamantine");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_PIERCING, nBonus);
ip = TagItemProperty(ip, "Material_Adamantine");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_SLASHING, nBonus);
ip = TagItemProperty(ip, "Material_Adamantine");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertyMaterial(IP_MATERIAL_ADAMANTINE);
ip = TagItemProperty(ip, "Material_Adamantine");
IPSafeAddItemProperty(oItem, ip, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
}
void MakeDarkwood(object oItem)
{
if(GetPlotFlag(oItem)) return; //sanity check
itemproperty ip = ItemPropertyWeightReduction(IP_CONST_REDUCEDWEIGHT_50_PERCENT);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
int nBase = GetBaseItemType(oItem);
if(((nBase == BASE_ITEM_SMALLSHIELD) ||
(nBase == BASE_ITEM_LARGESHIELD) ||
(nBase == BASE_ITEM_TOWERSHIELD))
)
{
int nBonus = 2;
if(nBase == BASE_ITEM_SMALLSHIELD) nBonus = 1;
ip = ItemPropertySkillBonus(SKILL_BALANCE, nBonus);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_CLIMB, nBonus);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_HIDE, nBonus);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_MOVE_SILENTLY, nBonus);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_PICK_POCKET, nBonus);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_SET_TRAP, nBonus);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_TUMBLE, nBonus);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_JUMP, nBonus);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertyMaterial(IP_MATERIAL_WOOD_DARKWOOD_ZALANTAR);
ip = TagItemProperty(ip, "Material_Darkwood");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
void MakeDragonhide(object oItem)
{
//Does nothing so far
}
void MakeMithral(object oItem)
{
if(GetPlotFlag(oItem)) return; //sanity check
itemproperty ip = ItemPropertyWeightReduction(IP_CONST_REDUCEDWEIGHT_50_PERCENT);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
int nBase = GetBaseItemType(oItem);
if(GetWeaponType(nBase))
{
ip = ItemPropertyMaterial(IP_MATERIAL_MITHRAL);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
else if(((nBase == BASE_ITEM_ARMOR) ||
(nBase == BASE_ITEM_SMALLSHIELD) ||
(nBase == BASE_ITEM_LARGESHIELD) ||
(nBase == BASE_ITEM_TOWERSHIELD))
)
{
int nBonus = 3;
int nPenalty = GetItemArmourCheckPenalty(oItem);
if(nBonus > nPenalty) nBonus = nPenalty;
ip = ItemPropertySkillBonus(SKILL_BALANCE, nBonus);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_CLIMB, nBonus);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_HIDE, nBonus);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_MOVE_SILENTLY, nBonus);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_PICK_POCKET, nBonus);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_SET_TRAP, nBonus);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_TUMBLE, nBonus);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertySkillBonus(SKILL_JUMP, nBonus);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
ip = ItemPropertyMaterial(IP_MATERIAL_MITHRAL);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
if(GetItemBaseAC(oItem) == 1)
{
ip = ItemPropertyArcaneSpellFailure(IP_CONST_ARCANE_SPELL_FAILURE_MINUS_5_PERCENT);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
else
{
ip = ItemPropertyArcaneSpellFailure(IP_CONST_ARCANE_SPELL_FAILURE_MINUS_10_PERCENT);
ip = TagItemProperty(ip, "Material_Mithral");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
}
void MakeColdIron(object oItem)
{
//Does nothing so far
itemproperty ip = ItemPropertyMaterial(IP_MATERIAL_COLD_IRON);
ip = TagItemProperty(ip, "Material_ColdIron");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
void MakeSilver(object oItem)
{
//Does nothing so far
itemproperty ip = ItemPropertyMaterial(IP_MATERIAL_SILVER);
ip = TagItemProperty(ip, "Material_ColdIron");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
void MakeMundaneCrystal(object oItem)
{
//Does nothing so far
itemproperty ip = ItemPropertyMaterial(IP_MATERIAL_GEM_CRYSTAL_MUNDANE);
ip = TagItemProperty(ip, "Material_MundaneCrystal");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
void MakeDeepCrystal(object oItem)
{
//Does nothing so far
itemproperty ip = ItemPropertyMaterial(IP_MATERIAL_GEM_CRYSTAL_DEEP);
ip = TagItemProperty(ip, "Material_DeepCrystal");
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
/* void MakeAdamantine(object oItem)
{
if(GetPlotFlag(oItem)) return; //sanity check
if(GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
@@ -1844,11 +2140,14 @@ void MakeAdamantine(object oItem)
IPSafeAddItemProperty(oItem, ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_BLUDGEONING, nBonus), 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
IPSafeAddItemProperty(oItem, ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_PIERCING, nBonus) , 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
IPSafeAddItemProperty(oItem, ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_SLASHING, nBonus) , 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
}
void MakeDarkwood(object oItem)
itemproperty ipAdamantine = ItemPropertyMaterial(IP_MATERIAL_ADAMANTINE);
IPSafeAddItemProperty(oItem, ipAdamantine, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
} */
/* void MakeDarkwood(object oItem)
{
if(GetPlotFlag(oItem)) return; //sanity check
IPSafeAddItemProperty(oItem, ItemPropertyWeightReduction(IP_CONST_REDUCEDWEIGHT_50_PERCENT), 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
@@ -1866,10 +2165,14 @@ void MakeDarkwood(object oItem)
IPSafeAddItemProperty(oItem, ItemPropertySkillBonus(SKILL_SET_TRAP, nBonus) , 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
IPSafeAddItemProperty(oItem, ItemPropertySkillBonus(SKILL_TUMBLE, nBonus) , 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
IPSafeAddItemProperty(oItem, ItemPropertySkillBonus(SKILL_JUMP, nBonus) , 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
void MakeDragonhide(object oItem)
itemproperty ipDarkwood = ItemPropertyMaterial(IP_MATERIAL_WOOD_DARKWOOD_ZALANTAR);
IPSafeAddItemProperty(oItem, ipDarkwood, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
*/
/* void MakeDragonhide(object oItem)
{
//Does nothing so far
}
@@ -1900,28 +2203,44 @@ void MakeMithral(object oItem)
IPSafeAddItemProperty(oItem, ItemPropertyArcaneSpellFailure(IP_CONST_ARCANE_SPELL_FAILURE_MINUS_5_PERCENT), 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
else
IPSafeAddItemProperty(oItem, ItemPropertyArcaneSpellFailure(IP_CONST_ARCANE_SPELL_FAILURE_MINUS_10_PERCENT), 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
void MakeColdIron(object oItem)
itemproperty ipMithral = ItemPropertyMaterial(IP_MATERIAL_MITHRAL);
IPSafeAddItemProperty(oItem, ipMithral, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
}
*/
/* void MakeColdIron(object oItem)
{
//Does nothing so far
itemproperty ipColdIron = ItemPropertyMaterial(IP_MATERIAL_COLD_IRON);
IPSafeAddItemProperty(oItem, ipColdIron, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
*/
void MakeSilver(object oItem)
/* void MakeSilver(object oItem)
{
//Does nothing so far
itemproperty ipSilver = ItemPropertyMaterial(IP_MATERIAL_SILVER);
IPSafeAddItemProperty(oItem, ipSilver, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
*/
void MakeMundaneCrystal(object oItem)
/* void MakeMundaneCrystal(object oItem)
{
//Does nothing so far
itemproperty ipCrystal = ItemPropertyMaterial(IP_MATERIAL_GEM_CRYSTAL_MUNDANE);
IPSafeAddItemProperty(oItem, ipCrystal, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
*/
void MakeDeepCrystal(object oItem)
/* void MakeDeepCrystal(object oItem)
{
//Does nothing so far
itemproperty ipDeepCrystal = ItemPropertyMaterial(IP_MATERIAL_GEM_CRYSTAL_DEEP);
IPSafeAddItemProperty(oItem, ipDeepCrystal, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
*/
//Creates an item on oOwner, from the baseitemtype and base AC (for armour)
object CreateStandardItem(object oOwner, int nBaseItemType, int nBaseAC = -1)
@@ -2950,4 +3269,4 @@ int ITEM_APPR_WEAPON_COLOR_MIDDLE = 1;
int ITEM_APPR_WEAPON_COLOR_TOP = 2;
*/
// void main () {}
//:: void main () {}

View File

@@ -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)
@@ -495,6 +498,7 @@ effect EffectFatigue(){
effect eReturn = EffectAbilityDecrease(ABILITY_STRENGTH, 2);
eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_DEXTERITY, 2));
eReturn = EffectLinkEffects(eReturn, EffectMovementSpeedDecrease(25));
eReturn = EffectLinkEffects(eReturn, EffectIcon(EFFECT_ICON_FATIGUE));
eReturn = TagEffect(eReturn, "PRCFatigue");
return eReturn;
}
@@ -746,7 +750,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 +771,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 +805,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() {}

View File

@@ -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;
@@ -333,6 +341,16 @@ const int FEAT_FOG_CLOUD_BREATH = 5434; //:: Spiretop Dragon
const int FEAT_LTSENSE = 4700;
const int FEAT_LTBLIND = 4701;
const int FEAT_RESIST_SONIC5 = 26398; //:: Shyft
const int FEAT_SHYFT_ETHEREAL_JAUNT = 26399;
const int FEAT_MECHA_ELECTRICY_HEALING = 4431; //:: Mechanatrix
const int FEAT_MECHA_SHOCKING_GRASP = 4432;
const int FEAT_WISPLING_CHANGE_SHAPE = 4433; //:: Wispling
const int FEAT_MAELUTH_FIEND_HAMMER = 4434; //:: Maeluth
const int FEAT_SPELL5 = 4702;
const int FEAT_SPELL10 = 4420;
const int FEAT_SPELL11 = 4703;
@@ -396,6 +414,8 @@ const int FEAT_CONSTRICT = 4740;
const int FEAT_REGEN5 = 4741;
const int FEAT_REND = 4742;
const int FEAT_RESIST_FIRE5 = 4743;
const int FEAT_RESIST_COLD5 = 4430;
const int FEAT_SUFFOCATION = 4744;
const int FEAT_VERYHEROIC = 4745;
const int FEAT_VULN_COLD = 4746;
@@ -958,32 +978,35 @@ const int FEAT_KOB_DRAGONWROUGHT_SR = 3855;
const int FEAT_DRAGON_AUGMENT_STR_1 = 3857;
const int FEAT_DRAGON_AUGMENT_STR_2 = 3858;
const int FEAT_DRAGON_AUGMENT_STR_3 = 3859;
const int FEAT_DRAGON_AUGMENT_STR_4 = 26382;
const int FEAT_DRAGON_AUGMENT_STR_5 = 26383;
const int FEAT_DRAGON_AUGMENT_STR_6 = 26384;
const int FEAT_DRAGON_AUGMENT_STR_7 = 26385;
const int FEAT_DRAGON_AUGMENT_STR_8 = 26386;
const int FEAT_DRAGON_AUGMENT_STR_9 = 26387;
const int FEAT_DRAGON_AUGMENT_STR_4 = 25645;
const int FEAT_DRAGON_AUGMENT_STR_5 = 25646;
const int FEAT_DRAGON_AUGMENT_STR_6 = 25647;
const int FEAT_DRAGON_AUGMENT_STR_7 = 25648;
const int FEAT_DRAGON_AUGMENT_STR_8 = 25649;
const int FEAT_DRAGON_AUGMENT_STR_9 = 25650;
const int FEAT_DRAGON_AUGMENT_STR_10 = 25651;
const int FEAT_DRAGON_AUGMENT_DEX_1 = 3860;
const int FEAT_DRAGON_AUGMENT_DEX_2 = 3861;
const int FEAT_DRAGON_AUGMENT_DEX_3 = 3862;
const int FEAT_DRAGON_AUGMENT_DEX_4 = 26388;
const int FEAT_DRAGON_AUGMENT_DEX_5 = 26389;
const int FEAT_DRAGON_AUGMENT_DEX_6 = 26390;
const int FEAT_DRAGON_AUGMENT_DEX_7 = 26391;
const int FEAT_DRAGON_AUGMENT_DEX_8 = 26392;
const int FEAT_DRAGON_AUGMENT_DEX_9 = 26393;
const int FEAT_DRAGON_AUGMENT_DEX_4 = 25653;
const int FEAT_DRAGON_AUGMENT_DEX_5 = 25654;
const int FEAT_DRAGON_AUGMENT_DEX_6 = 25655;
const int FEAT_DRAGON_AUGMENT_DEX_7 = 25656;
const int FEAT_DRAGON_AUGMENT_DEX_8 = 25657;
const int FEAT_DRAGON_AUGMENT_DEX_9 = 25658;
const int FEAT_DRAGON_AUGMENT_DEX_10 = 25659;
const int FEAT_DRAGON_AUGMENT_CON_1 = 3863;
const int FEAT_DRAGON_AUGMENT_CON_2 = 3864;
const int FEAT_DRAGON_AUGMENT_CON_3 = 3865;
const int FEAT_DRAGON_AUGMENT_CON_4 = 26394;
const int FEAT_DRAGON_AUGMENT_CON_5 = 26395;
const int FEAT_DRAGON_AUGMENT_CON_6 = 26396;
const int FEAT_DRAGON_AUGMENT_CON_7 = 26397;
const int FEAT_DRAGON_AUGMENT_CON_8 = 26398;
const int FEAT_DRAGON_AUGMENT_CON_9 = 26399;
const int FEAT_DRAGON_AUGMENT_CON_4 = 25661;
const int FEAT_DRAGON_AUGMENT_CON_5 = 25662;
const int FEAT_DRAGON_AUGMENT_CON_6 = 25663;
const int FEAT_DRAGON_AUGMENT_CON_7 = 25664;
const int FEAT_DRAGON_AUGMENT_CON_8 = 25665;
const int FEAT_DRAGON_AUGMENT_CON_9 = 25666;
const int FEAT_DRAGON_AUGMENT_CON_10 = 25667;
const int FEAT_CHANNEL_DRACLAWS = 3866;
const int FEAT_PSIONIC_BREATH = 3867;
@@ -1314,6 +1337,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;
@@ -1473,9 +1497,13 @@ const int FEAT_VILE_MARTIAL_MINDBLADE = 3624;
const int FEAT_VILE_MARTIAL_WHIP = 3598;
const int FEAT_VILE_MARTIAL_TRIDENT = 3599;
// Weapon Focus (Ray)
//:: Spell-like Weapons
const int FEAT_WEAPON_FOCUS_RAY = 4819;
const int FEAT_EPIC_WEAPON_FOCUS_RAY = 4820;
const int FEAT_IMPROVED_CRITICAL_TOUCH = 26009;
const int FEAT_IMPROVED_CRITICAL_RAY = 26010;
const int FEAT_WEAPON_FOCUS_TOUCH = 26011;
const int FEAT_EPIC_WEAPON_FOCUS_TOUCH = 26012;
// Battleguard Tempus
const int TEMPUS_ABILITY_ENHANC1 = 1;
@@ -3016,6 +3044,7 @@ const int FEAT_SPLIT_PSIONIC_RAY = 4941;
const int FEAT_TWIN_POWER = 4942;
const int FEAT_WIDEN_POWER = 4943;
const int FEAT_QUICKEN_POWER = 4944;
const int FEAT_DEFENSIVE_MANIFESTATION = 2350;
// Sanctified Mind
const int FEAT_SANCMIND_PARTITION_MIND = 2231;
@@ -3726,6 +3755,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 +6307,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;
@@ -6322,6 +6355,13 @@ const int FEAT_HIDDEN_TALENT_THICKSKIN = 25944;
const int FEAT_HIDDEN_TALENT_VIGOR = 25945;
const int FEAT_HIDDEN_TALENT_GRIP_IRON = 25946;
//:: Player's Handbook II feats
const int FEAT_COMBAT_FOCUS = -9999;
const int FEAT_COMBAT_STABILITY = -9998;
const int FEAT_COMBAT_DEFENSE = -9997;
const int FEAT_COMBAT_VIGOR = -9996;
const int FEAT_COMBAT_AWARENESS = -9995;
const int FEAT_COMBAT_STRIKE = -9994;

View File

@@ -244,7 +244,7 @@ void ApplyPseudonatural(object oFamiliar, object oFamSkin)
void ApplyIllmaster(object oCompanion, object oCompSkin)
{
//Give the companion permanent Str +4, Con +2, Wis -2, and Cha -2
if(GetPRCSwitch(PRC_NWNX_FUNCS))
if(GetPRCSwitch(PRC_NWNXEE_ENABLED))
{
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_STRENGTH, 4);
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_CONSTITUTION, 2);
@@ -305,7 +305,7 @@ void WinterWolfProperties(object oCompanion, int nLevel)
object oCreR = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oCompanion);
if(GetPRCSwitch(PRC_NWNX_FUNCS))
if(GetPRCSwitch(PRC_NWNXEE_ENABLED))
{
if(iStr > 0)
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_STRENGTH, iStr);
@@ -358,7 +358,10 @@ void WinterWolfProperties(object oCompanion, int nLevel)
void ApplyPnPFamiliarProperties(object oPC, object oFam)
{
int bFuncs = GetPRCSwitch(PRC_NWNX_FUNCS);
int nNWNxEE = GetPRCSwitch(PRC_NWNXEE_ENABLED);
int nPRCx = GetPRCSwitch(PRC_PRCX_ENABLED);
int bFuncs = (nNWNxEE && nPRCx);
effect eBonus;
//get familiar level

View File

@@ -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 */
@@ -166,8 +168,8 @@ void ExhaleImmunity(object oDragon, int nDamageType, location lTargetArea)
effect eLink = EffectLinkEffects(eImmune, eVis2);
//apply effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eImmune, oTarget, fDuration));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eImmune, oTarget, fDuration));
}
}
@@ -601,15 +603,15 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nSaveDC, SAVING_THROW_TYPE_NONE))
{
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_POISON_L), oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSickened(), oTarget, 12.0));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_POISON_L), oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSickened(), oTarget, 12.0));
}
//1 round otherwise
else
{
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_POISON_L), oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSickened(), oTarget, 6.0));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_POISON_L), oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSickened(), oTarget, 6.0));
}
}
@@ -657,16 +659,16 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nSaveDC, SAVING_THROW_TYPE_NONE))
{
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nSlowDuration)));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nSlowDuration)));
SetLocalInt(oTarget, "AffectedByBreath", TRUE);
}
//Adept breath effect still lasts for one round if save is made
else if(IsAdeptBreath())
{
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(1)));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(1)));
SetLocalInt(oTarget, "AffectedByBreath", TRUE);
}
}
@@ -683,10 +685,10 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
//Set Damage and VFX - Bioware Gold used VFX_IMP_REDUCE_ABILITY_SCORE originally
eVis = EffectVisualEffect(VFX_IMP_POISON_L);
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
//adept breath penalty only last 4 rounds on failure, gold breath has no duration
if(IsAdeptBreath())
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityDecrease(ABILITY_STRENGTH, BreathUsed.nDiceNumber), oTarget, 24.0));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityDecrease(ABILITY_STRENGTH, BreathUsed.nDiceNumber), oTarget, 24.0));
else
DelayCommand(fDelay, ApplyAbilityDamage(oTarget, ABILITY_STRENGTH, BreathUsed.nDiceNumber, DURATION_TYPE_PERMANENT, TRUE));
SetLocalInt(oTarget, "AffectedByBreath", TRUE);
@@ -697,8 +699,8 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
//Set Damage and VFX - Bioware Gold used VFX_IMP_REDUCE_ABILITY_SCORE originally
eVis = EffectVisualEffect(VFX_IMP_POISON_L);
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityDecrease(ABILITY_STRENGTH, BreathUsed.nDiceNumber), oTarget, 12.0));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityDecrease(ABILITY_STRENGTH, BreathUsed.nDiceNumber), oTarget, 12.0));
SetLocalInt(oTarget, "AffectedByBreath", TRUE);
}
bCanCling = TRUE;
@@ -727,7 +729,7 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nSaveDC, SAVING_THROW_TYPE_NONE))
{
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nParalDuration)));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nParalDuration)));
SetLocalInt(oTarget, "AffectedByBreath", TRUE);
}
}
@@ -747,8 +749,8 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
eBreath = EffectNegativeLevel(nLevelDrain);
eVis = EffectVisualEffect(VFX_IMP_NEGATIVE_ENERGY);
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget));
SetLocalInt(oTarget, "AffectedByBreath", TRUE);
}
}
@@ -767,11 +769,11 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
if (nAdjustedDamage > 0)
{
//Set Damage and VFX
eBreath = EffectDamage(nAdjustedDamage, BreathUsed.nDamageType);
eBreath = PRCEffectDamage(oTarget, nAdjustedDamage, BreathUsed.nDamageType);
eVis = EffectVisualEffect(VFX_IMP_SUNSTRIKE);
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget));
SetLocalInt(oTarget, "AffectedByBreath", TRUE);
bCanCling = TRUE;
}
@@ -828,8 +830,8 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
if(GetLocalInt(oTarget, "DragonWard"))
nAdjustedDamage -= 40;
effect eBreath1 = EffectDamage(nAdjustedDamage/2, DAMAGE_TYPE_FIRE);
effect eBreath2 = EffectDamage(nAdjustedDamage/2, DAMAGE_TYPE_SONIC);
effect eBreath1 = PRCEffectDamage(oTarget, nAdjustedDamage/2, DAMAGE_TYPE_FIRE);
effect eBreath2 = PRCEffectDamage(oTarget, nAdjustedDamage/2, DAMAGE_TYPE_SONIC);
eBreath = EffectLinkEffects(eBreath1, eBreath2);
eVis = EffectVisualEffect(chVisual);
}
@@ -837,12 +839,12 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
{
if(GetLocalInt(oTarget, "DragonWard"))
nAdjustedDamage -= 20;
eBreath = EffectDamage(nAdjustedDamage, BreathUsed.nDamageType);
eBreath = PRCEffectDamage(oTarget, nAdjustedDamage, BreathUsed.nDamageType);
eVis = EffectVisualEffect(nVisualType);
}
//Apply the VFX impact and effects
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget));
SetLocalInt(oTarget, "AffectedByBreath", TRUE);
bCanCling = TRUE;
}
@@ -857,7 +859,7 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nKnockdownDC, SAVING_THROW_TYPE_NONE))
{
effect eWindblown = EffectKnockdown();
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eWindblown, oTarget, 6.0));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eWindblown, oTarget, 6.0));
}
}
}
@@ -877,10 +879,10 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
//Warforged are only healed for half
if(GetIsWarforged(oTarget)) nHeal /= 2;
eBreath = EffectHeal(nHeal);
eBreath = PRCEffectHeal(nHeal, oTarget);
effect eHealVis = EffectVisualEffect(VFX_IMP_HEALING_S);
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eHealVis, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eBreath, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eHealVis, oTarget));
}
//Entangling Exhalation
@@ -894,22 +896,22 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
//only does damage if the original breath did damage
if(BreathUsed.nDamageType > 0)
{
effect eDamage = EffectDamage(d6(), BreathUsed.nDamageType);
effect eDamage = PRCEffectDamage(oTarget, d6(), BreathUsed.nDamageType);
switch(nEntangleRounds)
{
case 4:
DelayCommand(fDelay + RoundsToSeconds(4), ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget));
DelayCommand(fDelay + RoundsToSeconds(4), SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget));
case 3:
DelayCommand(fDelay + RoundsToSeconds(3), ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget));
DelayCommand(fDelay + RoundsToSeconds(3), SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget));
case 2:
DelayCommand(fDelay + RoundsToSeconds(2), ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget));
DelayCommand(fDelay + RoundsToSeconds(2), SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget));
case 1:
DelayCommand(fDelay + RoundsToSeconds(1), ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget)); break;
DelayCommand(fDelay + RoundsToSeconds(1), SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget)); break;
}
}
//but always entangles if the breath affects the target
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEntangled, oTarget, RoundsToSeconds(nEntangleRounds)));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEntangled, oTarget, RoundsToSeconds(nEntangleRounds)));
}
DeleteLocalInt(oTarget, "AffectedByBreath");
@@ -935,18 +937,18 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
{
if(nAdjustedDamage < 3) nCount = BreathUsed.nClinging;
effect eBreath1 = EffectDamage(nAdjustedDamage/2, DAMAGE_TYPE_FIRE);
effect eBreath2 = EffectDamage(nAdjustedDamage/2, DAMAGE_TYPE_SONIC);
effect eBreath1 = PRCEffectDamage(oTarget, nAdjustedDamage/2, DAMAGE_TYPE_FIRE);
effect eBreath2 = PRCEffectDamage(oTarget, nAdjustedDamage/2, DAMAGE_TYPE_SONIC);
effect eAfterBreath = EffectLinkEffects(eBreath1, eBreath2);
DelayCommand(fNewDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eAfterBreath, oTarget));
DelayCommand(fNewDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eAfterBreath, oTarget));
}
else
{
if(nAdjustedDamage < 2) nCount = BreathUsed.nClinging;
effect eAfterBreath = EffectDamage(nAdjustedDamage, BreathUsed.nDamageType);
DelayCommand(fNewDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eAfterBreath, oTarget));
effect eAfterBreath = PRCEffectDamage(oTarget, nAdjustedDamage, BreathUsed.nDamageType);
DelayCommand(fNewDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eAfterBreath, oTarget));
}
DelayCommand(fNewDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
DelayCommand(fNewDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
}
}
}
@@ -986,3 +988,5 @@ void PRCPlayDragonBattleCry()
PlayVoiceChat(VOICE_CHAT_BATTLECRY2);
}
}
//:: void main() {}

View File

@@ -576,7 +576,7 @@ int PRCGetCasterLevel(object oCaster = OBJECT_SELF)
}
// Casting as a bard but don't have any levels in the class //:: Double-dipping?
/* if(iCastingClass == CLASS_TYPE_BARD && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
if(iCastingClass == CLASS_TYPE_BARD && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
{
int nRace = GetRacialType(oCaster);
@@ -584,7 +584,7 @@ int PRCGetCasterLevel(object oCaster = OBJECT_SELF)
//otherwise use RHD instead of bard levels
if(nRace == RACIAL_TYPE_GLOURA)
iReturnLevel = GetLevelByClass(CLASS_TYPE_FEY);
} */
}
//Spell Rage ability
if(GetHasSpellEffect(SPELL_SPELL_RAGE, oCaster)
@@ -797,6 +797,10 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if (nCastingClass == CLASS_TYPE_BARD || GetLevelByClass(CLASS_TYPE_BARD, oCaster))
{
// Don't execute for Gloura Fey spellcasters - they're handled in the Fey section
if(GetRacialType(oCaster) == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
return nArcane;
//:: Includes RHD as bard. If they started with bard levels, then it
//:: counts as a prestige class, otherwise RHD is used instead of bard levels.
if(nRace == RACIAL_TYPE_GLOURA)
@@ -960,7 +964,7 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
}
//:: End Bard Arcane PrC casting calculations
if(nCastingClass == CLASS_TYPE_BARD || nCastingClass == CLASS_TYPE_BARD && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
if(nCastingClass == CLASS_TYPE_BARD || nCastingClass == CLASS_TYPE_FEY && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
{
if(DEBUG) DoDebug("prc_inc_castlvl >> Found Fey RHD caster (not bard)");
@@ -3861,6 +3865,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_ARCHIVIST, 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;
@@ -4195,6 +4202,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_CLERIC, 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 +4319,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_BFZ_SPELLCASTING_DRUID, oCaster))
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_DRUID, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
/* if(GetHasFeat(FEAT_BFZ_SPELLCASTING_DRUID, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_BFZ, oCaster + 1) / 2 */
// if(GetHasFeat(FEAT_BRIMSTONE_SPEAKER_SPELLCASTING_DRUID, oCaster))
@@ -4423,6 +4436,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_FAVOURED_SOUL, 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;
@@ -4536,6 +4552,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
/* if(GetHasFeat(FEAT_BFZ_SPELLCASTING_HEALER, oCaster))
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;
@@ -4643,6 +4662,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_JUSTICEWW, 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;
@@ -4743,6 +4765,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);
@@ -4850,6 +4875,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);
@@ -4963,6 +4991,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); */
@@ -5165,6 +5196,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);
@@ -5274,6 +5308,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_RANGER, 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;
@@ -5387,6 +5424,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_OASHAMAN, 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;
@@ -5601,6 +5641,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_SOHEI, 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;
@@ -5705,6 +5748,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);

View File

@@ -480,7 +480,7 @@ int Debug_ProcessChatCommand(object oPC, string sCommand)
HelpText(oPC, "=== INT: " + IntToString(GetAbilityScore(oTarget, ABILITY_INTELLIGENCE, TRUE)) + " / " + IntToString(GetAbilityScore(oTarget, ABILITY_INTELLIGENCE, FALSE)));
HelpText(oPC, "=== WIS: " + IntToString(GetAbilityScore(oTarget, ABILITY_WISDOM, TRUE)) + " / " + IntToString(GetAbilityScore(oTarget, ABILITY_WISDOM, FALSE)));
HelpText(oPC, "=== CHA: " + IntToString(GetAbilityScore(oTarget, ABILITY_CHARISMA, TRUE)) + " / " + IntToString(GetAbilityScore(oTarget, ABILITY_CHARISMA, FALSE)));
if (GetPersistantLocalInt(oTarget, SHIFTER_ISSHIFTED_MARKER) && GetPRCSwitch(PRC_NWNX_FUNCS))
if (GetPersistantLocalInt(oTarget, SHIFTER_ISSHIFTED_MARKER) && GetPRCSwitch(PRC_NWNXEE_ENABLED))
{
int iSTR = GetPersistantLocalInt(oTarget, "Shifting_NWNXSTRAdjust");
int iDEX = GetPersistantLocalInt(oTarget, "Shifting_NWNXDEXAdjust");
@@ -664,7 +664,7 @@ int Debug_ProcessChatCommand(object oPC, string sCommand)
}
/* else if (GetStringMatchesAbbreviation(sChangeWhat, CMD_ABILITY))
{
if (!GetPRCSwitch(PRC_NWNX_FUNCS))
if (!GetPRCSwitch(PRC_NWNXEE_ENABLED))
HelpText(oPC, "This command only works if NWNX funcs is installed");
else
{

View File

@@ -16,6 +16,7 @@ Command summary:
*/
#include "prc_inc_chat"
#include "inc_persist_loca"
const string CMD_POWER_ATTACK = "pow-erattack";

View File

@@ -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);

View File

@@ -265,7 +265,8 @@ struct WeaponFeat GetAllFeatsOfWeaponType(int iWeaponType);
// Returns the low end of oWeap's critical threat range
// Accounts for Keen and Improved Critical bonuses
int GetWeaponCriticalRange(object oPC, object oWeap);
//int GetWeaponCriticalRange(object oPC, object oWeap);
int GetWeaponCriticalRange(object oPC, object oWeap, int iTouchAttackType = FALSE);
// returns the critical multiplier of the weapons base type
int GetCriticalMultiplierOfWeaponType(int iWeaponType);
@@ -1082,7 +1083,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 +1142,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_CRAFTED_SCEPTER: return 1;
case BASE_ITEM_CLUB: return 2;
case BASE_ITEM_DAGGER: return 2;
case BASE_ITEM_LIGHTMACE: return 2;
case BASE_ITEM_SICKLE: return 2;
@@ -1279,6 +1280,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;
@@ -1986,10 +2000,36 @@ object GetAmmunitionFromWeapon(object oWeapon, object oAttacker)
return GetAmmunitionFromWeaponType(GetBaseItemType(oWeapon), oAttacker);
}
int GetWeaponCriticalRange(object oPC, object oWeap)
//int GetWeaponCriticalRange(object oPC, object oWeap)
// for a ranged weapon we should call this *after* we have ammo equipped, because it checks the ammo for keen
// if we (re)equip the ammo later, we don't get the right keen property
int GetWeaponCriticalRange(object oPC, object oWeap, int iTouchAttackType = FALSE)
{
// Check for spell-based touch attacks
if(iTouchAttackType == TOUCH_ATTACK_MELEE_SPELL)
{
if (DEBUG) DoDebug("prc_inc_combat >> GetWeaponCriticalRange() | TOUCH_ATTACK_MELEE_SPELL detected.");
// Spell-based melee touch attacks
if(GetHasFeat(FEAT_IMPROVED_CRITICAL_TOUCH, oPC))
{
if (DEBUG) DoDebug("prc_inc_combat >> GetWeaponCriticalRange() | Improved Critical: Touch detected.");
return 19; // Doubles threat range from 20 to 19-20
}
else
return 20;
}
else if(iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL)
{
if (DEBUG) DoDebug("prc_inc_combat >> GetWeaponCriticalRange() | TOUCH_ATTACK_RANGED_SPELL detected.");
// Ray attacks
if(GetHasFeat(FEAT_IMPROVED_CRITICAL_RAY, oPC))
{
if (DEBUG) DoDebug("prc_inc_combat >> GetWeaponCriticalRange() | Improved Critical: Ray detected.");
return 19; // Doubles threat range from 20 to 19-20
}
else
return 20;
}
//no weapon, touch attacks mainly
if(!GetIsObjectValid(oWeap))
return 20;
@@ -3296,6 +3336,32 @@ int GetAttackBonus(object oDefender, object oAttacker, object oWeap, int iOffhan
int bFocus = 0;
int bEpicFocus = 0;
int bIsRangedTouchAttack = iTouchAttackType == TOUCH_ATTACK_RANGED || iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL;
int bIsMeleeTouchAttack = iTouchAttackType == TOUCH_ATTACK_MELEE_SPELL;
if(bIsRangedTouchAttack)
{
// Weapon Focus(Ray) applies to ranged touch attacks
bFocus = GetHasFeat(FEAT_WEAPON_FOCUS_RAY, oAttacker);
if (bFocus) // no need to look for epic focus, if we don't have focus
bEpicFocus = GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_RAY, oAttacker);
}
else if(bIsMeleeTouchAttack)
{
// Weapon Focus(Touch Attack) applies to melee touch attacks
bFocus = GetHasFeat(FEAT_WEAPON_FOCUS_TOUCH, oAttacker);
if (bFocus) // no need to look for epic focus, if we don't have focus
bEpicFocus = GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_TOUCH, oAttacker);
}
else
{ // no touch attack, normal weapon focus feats
bFocus = GetHasFeat(sWeaponFeat.Focus, oAttacker);
if (bFocus) // no need to look for epic focus, if we don't have focus
bEpicFocus = GetHasFeat(sWeaponFeat.EpicFocus, oAttacker);
}
/* int bFocus = 0;
int bEpicFocus = 0;
int bIsRangedTouchAttack = iTouchAttackType == TOUCH_ATTACK_RANGED || iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL;
if(bIsRangedTouchAttack)
{
@@ -3309,7 +3375,7 @@ int GetAttackBonus(object oDefender, object oAttacker, object oWeap, int iOffhan
bFocus = GetHasFeat(sWeaponFeat.Focus, oAttacker);
if (bFocus) // no need to look for epic focus, if we don't have focus
bEpicFocus = GetHasFeat(sWeaponFeat.EpicFocus, oAttacker);
}
} */
int bEpicProwess = GetHasFeat(FEAT_EPIC_PROWESS, oAttacker);
@@ -3924,7 +3990,7 @@ int GetAttackRoll(object oDefender, object oAttacker, object oWeapon, int iOffha
//if (bDebug) sDebugFeedback = COLOR_WHITE + "Attack Roll = " + IntToString(iAttackBonus + iDiceRoll) + ": " + sDebugFeedback;
//if (DEBUG) DoDebug("GetAttackRoll: End Section #1");
int iWeaponType = GetBaseItemType(oWeapon);
int iCritThreat = GetWeaponCriticalRange(oAttacker, oWeapon);
int iCritThreat = GetWeaponCriticalRange(oAttacker, oWeapon, iTouchAttackType);
//If using Killing Shot, ciritical range improves by 2;
if(GetLocalInt(oAttacker, "KillingShotCritical") )
@@ -8090,7 +8156,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)

View File

@@ -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 */
@@ -354,6 +355,16 @@ int _DoGrappleCheck(object oPC, object oTarget, int nExtraBonus, int nSwitch = -
int nPCCheck = nPCBAB + nPCStr + nPCBonus + d20();
int nTargetCheck = nTargetBAB + nTargetStr + nTargetBonus + d20();
if (DEBUG)
{
DoDebug("Grapple Check - " + GetName(oPC) + ": " + IntToString(nPCCheck) +
" vs " + GetName(oTarget) + ": " + IntToString(nTargetCheck));
DoDebug("PC BAB:" + IntToString(nPCBAB) + " STR:" + IntToString(nPCStr) +
" Bonus:" + IntToString(nPCBonus));
DoDebug("Target BAB:" + IntToString(nTargetBAB) + " STR:" + IntToString(nTargetStr) +
" Bonus:" + IntToString(nTargetBonus));
}
// Now roll the ability check
SendMessageToPC(oPC, "PC Grapple Check: "+IntToString(nPCCheck)+" vs "+IntToString(nTargetCheck));
if (GetIsPC(oTarget))
@@ -1322,6 +1333,28 @@ int DoTrip(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TRUE,
}
}
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 +1371,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);
@@ -1479,7 +1512,46 @@ int DoGrapple(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TR
{
FloatingTextStringOnCreature("You have successfully grappled " + GetName(oTarget), oPC, FALSE);
int nBearFang = GetLocalInt(oPC, "BearFangGrapple");
SetGrapple(oPC);
SetGrapple(oTarget);
SetLocalInt(oPC, "GrappleOriginator", TRUE);
SetLocalObject(oTarget, "GrappledBy", oPC);
SetGrappleTarget(oPC, oTarget);
if (DEBUG)
{
DoDebug("DoGrapple: Set grapple state for " + GetName(oPC) + " -> " + GetName(oTarget));
DoDebug("DoGrapple: oPC IsGrappled = " + IntToString(GetLocalInt(oPC, "IsGrappled")));
DoDebug("DoGrapple: oTarget IsGrappled = " + IntToString(GetLocalInt(oTarget, "IsGrappled")));
DoDebug("DoGrapple: oPC GrappleTarget = " + GetName(GetLocalObject(oPC, "GrappleTarget")));
}
effect eHold = EffectCutsceneParalyze();
effect eEntangle = EffectVisualEffect(VFX_DUR_SPELLTURNING_R);
effect eLink = EffectLinkEffects(eHold, eEntangle);
if (!GetLocalInt(oPC, "Flay_Grapple"))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(eLink), oPC, 9999.0);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(eLink), oTarget, 9999.0);
nSucceed = TRUE;
if (nBearFang)
{
//DelayCommand(0.1, PerformAttack(oTarget, oPC, eNone, 0.0, -4, 0, 0, "Bear Fang Attack Hit", "Bear Fang Attack Miss"));
PerformAttack(oTarget, oPC, eNone, 0.0, -4, 0, 0, "Bear Fang Attack Hit", "Bear Fang Attack Miss");
DeleteLocalInt(oPC, "BearFangGrapple");
}
else
{
object oWeap = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oPC);
effect eDam = GetAttackDamage(oTarget, oPC, oWeap, GetWeaponBonusDamage(oWeap, oTarget), GetMagicalBonusDamage(oPC, oTarget));
//DelayCommand(0.1, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget)); // Delay damage
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
}
/* SetGrapple(oPC);
SetGrapple(oTarget);
SetLocalInt(oPC, "GrappleOriginator", TRUE);
effect eHold = EffectCutsceneParalyze();
@@ -1503,7 +1575,7 @@ int DoGrapple(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TR
effect eDam = GetAttackDamage(oTarget, oPC, oWeap, GetWeaponBonusDamage(oWeap, oTarget), GetMagicalBonusDamage(oPC, oTarget));
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
}
_HeartOfFireGrapple(oPC, oTarget);
*/ _HeartOfFireGrapple(oPC, oTarget);
// If you kill them with this, best to clean up right away
if (GetIsDead(oTarget) || !GetIsObjectValid(oTarget))
@@ -1516,10 +1588,30 @@ int DoGrapple(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TR
}
else
{
// //::Hook in the events and save the target for an ongoing grapple
// if(DEBUG) DoDebug("prc_grapple: Adding eventhooks");
// SetGrappleTarget(oPC, oTarget);
// AddEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
// Hook in the events and save the target for an ongoing grapple
if(DEBUG) DoDebug("prc_grapple: Adding eventhooks");
SetGrappleTarget(oPC, oTarget);
if(GetIsPC(oPC) || GetIsDMPossessed(oPC))
{
AddEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
if(DEBUG) DoDebug("DoGrapple: Set Heartbeat event for " + GetName(oPC));
}
else
{
// For summons, set a flag that prc_npc_hb.nss can check
SetLocalInt(oPC, "GrappleHeartbeatTimer", 1);
if(DEBUG) DoDebug("DoGrapple: Set GrappleHeartbeatTimer for " + GetName(oPC));
// Add this debug to verify the timer was set
if(DEBUG) DoDebug("DoGrapple: Verification - GrappleHeartbeatTimer = " +
IntToString(GetLocalInt(oPC, "GrappleHeartbeatTimer")));
}
}
}
else
@@ -1532,12 +1624,16 @@ int DoGrapple(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TR
void SetGrapple(object oTarget)
{
if(DEBUG) DoDebug("SetGrapple called on " + GetName(oTarget));
SetLocalInt(oTarget, "IsGrappled", TRUE);
}
int GetGrapple(object oTarget)
{
return GetLocalInt(oTarget, "IsGrappled");
int nResult = GetLocalInt(oTarget, "IsGrappled");
if(DEBUG) DoDebug("GetGrapple(" + GetName(oTarget) + ") = " + IntToString(nResult));
return nResult;
//return GetLocalInt(oTarget, "IsGrappled");
}
void SetGrappleTarget(object oPC, object oTarget)
@@ -1568,10 +1664,14 @@ void BreakPin(object oTarget)
void EndGrapple(object oPC, object oTarget)
{
if(DEBUG) DoDebug("EndGrapple called for " + GetName(oPC) + " -> " + GetName(oTarget));
DeleteLocalInt(oPC, "IsGrappled");
DeleteLocalInt(oTarget, "IsGrappled");
DeleteLocalInt(oPC, "GrappleHeartbeatTimer");
DeleteLocalInt(oTarget, "PinnedRounds");
DeleteLocalObject(oPC, "GrappleTarget");
DeleteLocalObject(oTarget, "GrappledBy");
DeleteLocalInt(oTarget, "UnconsciousGrapple");
DeleteLocalInt(oPC, "GrappleOriginator");
DeleteLocalInt(oPC, "ScorpionLight");
@@ -1656,6 +1756,20 @@ int DoGrappleOptions(object oPC, object oTarget, int nExtraBonus, int nSwitch =
int nPen = -4;
if (GetLocalInt(oPC, "ScorpionLight")) nPen = 0;
DelayCommand(0.0, PerformAttack(oTarget, oPC, eNone, 0.0, nPen, 0, 0, "Grapple Light Weapon Attack Hit", "Grapple Light Weapon Attack Miss"));
if (GetIsDead(oPC) || GetIsDead(oTarget) || !GetIsObjectValid(oPC) || !GetIsObjectValid(oTarget))
{
EndGrapple(oPC, oTarget);
//RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
if(GetIsPC(oPC) || GetIsDMPossessed(oPC))
RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
else
DeleteLocalInt(oPC, "PRC_GrappleActive");
if (GetIsDead(oPC)) FloatingTextStringOnCreature("You have died, ending grapple", oPC, FALSE);
if (GetIsDead(oTarget)) FloatingTextStringOnCreature("Your target is dead, ending grapple", oPC, FALSE);
return nSuccess;
}
}
}
else
@@ -1707,6 +1821,7 @@ int DoGrappleOptions(object oPC, object oTarget, int nExtraBonus, int nSwitch =
// Now hit them with an unarmed strike
object oWeap = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oPC);
effect eDam = GetAttackDamage(oTarget, oPC, oWeap, GetWeaponBonusDamage(oWeap, oTarget), GetMagicalBonusDamage(oPC, oTarget));
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
FloatingTextStringOnCreature("Grapple Unarmed Damage Hit",oPC, FALSE);
}
@@ -1720,6 +1835,21 @@ int DoGrappleOptions(object oPC, object oTarget, int nExtraBonus, int nSwitch =
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDam), oTarget);
FloatingTextStringOnCreature("Zagan Constrict Hit",oPC, FALSE);
}
if (GetIsDead(oPC) || GetIsDead(oTarget) || !GetIsObjectValid(oPC) || !GetIsObjectValid(oTarget))
{
EndGrapple(oPC, oTarget);
//RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
if(GetIsPC(oPC) || GetIsDMPossessed(oPC))
RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
else
DeleteLocalInt(oPC, "PRC_GrappleActive");
if (GetIsDead(oPC)) FloatingTextStringOnCreature("You have died, ending grapple", oPC, FALSE);
if (GetIsDead(oTarget)) FloatingTextStringOnCreature("Your target is dead, ending grapple", oPC, FALSE);
return nSuccess;
}
}
else if (nSwitch == GRAPPLE_ESCAPE)
{
@@ -1742,14 +1872,24 @@ int DoGrappleOptions(object oPC, object oTarget, int nExtraBonus, int nSwitch =
{
// Remove the hooks
if(DEBUG) DoDebug("prc_grapple: Removing eventhooks");
//RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
if(GetIsPC(oPC) || GetIsDMPossessed(oPC))
RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
else
DeleteLocalInt(oPC, "PRC_GrappleActive");
FloatingTextStringOnCreature("You have escaped the grapple", oPC, FALSE);
}
else
{
// Remove the hooks
if(DEBUG) DoDebug("prc_grapple: Removing eventhooks");
RemoveEventScript(oTarget, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
//RemoveEventScript(oTarget, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
if(GetIsPC(oPC) || GetIsDMPossessed(oPC))
RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
else
DeleteLocalInt(oPC, "PRC_GrappleActive");
FloatingTextStringOnCreature("Your target has escaped your grapple", oTarget, FALSE);
// Target is valid and we know it's an enemy and we're in combat
DelayCommand(0.25, AssignCommand(oTarget, ActionAttack(oPC)));
@@ -1807,6 +1947,22 @@ int DoGrappleOptions(object oPC, object oTarget, int nExtraBonus, int nSwitch =
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDam, DAMAGE_TYPE_BLUDGEONING), oTarget);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACDecrease(4)), oPC, 6.0);
}
else
FloatingTextStringOnCreature("You have failed your Grapple Pin Attempt",oPC, FALSE);
if (GetIsDead(oPC) || GetIsDead(oTarget) || !GetIsObjectValid(oPC) || !GetIsObjectValid(oTarget))
{
EndGrapple(oPC, oTarget);
//RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
if(GetIsPC(oPC) || GetIsDMPossessed(oPC))
RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_grapple", TRUE, FALSE);
else
DeleteLocalInt(oPC, "PRC_GrappleActive");
if (GetIsDead(oPC)) FloatingTextStringOnCreature("You have died, ending grapple", oPC, FALSE);
if (GetIsDead(oTarget)) FloatingTextStringOnCreature("Your target is dead, ending grapple", oPC, FALSE);
return nSuccess;
}
}
else
FloatingTextStringOnCreature("You have failed your Grapple Pin Attempt",oPC, FALSE);
@@ -1821,6 +1977,54 @@ int DoGrappleOptions(object oPC, object oTarget, int nExtraBonus, int nSwitch =
return nSuccess;
}
int OptimalGrapple(object oPC, object oTarget)
{
int nMauler = GetLevelByClass(CLASS_TYPE_REAPING_MAULER, oPC);
int nBBC = GetLevelByClass(CLASS_TYPE_BLACK_BLOOD_CULTIST, oPC);
int nDC = 10 + nMauler + GetAbilityModifier(ABILITY_WISDOM, oPC);
if (GetLocalInt(oPC, "Flay_Grapple"))
return GRAPPLE_DAMAGE;
// You need a greater than 10% chance of it happening to trigger these options
if (nMauler && (nDC > GetFortitudeSavingThrow(oTarget) + 2))
{
if (nMauler == 5 && !GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT)) // Devastating Grapple
return GRAPPLE_PIN;
if (nMauler >= 3 && !GetLocalInt(oTarget, "UnconsciousGrapple") && !GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT)) // Target isn't unconscious
return GRAPPLE_PIN;
}
if (GetHasSpellEffect(MOVE_SD_CRUSHING_WEIGHT, oPC))
return GRAPPLE_TOB_CRUSHING;
if ((nBBC >= 8 && GetHasSpellEffect(SPELLABILITY_BARBARIAN_RAGE, oPC)) || nBBC >= 10 || GetHasSpellEffect(VESTIGE_ZAGAN, oPC) && GetLocalInt(oPC, "ExploitVestige") != VESTIGE_ZAGAN_CONSTRICT)
return GRAPPLE_DAMAGE;
if (GetIsMeldBound(oPC, MELD_RAGECLAWS) == CHAKRA_TOTEM)
return GRAPPLE_ATTACK;
// You've got an ability that wants a light weapon
if (GetHasSpellEffect(MOVE_TC_WOLVERINE_STANCE, oPC) || GetLevelByClass(CLASS_TYPE_WARFORGED_JUGGERNAUT, oPC) || GetLocalInt(oPC, "ScorpionLight"))
return GRAPPLE_ATTACK;
if (GetHasFeat(FEAT_EARTHS_EMBRACE, oPC) && !GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT)) // Earth's Embrace
return GRAPPLE_PIN;
if (FindUnarmedDamage(oPC) > 2)
return GRAPPLE_DAMAGE;
object oPCWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
object oMonster = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
int nPCGold;
int nMonster;
if(GetIsLightWeapon(oTarget)) nMonster = GetGoldPieceValue(oMonster);
if(GetIsLightWeapon(oPC)) nPCGold = GetGoldPieceValue(oPCWeapon);
if (nMonster > nPCGold)
return GRAPPLE_OPPONENT_WEAPON;
else if (GetIsLightWeapon(oPC))
return GRAPPLE_ATTACK;
return GRAPPLE_DAMAGE;
}
int GetIsLightWeapon(object oPC)
{
// You may use any weapon in a grapple with this stance.
@@ -1942,9 +2146,20 @@ int DoDisarm(object oPC, object oTarget, int nExtraBonus = 0, int nGenerateAoO =
{
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;
}

View File

@@ -7,6 +7,8 @@
/* Function Prototypes */
//////////////////////////////////////////////////
string GetSpellsKnown_Array(int nClass, int nSpellLevel = -1);
//:: Returns true if oCaster's race can naturally cast sorcerer spells.
int GetIsRHDSorcerer(object oCaster = OBJECT_SELF);
@@ -133,6 +135,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 +413,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)
@@ -677,9 +682,37 @@ int PRCGetIsRealSpellKnownByClass(int nRealSpellID, int nClass, object oPC = OBJ
// at this stage, prepared casters know the spell and only spontaneous classes need checking
// there are exceptions and these need hardcoding:
// Archivist special case - check both feats and persistant arrays
if (nClass == CLASS_TYPE_ARCHIVIST)
{
// First check feat system (for backward compatibility)
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookSpell));
if (GetHasFeat(nFeatID, oPC))
return TRUE;
// Then check persistant spell arrays using GetSpellsKnown_Array()
int nSpellLevel = StringToInt(Get2DACache(sFile, "Level", nSpellbookSpell));
string sSpellbookArray = GetSpellsKnown_Array(nClass, nSpellLevel);
int nSize = persistant_array_get_size(oPC, sSpellbookArray);
int i;
for (i = 0; i < nSize; i++)
{
int nStoredSpellbookID = persistant_array_get_int(oPC, sSpellbookArray, i);
if (nStoredSpellbookID == nSpellbookSpell)
return TRUE;
}
return FALSE;
}
// Other prepared casters use original logic
if((GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED) && nClass != CLASS_TYPE_ARCHIVIST)
return TRUE;
/* if((GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED) && nClass != CLASS_TYPE_ARCHIVIST)
return TRUE; */
// spontaneous casters have all their known spells as hide feats
// get the featID of the spell
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookSpell));

View File

@@ -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 */

View File

@@ -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));

View File

@@ -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;
@@ -845,3 +932,5 @@ int PRCLargeWeaponCheck(int iBaseType, int nSize)
}
return sTest != "" && sTest != IntToString(nSize);
}
//::void main(){}

View File

@@ -187,6 +187,7 @@ void SetupCharacterData(object oPC)
case CLASS_TYPE_MASTER_OF_SHADOW: sScript = "shd_mastershadow"; break;
case CLASS_TYPE_MIGHTY_CONTENDER_KORD: sScript = "prc_contendkord"; break;
case CLASS_TYPE_MORNINGLORD: sScript = "prc_morninglord"; break;
case CLASS_TYPE_MONK: sScript = "prc_monk"; break;
case CLASS_TYPE_NIGHTSHADE: sScript = "prc_nightshade"; break;
case CLASS_TYPE_NINJA: sScript = "prc_ninjca"; break;
case CLASS_TYPE_OLLAM: sScript = "prc_ollam"; break;
@@ -366,7 +367,7 @@ void EvalPRCFeats(object oPC)
SetLocalInt(oPC, PRC_EvalPRCFeats_Generation, nGeneration);
//permanent ability changes
if(GetPRCSwitch(PRC_NWNX_FUNCS))
if(GetPRCSwitch(PRC_NWNXEE_ENABLED))
ExecuteScript("prc_nwnx_funcs", oPC);
//Add IP Feats to the hide
@@ -1571,7 +1572,7 @@ void BarbarianRage(object oPC)
if (nLevel > 0)
{
// Spell Rage: starts at 1st level, +1 use every 5 Rage Mage levels
int nUses = 1 + ((nLevel - 1) / 5);
int nUses = 1 + (nLevel / 5);
FeatUsePerDay(oPC, FEAT_SPELL_RAGE, -1, nUses);
}

View File

@@ -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";

View File

@@ -36,6 +36,8 @@ void CheckForPnPHolyAvenger(object oItem);
#include "inc_utility"
#include "prc_inc_newip"
#include "prc_inc_castlvl"
#include "inc_newspellbook"
//////////////////////////////////////////////////

2133
src/include/prc_inc_json.nss Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -249,7 +249,7 @@ void CancelGreatFeats(object oSpawn)
else if(GetHasFeat(FEAT_EPIC_GREAT_CHARISMA_1, oSpawn)) nGreatCha = 1;
//apply penalties to counter the GreatX feats
if(GetPRCSwitch(PRC_NWNX_FUNCS))
if(GetPRCSwitch(PRC_NWNXEE_ENABLED))
{
if(nGreatStr) PRC_Funcs_ModAbilityScore(oSpawn, ABILITY_STRENGTH, -nGreatStr);
if(nGreatDex) PRC_Funcs_ModAbilityScore(oSpawn, ABILITY_DEXTERITY, -nGreatDex);

View File

@@ -1,9 +1,68 @@
//:: prc_inc_nat_hb
//::
//:: void main(){}
void DoNaturalWeaponHB(object oPC = OBJECT_SELF);
#include "prc_inc_combat"
#include "prc_inc_template"
/**
* 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;
}
object GetProperTarget(object oPC, object oTarget)
// 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)
{
@@ -129,6 +188,17 @@ void DoNaturalAttack(object oWeapon)
FALSE, //offhand override (for half strength)
bCombatMode // prc scripted combat mode
);
//:: onHit processing for secondary natural attacks
if(GetLocalInt(oPC, "PRCCombat_StruckByAttack"))
{
// Apply onHit abilities from the creature weapon
ApplyAllOnHitCastSpellsOnItemExcludingSubType(
IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, oTarget, oWeapon, oPC);
// Clear the combat struck flag
DeleteLocalInt(oPC, "PRCCombat_StruckByAttack");
}
}
void DoOffhandAttack(int nAttackMod)
@@ -289,13 +359,13 @@ 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;
@@ -304,45 +374,58 @@ void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
&& !GetIsPolyMorphedOrShifted(oPC))
{
// DoDebug("DoNaturalWeaponHB: creature has natural secondary weapons");
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);
// Get stored weapon object, or create if doesn't exist
object oWeapon = GetLocalObject(oPC, "NAT_SEC_WEAP_" + 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_inc_nat_hb >> DoNaturalWeaponHB: creating and storing creature weapon " + sResRef);
oWeapon = CreateItemOnObject(sResRef, oPC);
if(!GetIsObjectValid(oWeapon))
{
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;
}
else
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: ERROR - weapon object is INVALID, cannot schedule attack");
}
}
i++;
}
}
int iMod = 5; // motu99: added check for monk weapon
if(GetHasMonkWeaponEquipped(oPC)) iMod = 3;
@@ -357,10 +440,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 +482,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

View File

@@ -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;

View File

@@ -9,6 +9,8 @@ const int PRC_SIZEMASK_SIMPLE = 4; // 'simple' size changes that have si
const int PRC_SIZEMASK_ALL = 7; // PRC_SIZEMASK_NORMAL | PRC_SIZEMASK_NOABIL | PRC_SIZEMASK_SIMPLE
const int PRC_SIZEMASK_PRC = 0x08; // For systems that need PRC size scale
//wrapper for biowares GetSpellId()
//used for actioncastspell
int PRCGetSpellId(object oCaster = OBJECT_SELF);
@@ -559,7 +561,6 @@ int PRCGetCreatureSize(object oObject = OBJECT_SELF, int nSizeMask = PRC_SIZEMAS
if (DEBUG) DoDebug("PRCGetCreatureSize, returning size: "+IntToString(nSize));
return nSize;
}
int GetIsChakraBound(object oMeldshaper, int nChakra)
{
int nTest = GetLocalInt(oMeldshaper, "BoundMeld"+IntToString(nChakra));

View File

@@ -97,7 +97,9 @@ int GetIsWarforged(object oCreature)
{
int nRace = GetRacialType(oCreature);
if (nRace == RACIAL_TYPE_WARFORGED || nRace == RACIAL_TYPE_WARFORGED_CHARGER) return TRUE;
if (nRace == RACIAL_TYPE_WARFORGED ||
nRace == RACIAL_TYPE_WARFORGED_CHARGER ||
nRace == RACIAL_TYPE_WARFORGED_SCOUT) return TRUE;
return FALSE;
}

View File

@@ -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
@@ -2457,6 +2459,7 @@ int GetCanShiftIntoCreature(object oShifter, int nShifterType, object oTemplate)
nRacialType == RACIAL_TYPE_HALFELF ||
nRacialType == RACIAL_TYPE_HALFLING ||
nRacialType == RACIAL_TYPE_HUMANOID_ORC ||
nRacialType == RACIAL_TYPE_HUMANOID_GOBLINOID ||
nRacialType == RACIAL_TYPE_HUMANOID_REPTILIAN
))
{
@@ -2486,6 +2489,7 @@ int GetCanShiftIntoCreature(object oShifter, int nShifterType, object oTemplate)
nRacialType == RACIAL_TYPE_HALFELF ||
nRacialType == RACIAL_TYPE_HALFLING ||
nRacialType == RACIAL_TYPE_HUMANOID_ORC ||
nRacialType == RACIAL_TYPE_HUMANOID_GOBLINOID ||
nRacialType == RACIAL_TYPE_HUMANOID_REPTILIAN
))
{
@@ -2521,6 +2525,7 @@ int GetCanShiftIntoCreature(object oShifter, int nShifterType, object oTemplate)
nTargetRacialType == RACIAL_TYPE_HALFORC ||
nTargetRacialType == RACIAL_TYPE_HALFELF ||
nTargetRacialType == RACIAL_TYPE_HALFLING ||
nTargetRacialType == RACIAL_TYPE_HUMANOID_GOBLINOID ||
nTargetRacialType == RACIAL_TYPE_HUMANOID_ORC ||
nTargetRacialType == RACIAL_TYPE_HUMANOID_REPTILIAN
) &&
@@ -2531,6 +2536,7 @@ int GetCanShiftIntoCreature(object oShifter, int nShifterType, object oTemplate)
nShifterRacialType == RACIAL_TYPE_HALFORC ||
nShifterRacialType == RACIAL_TYPE_HALFELF ||
nShifterRacialType == RACIAL_TYPE_HALFLING ||
nShifterRacialType == RACIAL_TYPE_HUMANOID_GOBLINOID ||
nShifterRacialType == RACIAL_TYPE_HUMANOID_ORC ||
nShifterRacialType == RACIAL_TYPE_HUMANOID_REPTILIAN
))
@@ -3092,7 +3098,7 @@ void HandleApplyShiftTemplate(object oPC)
int PnPShifterFeats()
{
if(GetPRCSwitch(PRC_NWNX_FUNCS))
if(GetPRCSwitch(PRC_NWNXEE_ENABLED))
{
//If any stats have been changed by NWNX, this could qualify the PC for feats they should
//not actually qualify for, so force unshifting before levelling up.

View 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(){}

View File

@@ -112,13 +112,13 @@ int PerformJump(object oPC, location lLoc, int bDoKnockDown = TRUE)
if (Ninja_AbilitiesEnabled(oPC))
{
bIsRunningJump = TRUE;
iBonus = 4;
iBonus += 4;
}
}
if (GetHasSpellEffect(MOVE_TC_LEAPING_DRAGON, oPC))
{
bIsRunningJump = TRUE;
//iBonus = 10; //:: This is granted in the stance.
//iBonus += 10; //:: This is handled in the stance now.
}
// PnP rules are height * 6 for run and height * 2 for jump.
// I can't get height so that is assumed to be 6.
@@ -363,7 +363,10 @@ int PRCIsFlying(object oCreature)
bFlying = TRUE;
}
if(!bFlying
&& ((nWings > 0 && nWings < 79) || nWings == 90))//CEP and Project Q wing models
&& ((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))

View File

@@ -47,7 +47,7 @@ int PRCDoRangedTouchAttack(object oTarget, int nDisplayFeedback = TRUE, object o
{
SetLocalInt(oCaster, "RangedRecall", nRecall+1);
// Reroll with a -5 penalty
nResult = GetAttackRoll(oTarget,oCaster,OBJECT_INVALID,0,nAttackBonus-5,0,nDisplayFeedback,0.0,TOUCH_ATTACK_MELEE_SPELL);
nResult = GetAttackRoll(oTarget,oCaster,OBJECT_INVALID,0,nAttackBonus-5,0,nDisplayFeedback,0.0,TOUCH_ATTACK_RANGED_SPELL);
}
}
}

Binary file not shown.

View File

@@ -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;
}
@@ -417,7 +417,10 @@ int GetPrCAdjustedClassLevel(int nClass, object oCaster = OBJECT_SELF)
// is it arcane, divine or neither?
if(GetIsArcaneClass(nClass, oCaster) && nClass != CLASS_TYPE_SUBLIME_CHORD)
{
if (GetPrimaryArcaneClass(oCaster) == nClass) // adjust for any PrCs
if(nClass == CLASS_TYPE_FEY && GetRacialType(oCaster) == RACIAL_TYPE_GLOURA)
iTemp = GetArcanePRCLevels(oCaster, nClass);
else if (GetPrimaryArcaneClass(oCaster) == nClass) // adjust for any PrCs
iTemp = GetArcanePRCLevels(oCaster, nClass);
}
else if(GetIsDivineClass(nClass, oCaster))
@@ -1011,11 +1014,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)
{
@@ -1064,6 +1072,10 @@ int PRCMySavingThrow(int nSavingThrow, object oTarget, int nDC, int nSaveType =
nDC -= 1 + (GetHitDice(oTarget) / 5);
else if(GetHasFeat(FEAT_HARD_ELEC, oTarget))
nDC -= 2;
//:: Mechanatrix always fail saves vs electricity.
if(GetRacialType(oTarget) == RACIAL_TYPE_MECHANATRIX)
return 0;
}
else if(nSaveType == SAVING_THROW_TYPE_SONIC)
{
@@ -2783,6 +2795,19 @@ effect PRCEffectDamage(object oTarget, int nDamageAmount, int nDamageType=DAMAGE
effect eEffect;
return eEffect; //Doesn't hurt him
}
// Mechanatrix heals from electrical damage. +1 HP for every 3 electrical damage.
if (GetRacialType(oTarget) == RACIAL_TYPE_MECHANATRIX && nDamageType == DAMAGE_TYPE_ELECTRICAL)
{
nDamageAmount /= 3;
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(nDamageAmount), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEAD_ELECTRICITY), oTarget);
FloatingTextStringOnCreature("Electricty Healing restored " + IntToString(nDamageAmount) +" HP.", oTarget, FALSE);
effect eEffect;
return eEffect; //Doesn't hurt him
}
// Phoenix Belt gains fast healing when hit by fire damage
if (GetHasSpellEffect(MELD_PHOENIX_BELT, oTarget) && nDamageType == DAMAGE_TYPE_FIRE)
{

View File

@@ -76,7 +76,7 @@
/* 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.84";
/* This variable MUST be updated every time 'assemble_spellbooks.bat' is run!!! */
@@ -86,6 +86,13 @@
* Spell switches *
\******************************************************************************/
/**
* Show detailed spell resistance check information to the caster
* When enabled, displays the roll vs SR values when checking spell resistance
*/
const string PRC_SHOW_SR_CHECK_DETAILS = "PRC_SHOW_SR_CHECK_DETAILS";
/** Material Components
* Set switch to 1 to activate this
* This allows material components in NWN through the materialcomp.2da
@@ -614,7 +621,7 @@ const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_R
* Values: 0 [Default] (Werewolf Hybrid Shapchange uses Bioware Polymorph)
* 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
@@ -1204,8 +1211,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 *
@@ -1493,7 +1503,7 @@ const string PRC_POISON_ALLOW_CLEAN_IN_EQUIP = "PRC_POISON_ALLOW_CLEAN_I
*
* 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 *
@@ -1908,7 +1918,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
@@ -1954,6 +1964,11 @@ 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 scepters
*/
const string PRC_CRAFT_SCEPTER_CASTER_LEVEL = "PRC_CRAFT_SCEPTER_CASTER_LEVEL";
/*
* As above, except it applies to herbal infusions
*/
@@ -2015,6 +2030,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%
@@ -2371,7 +2393,15 @@ const string PRC_XP_MAX_LEVEL_DIFF = "PRC_XP_MAX_LEVEL_DIFF";
*/
const string PRC_XP_GIVE_XP_TO_NON_PC_FACTIONS = "PRC_XP_GIVE_XP_TO_NON_PC_FACTIONS";
/******************************************************************************\
* NWNxEE switches *
\******************************************************************************/
//:: This switch enables the PRC8 -> NWNxEE shims. Don't use without NWNxEE
const string PRC_PRCX_ENABLED = "PRC_PRCX_ENABLED";
//:: This switch is set automatically after prc_onmodload detects NWNxEE.
const string PRC_NWNXEE_ENABLED = "PRC_NWNXEE_ENABLED";
/******************************************************************************\
@@ -2495,10 +2525,6 @@ const string PRC_LETOSCRIPT_PORTAL_PASSWORD = "PRC_LETOSCRIPT_PORTAL_PA
*/
const string PRC_LETOSCRIPT_GETNEWESTBIC = "PRC_LETOSCRIPT_GETNEWESTBIC";
//This switch is set automatically after prc_onmodload detects NWNX_Funcs plugin
const string PRC_NWNX_FUNCS = "PRC_NWNX_FUNCS";
/******************************************************************************\
* ConvoCC switches [DEFUNCT] *
\******************************************************************************/
@@ -2941,6 +2967,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";

View File

@@ -10,6 +10,8 @@
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "prc_spell_const"
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////

View File

@@ -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,7 +269,7 @@ 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
@@ -195,36 +296,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
@@ -243,38 +338,55 @@ int FindUnarmedDamage(object oCreature)
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
iMonk += iAscetic;
// In 3.0e, Monk progression stops after level 16:
// Cap monk progression
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;
// 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));
//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)
{
// 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+
// 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
nRow += iDieIncrease;
if (nRow > 10) nRow = 10; // clamp to max row
// 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.
// Lookup damage in unarmed_damage.2da using size column
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);
@@ -284,12 +396,9 @@ 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)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
@@ -299,28 +408,12 @@ int FindUnarmedDamage(object oCreature)
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 3 || bShieldEq)
{
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 (Double dipping?)
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;
@@ -328,24 +421,18 @@ int FindUnarmedDamage(object oCreature)
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;
@@ -355,6 +442,7 @@ int FindUnarmedDamage(object oCreature)
return iDamage;
}
// Adds appropriate feats to the skin. Stolen from SoulTaker + expanded with overwhelming/devastating critical.
void UnarmedFeats(object oCreature)
{

View File

@@ -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,7 +73,6 @@
* @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)
{
@@ -827,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:
@@ -1024,8 +1074,8 @@ void DoWeaponEquip(object oPC, object oItem, int nHand)
if(GetTag(oItem) == "PRC_PYRO_LASH_WHIP") return;
//initialize variables
int nRealSize = PRCGetCreatureSize(oPC); //size for Finesse/TWF
int nSize = nRealSize; //size for equipment restrictions
int nRealSize = PRCGetCreatureSize(oPC); //:: size for Finesse/TWF
int nSize = nRealSize-2; //:: size for equipment restrictions
int nWeaponSize = GetWeaponSize(oItem);
int nStrMod = GetAbilityModifier(ABILITY_STRENGTH, oPC);
int nElfFinesse = GetAbilityModifier(ABILITY_DEXTERITY, oPC) - nStrMod;
@@ -1159,6 +1209,12 @@ void DoWeaponEquip(object oPC, object oItem, int nHand)
DoEquipCourtblade(oPC, oItem);
DoRacialEquip(oPC, nBaseType);
if(DEBUG) DoDebug("GetWeaponRanged: " + IntToString(GetWeaponRanged(oItem)));
if(DEBUG) DoDebug("PRCLargeWeaponCheck: " + IntToString(PRCLargeWeaponCheck(nBaseType, nWeaponSize)));
if(DEBUG) DoDebug("Size check - Weapon: " + IntToString(nWeaponSize) + ", Size: " + IntToString(nSize) + ", RealSize: " + IntToString(nRealSize));
if(DEBUG) DoDebug("Offhand empty: " + IntToString(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC) == OBJECT_INVALID));
if(DEBUG) DoDebug("RealSize > Small: " + IntToString(nRealSize > CREATURE_SIZE_SMALL));
}
void DoWeaponsEquip(object oPC)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -111,3 +111,61 @@ const string NUI_PRC_PA_TEXT_BIND = "nui_prc_pa_text_bind";
const string NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND = "leftButtonEnabled";
// Right Button Enabled Bind for Power Attack NUI
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";
//////////////////////////////////////////////////
// //
// NUI Level Up //
// //
//////////////////////////////////////////////////
const string NUI_LEVEL_UP_WINDOW_ID = "prcLevelUpNui";
const string NUI_LEVEL_UP_SPELL_CIRCLE_BUTTON_BASEID = "NuiLevelUpCircleButton_";
const string NUI_LEVEL_UP_SPELL_BUTTON_BASEID = "NuiLevelUpSpellButton_";
const string NUI_LEVEL_UP_SPELL_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledSpellButton_";
const string NUI_LEVEL_UP_SPELL_CHOSEN_BUTTON_BASEID = "NuiLevelUpChosenSpellButton_";
const string NUI_LEVEL_UP_SPELL_CHOSEN_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledChosenSpellButton_";
const string NUI_LEVEL_UP_DONE_BUTTON = "NuiLevelUpDoneButton";
const string NUI_LEVEL_UP_RESET_BUTTON = "NuiLevelUpResetButton";
const string NUI_LEVEL_UP_SELECTED_CLASS_VAR = "NUILevelUpSelectedClass";
const string NUI_LEVEL_UP_SELECTED_CIRCLE_VAR = "NUILevelUpSelectedCircle";
const string NUI_LEVEL_UP_KNOWN_SPELLS_VAR = "NUILevelUpKnownSpells";
const string NUI_LEVEL_UP_CHOSEN_SPELLS_VAR = "NUILevelUpChosenSpells";
const string NUI_LEVEL_UP_EXPANDED_KNOW_LIST_VAR = "NUILevelUpExpKnowList";
const string NUI_LEVEL_UP_POWER_LIST_VAR = "NUILevelUpPowerList";
const string NUI_LEVEL_UP_DISCIPLINE_INFO_VAR = "GetDisciplineInfoObjectCache_";
const string NUI_LEVEL_UP_SPELLID_LIST_VAR = "NUILevelUpSpellIDList_";
const string NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR = "NUIRemainingChoicesCache";
const string NUI_LEVEL_UP_RELEARN_LIST_VAR = "NUILevelUpRelearnList";
const string NUI_LEVEL_UP_ARCHIVIST_NEW_SPELLS_LIST_VAR = "NUILevelUpArchivistNewSpellsList";
const string NUI_LEVEL_UP_EXPANDED_CHOICES_VAR = "NUIExpandedChoices";
const string NUI_LEVEL_UP_EPIC_EXPANDED_CHOICES_VAR = "NUIEpicExpandedChoices";
const int NUI_LEVEL_UP_MANEUVER_PREREQ_LIMIT = 6;
const string NUI_LEVEL_UP_MANEUVER_TOTAL = "ManeuverTotal";
const string NUI_LEVEL_UP_STANCE_TOTAL = "StanceTotal";
const string NUI_LEVEL_UP_SPELLBOOK_OBJECT_CACHE_VAR = "GetSpellListObjectCache_";
const string NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR = "GetInvokerKnownListObjectCache_";
const string NUI_SPELL_DESCRIPTION_FEATID_VAR = "NUISpellDescriptionFeatID";
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";

View File

@@ -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
@@ -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);
}
}
@@ -2563,6 +2529,78 @@ int IsRequiredForOtherManeuvers(int nClass, int prereq, string discipline, objec
}
int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_SELF)
{
string sFile = GetClassSpellbookFile(nClass);
int prereqs = StringToInt(Get2DACache(sFile, "Prereqs", spellbookId));
string discipline = Get2DACache(sFile, "Discipline", spellbookId);
// First check if this class is allowed to access this discipline
if (!IsAllowedDiscipline(nClass, spellbookId, oPC))
return FALSE;
// If no prerequisites required and class has access, allow it
if (!prereqs)
return TRUE;
// For maneuvers with prerequisites, count across all Blade Magic classes
json discInfo = GetDisciplineInfoObject(nClass, oPC);
json classDisc2Info = JsonObject();
json classDisc3Info = JsonObject();
if (nClass == CLASS_TYPE_SWORDSAGE)
{
if (GetLevelByClass(CLASS_TYPE_WARBLADE, oPC))
classDisc2Info = GetDisciplineInfoObject(CLASS_TYPE_WARBLADE, oPC);
if (GetLevelByClass(CLASS_TYPE_CRUSADER, oPC))
classDisc3Info = GetDisciplineInfoObject(CLASS_TYPE_CRUSADER, oPC);
}
if (nClass == CLASS_TYPE_CRUSADER)
{
if (GetLevelByClass(CLASS_TYPE_WARBLADE, oPC))
classDisc2Info = GetDisciplineInfoObject(CLASS_TYPE_WARBLADE, oPC);
if (GetLevelByClass(CLASS_TYPE_SWORDSAGE, oPC))
classDisc3Info = GetDisciplineInfoObject(CLASS_TYPE_SWORDSAGE, oPC);
}
if (nClass == CLASS_TYPE_WARBLADE)
{
if (GetLevelByClass(CLASS_TYPE_CRUSADER, oPC))
classDisc2Info = GetDisciplineInfoObject(CLASS_TYPE_CRUSADER, oPC);
if (GetLevelByClass(CLASS_TYPE_SWORDSAGE, oPC))
classDisc3Info = GetDisciplineInfoObject(CLASS_TYPE_SWORDSAGE, oPC);
}
// Sum up maneuver counts from all classes for this discipline
int nManCount = 0;
// Check primary class
json chosenDisc = JsonObjectGet(discInfo, discipline);
if (chosenDisc != JsonNull())
{
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)));
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE)));
}
// Check second class
chosenDisc = JsonObjectGet(classDisc2Info, discipline);
if (chosenDisc != JsonNull())
{
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)));
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE)));
}
// Check third class
chosenDisc = JsonObjectGet(classDisc3Info, discipline);
if (chosenDisc != JsonNull())
{
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)));
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE)));
}
// Check if we have enough maneuvers for the prerequisite
return nManCount >= prereqs;
}
/* int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_SELF)
{
string sFile = GetClassSpellbookFile(nClass);
int prereqs = StringToInt(Get2DACache(sFile, "Prereqs", spellbookId));
@@ -2573,13 +2611,14 @@ 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;
}
return FALSE;
}
} */
int GetMaxInitiatorCircle(int nClass, object oPC=OBJECT_SELF)
{
@@ -3169,13 +3208,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 +3247,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,

View File

@@ -10,10 +10,8 @@
//:: Created By: Rakiov
//:: Created On: 24.05.2005
//:://////////////////////////////////////////////
#include "inc_newspellbook"
#include "psi_inc_psifunc"
#include "inc_lookups"
#include "prc_nui_consts"
#include "prc_nui_com_inc"
//
// GetSpellListForCircle
@@ -43,69 +41,6 @@ json GetSpellListForCircle(object oPlayer, int nClass, int circle);
//
json GetSupportedNUISpellbookClasses(object oPlayer);
//
// GetCurrentSpellLevel
// Gets the current spell level the class can achieve at the current
// caster level (ranging from 0-9)
//
// Arguments:
// nClass:int the ClassID
// nLevel:int the caster level
//
// Returns:
// int the circle the class can achieve currently
//
int GetCurrentSpellLevel(int nClass, int nLevel);
//
// GetMaxSpellLevel
// Gets the highest possible circle the class can achieve (from 0-9)
//
// Arguments:
// nClass:int the ClassID
//
// Returns:
// int the highest circle that can be achieved
//
int GetMaxSpellLevel(int nClass);
//
// GetMinSpellLevel
// Gets the lowest possible circle the class can achieve (from 0-9)
//
// Arguments:
// nClass:int the ClassID
//
// Returns:
// int the lowest circle that can be achieved
//
int GetMinSpellLevel(int nClass);
//
// GetHighestLevelPossibleInClass
// Given a class Id this will determine what the max level of a class can be
// achieved
//
// Arguments:
// nClass:int the ClassID
//
// Returns:
// int the highest possible level the class can achieve
//
int GetHighestLevelPossibleInClass(int nClass);
//
// GetClassSpellbookFile
// Gets the class 2da spellbook/ability for the given class Id
//
// Arguments:
// nClass:int the classID
//
// Returns:
// string the 2da file name for the spell/abilities of the ClassID
//
string GetClassSpellbookFile(int nClass);
//
// IsSpellKnown
// Returns whether the player with the given class, spell file, and spellbook id
@@ -234,23 +169,6 @@ json GetMetaMysteryFeatList();
//
int GetTrueClassIfRHD(object oPlayer, int nClass);
//
// GetBinderSpellToFeatDictionary
// Sets up the Binder Spell Dictionary that is used to match a binder's vestige
// to their feat. This is constructed based off the binder's known location of
// their feat and spell ranges in the base 2das respectivly. After constructing
// this it will be saved to the player locally as a cached result since we do
// not need to call this again.
//
// Argument:
// oPlayer:object the player
//
// Returns:
// json:Dictionary<String,Int> a dictionary of mapping between the SpellID
// and the FeatID of a vestige ability
//
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF);
//
// ShouldAddSpell
// Given a spellId and a class, determines if the spell should be added to the
@@ -318,6 +236,18 @@ json GetInvokerEssenceSpellList(int nClass, object oPlayer=OBJECT_SELF);
//
int JsonArrayContainsInt(json list, int item);
//
// IsSpellbookNUIOpen
// Checks to see if the Spellbook NUI is open on a given player.
//
// Arguments:
// oPC:object the player
//
// Returns:
// int:Boolean TRUE if window is open, FALSE otherwise
//
int IsSpellbookNUIOpen(object oPC);
json GetSpellListForCircle(object oPlayer, int nClass, int circle)
{
json retValue = JsonArray();
@@ -397,86 +327,6 @@ int ShouldAddSpell(int nClass, int spellId, object oPlayer=OBJECT_SELF)
return TRUE;
}
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF)
{
// a dictionary of <SpellID, FeatID>
json binderDict = GetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR);
// if this hasn't been created, create it now.
if (binderDict == JsonNull())
binderDict = JsonObject();
else
return binderDict;
// the starting row for binder spells
int spellIndex = 19070;
// the starting row for binder feats
int featIndex = 9030;
//the end of the binder spells/feats
while (spellIndex <= 19156 && featIndex <= 9104)
{
// get the SpellID tied to the feat
int spellID = StringToInt(Get2DACache("feat", "SPELLID", featIndex));
// if the spellID matches the current index, then this is the spell
// attached to the feat
if (spellID == spellIndex)
{
binderDict = JsonObjectSet(binderDict, IntToString(spellID), JsonInt(featIndex));
// move to next spell/feat
featIndex++;
spellIndex++;
}
// else we have reached a subdial spell
else
{
// loop through until we reach back at spellID
while (spellIndex < spellID)
{
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellIndex));
// add the sub radial to the dict, tied to the master's FeatID
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(masterSpell)));
binderDict = JsonObjectSet(binderDict, IntToString(spellIndex), JsonInt(featId));
spellIndex++;
}
// some feats overlap the same FeatID, can cause this to get stuck.
// if it happens then move on
if (spellIndex > spellID)
featIndex++;
}
}
// cache the result
SetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR, binderDict);
return binderDict;
}
string GetClassSpellbookFile(int nClass)
{
string sFile;
// Spontaneous casters use a specific file name structure
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|| nClass == CLASS_TYPE_ARCHIVIST)
{
sFile = GetFileForClass(nClass);
}
// everyone else uses this structure
else
{
sFile = GetAMSDefinitionFileName(nClass);
if (nClass == CLASS_TYPE_BINDER)
{
sFile = "vestiges";
}
}
return sFile;
}
json GetSupportedNUISpellbookClasses(object oPlayer)
{
json retValue = JsonArray();
@@ -512,6 +362,12 @@ int IsSpellKnown(object oPlayer, int nClass, int spellId)
return GetHasFeat(featID, oPlayer);
}
// Divine Surge Greater hardcoding to fix NUI display issue
if (spellId == 15840 || spellId == 16051 || spellId == 16262)
{
spellId = MOVE_DS_GREATER_DIVINE_SURGE; // 17337
}
int currentSpell = spellId;
int masterSpell = StringToInt(Get2DACache("spells", "Master", currentSpell));
if (masterSpell) // If this is not 0 then this is a radial spell, check the radial master
@@ -526,167 +382,6 @@ int IsSpellKnown(object oPlayer, int nClass, int spellId)
return FALSE;
}
int GetCurrentSpellLevel(int nClass, int nLevel)
{
int currentLevel = nLevel;
// ToB doesn't have a concept of spell levels, but still match up to it
if(nClass == CLASS_TYPE_WARBLADE
|| nClass == CLASS_TYPE_SWORDSAGE
|| nClass == CLASS_TYPE_CRUSADER
|| nClass == CLASS_TYPE_SHADOWCASTER)
{
return 9;
}
// Binders don't really have a concept of spell level
if (nClass == CLASS_TYPE_BINDER
|| nClass == CLASS_TYPE_DRAGON_SHAMAN) // they can only reach 1st circle
return 1;
//Shadowsmith has no concept of spell levels
if (nClass == CLASS_TYPE_SHADOWSMITH)
return 2;
if (nClass == CLASS_TYPE_WARLOCK
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
return 4;
// Spont casters have their own function
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|| nClass == CLASS_TYPE_ARCHIVIST)
{
int maxLevel = GetMaxSpellLevelForCasterLevel(nClass, currentLevel);
return maxLevel;
}
else
{
// everyone else uses this
string spellLevel2da = GetAMSKnownFileName(nClass);
currentLevel = nLevel - 1; // Level is 1 off of the row in the 2da
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|| nClass == CLASS_TYPE_PSION
|| nClass == CLASS_TYPE_PSYWAR
|| nClass == CLASS_TYPE_WILDER
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|| nClass == CLASS_TYPE_WARMIND)
currentLevel = GetManifesterLevel(OBJECT_SELF, nClass, TRUE) - 1;
int totalLevel = Get2DARowCount(spellLevel2da);
// in case we somehow go over bounds just don't :)
if (currentLevel >= totalLevel)
currentLevel = totalLevel - 1;
//Psionics have MaxPowerLevel as their column name
string columnName = "MaxPowerLevel";
//Invokers have MaxInvocationLevel
if (nClass == CLASS_TYPE_WARLOCK
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
columnName = "MaxInvocationLevel";
// Truenamers have 3 sets of utterances, ranging from 1-6, EvolvingMind covers the entire range
if (nClass == CLASS_TYPE_TRUENAMER)
{
columnName = "EvolvingMind";
spellLevel2da = "cls_true_maxlvl"; //has a different 2da we want to look at
}
if (nClass == CLASS_TYPE_BINDER)
{
columnName = "VestigeLvl";
spellLevel2da = "cls_bind_binder";
}
// ToB doesn't have a concept of this, but we don't care.
int maxLevel = StringToInt(Get2DACache(spellLevel2da, columnName, currentLevel));
return maxLevel;
}
}
int GetMinSpellLevel(int nClass)
{
// again sponts have their own function
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|| nClass == CLASS_TYPE_ARCHIVIST)
{
return GetMinSpellLevelForCasterLevel(nClass, GetHighestLevelPossibleInClass(nClass));
}
else
{
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|| nClass == CLASS_TYPE_PSION
|| nClass == CLASS_TYPE_PSYWAR
|| nClass == CLASS_TYPE_WILDER
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|| nClass == CLASS_TYPE_WARMIND
|| nClass == CLASS_TYPE_WARBLADE
|| nClass == CLASS_TYPE_SWORDSAGE
|| nClass == CLASS_TYPE_CRUSADER
|| nClass == CLASS_TYPE_WARLOCK
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|| nClass == CLASS_TYPE_SHADOWCASTER
|| nClass == CLASS_TYPE_SHADOWSMITH
|| nClass == CLASS_TYPE_BINDER)
return 1;
return GetCurrentSpellLevel(nClass, 1);
}
}
int GetMaxSpellLevel(int nClass)
{
if (nClass == CLASS_TYPE_WILDER
|| nClass == CLASS_TYPE_PSION)
return 9;
if (nClass == CLASS_TYPE_PSYCHIC_ROGUE
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|| nClass == CLASS_TYPE_WARMIND)
return 5;
if (nClass == CLASS_TYPE_PSYWAR)
return 6;
return GetCurrentSpellLevel(nClass, GetHighestLevelPossibleInClass(nClass));
}
int GetHighestLevelPossibleInClass(int nClass)
{
string sFile;
//sponts have their spells in the classes.2da
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|| nClass == CLASS_TYPE_ARCHIVIST)
{
sFile = Get2DACache("classes", "SpellGainTable", nClass);
}
else
{
// everyone else uses this
sFile = GetAMSKnownFileName(nClass);
if (nClass == CLASS_TYPE_TRUENAMER)
{
sFile = "cls_true_maxlvl"; //has a different 2da we want to look at
}
if (nClass == CLASS_TYPE_BINDER)
{
sFile = "cls_bind_binder";
}
}
return Get2DARowCount(sFile);
}
int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
{
// This controls who can use the Spellbook NUI, if for some reason you don't
@@ -698,8 +393,7 @@ int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
return TRUE;
// Arcane Spont
if (nClass == CLASS_TYPE_ASSASSIN
|| nClass == CLASS_TYPE_BEGUILER
if (nClass == CLASS_TYPE_BEGUILER
|| nClass == CLASS_TYPE_CELEBRANT_SHARESS
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|| nClass == CLASS_TYPE_DUSKBLADE
@@ -817,8 +511,7 @@ int CanClassUseMetamagicFeats(int nClass)
// I don't want to spend the time looping through each class's
// feat 2da so this is the list of all classes that are allowed to use the
// Spellbook NUI and can use Metamagic
return (nClass == CLASS_TYPE_ASSASSIN
|| nClass == CLASS_TYPE_BARD
return (nClass == CLASS_TYPE_BARD
|| nClass == CLASS_TYPE_SORCERER
|| nClass == CLASS_TYPE_BEGUILER
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
@@ -838,7 +531,6 @@ int CanClassUseSuddenMetamagicFeats(int nClass)
// Spellbook NUI and can use Sudden Metamagic
return (nClass == CLASS_TYPE_SHADOWLORD
|| nClass == CLASS_TYPE_ARCHIVIST
|| nClass == CLASS_TYPE_ASSASSIN
|| nClass == CLASS_TYPE_BARD
|| nClass == CLASS_TYPE_BEGUILER
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
@@ -1146,3 +838,16 @@ int JsonArrayContainsInt(json list, int item)
return FALSE;
}
int IsSpellbookNUIOpen(object oPC)
{
int nPreviousToken = NuiFindWindow(oPC, PRC_SPELLBOOK_NUI_WINDOW_ID);
if (nPreviousToken != 0)
{
return TRUE;
}
return FALSE;
}
//:: void main(){}

View File

@@ -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;

View File

@@ -29,6 +29,7 @@ const int RACIAL_TYPE_SILVANESTI_ELF = 999;
const int RACIAL_TYPE_TINK_GNOME = 999;
//Eberron Races
const int RACIAL_TYPE_WARFORGED_SCOUT = 144;
const int RACIAL_TYPE_WARFORGED_CHARGER = 145;
const int RACIAL_TYPE_SHIFTER = 146;
const int RACIAL_TYPE_CHANGELING = 147;
@@ -39,15 +40,15 @@ const int RACIAL_TYPE_EMPTY_VESSEL = 154;
//Planescape Races
const int RACIAL_TYPE_BARIAUR = 207;
const int RACIAL_TYPE_BLADELING = 195;
const int RACIAL_TYPE_CHAOND = 196;
const int RACIAL_TYPE_BLADELING = 999;
const int RACIAL_TYPE_CHAOND = 999;
const int RACIAL_TYPE_NATHRI = 237;
const int RACIAL_TYPE_TULADHARA = 197;
const int RACIAL_TYPE_ZENYRTHRI = 206;
const int RACIAL_TYPE_TULADHARA = 999;
const int RACIAL_TYPE_ZENYRTHRI = 999;
//Ravenloft Races
const int RACIAL_TYPE_HVISTANI = 146;
const int RACIAL_TYPE_VISTANI = 147;
const int RACIAL_TYPE_HVISTANI = 999;
const int RACIAL_TYPE_VISTANI = 999;
//:: Rokugan/Kara-Tur Races
const int RACIAL_TYPE_TASLOI = 140;
@@ -57,85 +58,89 @@ const int RACIAL_TYPE_NEZUMI = 246;
//Spelljammer Races
const int RACIAL_TYPE_SCRO = 182;
const int RACIAL_TYPE_XIXCHIL = 181;
const int RACIAL_TYPE_SCRO = 999;
const int RACIAL_TYPE_XIXCHIL = 999;
// DMG
const int RACIAL_TYPE_PLANT = 52;
//Draconic Races
const int RACIAL_TYPE_DRAGONBORN = 128;
const int RACIAL_TYPE_SPELLSCALE = 129;
const int RACIAL_TYPE_DRAGONBORN = 999;
const int RACIAL_TYPE_SPELLSCALE = 999;
const int RACIAL_TYPE_REDSPAWN_ARCANISS = 72;
const int RACIAL_TYPE_SPIRETOPDRAGON = 77;
//Fey-type Races
const int RACIAL_TYPE_BRALANI = 159;
const int RACIAL_TYPE_BROWNIE = 53;
const int RACIAL_TYPE_GRIG = 133;
const int RACIAL_TYPE_GRIG = 999;
const int RACIAL_TYPE_JAEBRIN = 78;
const int RACIAL_TYPE_NIXIE = 134;
const int RACIAL_TYPE_NYMPH = 135;
const int RACIAL_TYPE_NIXIE = 999;
const int RACIAL_TYPE_NYMPH = 999;
const int RACIAL_TYPE_PIXIE = 226;
const int RACIAL_TYPE_SATYR = 136;
const int RACIAL_TYPE_SATYR = 999;
const int RACIAL_TYPE_HYBSIL = 66;
//Outsider Races
const int RACIAL_TYPE_ASURA = 80;
const int RACIAL_TYPE_ASURA = 999;
const int RACIAL_TYPE_AZER = 227;
const int RACIAL_TYPE_BUOMMANS = 238;
const int RACIAL_TYPE_DJINNI = 81;
const int RACIAL_TYPE_EFREETI = 82;
const int RACIAL_TYPE_FORMIAN = 232;
const int RACIAL_TYPE_DJINNI = 999;
const int RACIAL_TYPE_EFREETI = 999;
const int RACIAL_TYPE_FORMIAN = 999;
const int RACIAL_TYPE_GITHYANKI = 222;
const int RACIAL_TYPE_GITHZERAI = 223;
const int RACIAL_TYPE_GLOAMING = 83;
const int RACIAL_TYPE_GLOAMING = 999;
const int RACIAL_TYPE_HOUND_ARCHON = 84;
const int RACIAL_TYPE_KHAASTA = 94;
const int RACIAL_TYPE_JANNI = 85;
const int RACIAL_TYPE_MEPHIT_AIR = 86;
const int RACIAL_TYPE_MEPHIT_EARTH = 87;
const int RACIAL_TYPE_MEPHIT_FIRE = 88;
const int RACIAL_TYPE_MEPHIT_WATER = 89;
const int RACIAL_TYPE_JANNI = 999;
const int RACIAL_TYPE_MEPHIT_AIR = 999;
const int RACIAL_TYPE_MEPHIT_EARTH = 999;
const int RACIAL_TYPE_MEPHIT_FIRE = 999;
const int RACIAL_TYPE_MEPHIT_WATER = 999;
const int RACIAL_TYPE_MEPHLING_AIR = 90;
const int RACIAL_TYPE_MEPHLING_EARTH = 91;
const int RACIAL_TYPE_MEPHLING_FIRE = 92;
const int RACIAL_TYPE_MEPHLING_WATER = 93;
const int RACIAL_TYPE_NERAPHIM = 235;
const int RACIAL_TYPE_RAKSHASA = 224;
const int RACIAL_TYPE_SALAMANDER = 95;
const int RACIAL_TYPE_SHADE = 210;
const int RACIAL_TYPE_SALAMANDER = 999;
const int RACIAL_TYPE_SHADE = 999;
const int RACIAL_TYPE_SPIKER = 239;
const int RACIAL_TYPE_WILDREN = 240;
const int RACIAL_TYPE_NAZTHARUNE_RAKSHASA = 96;
const int RACIAL_TYPE_RETH_DEKALA = 67;
//Planetouched Races
const int RACIAL_TYPE_WISPLING = 195;
const int RACIAL_TYPE_SHYFT = 196;
const int RACIAL_TYPE_MECHANATRIX = 197;
const int RACIAL_TYPE_AASIMAR = 198;
const int RACIAL_TYPE_AIR_GEN = 199;
const int RACIAL_TYPE_EARTH_GEN = 200;
const int RACIAL_TYPE_FEYRI = 201;
const int RACIAL_TYPE_FIRE_GEN = 202;
const int RACIAL_TYPE_MORTIF = 132;
const int RACIAL_TYPE_MAELUTH = 206;
const int RACIAL_TYPE_MORTIF = 999;
const int RACIAL_TYPE_TANARUKK = 203;
const int RACIAL_TYPE_TIEFLING = 204;
const int RACIAL_TYPE_WATER_GEN = 205;
const int RACIAL_TYPE_SHADOWSWYFT = 236;
//Serpent Kingdom and Reptillian Races
const int RACIAL_TYPE_ABOM_YUAN = 228;
const int RACIAL_TYPE_ABOM_YUAN = 999;
const int RACIAL_TYPE_ASABI = 999;
const int RACIAL_TYPE_ASABI_STINGTAIL = 999;
const int RACIAL_TYPE_KUOTOA = 999;
const int RACIAL_TYPE_LIZARDFOLK = 219;
const int RACIAL_TYPE_LIZARDKING = 68;
const int RACIAL_TYPE_MEDUSA = 69;
const int RACIAL_TYPE_LIZARDKING = 999;
const int RACIAL_TYPE_MEDUSA = 999;
const int RACIAL_TYPE_OPHIDIAN = 999;
const int RACIAL_TYPE_POISON_DUSK = 248;
const int RACIAL_TYPE_PURE_YUAN = 220;
const int RACIAL_TYPE_SAHUAGIN = 71;
const int RACIAL_TYPE_SK_YUANTI = 233;
const int RACIAL_TYPE_TREN = 72;
const int RACIAL_TYPE_SAHUAGIN = 999;
const int RACIAL_TYPE_SK_YUANTI = 999;
const int RACIAL_TYPE_TREN = 999;
const int RACIAL_TYPE_VILETOOTH_LIZARDFOLK = 112;
const int RACIAL_TYPE_MUCKDWELLER = 74;
@@ -143,32 +148,32 @@ const int RACIAL_TYPE_MUCKDWELLER = 74;
const int RACIAL_TYPE_ARANEA = 75;
const int RACIAL_TYPE_BEHOLDER = -1;
const int RACIAL_TYPE_DRIDER = 50;
const int RACIAL_TYPE_GRIMLOCK = 77;
const int RACIAL_TYPE_GRIMLOCK = 999;
const int RACIAL_TYPE_ILLITHID = 225;
const int RACIAL_TYPE_IMASKARI = 230;
const int RACIAL_TYPE_SLYTH = 78;
const int RACIAL_TYPE_SLYTH = 999;
const int RACIAL_TYPE_TROGLODYTE = 234;
const int RACIAL_TYPE_UMBER_HULK = 79;
const int RACIAL_TYPE_UMBER_HULK = 999;
const int RACIAL_TYPE_GLOURA = 73;
//Other Monsterous Races
const int RACIAL_TYPE_CENTAUR = 208;
const int RACIAL_TYPE_CATFOLK = 209;
const int RACIAL_TYPE_DIABOLUS = 113;
const int RACIAL_TYPE_DIOPSID = 114;
const int RACIAL_TYPE_DRAGONKIN = 58;
const int RACIAL_TYPE_ETTERCAP = 73;
const int RACIAL_TYPE_FIRENEWT = 59;
const int RACIAL_TYPE_GARGOYLE = 185;
const int RACIAL_TYPE_KIRLANAN = 60;
const int RACIAL_TYPE_LUPIN = 186;
const int RACIAL_TYPE_PTERAFOLK = 61;
const int RACIAL_TYPE_RAPTORAN = 130;
const int RACIAL_TYPE_SAURIAL_BLADEBACK = 62;
const int RACIAL_TYPE_SAURIAL_FINHEAD = 63;
const int RACIAL_TYPE_SAURIAL_FLYER = 64;
const int RACIAL_TYPE_SAURIAL_HORNHEAD = 65;
const int RACIAL_TYPE_TORTLE = 118;
const int RACIAL_TYPE_DIABOLUS = 999;
const int RACIAL_TYPE_DIOPSID = 999;
const int RACIAL_TYPE_DRAGONKIN = 999;
const int RACIAL_TYPE_ETTERCAP = 999;
const int RACIAL_TYPE_FIRENEWT = 999;
const int RACIAL_TYPE_GARGOYLE = 999;
const int RACIAL_TYPE_KIRLANAN = 999;
const int RACIAL_TYPE_LUPIN = 999;
const int RACIAL_TYPE_PTERAFOLK = 999;
const int RACIAL_TYPE_RAPTORAN = 999;
const int RACIAL_TYPE_SAURIAL_BLADEBACK = 999;
const int RACIAL_TYPE_SAURIAL_FINHEAD = 999;
const int RACIAL_TYPE_SAURIAL_FLYER = 999;
const int RACIAL_TYPE_SAURIAL_HORNHEAD = 999;
const int RACIAL_TYPE_TORTLE = 999;
const int RACIAL_TYPE_VOLODNI = 131;
const int RACIAL_TYPE_WEMIC = 51;
const int RACIAL_TYPE_ARKAMOI = 68;
@@ -226,7 +231,7 @@ const int RACIAL_TYPE_MARRUSAULT = 119;
const int RACIAL_TYPE_MARRUTACT = 120;
//Stormwrack
const int RACIAL_TYPE_DARFELLAN = 117;
const int RACIAL_TYPE_DARFELLAN = 999;
const int RACIAL_TYPE_HADOZEE = 180;
//Champions of Ruin
@@ -257,7 +262,7 @@ const int RACIAL_TYPE_GREY_ELF = 169;
//:: Dwarf
const int RACIAL_TYPE_ARC_DWARF = 151;
const int RACIAL_TYPE_DREAM_DWARF = 157;
const int RACIAL_TYPE_DREAM_DWARF = 999;
const int RACIAL_TYPE_FIREBLOOD_DWARF = 106;
const int RACIAL_TYPE_FROST_DWARF = 158;
const int RACIAL_TYPE_GOLD_DWARF = 152;
@@ -267,11 +272,11 @@ const int RACIAL_TYPE_URDINNIR = 155;
const int RACIAL_TYPE_WILD_DWARF = 156;
//:: Gnome
const int RACIAL_TYPE_CHAOS_GNOME = 177;
const int RACIAL_TYPE_CHAOS_GNOME = 999;
const int RACIAL_TYPE_DEEP_GNOME = 174;
const int RACIAL_TYPE_FIRE_GNOME = 173;
const int RACIAL_TYPE_FOR_GNOME = 175;
const int RACIAL_TYPE_ICE_GNOME = 178;
const int RACIAL_TYPE_ICE_GNOME = 999;
const int RACIAL_TYPE_ROCK_GNOME = 176;
const int RACIAL_TYPE_STONEHUNTER_GNOME = 105;
const int RACIAL_TYPE_SVIRFNEBLIN = 174;

View File

@@ -93,7 +93,9 @@ struct _prc_inc_ability_info_struct _prc_inc_CountItemAbilities(object oCreature
struct _prc_inc_ability_info_struct _prc_inc_shifter_GetAbilityInfo(object oTemplate, object oShifter)
{
int bFuncs = GetPRCSwitch(PRC_NWNX_FUNCS);
int nNWNxEE = GetPRCSwitch(PRC_NWNXEE_ENABLED);
int nPRCx = GetPRCSwitch(PRC_PRCX_ENABLED);
int bFuncs = (nNWNxEE && nPRCx);
//Initialize with item ability bonuses

View File

@@ -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;
@@ -544,6 +547,18 @@ const int SPELL_TURLEMOI_STRENGTH = 19013;
const int SPELL_HADRIMOI_STRENGTH = 19014;
const int SPELL_GLOURA_GRACE = 19015;
const int SPELL_SHYFT_ETHEREAL_JAUNT = 17977; //:: Shyft
const int SPELL_MECHA_SHOCKING_GRASP = 17978; //:: Mechanatrix
const int SPELL_MAELUTH_FIEND_HAMMER = 17979; //:: Maeloth
const int SPELL_WISPLING_CHANGE_SHAPE_LEARN = 17980; //:: Wispling
const int SPELL_WISPLING_CHANGE_SHAPE_OPTIONS = 17981;
const int SPELL_WISPLING_CHANGE_SHAPE_TRUE = 17982;
const int SPELL_WISPLING_CHANGE_SHAPE_QS1 = 17983;
const int SPELL_WISPLING_CHANGE_SHAPE_QS2 = 17984;
// Poison system spells
const int SPELL_POISONED_WEAPON = 2880;
const int SPELL_GRENADE_POISONVIAL = 2881;
@@ -552,7 +567,6 @@ const int SPELL_POISON_ITEM = 2883;
const int SPELL_POISON_FOOD = 2884;
const int SPELL_CLEAN_POISON_OFF = 2885;
// Psionic feat spells
const int SPELL_FEAT_SPEED_OF_THOUGHT_BONUS = 2820;
@@ -1359,8 +1373,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_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 +1425,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;

View File

@@ -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
}

View File

@@ -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);

View File

@@ -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
@@ -119,6 +120,10 @@ const int PRC_GEM_PERLEVEL = 6;
// Craft Skull Talisman constants
const int PRC_SKULL_BASECOST = 7;
int GetWeaponType(int nBaseItem);
void RemoveMasterworkProperties(object oItem);
// * Returns TRUE if an item is a Craft Base Item
// * to be used in spellscript that can be cast on items - i.e light
int CIGetIsCraftFeatBaseItem( object oItem );
@@ -213,6 +218,78 @@ int CICraftCheckCreateInfusion(object oSpellTarget, object oCaster, int nID = 0)
/* Function definitions */
//////////////////////////////////////////////////
void RemoveMasterworkProperties(object oItem)
{
if(DEBUG) DoDebug("RemoveMasterworkProperties() called on: " + DebugObject2Str(oItem));
int nBase = GetBaseItemType(oItem);
if(DEBUG) DoDebug("prc_x2_craft >> RemoveMasterworkProperties(): Item base type: " + IntToString(nBase));
int nRemoved = 0;
// For armor/shields: remove only the Quality property, keep skill bonuses
if((nBase == BASE_ITEM_ARMOR) ||
(nBase == BASE_ITEM_SMALLSHIELD) ||
(nBase == BASE_ITEM_LARGESHIELD) ||
(nBase == BASE_ITEM_TOWERSHIELD))
{
if(DEBUG) DoDebug("prc_x2_craft >> RemoveMasterworkProperties(): Processing armor/shield");
itemproperty ip = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ip))
{
string sTag = GetItemPropertyTag(ip);
int nType = GetItemPropertyType(ip);
if(DEBUG) DoDebug("prc_x2_craft >> RemoveMasterworkProperties(): Found property - Type: " + IntToString(nType) +
", Tag: " + sTag +
", String: " + DebugIProp2Str(ip));
if(sTag == "Quality_Masterwork" && nType == ITEM_PROPERTY_QUALITY)
{
if(DEBUG) DoDebug("prc_x2_craft >> RemoveMasterworkProperties(): Removing Quality property");
RemoveItemProperty(oItem, ip);
nRemoved++;
ip = GetFirstItemProperty(oItem); // Restart iteration
continue;
}
ip = GetNextItemProperty(oItem);
}
}
// For weapons/ammo: remove both Quality and Attack Bonus properties
if(GetWeaponType(nBase) ||
StringToInt(Get2DACache("prc_craft_gen_it", "Type", nBase)) == 4)
{
if(DEBUG) DoDebug("prc_x2_craft >> RemoveMasterworkProperties(): Processing weapon/ammo");
itemproperty ip = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ip))
{
string sTag = GetItemPropertyTag(ip);
int nType = GetItemPropertyType(ip);
if(DEBUG) DoDebug("prc_x2_craft >> RemoveMasterworkProperties(): Found property - Type: " + IntToString(nType) +
", Tag: " + sTag +
", String: " + DebugIProp2Str(ip));
// Check for both Quality and Attack Bonus with Quality_Masterwork tag
if(sTag == "Quality_Masterwork" &&
(nType == ITEM_PROPERTY_QUALITY || nType == ITEM_PROPERTY_ATTACK_BONUS))
{
if(DEBUG) DoDebug("prc_x2_craft >> RemoveMasterworkProperties(): Removing property type " + IntToString(nType));
RemoveItemProperty(oItem, ip);
nRemoved++;
ip = GetFirstItemProperty(oItem); // Restart iteration
continue;
}
ip = GetNextItemProperty(oItem);
}
}
if(DEBUG) DoDebug("prc_x2_craft: RemoveMasterworkProperties() completed. Removed " +
IntToString(nRemoved) + " properties.");
}
// * Returns the innate level of a spell. If bDefaultZeroToOne is given
// * Level 0 spell will be returned as level 1 spells
@@ -276,6 +353,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 +380,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 +607,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 +788,7 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
return oTarget;
}
*/
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to brew a potion
// -----------------------------------------------------------------------------
@@ -864,7 +944,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 +1211,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 +1522,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 +1671,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 +1722,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 +1749,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;
@@ -1608,7 +1860,12 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
if(GetHasSpellEffect(SPELL_RUNE_CHANT))
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 +1972,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);
@@ -2118,6 +2385,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 :
// -------------------------------------------------
// Create Infusion
@@ -2283,6 +2557,8 @@ int CIDoCraftItemFromConversation(int nNumber)
if (GetIsObjectValid(oRet))
{
RemoveMasterworkProperties(oMajor);
// -----------------------------------------------------------------------
// Copy all item properties from the major object on the resulting item
// Through we problably won't use this, its a neat thing to have for the
@@ -2301,6 +2577,7 @@ int CIDoCraftItemFromConversation(int nNumber)
{
//TakeGoldFromCreature(stItem.nCost, oPC,TRUE);
SpendGP(oPC, stItem.nCost);
RemoveMasterworkProperties(oMajor);
IPCopyItemProperties(oMajor,oRet);
}
// set success variable for conversation
@@ -2917,6 +3194,11 @@ 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,14 +3591,16 @@ 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.
// 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);

View File

@@ -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
@@ -213,6 +210,7 @@ int IPDamageConstant(int nDamBon);
#include "prc_ipfeat_const"
#include "inc_utility"
#include "prc_craft_inc"
//------------------------------------------------------------------------------
// I M P L E M E N T A T I O N
@@ -697,6 +695,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 +728,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
@@ -1615,14 +1615,124 @@ int IPGetDamageBonusConstantFromNumber(int nNumber)
// ----------------------------------------------------------------------------
void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE)
{
if (GetIsObjectValid(oOld) && GetIsObjectValid(oNew))
// 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)
{
if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) )
// 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);
}
@@ -1631,11 +1741,10 @@ void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
ip = GetNextItemProperty(oOld);
ip = GetNextItemProperty(oOld);
}
}
}
} */
// ----------------------------------------------------------------------------
// Returns the current enhancement bonus of a weapon (+1 to +20), 0 if there is
@@ -2019,3 +2128,5 @@ int IPOnHitSaveDC(int nSaveDC)
return nIPBonus;
} */
//:: void main(){}

View File

@@ -73,6 +73,7 @@ void SetMasteryOfElements();
//#include "lookup_2da_spell"
#include "prcsp_reputation"
#include "prc_inc_core"
//#include "prc_inc_spells"

View File

@@ -304,10 +304,31 @@ int PRCDoResistSpell(object oCaster, object oTarget, int nEffCasterLvl=0, float
}
}
//:: A tie favors the caster.
int nSRValue = PRCGetSpellResistance(oTarget, oCaster);
int nD20Roll = d20(1);
int nCasterTotal = nEffCasterLvl + nD20Roll + iWeav;
// A tie favors the caster.
if ((nEffCasterLvl + d20(1)+iWeav) < PRCGetSpellResistance(oTarget, oCaster))
if (nCasterTotal < nSRValue)
nResist = SPELL_RESIST_PASS;
//:: Optional Detailed SR check to caster
if (GetIsPC(oCaster) && nResist != SPELL_RESIST_MANTLE && nResist != SPELL_RESIST_GLOBE && nSRValue > 0 && GetPRCSwitch(PRC_SHOW_SR_CHECK_DETAILS))
{
string message = nResist == SPELL_RESIST_FAIL ?
"Target affected. Roll: " + IntToString(nCasterTotal) + " vs SR: " + IntToString(nSRValue) :
"Target resisted. Roll: " + IntToString(nCasterTotal) + " vs SR: " + IntToString(nSRValue) +
" (missed by " + IntToString(nSRValue - nCasterTotal) + ")";
SendMessageToPC(oCaster, message);
}
//:: Basic pass/fail messages
PRCShowSpellResist(oCaster, oTarget, nResist, fDelay);
/* // A tie favors the caster.
if ((nEffCasterLvl + d20(1)+iWeav) < PRCGetSpellResistance(oTarget, oCaster))
nResist = SPELL_RESIST_PASS; */
}
}
@@ -399,3 +420,5 @@ int CheckSpellfire(object oCaster, object oTarget, int bFriendly = FALSE)
//absorbed
return 1;
}
//:; void main(){}

View File

@@ -11,6 +11,7 @@
#include "prc_ipfeat_const"
#include "prc_feat_const"
#include "inc_vfx_const"
#include "prc_inc_nwscript"
//////////////////////////////////////////////////

View File

@@ -713,5 +713,8 @@ void SetAugmentationOverride(object oCreature, struct user_augment_profile uap)
SetLocalInt(oCreature, PRC_AUGMENT_OVERRIDE, _EncodeProfile(uap) + 1);
}
// Test main
//void main(){}

View File

@@ -70,6 +70,7 @@ const int METAPSIONIC_WIDEN = 0x80;
/// Quicken Power
const int METAPSIONIC_QUICKEN = 0x100;
/// How much PP Chain Power costs to use
const int METAPSIONIC_CHAIN_COST = 6;
/// How much PP Empower Power costs to use

View File

@@ -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
@@ -441,6 +443,8 @@ struct manifestation{
int bWiden;
/// Whether Quicken Power was used with this manifestation
int bQuicken;
//:: Whether Defensive Manifesation was used with this manifestation
int bDefensive;
};
//////////////////////////////////////////////////
@@ -786,69 +790,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 +932,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");
@@ -1055,11 +1044,21 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
//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;
// 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)
@@ -1087,6 +1086,36 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
// 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);
nLevel = GetLevelByClass(nClass, oManifester);
@@ -1102,7 +1131,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))
@@ -1666,3 +1695,227 @@ int GetMaxPowerLevel(object oManifester)
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_FIRE && GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) return TRUE;
if(nPower == POWER_ENERGYRAY_COLD && GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) return TRUE;
if(nPower == POWER_ENERGYRAY_ELEC && GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) return TRUE;
if(nPower == POWER_ENERGYRAY_SONIC && 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;
}

View File

@@ -110,6 +110,7 @@ object GetSplitPsionicRayTarget(struct manifestation manif, object oPrimaryTarge
//////////////////////////////////////////////////
#include "psi_inc_core"
#include "psi_inc_psifunc"
//////////////////////////////////////////////////
/* Internal functions */

View File

@@ -29,7 +29,7 @@
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "prc_inc_spells"
//////////////////////////////////////////////////
/* Constants */
//////////////////////////////////////////////////
@@ -572,6 +572,26 @@ int GetMaxPowerCount(object oCreature, int nList)
int GetHasPower(int nPower, object oCreature = OBJECT_SELF)
{
// Debug output
if (DEBUG) DoDebug("GetHasPower: Checking power " + IntToString(nPower));
// Check if it's a subradial spell first
if (GetIsSubradialSpell(nPower))
{
if(DEBUG) DoDebug("GetHasPower: " + IntToString(nPower) + " is a subradial");
int nMasterSpell = GetMasterSpellFromSubradial(nPower);
if (nMasterSpell != -1)
{
if(DEBUG) DoDebug("GetHasPower: Master spell is " + IntToString(nMasterSpell));
nPower = nMasterSpell;
}
}
// 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)
) ||
@@ -593,6 +613,7 @@ int GetHasPower(int nPower, object oCreature = OBJECT_SELF)
// add new psionic classes here
)
return TRUE;
return FALSE;
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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.
@@ -556,6 +558,9 @@ void _ManifestationHB(object oManifester, location lManifester, object oMfToken)
if(DEBUG) DoDebug("_ManifestationHB(): Manifester moved or lost concentration, destroying token");
_DestroyManifestationToken(oManifester, oMfToken);
//:: Clean up variables
_CleanManifestationVariables(oManifester);
// Inform manifester
FloatingTextStrRefOnCreature(16828435, oManifester, FALSE); // "You have lost concentration on the power you were attempting to manifest!"
}
@@ -692,10 +697,28 @@ void _UsePowerAux(object oManifester, object oMfToken, int nSpellId,
struct manifestation EvaluateManifestation(object oManifester, object oTarget, struct power_augment_profile pap, int nMetaPsiFlags)
{
//:: 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 +737,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,6 +792,8 @@ 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)
{
// 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;
}
@@ -786,6 +813,25 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
manif.bCanManifest = FALSE;
}
// Check defensive manifestation BEFORE PP deduction
if(GetLocalInt(oManifester, "PRC_DefensiveManifestActive"))
{
int nPowerLevel = GetPowerLevel(oManifester);
int nDC = 15 + nPowerLevel;
if(!GetPRCIsSkillSuccessful(oManifester, SKILL_CONCENTRATION, nDC))
{
// Failed - deduct PP and prevent manifestation
LosePowerPoints(oManifester, manif.nPPCost, TRUE);
PayMetapsionicsFocuses(manif);
manif.bCanManifest = FALSE;
SendMessageToPC(oManifester, "Defensive manifestation concentration check failed.");
return manif;
}
manif.bDefensive = TRUE;
}
// Psi-like abilities ignore PP costs and metapsi
if(!bIsPsiLike)
{
@@ -796,6 +842,25 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
PayMetapsionicsFocuses(manif);
}
/* if(GetLocalInt(oManifester, "PRC_DefensiveManifestActive"))
{
// Concentration check (DC 15 + power level)
int nPowerLevel = GetPowerLevel(oManifester);
int nDC = 15 + nPowerLevel;
if(!GetPRCIsSkillSuccessful(oManifester, SKILL_CONCENTRATION, nDC))
{
// Failed - PP already deducted, but prevent manifestation
manif.bCanManifest = FALSE;
SendMessageToPC(oManifester, "Defensive manifestion concentration check failed.");
return manif;
}
// Set defensive flag for any other systems that need it
SendMessageToPC(oManifester, "Defensive manifestion concentration check successful.");
manif.bDefensive = TRUE;
} */
//* APPLY SIDE-EFFECTS THAT RESULT FROM SUCCESSFULL MANIFESTATION HERE *//
// Psicraft for all those who can see
IdentifyPower(oManifester, manif.nSpellID);
@@ -1075,4 +1140,4 @@ struct manifestation EvaluateDiaDragChannel(object oManifester, object oTarget,
}
// Test main
//void main(){}
//:: void main(){}

View File

@@ -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;

View File

@@ -1,3 +1,6 @@
const int DEFENSIVE_MANIFESTATION = 2375;
//real power spell constants
// Level 1 Powers
@@ -173,6 +176,7 @@ const int POWER_PSYCHICREFORMATION = 14155;
const int POWER_TELEKINETICMANEUVER = 14156;
const int POWER_DIMENSIONALANCHOR = 14157;
const int POWER_DISMISSAL = 14158;
const int POWER_DIMENSIONDOOR = 14162;
const int POWER_DIMENSIONDOOR_SELFONLY = 14159;
const int POWER_DIMENSIONDOOR_PARTY = 14160;
const int POWER_DOMINATE = 14161;
@@ -183,6 +187,7 @@ const int POWER_ENERGYBALL_ELEC = 14166;
const int POWER_ENERGYBALL_FIRE = 14167;
const int POWER_ENERGYBALL_SONIC = 14168;
const int POWER_PSYCHICVAMPIRE = 14169;
const int POWER_CLAW_ENERGY = 14350;
const int POWER_CLAW_ENERGY_COLD = 14170;
const int POWER_CLAW_ENERGY_ELEC = 14171;
const int POWER_CLAW_ENERGY_FIRE = 14172;

View File

@@ -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 (){}

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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
//---------------------------------------------------------------------------
@@ -278,3 +289,5 @@ int ShadPreMystCastCode()
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #6: " + IntToString(nContinue));
return nContinue;
}
//:: void main (){}

View File

@@ -790,6 +790,10 @@ int CheckManeuverPrereqs(int nClass, int nPrereqs, int nDiscipline, object oPC)
DoDebug("CheckManeuverPrereqs: sFeatName: " + sFeatName);
} */
DoDebug("CheckManeuverPrereqs: nClass=" + IntToString(nClass) +
" nDiscipline=" + IntToString(nDiscipline) +
" nPrereqs=" + IntToString(nPrereqs));
// Prestige classes can only access certain disciplines
if(!_AllowedDiscipline(oPC, nClass, nDiscipline))
return FALSE;

View File

@@ -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
//---------------------------------------------------------------------------

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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
//---------------------------------------------------------------------------

View File

@@ -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)
@@ -327,8 +327,25 @@ int ArcaneSpellFailure(object oCaster, int nCastingClass, int nSpellLevel, int n
default: break;
}
}
// Hexblade can cast in light/medium armour and while using small shield.
// Hexblade can cast in light armour only.
else if(nCastingClass == CLASS_TYPE_HEXBLADE)
{
//armors
switch(nAC)
{
case 1: nASF -= 5; break; //light
case 2: nASF -= 10; break; //light
case 3: nASF -= 20; break; //light
case 4: nASF = bBattleCaster ? 0 : nASF; break; //medium with Battlecaster
case 5: nASF = bBattleCaster ? 0 : nASF; break; //medium with Battlecaster
default: break;
}
}
// WRONG: Hexblade can cast in light/medium armour and while using small shield.
//:: RIGHT: Hexblades are proficient with all simple and martial weapons, and with light armor but not with shields.
/* else if(nCastingClass == CLASS_TYPE_HEXBLADE)
{
//shields
if(GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD) nASF -= 5;
@@ -345,7 +362,7 @@ int ArcaneSpellFailure(object oCaster, int nCastingClass, int nSpellLevel, int n
case 8: nASF -= bBattleCaster ? 45 : 0; break;
default: break;
}
}
} */
// Bards cannot cast in light armour and while using small shield in 3e
/* else if(nCastingClass == CLASS_TYPE_BARD)
{
@@ -2163,8 +2180,33 @@ int PRCSpellEffects(object oCaster, object oTarget, int nSpellID, int nSpellLeve
if(GetPRCSwitch(PRC_PNP_TENSERS_TRANSFORMATION))
{
if(GetHasSpellEffect(SPELL_TENSERS_TRANSFORMATION, oCaster))
return FALSE;
{
// Allow potions - they are not spell trigger/completion items
object oSpellCastItem = PRCGetSpellCastItem();
if(GetIsObjectValid(oSpellCastItem))
{
int nItemType = GetBaseItemType(oSpellCastItem);
if(nItemType == BASE_ITEM_ENCHANTED_POTION
|| nItemType == BASE_ITEM_POTIONS)
{
// Continue with other checks
}
else
{
return FALSE; // Block other magic items
}
}
else
{
return FALSE; // Block regular spellcasting
}
}
}
/* {
if(GetHasSpellEffect(SPELL_TENSERS_TRANSFORMATION, oCaster))
return FALSE;
} */
// Gaseous Form check
if(GetHasSpellEffect(SPELL_GASEOUS_FORM, oCaster))
@@ -2902,7 +2944,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 +2952,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
}
}
@@ -3346,6 +3388,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
//---------------------------------------------------------------------------
@@ -3355,11 +3419,6 @@ 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

View File

@@ -4025,6 +4025,10 @@
}
]
},
"TileBrdrDisabled": {
"type": "byte",
"value": 0
},
"Tileset": {
"type": "resref",
"value": "tdr01"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More