2025/12/25 Update

Hooked up new GUI module event.
Updated PRC8 includes.
Updated nasher.cfg.
This commit is contained in:
Jaysyn904
2025-12-25 20:04:29 -05:00
parent 2b0d12d1b1
commit 245c2c04a2
75 changed files with 4022 additions and 475 deletions

View File

@@ -227,7 +227,20 @@ description = "PRC8 version of The Lord of Terror module."
filter = "x2_inc_cutscenep.nss"
filter = "x2_inc_spellhook.nss"
filter = "x3_inc_horse.nss"
filter = "xchst_inc.nss"
filter = "prc_inc_string.nss"
filter = "prc_nui_sc_inc.nss"
filter = "prc_nui_scd_inc.nss"
filter = "prc_nui_consts.nss"
filter = "nw_inc_nui.nss"
filter = "xchst_inc.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 = "tophak"

View File

@@ -4,12 +4,15 @@
//:://////////////////////////////////////////////
/** @file
@author Primogenitor
@date 2005.09.23 - Rebuilt the system - Ornedan
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
//PRC8 Token pre-fix = 161838
//////////////////////////////////////////////////
/* Constant definitions */
@@ -37,11 +40,11 @@ const int DYNCONV_TOKEN_PREV = 161838113;
const int DYNCONV_MIN_TOKEN = 16183899;
const int DYNCONV_MAX_TOKEN = 161838113;
const int DYNCONV_STRREF_PLEASE_WAIT = 16824202; // "Please wait"
const int DYNCONV_STRREF_PREVIOUS = 16824203; // "Previous"
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_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 = 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

@@ -303,11 +303,18 @@ int GetIsEpicShaman(object oPC)
&& GetAbilityScore(oPC, ABILITY_WISDOM) > 18;
}
int GetIsEpicSorcerer(object oPC)
int GetIsEpicSorcerer(object oPC)
{
return GetHitDice(oPC) >= 21
&& GetCasterLvl(CLASS_TYPE_SORCERER, oPC) > 17
&& GetAbilityScore(oPC, ABILITY_CHARISMA) > 18;
}
/* int GetIsEpicSorcerer(object oPC)
{
return GetPrCAdjustedCasterLevel(CLASS_TYPE_SORCERER, oPC, FALSE) > 17
&& GetAbilityScore(oPC, ABILITY_CHARISMA) > 18;
}
} */
int GetIsEpicSublimeChord(object oPC)
{

View File

@@ -1686,7 +1686,7 @@ int FeatToIprop(int nFeat)
case FEAT_WEAPON_PROFICIENCY_HEAVY_PICK: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_PICK;
case FEAT_WEAPON_PROFICIENCY_LIGHT_PICK: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_PICK;
case FEAT_WEAPON_PROFICIENCY_SAI: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SAI;
case FEAT_WEAPON_PROFICIENCY_NUNCHUKU: return IP_CONST_FEAT_WEAPON_PROFICIENCY_NUNCHUKU;
case FEAT_WEAPON_PROFICIENCY_NUNCHAKU: return IP_CONST_FEAT_WEAPON_PROFICIENCY_NUNCHAKU;
case FEAT_WEAPON_PROFICIENCY_FALCHION: return IP_CONST_FEAT_WEAPON_PROFICIENCY_FALCHION;
case FEAT_WEAPON_PROFICIENCY_SAP: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SAP;
case FEAT_WEAPON_PROFICIENCY_KATAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KATAR;

View File

@@ -108,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 */
@@ -1622,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);
@@ -111,7 +113,7 @@ object CreateLocalNextNPC(object oMaster,int nAssociateType,string sTemplate,loc
SetLocalObject(oMaster, IntToString(nAssociateType)+"oHench"+IntToString(nCount), oSummon);
SetLocalInt(oSummon, "iAssocNth", nCount);
SetAssociateState(NW_ASC_HAVE_MASTER,TRUE,oSummon);
SetAssociateState(NW_ASC_HAVE_MASTER, TRUE, oSummon);
SetAssociateState(NW_ASC_DISTANCE_2_METERS);
SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE);
SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE);
@@ -122,6 +124,7 @@ object CreateLocalNextNPC(object oMaster,int nAssociateType,string sTemplate,loc
return oSummon;
}
object GetMasterNPC(object oAssociate=OBJECT_SELF)
{
object oMaster = GetLocalObject(oAssociate, "oMaster");
@@ -220,4 +223,173 @@ int GetAssociateHealMasterNPC()
return FALSE;
}
/**
* @brief Levels up a summoned creature based on its master's total casting level,
* while respecting configured HD limits and multiclass transition rules.
* Should only be called on the NPC onSpawn event.
*
* This function:
* - Retrieves the master<65>s total casting level and clamps it to the creature<72>s
* minimum and maximum HD (iMinHD, iMaxHD).
* - Repeatedly calls LevelUpHenchman() until the creature reaches that level,
* switching classes when the creature's stored "ClassXStart" thresholds are met.
*
* Local variables recognized on the summoned creature:
*
* | Variable Name | Purpose |
* |-----------------|-------------------------------------------------------------|
* | iMinHD | Minimum HD allowed |
* | iMaxHD | Maximum HD allowed |
* | Class2Start | Level to begin second class progression |
* | Class2 | Class type for second progression |
* | Class2Package | Package for second progression |
* | Class3Start | Level to begin third class progression |
* | Class3 | Class type for third progression |
* | Class3Package | Package for third progression |
* | Class4Start | Level to begin fourth class progression |
* | Class4 | Class type for fourth progression |
* | Class4Package | Package for fourth progression |
*
* Behavior notes:
* - Leveling continues until the creature reaches the master<65>s effective
* casting level (bounded by iMinHD/iMaxHD).
* - If LevelUpHenchman() returns 0, the creature shouts a failure message.
* - CLASS_TYPE_INVALID causes the creature to level in its current class.
*
* @param oCreature The summoned creature being leveled. Defaults to OBJECT_SELF.
*
* @see LevelUpHenchman
* @see GetLocalInt
* @see GetHitDice
*/
void LevelUpSummon(object oSummon, int iTargetLvl)
{
int nCurrentHD = GetHitDice(oSummon);
int iNewHD = nCurrentHD;
// Read multiclassing info from locals
int iClass2Start = GetLocalInt(oSummon, "Class2Start");
int iClass2 = GetLocalInt(oSummon, "Class2");
int iClass2Package = GetLocalInt(oSummon, "Class2Package");
int iClass3Start = GetLocalInt(oSummon, "Class3Start");
int iClass3 = GetLocalInt(oSummon, "Class3");
int iClass3Package = GetLocalInt(oSummon, "Class3Package");
int iClass4Start = GetLocalInt(oSummon, "Class4Start");
int iClass4 = GetLocalInt(oSummon, "Class4");
int iClass4Package = GetLocalInt(oSummon, "Class4Package");
int iClass; // current class to level
int iPackage; // package to use
// Main leveling loop
while (nCurrentHD < iTargetLvl && nCurrentHD > 0)
{
// Determine which class and package to use
if (iClass4Start != 0 && nCurrentHD >= iClass4Start)
{
iClass = iClass4;
iPackage = iClass4Package;
}
else if (iClass3Start != 0 && nCurrentHD >= iClass3Start)
{
iClass = iClass3;
iPackage = iClass3Package;
}
else if (iClass2Start != 0 && nCurrentHD >= iClass2Start)
{
iClass = iClass2;
iPackage = iClass2Package;
}
else
{
// Base class (first class in the sheet)
iClass = CLASS_TYPE_INVALID; // keeps current
iPackage = PACKAGE_INVALID;
}
// Level up one HD
iNewHD = LevelUpHenchman(oSummon, iClass, TRUE, iPackage);
if (iNewHD == 0)
{
SpeakString(GetName(oSummon) + " failed to level properly!", TALKVOLUME_SHOUT);
break;
}
nCurrentHD = iNewHD;
}
// Force the creature to rest to memorize spells
// PRCForceRest(oSummon);
}
/* void LevelUpSummon(object oSummon, int iTargetLvl)
{
//get the default hit dice of the summon
int nDefaultHD = GetHitDice(oSummon);
if (DEBUG) DoDebug("inc_npc >> LevelUpSummon: nDefaultHD = " +IntToString(nDefaultHD)+".");
if (DEBUG) DoDebug("inc_npc >> LevelUpSummon: iTargetLvl = " +IntToString(iTargetLvl)+".");
//get the multiclassing variables to see if we need to change classes from its base class
int iClass2Start = GetLocalInt(oSummon, "Class2Start");
int iClass2 = GetLocalInt(oSummon, "Class2");
int iClass2Package = GetLocalInt(oSummon, "Class2Package");
int iClass3Start = GetLocalInt(oSummon, "Class3Start");
int iClass3 = GetLocalInt(oSummon, "Class3");
int iClass3Package = GetLocalInt(oSummon, "Class3Package");
int iClass4Start = GetLocalInt(oSummon, "Class4Start");
int iClass4 = GetLocalInt(oSummon, "Class4");
int iClass4Package = GetLocalInt(oSummon, "Class4Package");
//check for zero cause thats an error
//if creatures are not leveling then best bet is they are not legal creatures
while( (nDefaultHD < iTargetLvl) && (nDefaultHD > 0) )
{
//check the multiclassing numbers to change classes
if( (iClass4Start != 0) && (nDefaultHD >= iClass4Start) )
{
//level up using the new class and Packageage
nDefaultHD = LevelUpHenchman(oSummon, iClass4 ,TRUE, iClass4Package);
if(nDefaultHD == 0)
SpeakString(GetName(oSummon) + " Failed on fourth class", TALKVOLUME_SHOUT);
}
else if( (iClass3Start != 0) && (nDefaultHD >= iClass3Start) )
{
//level up using the new class and Packageage
nDefaultHD = LevelUpHenchman(oSummon, iClass3 ,TRUE, iClass3Package);
if(nDefaultHD == 0)
SpeakString(GetName(oSummon) + " Failed on third class", TALKVOLUME_SHOUT);
}
else if( (iClass2Start != 0) && (nDefaultHD >= iClass2Start) )
{
//level up using the new class and Packageage
nDefaultHD = LevelUpHenchman(oSummon, iClass2 ,TRUE, iClass2Package);
if(nDefaultHD == 0)
SpeakString(GetName(oSummon) + " Failed on second class", TALKVOLUME_SHOUT);
}
else
{
//just level up using the class it already has
nDefaultHD = LevelUpHenchman(oSummon, CLASS_TYPE_INVALID ,TRUE);
if(nDefaultHD == 0)
SpeakString(GetName(oSummon) + " Failed to level properly", TALKVOLUME_SHOUT);
}
}
}
*/
//:: void main() {}

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 */
@@ -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);
@@ -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);
@@ -430,8 +431,8 @@ void SetDefaultFileEnds()
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);
@@ -866,6 +867,31 @@ void CreateSwitchNameArray()
//if you add more switches, add them to this list
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DEBUG);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_COMBAT_DEBUG);
//craft
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_CRAFT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MULTIPLIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MAX);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MIN);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BREW_POTION_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_SCRIBE_SCROLL_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_WAND_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_ROD_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_STAFF_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_BASE_ITEMS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_MAXLEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_COSTMODIFIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_SCRIBESCROLL_COSTMODIFIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_MAXLEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_COSTMODIFIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CREATEINFUSION_COSTMODIFIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_ARBITRARY);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_COST_SCALE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_TIME_SCALE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_OPTIONAL_HERBS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_SCEPTER_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_MATERIAL_COMPONENTS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_COMPONENTS_SHOP);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PNP_TRUESEEING);
@@ -876,6 +902,8 @@ void CreateSwitchNameArray()
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_HARM);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_NEUTRALIZE_POISON);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_REMOVE_DISEASE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIO_UNLEARN);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_UNLEARN_SPELL_MAXNR);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TIMESTOP_BIOWARE_DURATION);
@@ -994,7 +1022,7 @@ void CreateSwitchNameArray()
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_USES_PER_WEAPON_POISON_COUNT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_USES_PER_WEAPON_POISON_DIE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_POISON_ALLOW_CLEAN_IN_EQUIP);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_POISON_USE_INGREDIENST);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_POISON_USE_INGREDIENTS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PSI_ASTRAL_CONSTRUCT_USE_2DA);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PNP_RAPID_METABOLISM);
@@ -1058,31 +1086,31 @@ void CreateSwitchNameArray()
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_LETOSCRIPT_UNICORN_SQL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_LETOSCRIPT_GETNEWESTBIC);
//craft
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_CRAFT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MULTIPLIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MAX);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MIN);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BREW_POTION_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_SCRIBE_SCROLL_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_WAND_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_ROD_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_STAFF_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_BASE_ITEMS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_MAXLEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_COSTMODIFIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_SCRIBESCROLL_COSTMODIFIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_MAXLEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_COSTMODIFIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CREATEINFUSION_COSTMODIFIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_ARBITRARY);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_COST_SCALE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_TIME_SCALE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_CASTER_LEVEL);
//spells
//shifter
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_USECR);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_HUGE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_LARGE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_MEDIUM);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_SMALL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_TINY);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OUTSIDER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ELEMENTAL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_CONSTRUCT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_UNDEAD);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_DRAGON);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ABERRATION);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OOZE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MAGICALBEAST);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_GIANT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_VERMIN);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_BEAST);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ANIMAL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MONSTROUSHUMANOID);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_HUMANOID);
//general

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

@@ -77,6 +77,15 @@ int PreInvocationCastCode()
int nContinue = !ExecuteScriptAndReturnInt("prespellcode", oInvoker);
//---------------------------------------------------------------------------
// Block forsakers from using invocations
//---------------------------------------------------------------------------
if(GetLevelByClass(CLASS_TYPE_FORSAKER, oInvoker) > 0)
{
SendMessageToPC(oInvoker, "Forsakers cannot use invocations.");
return FALSE;
}
//---------------------------------------------------------------------------
// Break any spell require maintaining concentration
//---------------------------------------------------------------------------
@@ -168,3 +177,4 @@ int PreInvocationCastCode()
return nContinue;
}
//:: void main (){}

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)
{
@@ -246,4 +823,6 @@ void DoTail(object oPC, int nTailType)
SetCreatureTailType(nTailType, oPC);
//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

@@ -444,6 +444,7 @@ int Get2DALineFromItemprop(string sFile, itemproperty ip, object oItem)
}
break;
}
case ITEM_PROPERTY_ECHOBLADE: return 46; break;
}
}
return -1;
@@ -1529,7 +1530,12 @@ void ApplyItemProps(object oItem, string sFile, int nLine)
break; //no more itemprops, no gaps, assuming no errors
}
if(sFile != "craft_weapon" && sFile != "craft_armour")
SetName(oItem, GetStringByStrRef(StringToInt(Get2DACache(sFile, "Name", nLine))));
{
SetName(oItem, GetStringByStrRef(StringToInt(Get2DACache(sFile, "Name", nLine))));
string sDescRef = Get2DACache(sFile, "CraftedDescription", nLine);
if(sDescRef != "")
SetDescription(oItem, GetStringByStrRef(StringToInt(sDescRef)));
}
}
//Partly ripped off the lexicon :P
@@ -1620,7 +1626,8 @@ string GetCrafting2DA(object oItem)
(nBase == BASE_ITEM_BOOTS) ||
(nBase == BASE_ITEM_GLOVES) ||
(nBase == BASE_ITEM_BRACER) ||
(nBase == BASE_ITEM_CLOAK))
(nBase == BASE_ITEM_CLOAK) ||
(nBase == BASE_ITEM_CRAFTED_VIAL))
)
return "craft_wondrous";
@@ -1657,19 +1664,28 @@ int GetCraftingFeat(object oItem)
if(nBase == BASE_ITEM_RING) return FEAT_FORGE_RING;
//routing bioware feats through this convo
if((nBase == BASE_ITEM_CRAFTED_SCEPTER) ||
(nBase == BASE_ITEM_CRAFTED_SCEPTER)
)
return FEAT_CRAFT_SCEPTER;
if((nBase == BASE_ITEM_MAGICROD) ||
(nBase == BASE_ITEM_CRAFTED_ROD)
)
return FEAT_CRAFT_ROD;
if((nBase == BASE_ITEM_MAGICSTAFF) ||
(nBase == BASE_ITEM_CRAFTED_STAFF)
)
return FEAT_CRAFT_STAFF;
if((nBase == BASE_ITEM_MAGICWAND) ||
(nBase == BASE_ITEM_BLANK_WAND)
)
return FEAT_CRAFT_WAND;
if(nBase == BASE_ITEM_BLANK_POTION) return FEAT_BREW_POTION;
if(nBase == BASE_ITEM_BLANK_SCROLL) return FEAT_SCRIBE_SCROLL;
if(((nBase == BASE_ITEM_HELMET) ||
@@ -1678,7 +1694,8 @@ int GetCraftingFeat(object oItem)
(nBase == BASE_ITEM_BOOTS) ||
(nBase == BASE_ITEM_GLOVES) ||
(nBase == BASE_ITEM_BRACER) ||
(nBase == BASE_ITEM_CLOAK))
(nBase == BASE_ITEM_CLOAK) ||
(nBase == BASE_ITEM_CRAFTED_VIAL))
)
return FEAT_CRAFT_WONDROUS;

View File

@@ -75,6 +75,7 @@ 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
*
@@ -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,13 +181,9 @@ 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"
@@ -269,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)
@@ -802,5 +804,11 @@ int GetIsShaken(object oTarget)
return FALSE;
}
// Forward declarations for size change effects
// Implementations are in prc_inc_size
effect EffectSizeChange(object oTarget, int nObjectType, int bEnlarge, int nChanges);
void DelayedSetVisualTransform(int nExpectedGeneration, object oTarget, int nTransform, float fValue);
void DelaySetVisualTransform(float fDelay, object oTarget, string sGenerationName, int nTransform, float fValue);
//:: Test void
//:: void main() {}
//::void main() {}

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;
@@ -1314,6 +1322,7 @@ const int FEAT_SOMATIC_WEAPONRY = 5186;
// Forgotten Realms Campaign Setting
const int FEAT_INSCRIBE_RUNE = 2462;
const int EPIC_FEAT_INSCRIBE_EPIC_RUNES = 2549;
// Miniature Handbook
const int FEAT_SHIELDMATE = 3258;
@@ -3726,6 +3735,9 @@ const int FEAT_EPIC_ARTIFICER = 4072;
//////////////// END INFUSIONS /////////////////
//////////////////////////////////////////////////*/
//:: Monk
const int FEAT_MONK_ABUNDANT_STEP = 2351;
//Justice of Weald and Woe
const int FEAT_LUCKY_SHOT = 24021;
@@ -6275,6 +6287,7 @@ const int FEAT_DSONG_SPELLCASTING_NONE = 19592;
const int FEAT_OLLAM_SPELLCASTING_NONE = 19593;
//:: PRC8 Hidden Talent Feats
const int FEAT_HIDDEN_TALENT = 25900;
const int FEAT_HIDDEN_TALENT_BIOFEEDBACK = 25901;
const int FEAT_HIDDEN_TALENT_BITE_WOLF = 25902;
const int FEAT_HIDDEN_TALENT_BOLT = 25903;

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

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

@@ -1082,7 +1082,7 @@ int GetIsTwoHandedMeleeWeaponType(int iWeaponType)
case BASE_ITEM_HEAVYFLAIL: return TRUE;
case BASE_ITEM_SCYTHE: return TRUE;
case BASE_ITEM_QUARTERSTAFF: return TRUE;
case BASE_ITEM_MAGICSTAFF: return TRUE;
//case BASE_ITEM_MAGICSTAFF: return TRUE;
case BASE_ITEM_ELVEN_COURTBLADE: return TRUE;
case BASE_ITEM_MAUL: return TRUE;
case BASE_ITEM_FALCHION: return TRUE;
@@ -1141,8 +1141,8 @@ int GetIsSimpleWeaponType(int iWeaponType)
case BASE_ITEM_CSLSHPRCWEAP: return 1;
case BASE_ITEM_GLOVES: return 1;
case BASE_ITEM_BRACER: return 1;
case BASE_ITEM_CLUB: return 2;
case BASE_ITEM_CRAFTED_SCEPTER: return 1;
case BASE_ITEM_DAGGER: return 2;
case BASE_ITEM_LIGHTMACE: return 2;
case BASE_ITEM_SICKLE: return 2;
@@ -1279,6 +1279,19 @@ struct WeaponFeat GetAllFeatsOfWeaponType(int iWeaponType)
sFeat.VileMartialStrike = FEAT_VILE_MARTIAL_CLUB;
break;
}
case BASE_ITEM_CRAFTED_SCEPTER: {
sFeat.Focus = FEAT_WEAPON_FOCUS_CLUB;
sFeat.Specialization = FEAT_WEAPON_SPECIALIZATION_CLUB;
sFeat.EpicFocus = FEAT_EPIC_WEAPON_FOCUS_CLUB;
sFeat.EpicSpecialization = FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB;
sFeat.ImprovedCritical = FEAT_IMPROVED_CRITICAL_CLUB;
sFeat.OverwhelmingCritical = FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB;
sFeat.DevastatingCritical = FEAT_EPIC_DEVASTATING_CRITICAL_CLUB;
sFeat.WeaponOfChoice = FEAT_WEAPON_OF_CHOICE_CLUB;
sFeat.SanctifyMartialStrike = FEAT_SANCTIFY_MARTIAL_CLUB;
sFeat.VileMartialStrike = FEAT_VILE_MARTIAL_CLUB;
break;
}
case BASE_ITEM_DAGGER: {
sFeat.Focus = FEAT_WEAPON_FOCUS_DAGGER;
sFeat.Specialization = FEAT_WEAPON_SPECIALIZATION_DAGGER;
@@ -8090,7 +8103,12 @@ void AttackLoopLogic(object oDefender, object oAttacker,
if (DEBUG) DoDebug("entered AttackLoopLogic: bFirstAttack = " + IntToString(bFirstAttack) + ", cleave = " + IntToString(bIsCleaveAttack) + ", current action = " + GetActionName(iAction));
if (DEBUG) DoDebug("AttackLoopLogic: iMainAttacks = " + IntToString(iMainAttacks) + ", iOffHandAttacks = " + IntToString(iOffHandAttacks) + ", iBonusAttacks = " + IntToString(iBonusAttacks));
int bIsRangedAttack = sAttackVars.bIsRangedWeapon || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED;
//int bIsRangedAttack = sAttackVars.bIsRangedWeapon || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED;
int bIsRangedAttack = sAttackVars.bIsRangedWeapon ||
sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL ||
sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED ||
GetLocalInt(oAttacker, "WhirlingBlade");
// check for valid target etc., but only if it is not a cleave or circle kick (in this case we checked all of this before)
if (!bIsCleaveAttack)

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 */
@@ -1321,7 +1322,29 @@ int DoTrip(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TRUE,
DelayCommand(0.0, PerformAttack(oTarget, oPC, eNone, 0.0, 0, 0, 0, "Improved Trip Free Attack Hit", "Improved Trip Free Attack Miss"));
}
}
else // If you fail, enemy gets a counter trip attempt, using Strength
else // If you fail, enemy gets a counter trip attempt, using Strength
{
if(!nCounterTrip)
{
nTargetStat = GetAbilityModifier(ABILITY_STRENGTH, oTarget) + GetCombatMoveCheckBonus(oTarget, COMBAT_MOVE_TRIP, FALSE, TRUE);
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
// Roll counter trip attempt
nTargetCheck = nTargetStat + nTargetBonus + d20();
nPCCheck = nPCStat + nPCBonus + d20();
// If counters aren't allowed, don't knock em down
// Its down here to allow the text message to go through
SendMessageToPC(oPC, "Enemy Counter Trip Check: "+IntToString(nPCCheck)+" vs "+IntToString(nTargetCheck));
SetLocalInt(oPC, "TripDifference", nTargetCheck - nPCCheck);
DelayCommand(2.0, DeleteLocalInt(oPC, "TripDifference"));
}
if (nTargetCheck >= nPCCheck && nCounterTrip)
{
// Knock em down
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectKnockdown()), oPC, 6.0);
}
}
/* else // If you fail, enemy gets a counter trip attempt, using Strength
{
nTargetStat = GetAbilityModifier(ABILITY_STRENGTH, oTarget) + GetCombatMoveCheckBonus(oTarget, COMBAT_MOVE_TRIP, FALSE, TRUE);
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
@@ -1338,7 +1361,7 @@ int DoTrip(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TRUE,
}
SetLocalInt(oPC, "TripDifference", nTargetCheck - nPCCheck);
DelayCommand(2.0, DeleteLocalInt(oPC, "TripDifference"));
}
} */
}
else
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
@@ -1941,10 +1964,21 @@ void TigerBlooded(object oInitiator, object oTarget)
int DoDisarm(object oPC, object oTarget, int nExtraBonus = 0, int nGenerateAoO = TRUE, int nCounter = TRUE)
{
object oTargetWep = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
int bNoDisarm = GetHasFeat(FEAT_INTRINSIC_WEAPON, oTarget);
string sName = GetName(oTarget);
if(bNoDisarm)
{
FloatingTextStringOnCreature(sName+" is wielding an intrinsic weapon", oPC, FALSE);
AssignCommand(oPC, ActionAttack(oTarget));
return FALSE;
}
if (!GetIsObjectValid(oTargetWep) || GetPlotFlag(oTargetWep) || (!GetIsCreatureDisarmable(oTarget) && !GetPRCSwitch(PRC_PNP_DISARM)) || GetLocalInt(oTarget, "TigerFangDisarm"))
{
FloatingTextStringOnCreature("Target is not a legal target", oPC, FALSE);
FloatingTextStringOnCreature(sName+" is not a legal target", oPC, FALSE);
AssignCommand(oPC, ActionAttack(oTarget));
return FALSE;
}

View File

@@ -133,6 +133,7 @@ const int METAMAGIC_QUICKEN_LEVEL = 4;
#include "prc_inc_damage"
#include "prc_inc_sb_const" // Spell Book Constants
#include "x0_i0_position"
#include "inc_newspellbook"
/*
access to prc_inc_nwscript via prc_inc_damage

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

@@ -231,6 +231,7 @@ int GetProficiencyFeatOfWeaponType(int iWeaponType)
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;
@@ -304,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;
@@ -375,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;
@@ -446,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;
@@ -517,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;
@@ -588,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;
@@ -659,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;
@@ -730,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;
@@ -796,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;

View File

@@ -431,7 +431,7 @@ void EvalPRCFeats(object oPC)
ExecuteScript("moi_events", oPC);
if (GetIsBinder(oPC))
ExecuteScript("bnd_events", oPC);
ExecuteScript("bnd_events", oPC);
// check if character with crafting feat has appropriate base item in her inventory
// x - moved from prc_onhb_indiv.nss

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

File diff suppressed because it is too large Load Diff

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"
object GetProperTarget(object oPC, object oTarget)
/**
* Finds a valid enemy target in melee range when the original target is invalid.
* Now includes input validation, LOS checks, configurable radius, and target priority.
*
* @param oPC The creature seeking a new target
* @param oTarget The original (invalid) target
* @param fRadius Search radius in meters (optional, defaults to melee range)
* @return A valid enemy target or OBJECT_INVALID if none found
*/
object GetProperTarget(object oPC, object oTarget, float fRadius = MELEE_RANGE_METERS)
{
// Input validation
if(!GetIsObjectValid(oPC))
{
DoDebug("GetProperTarget(): Invalid oPC parameter");
return OBJECT_INVALID;
}
// Use target list system for better target selection
PurgeTargetList(oPC);
location lPC = GetLocation(oPC);
object oTest = MyFirstObjectInShape(SHAPE_SPHERE, fRadius, lPC, TRUE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oTest))
{
// Basic validation checks
if(oTest != oPC && // Not self
GetIsEnemy(oPC, oTest) && // Is enemy
GetIsInMeleeRange(oPC, oTest) && // In melee range
!GetIsDead(oTest) && // Is alive
LineOfSightObject(oPC, oTest)) // Has line of sight
{
// Add to target list with priority based on distance (nearest first)
AddToTargetList(oTest, oPC, INSERTION_BIAS_DISTANCE, FALSE);
}
oTest = MyNextObjectInShape(SHAPE_SPHERE, fRadius, lPC, TRUE, OBJECT_TYPE_CREATURE);
}
// Get the highest priority target (nearest enemy)
object oBestTarget = GetTargetListHead(oPC);
PurgeTargetList(oPC);
if(GetIsObjectValid(oBestTarget))
{
DoDebug("GetProperTarget(): Selected target " + GetName(oBestTarget) +
" for " + GetName(oPC));
return oBestTarget;
}
// No valid target found
DoDebug("GetProperTarget(): No valid target found for " + GetName(oPC));
return OBJECT_INVALID;
}
/* object GetProperTarget(object oPC, object oTarget)
{
location lTarget = GetLocation(oPC);
// Use the function to get the closest creature as a target
@@ -21,7 +80,7 @@ object GetProperTarget(object oPC, object oTarget)
}
return oTarget;
}
} */
void DoNaturalAttack(object oWeapon)
{
@@ -289,59 +348,72 @@ void DoOverflowOnhandAttack(int nAttackMod)
);
}
void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
/* void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
{
//not in combat, abort
if(!GetIsInCombat(oPC))
return;
// if(DEBUG) DoDebug("entered DoNaturalWeaponHB");
if(DEBUG) DoDebug("prc_inc_nat_hb: entered DoNaturalWeaponHB");
float fDelay = 0.1 + IntToFloat(Random(10))/100.0;
//no natural weapons, abort
//in a different form, abort for now fix it later
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
&& !GetIsPolyMorphedOrShifted(oPC))
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
&& !GetIsPolyMorphedOrShifted(oPC))
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creature has natural secondary weapons");
UpdateSecondaryWeaponSizes(oPC);
int i;
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
{
// DoDebug("DoNaturalWeaponHB: creature has natural secondary weapons");
UpdateSecondaryWeaponSizes(oPC);
int i;
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
if(sResRef != "")
{
//get the resref to use
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
//if null, move to next
if(sResRef != "")
// Get stored weapon object, or create if doesn't exist
object oWeapon = GetLocalObject(oPC, "NAT_SEC_WEAP_" + sResRef);
if(!GetIsObjectValid(oWeapon))
{
//get the created item
object oWeapon = GetObjectByTag(sResRef);
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creating and storing creature weapon " + sResRef);
oWeapon = CreateItemOnObject(sResRef, oPC);
if(!GetIsObjectValid(oWeapon))
{
object oLimbo = GetObjectByTag("HEARTOFCHAOS");
location lLimbo = GetLocation(oLimbo);
if(!GetIsObjectValid(oLimbo))
lLimbo = GetStartingLocation();
oWeapon = CreateObject(OBJECT_TYPE_ITEM, sResRef, lLimbo);
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: ERROR - CreateItemOnObject FAILED for " + sResRef);
}
else
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: SUCCESS - weapon created, tag=" + GetTag(oWeapon) + ", name=" + GetName(oWeapon));
SetIdentified(oWeapon, TRUE);
SetLocalObject(oPC, "NAT_SEC_WEAP_" + sResRef, oWeapon);
}
}
else
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: using stored creature weapon object");
}
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
//do the attack within a delay
/*
// motu99: commented this out; AssignCommand ist not needed, because OBJECT_SELF is oPC - using AssignCommand will only degrade performance
AssignCommand(oPC, DelayCommand(fDelay, DoNaturalAttack(oWeapon)));
*/
// Double-check validity before scheduling
if(GetIsObjectValid(oWeapon))
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
DelayCommand(fDelay, DoNaturalAttack(oWeapon));
//calculate the delay to use next time
fDelay += 2.05;
if(fDelay > 6.0)
fDelay -= 6.0;
fDelay -= 6.0;
}
else
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: ERROR - weapon object is INVALID, cannot schedule attack");
}
i++;
}
i++;
}
}
int iMod = 5; // motu99: added check for monk weapon
if(GetHasMonkWeaponEquipped(oPC)) iMod = 3;
@@ -357,10 +429,10 @@ void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
for(i = 0; i < nOverflowAttackCount; i++)
{
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted overflow attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
/*
// motu99: see comment above why this is commented out
AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
*/
//AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty));
//calculate the delay to use
@@ -399,6 +471,128 @@ void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
}
}
}
*/
void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
{
//not in combat, abort
if(!GetIsInCombat(oPC))
return;
if(DEBUG) DoDebug("prc_inc_nat_hb: entered DoNaturalWeaponHB");
float fDelay = 0.1 + IntToFloat(Random(10))/100.0;
//no natural weapons, abort
//in a different form, abort for now fix it later
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
&& !GetIsPolyMorphedOrShifted(oPC))
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creature has natural secondary weapons");
UpdateSecondaryWeaponSizes(oPC);
int i;
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
{
//get the resref to use
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
//if null, move to next
if(sResRef != "")
{
//get the created item
object oWeapon = GetObjectByTag(sResRef);
if(!GetIsObjectValid(oWeapon))
{
object oLimbo = GetObjectByTag("HEARTOFCHAOS");
location lLimbo = GetLocation(oLimbo);
if(!GetIsObjectValid(oLimbo))
lLimbo = GetStartingLocation();
oWeapon = CreateObject(OBJECT_TYPE_ITEM, sResRef, lLimbo);
DoDebug(PRC_TEXT_WHITE + "prc_inc_nat_hb >> DoNaturalWeaponHB: creature weapon object found!!!");
}
// Check for enhancements after creating the weapon object
int nEnhance = GetLocalInt(oPC, "PRC_NAT_WEAPON_ENHANCE");
if(nEnhance > 0)
{
DoDebug(PRC_TEXT_WHITE + "prc_inc_nat_hb >> DoNaturalWeaponHB: Applying enhancement.");
float fDuration = GetLocalFloat(oPC, "PRC_NAT_WEAPON_ENH_DUR");
IPSafeAddItemProperty(oWeapon, ItemPropertyEnhancementBonus(nEnhance), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
}
if(DEBUG) DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
//do the attack within a delay
// motu99: commented this out; AssignCommand ist not needed, because OBJECT_SELF is oPC - using AssignCommand will only degrade performance
//AssignCommand(oPC, DelayCommand(fDelay, DoNaturalAttack(oWeapon)));
DelayCommand(fDelay, DoNaturalAttack(oWeapon));
//calculate the delay to use next time
fDelay += 2.05;
if(fDelay > 6.0)
fDelay -= 6.0;
}
i++;
}
}
int iMod = 5; // motu99: added check for monk weapon
if(GetHasMonkWeaponEquipped(oPC)) iMod = 3;
// check for overflow (main hand) attacks
int nOverflowAttackCount = GetLocalInt(oPC, "OverflowBaseAttackCount");
if(nOverflowAttackCount)
{
int i;
// the first overflow attack would be the seventh main hand attack, at an AB of -30
int nAttackPenalty = -6 * iMod; // -30 for normal bab, -18 for monks
// DoDebug("DoNaturalWeaponHB(): number of scripted overflow attacks: "+IntToString(nOverflowAttackCount));
for(i = 0; i < nOverflowAttackCount; i++)
{
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted overflow attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
// motu99: see comment above why this is commented out
// AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty));
//calculate the delay to use
fDelay += 2.05;
if(fDelay > 6.0)
fDelay -= 6.0;
//calculate new attack penalty
nAttackPenalty -= iMod; // motu99: usually -5, for monks -3 (unarmed or kama)
}
}
// motu99: this is only here for debugging in order to test PerformAttackRound()
// must be deleted after debugging!!!
//if (GetPRCSwitch(PRC_PNP_TRUESEEING)) DelayCommand(0.01, DoOffhandAttackRound());
// check for overflow offhand attacks
int nOffhandAttackCount = GetLocalInt(oPC, "OffhandOverflowAttackCount");
// if (DEBUG) DoDebug("DoNaturalWeaponHB: number of scripted offhand attacks = "+IntToString(nOffhandAttackCount));
if(nOffhandAttackCount)
{
int i;
int nAttackPenalty = -2 * iMod; // offhand attacks always come at -5 per additional attack (but for monks we assume -3)
for(i = 0; i < nOffhandAttackCount; i++)
{
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted offhand attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
DelayCommand(fDelay, DoOffhandAttack(nAttackPenalty));
//calculate the delay to use
fDelay += 2.05;
if(fDelay > 6.0)
fDelay -= 6.0;
//calculate new attack penalty
nAttackPenalty -= iMod;
}
}
}
/*
* motu99's test functions. Not actually used by PRC scripts

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

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

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

@@ -363,8 +363,11 @@ int PRCIsFlying(object oCreature)
bFlying = TRUE;
}
if(!bFlying
&& ((nWings > 0 && nWings < 79) || nWings == 90))//CEP and Project Q wing models
bFlying = TRUE;
&& ((nWings > 0 && nWings < 79)
|| (nWings > 1959 && nWings < 1962)
|| (nWings > 1962 && nWings < 1966)
|| nWings == 90))//CEP and Project Q wing models
bFlying = TRUE;
if (GetHasSpellEffect(MOVE_SH_BALANCE_SKY, oCreature))
bFlying = TRUE;

View File

@@ -1011,11 +1011,16 @@ int PRCMySavingThrow(int nSavingThrow, object oTarget, int nDC, int nSaveType =
// Plague Resistant gives a +4 bonus on disease saves
if(GetHasFeat(FEAT_PLAGUE_RESISTANT, oTarget))
nDC -= 4;
// Racial +2 vs disease saves
if(GetHasFeat(FEAT_RACE_HARDINESS_VS_DISEASE, oTarget))
nDC -= 2;
// +4/+2 bonus on saves against disease, done here
if(GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oTarget) > 13)
nDC -= 4;
else if(GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oTarget) > 3)
nDC -= 2;
}
else if(nSaveType == SAVING_THROW_TYPE_POISON)
{

View File

@@ -70,13 +70,13 @@
43 PRC_CRAFTING_BASE_ITEMS int 1
44 PRC_XP_USE_SIMPLE_LA int 1
45 PRC_XP_USE_SIMPLE_RACIAL_HD int 1
46 PRC_CREATE_INFUSION_CASTER_LEVEL int 1
47 PRC_CREATE_INFUSION_OPTIONAL_HERBS int 0
46 PRC_CREATE_INFUSION_CASTER_LEVEL int 1
47 PRC_CREATE_INFUSION_OPTIONAL_HERBS int 0
*/
/* This variable MUST be updated with every new version of the PRC!!! */
const string PRC_VERSION = "PRC 3.9.0";
const string PRC_VERSION = "PRC8 4.76";
/* This variable MUST be updated every time 'assemble_spellbooks.bat' is run!!! */
@@ -91,11 +91,11 @@
* This allows material components in NWN through the materialcomp.2da
* Just put the SpellID and UTC resref in, MINUS the .utc on the end.
* This also requires the names of the items, formatted like so ("" included): "Object Name"
*
*
* Set switch to 2 to activate this
* Deducts gold instead of requiring material components
* Put the gold value in the Cost column
* Set switch to 3 to activate both at the same time
* WARNING: This will slow spellcasting down due to 2da reads and inventory loops
*/
@@ -129,7 +129,7 @@ const string PRC_BIOWARE_NEUTRALIZE_POISON = "PRC_BIOWARE_NEUTRALIZE_P
/** Remove the cap PRC added to this spell */
const string PRC_BIOWARE_REMOVE_DISEASE = "PRC_BIOWARE_REMOVE_DISEASE";
/**
/**
* This replaces the 3.0 Spell Focus bonuses with the 3.5 edition ones
*/
const string PRC_35_SPELL_FOCUS = "PRC_35_SPELL_FOCUS";
@@ -263,8 +263,8 @@ const string PRC_165_DEATH_IMMUNITY = "PRC_165_DEATH_IMMUNITY";
/*
* PRC_ACTIVATE_MAX_SPELL_DC_CAP: activate a max cap on DC casted by creature/player
* PRC_SET_MAX_SPELL_DC_CAP: the max value ex: 99
*
* PRC_SET_MAX_SPELL_DC_CAP: the max value ex: 99
*
*/
const string PRC_ACTIVATE_MAX_SPELL_DC_CAP = "PRC_ACTIVATE_MAX_SPELL_DC_CAP";
const string PRC_SET_MAX_SPELL_DC_CAP = "PRC_SET_MAX_SPELL_DC_CAP";
@@ -291,8 +291,8 @@ const string PRC_DC_BASE_OVERRIDE = "PRC_DC_BASE_OVERRIDE";
const string PRC_DC_ADJUSTMENT = "PRC_DC_ADJUSTMENT";
/*
* By default when calculating caster level for characters with PrCs, the highest class rule will
* be used (ie. Bard 2/Wizard 4/Elemental Savant 6 - Wizard is the highest arcane class so levels
* By default when calculating caster level for characters with PrCs, the highest class rule will
* be used (ie. Bard 2/Wizard 4/Elemental Savant 6 - Wizard is the highest arcane class so levels
* form PrC will be added to that class, and the caster level will be 2 for Bard and 10 for Wizard).
* When this is set, the first class rule will be used (with the same character caster level would
* be 8 for Bard and 4 for Wizard).
@@ -572,12 +572,12 @@ const string PRC_SOUL_EATER_MAX_SLAVES = "PRC_SOUL_EATER_MAX_SLAVES";
* For the Psionic Slayer prestige class, this switch limits the Favored Enemy selection
* to the Aberration racial type.
*
* This switch is provided to allow builders to more closely represent the Pen and Paper
* This switch is provided to allow builders to more closely represent the Pen and Paper
* Illithid Slayer class, instead of the broader Open Game License "Slayer" class.
*
* Type: Int
* Type: Int
* Values: 0 [Default] (Favored Enemy racial type is not limited)
* 1 (Favored Enemy race is limited to Aberration only)
* 1 (Favored Enemy race is limited to Aberration only)
*/
const string PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY = "PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY";
@@ -585,20 +585,20 @@ const string PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY = "PRC_PSIONIC_S
* For the Psionic Slayer prestige class, this switch requires a character to make a "kill"
* of a specific type of creature before the class becomes available.
*
* Use of this switch requires that the module builder add a "Psionic Slayer Kill Token"
* (included in the PRC Items) to the designated creature.
* Use of this switch requires that the module builder add a "Psionic Slayer Kill Token"
* (included in the PRC Items) to the designated creature.
*
* Alternately, a script or item can be made that will run the script "prc_psysly_killt"
* Alternately, a script or item can be made that will run the script "prc_psysly_killt"
* on the PC. This script will set the flag that allows the target PC to take the Psionic Slayer Class.
* Example code:
* ExecuteScript("prc_psysly_killt", oPC); // Where oPC is an player charcter object
* Example code:
* ExecuteScript("prc_psysly_killt", oPC); // Where oPC is an player charcter object
*
* This switch is provided to allow builders to more closely represent the Pen and Paper
* This switch is provided to allow builders to more closely represent the Pen and Paper
* Illithid Slayer class, instead of the broader Open Game License "Slayer" class.
*
* Type: Int
* Type: Int
* Values: 0 [Default] (Kill Token / Script NOT required for taking the Psionic Slayer Class)
* 1 (Kill Token / Script REQUIRED before the Psionic Slayer Class is available to take)
* 1 (Kill Token / Script REQUIRED before the Psionic Slayer Class is available to take)
*/
const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN";
@@ -607,19 +607,19 @@ const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_R
* By default the Werewolf class uses the Bioware Polymorph effect to perfrom its
* Hybrid Form Shapchange.
*
* This switch allows the Werewolf class to be toggled to use the PRC Shifter
* Shapchange code instead.
* This switch allows the Werewolf class to be toggled to use the PRC Shifter
* Shapchange code instead.
*
* Type: Int
* Type: Int
* Values: 0 [Default] (Werewolf Hybrid Shapchange uses Bioware Polymorph)
* 1 (Werewolf Hybrid Shapchange uses PRC Shifter shape change code)
* 1 (Werewolf Hybrid Shapchange uses PRC Shifter shape change code)
*/
const string PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE = "PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE";
const string PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE = "PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE";
/**
* Sets the max bonus for the PnP Shifter shifting systems
*
* Type: Int
* Type: Int
* Values: any greater than 0
*/
const string PRC_PNP_SHIFTER_BONUS = "PRC_PNP_SHIFTER_BONUS";
@@ -783,7 +783,7 @@ const string PRC_STAFF_CASTER_LEVEL = "PRC_STAFF_CASTER_LEVEL";
/**
* [DEFUNCT]
* A wand must be equipped before it can cast a spell
*
*
* Any value above 0 turns off the requirement to have a wand equipped to use it
*
* This switch is defunct, wands must *always* be equipped to use them.
@@ -931,7 +931,7 @@ const string PRC_PNP_FAMILIAR_FEEDING = "PRC_PNP_FAMILIAR_FEEDING
/**
* Use PRC henchmen-familiars instead of BioWare's - this will allow
* new classes to have familiars, but summoned creatures will no longer
* new classes to have familiars, but summoned creatures will no longer
* be 'true' familiars (ie. can't possess PRC familiar)
*/
const string PRC_FAMILIARS = "PRC_FAMILIARS";
@@ -1114,7 +1114,7 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
* Disable registration of custom cohorts
*/
const string PRC_DISABLE_REGISTER_COHORTS = "PRC_DISABLE_REGISTER_COHORTS";
/*
* Disable cohorts starting with gear
*/
@@ -1144,19 +1144,19 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
* Medium armor is a 25% speed reduction, Heavy is a 33% reduction
*/
const string PRC_PNP_ARMOR_SPEED = "PRC_PNP_ARMOR_SPEED";
/*
* Applies a 99% speed boost when out of combat
* Warning that it will likely cause PCs to be overly speedy when combat starts
* Potential problem causer
*/
const string PRC_FAST_TRAVEL_SPEED = "PRC_FAST_TRAVEL_SPEED";
/*
* Applys a Discipline bonus equal to BAB to all characters if turned on
* Bonus only applies to characters with 0 ranks in Discipline
*/
const string PRC_PNP_KNOCKDOWN = "PRC_PNP_KNOCKDOWN";
const string PRC_PNP_KNOCKDOWN = "PRC_PNP_KNOCKDOWN";
/*
* by Bioware rules, PCs have approximatly a 7th faster movement than NPCs
@@ -1204,8 +1204,11 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
*/
const string PRC_APPEARNCE_CHANGE_DISABLE = "PRC_APPEARNCE_CHANGE_DISABLE";
/*
* Allow "Monk" gloves to merge with a creature weapons when Wildshaped.
* Will also merge bracers with creature hides when Wildshaped.
*/
const string PRC_WILDSHAPE_ALLOWS_ARMS_SLOT = "PRC_WILDSHAPE_ALLOWS_ARMS_SLOT";
/******************************************************************************\
* Death/Bleeding system *
@@ -1223,7 +1226,7 @@ const string PRC_PNP_DEATH_ENABLE = "PRC_PNP_DEATH_ENA
* if FALSE, dont bleed just die
* By PnP this would be 1 round, or 6 seconds
*/
const string PRC_DEATH_OR_BLEED = "PRC_DEATH_OR_BLEED";
const string PRC_DEATH_OR_BLEED = "PRC_DEATH_OR_BLEED";
/*
* Damage when bleeding
@@ -1316,7 +1319,7 @@ const string PRC_ACP_DELAY = "PRC_ACP_DELAY";
/******************************************************************************
* File End switches
* File End switches
******************************************************************************/
/**
@@ -1490,10 +1493,10 @@ const string PRC_POISON_IS_FOOD_SCRIPT_NAME = "PRC_POISON_IS_FOOD_SCRIP
const string PRC_POISON_ALLOW_CLEAN_IN_EQUIP = "PRC_POISON_ALLOW_CLEAN_IN_EQUIP";
/**
*
*
* Default: crafting requires only gold and xp
*/
const string PRC_CRAFT_POISON_USE_INGREDIENST = "PRC_CRAFT_POISON_USE_INGREDIENST";
const string PRC_CRAFT_POISON_USE_INGREDIENTS = "PRC_CRAFT_POISON_USE_INGREDIENTS";
/******************************************************************************\
* PRGT system switches *
@@ -1542,10 +1545,10 @@ const string PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD = "PRC_PSI_ASTRAL_CONSTRUCT
/**
* If this is set, The Astral Seed power will attempt to use the provided string as
* the ResRef to create the Astral Seed object instead of the of the phylactery
* the ResRef to create the Astral Seed object instead of the of the phylactery
* ResRef("x2_plc_phylact").
* May be used by builders to create an object that CAN be destroyed, or has other traits,
* as desired.
* as desired.
* Type: String
* Values: "" [Default] (Blank, or not set: Use default phylactery ResRef for Astral Seed)
* STRING (Entered String will be used as the ResRef of created Astral Seed object)
@@ -1553,14 +1556,14 @@ const string PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD = "PRC_PSI_ASTRAL_CONSTRUCT
const string PRC_PSI_ASTRAL_SEED_RESREF = "PRC_PSI_ASTRAL_SEED_RESREF";
/**
* By default the Astral Seed power respawns the player, and then makes them immobile for
* By default the Astral Seed power respawns the player, and then makes them immobile for
* 24-game-hours.
* If this switch is set, it will adjust the imobility time period; shortening it, lengthing it, or
* If this switch is set, it will adjust the imobility time period; shortening it, lengthing it, or
* effectively eliminating it.
* Type: Int
* Values: 0 [Default] (Not set: Use default 24 hour duration)
* -1 (Any negative value will result in a fixed duratoion of 2 seconds, which effectively eliminates the wait period)
* 1 (Any potitive value: multiply duration by the value provided and then divide result by 1000.
* 1 (Any potitive value: multiply duration by the value provided and then divide result by 1000.
* Values less than 1000 will shorten the duration, values higher than 1000 will lengthen it.)
*/
const string PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000 = "PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000";
@@ -1571,7 +1574,7 @@ const string PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000 = "PRC_PSI_ASTRAL_SE
* If this flag is set, the XP loss is completely eliminated. The standard PRC event hook script
* of "prc_pw_astralseed" may be used to script any additional effects to occure upon Astral Seed
* respawning, including scripting specific XP loss amount.
* Type: Int
* Type: Int
* Values: 0 [Default] (Not set: lose 1 level worth of XP upon Astral Seed respawn)
* 1 (Any potitive value: Remove all XP loss from Astral Seed respawn)
*/
@@ -1908,7 +1911,7 @@ const string PRC_CRAFT_TIMER_MAX = "PRC_CRAFT_TIMER_MAX";
*/
const string PRC_CRAFT_TIMER_MIN = "PRC_CRAFT_TIMER_MIN";
/**
/*
* These three switches modify Bioware crafting so that the items produced have the
* casterlevel of the spellcaster who created them. Normally under Bioware, it is possible
* for a level 3 caster to produce level 9 items and for a level 40 caster to only produce
@@ -1955,16 +1958,21 @@ const string PRC_CRAFT_ROD_CASTER_LEVEL = "PRC_CRAFT_ROD_CASTER_LEVE
const string PRC_CRAFT_STAFF_CASTER_LEVEL = "PRC_CRAFT_STAFF_CASTER_LEVEL";
/*
* As above, except it applies to herbal infusions
* As above, except it applies to scepters
*/
const string PRC_CREATE_INFUSION_CASTER_LEVEL = "PRC_CREATE_INFUSION_CASTER_LEVEL";
const string PRC_CRAFT_SCEPTER_CASTER_LEVEL = "PRC_CRAFT_SCEPTER_CASTER_LEVEL";
/*
* Builder's Option: Enables the optional PnP herbs for creating infusions.
* As above, except it applies to herbal infusions
*/
const string PRC_CREATE_INFUSION_CASTER_LEVEL = "PRC_CREATE_INFUSION_CASTER_LEVEL";
/*
* Builder's Option: Enables the optional PnP herbs for creating infusions.
* Each herb is keyed to a spell circle level & spell school as shown on pg. 33
* of the Master's of the Wild sourcebook.
*/
const string PRC_CREATE_INFUSION_OPTIONAL_HERBS = "PRC_CREATE_INFUSION_OPTIONAL_HERBS";
const string PRC_CREATE_INFUSION_OPTIONAL_HERBS = "PRC_CREATE_INFUSION_OPTIONAL_HERBS";
/*
* Characters with a crafting feat always have the appropriate base item in their inventory
@@ -2015,6 +2023,13 @@ const string PRC_X2_CRAFTWAND_COSTMODIFIER = "PRC_X2_CRAFTWAND_COSTMO
*/
const string PRC_X2_CRAFTROD_COSTMODIFIER = "PRC_X2_CRAFTROD_COSTMODIFIER";
/*
* cost modifier of spells crafted into scepters
* note that adding a second spell costs 75%
* defaults to 750
*/
const string PRC_X2_CRAFTSCEPTER_COSTMODIFIER = "PRC_X2_CRAFTSCEPTER_COSTMODIFIER";
/*
* cost modifier of spells crafted into staffs
* note that adding a second spell costs 75% and 3 or more costs 50%
@@ -2342,7 +2357,7 @@ const string PRC_XP_GIVE_XP_TO_NPCS = "PRC_XP_GIVE_XP_TO_NPCS";
/**
* Setting this switch will turn off the messages about being too far awy to gain XP
*/
const string PRC_XP_DISABLE_SPAM = "PRC_XP_DISABLE_SPAM";
const string PRC_XP_DISABLE_SPAM = "PRC_XP_DISABLE_SPAM";
/**
* PCs must be in the same area as the CR to gain XP.
@@ -2901,13 +2916,13 @@ const string PRC_PERFECTED_MAP_MULTIPLIER = "PRC_PERFECTED_MAP_MULTIP
\******************************************************************************/
/**
* Sets how many seconds it takes to contact a vestige.
* Sets how many seconds it takes to contact a vestige.
* Any number less than 6 is ignored
*/
const string PRC_CONTACT_VESTIGE_TIMER = "PRC_CONTACT_VESTIGE_TIMER";
/**
* Sets how many seconds it takes to bind a vestige.
* Sets how many seconds it takes to bind a vestige.
* Any number less than 12 is ignored
*/
const string PRC_BIND_VESTIGE_TIMER = "PRC_BIND_VESTIGE_TIMER";
@@ -2941,6 +2956,20 @@ const string PRC_PW_SECURITY_CD_CHECK = "PRC_PW_SECURITY_CD_CHECK";
*/
const string PRC_DEBUG = "PRC_DEBUG";
/******************************************************************************\
* Duration NUI Switches *
\******************************************************************************/
/**
* Toggles allowing player to remove friendly PC spells on player through Duration NUI
* instead of just their own spells.
*/
const string PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS = "PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS";
/**
* Toggles allowing players to see the duration of hostile spells on them.
*/
const string PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS = "PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS";

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,12 +269,169 @@ void ApplyUnarmedAttackEffects(object oCreature)
}
// Determines the amount of damage a character can do.
// IoDM: +1 dice at level 4, +2 dice at level 8
// IoDM: +1 die at level 4, +2 dice at level 8
// Sacred Fist: Levels add to monk levels, or stand alone as monk levels.
// Shou: 1d6 at level 1, 1d8 at level 2, 1d10 at level 3, 2d6 at level 5
// Monk: 1d6 at level 1, 1d8 at level 4, 1d10 at level 8, 2d6 at level 12, 2d8 at level 16, 2d10 at level 20
// Frostrager: 1d6 at level 1, 1d8 at level 4
int FindUnarmedDamage(object oCreature)
{
int iDamage = 0;
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
int iShou = GetLevelByClass(CLASS_TYPE_SHOU, oCreature);
int iBrawler = GetLevelByClass(CLASS_TYPE_BRAWLER, oCreature);
int iSacredFist = GetLevelByClass(CLASS_TYPE_SACREDFIST, oCreature);
int iEnlightenedFist = GetLevelByClass(CLASS_TYPE_ENLIGHTENEDFIST, oCreature);
int iHenshin = GetLevelByClass(CLASS_TYPE_HENSHIN_MYSTIC, oCreature);
int iZuoken = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oCreature);
int iShadowSunNinja = GetLevelByClass(CLASS_TYPE_SHADOW_SUN_NINJA, oCreature);
int iFrost = GetLevelByClass(CLASS_TYPE_FROSTRAGER, oCreature);
int iAscetic = GetLevelByClass(CLASS_TYPE_NINJA, oCreature);
int iRonove = 0;
int iMonkDamage = 1;
int iShouDamage = 1;
int iBrawlerDamage = 1;
int iFrostDamage = 1;
int iSUSDamage = 1;
int iDieIncrease = 0;
int iSize;
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature))
iRonove = GetLocalInt(oCreature, "RonovesFists");
//:: Determine creature size
if( GetIsPolyMorphedOrShifted(oCreature) || GetPRCSwitch(PRC_APPEARANCE_SIZE))
{
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5;
}
else
{
iSize = 5; // medium
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
if (iSize < 1) iSize = 1;
if (iSize > 9) iSize = 9;
}
// Sacred Fist code break protection
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
// Combine monk-like levels
iMonk += iSacredFist + iHenshin + iEnlightenedFist + iShou + iZuoken + iShadowSunNinja;
// Superior Unarmed Strike
if (GetHasFeat(FEAT_SUPERIOR_UNARMED_STRIKE, oCreature))
{
iMonk += 4;
int nHD = GetHitDice(oCreature);
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
else if (nHD >= 12) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d10;
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
}
// Ascetic Stalker
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
iMonk += iAscetic;
// Cap monk progression
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE)) iMonk = 16;
else if (iMonk > 20) iMonk = 20;
// Ronove replacement
if (iRonove > iMonk) iMonk = iRonove;
// Monk damage calculation (2DA row)
if (iMonk > 0) iMonkDamage = iMonk / 4 + 3;
if (iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
iMonkDamage = 8;
// Shou Disciple base damage
if (iShou > 0)
{
int nRow;
if (iShou == 1) nRow = 3;
else if (iShou == 2) nRow = 4;
else if (iShou == 3) nRow = 5;
else if (iShou == 4) nRow = 5;
else if (iShou == 5) nRow = 6;
else nRow = 3;
if (nRow > 6) nRow = 6;
iShouDamage = StringToInt(Get2DACache("unarmed_dmg", "size" + IntToString(iSize), nRow));
}
// Frostrager
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6;
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8;
// Brawler
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3;
if (iBrawler >= 36) iBrawlerDamage += 2;
// Armor/shield penalties
if (iMonkDamage > 1)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 0 || bShieldEq)
iMonkDamage = 1;
}
if (iShouDamage > 1)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 3 || bShieldEq)
iShouDamage = 1;
}
// Determine IoDM die increase
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
// Lookup monk damage in 2DA
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
// 3.0e monk special cases
if (iSize <= 5 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
{
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d6) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d12;
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d10) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d20;
}
// Apply IoDM die increase last, after 2DA lookups
if (iMonkDamage > 0) iMonkDamage = StepDie(iMonkDamage, iDieIncrease);
if (iShouDamage > 0) iShouDamage = StepDie(iShouDamage, iDieIncrease);
if (iBrawlerDamage > 0) iBrawlerDamage = StepDie(iBrawlerDamage, iDieIncrease);
if (iFrostDamage > 0) iFrostDamage = StepDie(iFrostDamage, iDieIncrease);
if (iSUSDamage > 0) iSUSDamage = StepDie(iSUSDamage, iDieIncrease);
// Select best damage
iDamage = iMonkDamage;
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
iDamage = (DamageAvg(iBrawlerDamage) > DamageAvg(iDamage)) ? iBrawlerDamage : iDamage;
if (DEBUG) DoDebug("prc_inc_unarmed: iDamage "+IntToString(iDamage));
return iDamage;
}
/* int FindUnarmedDamage(object oCreature)
{
int iDamage = 0;
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
@@ -195,36 +453,30 @@ int FindUnarmedDamage(object oCreature)
int iDieIncrease = 0;
int iSize;
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature)) iRonove = GetLocalInt(oCreature, "RonovesFists");
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature))
iRonove = GetLocalInt(oCreature, "RonovesFists");
// if the creature is shifted, use model size
// otherwise, we want to stick to what the feats say they "should" be.
// No making pixies with Dragon Appearance for "huge" fist damage.
if( GetIsPolyMorphedOrShifted(oCreature)
|| GetPRCSwitch(PRC_APPEARANCE_SIZE))
// Determine creature size
if( GetIsPolyMorphedOrShifted(oCreature) || GetPRCSwitch(PRC_APPEARANCE_SIZE))
{
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5; // medium is size 5 for us
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5;
}
else
{
// Determine creature size by feats.
iSize = 5; // medium is size 5 for us
iSize = 5; // medium
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
// include size changes
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
// cap if needed
if (iSize < 1) iSize = 1;
if (iSize > 9) iSize = 9;
}
// Sacred Fist cannot add their levels if they've broken their code.
// Sacred Fist code break protection
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
// several classes add their levels to the monk class,
// or use monk progression if the character has no monk levels
// Combine monk-like levels
iMonk += iSacredFist + iHenshin + iEnlightenedFist + iShou + iZuoken + iShadowSunNinja;
// Superior Unarmed Strike
@@ -232,49 +484,66 @@ int FindUnarmedDamage(object oCreature)
{
iMonk += 4;
int nHD = GetHitDice(oCreature);
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
else if (nHD >= 12) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d10;
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
}
// Ascetic Stalker
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
iMonk += iAscetic;
// In 3.0e, Monk progression stops after level 16:
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE) ) iMonk = 16;
// in 3.5e, monk progression stops at 20.
else if(iMonk > 20) iMonk = 20;
// Cap monk progression
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE)) iMonk = 16;
else if (iMonk > 20) iMonk = 20;
// Ronove is in place of monk, does not stack
// Ronove replacement
if (iRonove > iMonk) iMonk = iRonove;
// monks damage progesses every four levels, starts at 1d6
if (iMonk > 0)
iMonkDamage = iMonk / 4 + 3;
// Monk damage calculation
if (iMonk > 0) iMonkDamage = iMonk / 4 + 3;
// For medium monks in 3.0e skip 2d8 and go to 1d20
if(iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE) ) iMonkDamage = 8;
if(iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
iMonkDamage = 8;
// Shou Disciple either adds its level to existing class or does its own damage, depending
// on which is better. Here we will determine how much damage the Shou Disciple does
// without stacking.
if (iShou > 0) iShouDamage = iShou + 2; // Lv. 1: 1d6, Lv. 2: 1d8, Lv. 3: 1d10
if (iShou > 3) iShouDamage--; // Lv. 4: 1d10, Lv. 5: 2d6
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
// Frostrager does not stack with other damage types
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6; // Lv. 1: 1d6
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8; // Lv. 3: 1d8
//if (iShou > 0) iShouDamage = iShou + 2; // Lv. 1: 1d6, Lv. 2: 1d8, Lv. 3: 1d10
//if (iShou > 3) iShouDamage--; // Lv. 4: 1d10, Lv. 5: 2d6
//iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
if (iShou > 0)
{
// Determine 2DA row for Shou progression
int nRow;
if (iShou == 1) nRow = 3; // monk1
else if (iShou == 2) nRow = 4; // monk2
else if (iShou == 3) nRow = 5; // monk3
else if (iShou == 4) nRow = 6; // monk4
else if (iShou == 5) nRow = 7; // monk5
else if (iShou == 6) nRow = 8; // monk6
else if (iShou == 7) nRow = 9; // monk7
else nRow = 10; // monk8+
nRow += iDieIncrease;
if (nRow > 10) nRow = 10; // clamp to max row
// Brawler follows monk progression except for the last one (3d8)
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3; // 1d6, 1d8, 1d10, 2d6, 2d8, 2d10
if (iBrawler >= 36) iBrawlerDamage += 2; // 3d8
// Lookup damage in unarmed_damage.2da using size column
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), nRow));
}
// Monks and monk-like classes deal no additional damage when wearing any armor, at
// least in NWN. This is to reflect that. No shields too.
// Frostrager
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6;
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8;
// Brawler
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3;
if (iBrawler >= 36) iBrawlerDamage += 2;
// Armor/shield penalties
if (iMonkDamage > 1)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
@@ -284,13 +553,10 @@ int FindUnarmedDamage(object oCreature)
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 0 || bShieldEq)
{
iMonkDamage = 1;
}
}
// Shou Disciples can wear light armor
if (iShouDamage > 1)
if (iShouDamage > 1)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
@@ -299,53 +565,31 @@ int FindUnarmedDamage(object oCreature)
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 3 || bShieldEq)
{
iShouDamage = 1;
}
iShouDamage = 1;
}
// For Initiate of Draconic Mysteries
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
/* //:: Expansion / Compression powers (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;
iBrawlerDamage += iDieIncrease;
iFrostDamage += iDieIncrease;
iSUSDamage += iDieIncrease;
//FloatingTextStringOnCreature("prc_inc_unarmed: Size is: "+IntToString(iSize)+".", oCreature);
//FloatingTextStringOnCreature("prc_inc_unarmed: Pre 2DA Lookup >> iMonkDamage = "+IntToString(iMonkDamage)+".", oCreature);
// now, read the damage from the table in unarmed_dmg.2da
// Lookup final monk damage in 2DA
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
//FloatingTextStringOnCreature("prc_inc_unarmed: Post 2DA Lookup >> iMonkDamage = "+IntToString(iMonkDamage)+".", oCreature);
// Medium+ monks have some special values on the table in 3.0:
// 3.0e monk special cases
if (iSize >= 5 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
{
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d6) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d12;
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d10) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d20;
}
// Select best damage
iDamage = iMonkDamage;
// Future unarmed classes: if you do your own damage, add in "comparisons" below here.
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
@@ -354,6 +598,8 @@ int FindUnarmedDamage(object oCreature)
return iDamage;
}
*/
// Adds appropriate feats to the skin. Stolen from SoulTaker + expanded with overwhelming/devastating critical.
void UnarmedFeats(object oCreature)
@@ -426,13 +672,13 @@ void UnarmedFists(object oCreature)
// Sacred Fists who break their code get no benefits.
if (GetHasFeat(FEAT_SF_CODE,oCreature)) iSacFist = 0;
// The monk adds all these classes.
int iMonkEq = iMonk + iShou + iSacFist + iHenshin + iZuoken + iShadowSunNinja;
int iMonkEq = iMonk + iShou + iSacFist + iHenshin + iZuoken + iShadowSunNinja;
// Ascetic Stalker
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
iMonkEq += iAscetic;
iMonkEq += iAscetic;
// Determine the type of damage the character should do.
string sWeapType;

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:

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

@@ -156,3 +156,16 @@ const string NUI_SPELL_DESCRIPTION_CLASSID_VAR = "NUISpellDescriptionClassID";
const string NUI_SPELL_DESCRIPTION_SPELLID_VAR = "NUISpellDescriptionSpellID";
const string NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR = "NUISpellDescriptionRealSpellID";
//////////////////////////////////////////////////
// //
// Spell Duration NUI //
// //
//////////////////////////////////////////////////
const string DURATION_NUI_WINDOW_ID = "DurationNUI";
const string NUI_DURATION_MANUALLY_OPENED_PARAM = "DurationNUIManuallyOpenedParam";
const string NUI_DURATION_NO_LOOP_PARAM = "DurationNUINoLoopParam";
const string NUI_DURATION_TRACKED_SPELLS = "durationNUI_trackedSpellList";
const string NUI_SPELL_DURATION_BASE_BIND = "durationNUI_durationSpellId";
const string NUI_SPELL_DURATION_SPELLID_BASE_CANCEL_BUTTON = "NuiDurationCancelButtonSpellID";

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);
@@ -1539,7 +1494,7 @@ int GetRemainingSpellChoices(int nClass, int circleLevel, object oPC=OBJECT_SELF
// default logic for spont casters
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 > 7)
if (nClass == CLASS_TYPE_FAVOURED_SOUL && circleLevel == 0 && totalSpellsKnown > 6)
totalSpellsKnown = 7;
// logic for spont casters
@@ -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;
}
@@ -1664,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);
}
}
}
@@ -1779,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
@@ -1789,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));
@@ -1975,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;
}
}
@@ -2002,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)
@@ -2088,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);
@@ -2322,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)
@@ -2346,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
@@ -2360,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;
@@ -2383,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);
}
}
@@ -2570,7 +2540,7 @@ int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_S
if (chosenDisc != JsonNull())
{
int nManCount = (JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)))
+ JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE))));
+ JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE))));
if (nManCount >= prereqs)
return TRUE;
}
@@ -3166,13 +3136,18 @@ json GetInvokerKnownListObject(int nClass, object oPC=OBJECT_SELF)
}
SetLocalJson(oPC, NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR + IntToString(nClass), knownObject);
if (DEBUG) DoDebug("Printing json representation of allowed invocations for class " + IntToString(nClass));
if (DEBUG) DoDebug(JsonDump(knownObject, 2));
return knownObject;
}
int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJECT_SELF, int extra=TRUE)
{
if (DEBUG) DoDebug ("Getting remaining invocation choices at " + IntToString(chosenCircle) + " circle");
int remaining = 0;
int nLevel = GetInvokerLevel(oPC, nClass);
if (nClass == CLASS_TYPE_DRAGON_SHAMAN) nLevel = GetLevelByClass(nClass, oPC);
if (DEBUG) DoDebug("Invoker level is " + IntToString(nLevel));
json knownObject = GetInvokerKnownListObject(nClass, oPC);
json chosenInv = GetChosenSpellListObject(nClass, oPC);
@@ -3200,8 +3175,10 @@ int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJEC
currentChosen += 1;
}
}
if (DEBUG) DoDebug(IntToString(currentChosen) + " incantations chosen at " + IntToString(chosenCircle) + " circle");
int allowedAtCircle = JsonGetInt(JsonObjectGet(currentLevelKnown, IntToString(i)));
if (DEBUG) DoDebug(IntToString(allowedAtCircle) + " incantations allowed at " + IntToString(chosenCircle) + " circle");
remaining = (allowedAtCircle - currentChosen + remaining);
// if the circle is below the chosen circle and we have a positive remaining,

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

@@ -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;
@@ -1411,6 +1414,10 @@ const int SPELL_FOT_LEONALS_ROAR = 17993;
const int SPELL_FOT_LIONS_SWIFTNESS = 17994;
const int SPELL_FAVORED_OF_THE_COMPANIONS = 17995;
//:: Magic Item Compendium
const int SPELL_AROMA_OF_CURDLED_DEATH = 17987;
const int SPELL_ELIXIR_OF_THE_BEETLE = 17987;
//x
const int SPELL_TENSERS_FLOATING_DISK = 3849;
const int SPELL_WOLFSKIN = 3850;

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
@@ -276,6 +277,7 @@ int CIGetIsCraftFeatBaseItem(object oItem)
nBt == BASE_ITEM_BLANK_WAND ||
nBt == BASE_ITEM_CRAFTED_ROD ||
nBt == BASE_ITEM_CRAFTED_STAFF ||
nBt == BASE_ITEM_CRAFTED_SCEPTER ||
nBt == BASE_ITEM_MUNDANE_HERB)
return TRUE;
else
@@ -302,7 +304,7 @@ object CICraftBrewPotion(object oCreator, int nSpellID )
return OBJECT_INVALID;
}
/* //just a tad retarded, don't you think? other crafting feats are not similarly restricted
/* //just a tad silly, don't you think? other crafting feats are not similarly restricted
//Uses per day
int nUsesAllowed;
@@ -710,6 +712,7 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
return oTarget;
}
*/
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to brew a potion
// -----------------------------------------------------------------------------
@@ -865,7 +868,6 @@ These dont work as IPs since they are hardcoded */
}
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to create a scroll
// -----------------------------------------------------------------------------
@@ -1133,6 +1135,169 @@ These dont work as IPs since they are hardcoded */
return FALSE;
}
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to craft a scepter
// -----------------------------------------------------------------------------
int CICraftCheckCraftScepter(object oSpellTarget, object oCaster, int nSpellID = 0)
{
if(nSpellID == 0) nSpellID = PRCGetSpellId();
int nCasterLevel = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
int bSuccess = TRUE;
int nCount = 0;
itemproperty ip = GetFirstItemProperty(oSpellTarget);
int nMetaMagic = PRCGetMetaMagicFeat();
while(GetIsItemPropertyValid(ip))
{
if(GetItemPropertyType(ip) == ITEM_PROPERTY_CAST_SPELL)
nCount++;
ip = GetNextItemProperty(oSpellTarget);
}
if(nCount >= 2) //:: Scepters are limited to two spells
{
FloatingTextStringOnCreature("* Failure - Too many castspell itemproperties *", oCaster);
return TRUE;
}
if(!GetHasFeat(X2_CI_CRAFTSCEPTER_FEAT_ID, oCaster))
{
FloatingTextStrRefOnCreature(40487, oCaster); // Item Creation Failed - Don't know how to create that type of item
return TRUE; // tried item creation but do not know how to do it
}
if(CIGetIsSpellRestrictedFromCraftFeat(nSpellID, X2_CI_CRAFTSCEPTER_FEAT_ID))
{
FloatingTextStrRefOnCreature(16829169, oCaster); // can not be used with this feat
return TRUE;
}
// Get the base spell level (circle) before metamagic adjustments
int nBaseLevel = CIGetSpellInnateLevel(nSpellID, TRUE);
// Check if spell circle is 7th level or lower
if (nBaseLevel > 7)
{
//FloatingTextStrRefOnCreature(83623, oCaster); // Spell level too high
FloatingTextStringOnCreature("* Failure - scepters can not hold spells higher than level 7", oCaster);
return TRUE;
}
int nLevel = nBaseLevel;
if(GetPRCSwitch(PRC_CRAFT_SCEPTER_CASTER_LEVEL))
{
switch(nMetaMagic)
{
case METAMAGIC_EMPOWER:
nLevel += 2;
break;
case METAMAGIC_EXTEND:
nLevel += 1;
break;
case METAMAGIC_MAXIMIZE:
nLevel += 3;
break;
/* case METAMAGIC_QUICKEN:
nLevel += 1;
break;
case METAMAGIC_SILENT:
nLevel += 5;
break;
case METAMAGIC_STILL:
nLevel += 6;
break;
These dont work as IPs since they are hardcoded */
}
}
int nCostMod = GetPRCSwitch(PRC_X2_CRAFTSCEPTER_COSTMODIFIER);
if(!nCostMod) nCostMod = 750;
int nLvlRow = IPGetIPConstCastSpellFromSpellID(nSpellID);
int nCLevel = StringToInt(Get2DACache("iprp_spells","CasterLvl",nLvlRow));
int nCost = CIGetCraftGPCost(nLevel, nCostMod, PRC_CRAFT_SCEPTER_CASTER_LEVEL);
//discount for second spell
if(nCount+1 == 2)
nCost = (nCost/2);
//takes epic xp costs into account
struct craft_cost_struct costs = GetModifiedCostsFromBase(nCost, oCaster, FEAT_CRAFT_SCEPTER, (nMetaMagic > 0));
if(costs.nGoldCost < 1) costs.nXPCost = 1;
if(costs.nXPCost < 1) costs.nXPCost = 1;
//if(GetGold(oCaster) < nGoldCost) // enough gold?
if (!GetHasGPToSpend(oCaster, costs.nGoldCost))
{
FloatingTextStrRefOnCreature(3786, oCaster); // Item Creation Failed - not enough gold!
return TRUE;
}
int nHD = GetHitDice(oCaster);
int nMinXPForLevel = (nHD * (nHD - 1)) * 500;
int nNewXP = GetXP(oCaster) - costs.nXPCost;
//if (nMinXPForLevel > nNewXP || nNewXP == 0 )
if (!GetHasXPToSpend(oCaster, costs.nXPCost))
{
FloatingTextStrRefOnCreature(3785, oCaster); // Item Creation Failed - Not enough XP
return TRUE;
}
//check spell emulation
if(!CheckAlternativeCrafting(oCaster, nSpellID, costs))
{
FloatingTextStringOnCreature("*Crafting failed!*", oCaster, FALSE);
return TRUE;
}
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellID);
if (nPropID == 0 && nSpellID != 0)
{
FloatingTextStrRefOnCreature(84544,oCaster);
return TRUE;
}
if (nPropID != -1)
{
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpell(nPropID,IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE),oSpellTarget);
if(GetPRCSwitch(PRC_CRAFT_SCEPTER_CASTER_LEVEL))
{
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellCasterLevel(nSpellID, nCasterLevel),oSpellTarget);
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellMetamagic(nSpellID, PRCGetMetaMagicFeat()),oSpellTarget);
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellDC(nSpellID, PRCGetSaveDC(PRCGetSpellTargetObject(), OBJECT_SELF)),oSpellTarget);
}
}
else
bSuccess = FALSE;
if(bSuccess)
{
//TakeGoldFromCreature(nGoldCost, oCaster, TRUE);
//SetXP(oCaster, nNewXP);
SpendXP(oCaster, costs.nXPCost);
SpendGP(oCaster, costs.nGoldCost);
//DestroyObject (oSpellTarget);
FloatingTextStrRefOnCreature(8502, oCaster); // Item Creation successful
//advance time here
if(!costs.nTimeCost) costs.nTimeCost = 1;
AdvanceTimeForPlayer(oCaster, RoundsToSeconds(costs.nTimeCost));
string sName;
sName = GetName(oCaster)+"'s Magic Scepter";
SetItemCharges(oSpellTarget, 50);
//sName = Get2DACache("spells", "Name", nID);
//sName = "Wand of "+GetStringByStrRef(StringToInt(sName));
SetName(oSpellTarget, sName);
SetItemCursedFlag(oSpellTarget, FALSE);
SetDroppableFlag(oSpellTarget, TRUE);
return TRUE;
}
else
{
FloatingTextStrRefOnCreature(76417, oCaster); // Item Creation Failed
return TRUE;
}
return TRUE;
}
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to craft a staff
// -----------------------------------------------------------------------------
int CICraftCheckCraftStaff(object oSpellTarget, object oCaster, int nSpellID = 0)
{
@@ -1281,6 +1446,9 @@ These dont work as IPs since they are hardcoded */
return TRUE;
}
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to craft a rod
// -----------------------------------------------------------------------------
int CICraftCheckCraftRod(object oSpellTarget, object oCaster, int nSpellID = 0)
{
@@ -1427,6 +1595,7 @@ These dont work as IPs since they are hardcoded */
return TRUE;
}
int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID, int nSpell = 0)
{
if(!GetIsObjectValid(oCaster)) oCaster = OBJECT_SELF;
@@ -1478,8 +1647,9 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
if(!GetIsObjectValid(oTarget)) oTarget = PRCGetSpellTargetObject();
int nCaster = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
//:: [TO DO] make Inscribe Epic Rune.
if(nCaster > 20) nCaster = 20;
//:: 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();
@@ -1612,9 +1782,14 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
// If they have this active, the bonuses are already added, so skip
// If they don't, add the bonuses down below
if(GetHasSpellEffect(SPELL_RUNE_CHANT))
nRuneChant = 0;
nRuneChant = 0;
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, PRCGetCasterLevel());
//:: Check for Inscribe Epic Runes and cap CL at 20 if it doesn't exist.
nCaster = PRCGetCasterLevel();
if (!bEpicRunes) { if(nCaster > 20) nCaster = 20; }
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, nCaster);
AddItemProperty(DURATION_TYPE_PERMANENT,ipLevel,oRune);
itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpell, PRCGetMetaMagicFeat());
AddItemProperty(DURATION_TYPE_PERMANENT,ipMeta,oRune);
@@ -1721,13 +1896,23 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
}
// oTarget here should be the gem. If it's not, fail.
if(!GetIsObjectValid(oTarget)) oTarget = PRCGetSpellTargetObject();
// Only accepts bioware gems
if (GetStringLeft(GetResRef(oTarget), 5) == "it_gem")
// Only accepts bioware gems & Craftable Natural Resources gems, but not gem dust.
int bIsBioGem = (GetStringLeft(GetResRef(oTarget), 5) == "it_gem");
int bIsCNRGem = (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem");
int bIsDust = (GetStringLeft(GetResRef(oTarget), 10) == "cnrgemdust");
if (!(bIsBioGem || bIsCNRGem) || bIsDust)
{
FloatingTextStringOnCreature("Spell target is not a valid gem.", oCaster, FALSE);
return TRUE;
}
/* if ((GetStringLeft(GetResRef(oTarget), 5) == "it_gem") || (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem") && (GetStringLeft(GetResRef(oTarget), 10) != "cnrgemdust"))
{
FloatingTextStringOnCreature("Spell target is not a valid gem.", oCaster, FALSE);
// And out we go
return TRUE;
}
} */
int nCaster = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
int nDC = PRCGetSaveDC(oTarget, oCaster);
@@ -2123,6 +2308,13 @@ int CIGetSpellWasUsedForItemCreation(object oSpellTarget)
// -------------------------------------------------
nRet = CICraftCheckCraftStaff(oSpellTarget,oCaster);
break;
case BASE_ITEM_CRAFTED_SCEPTER :
// -------------------------------------------------
// Craft Scepter
// -------------------------------------------------
nRet = CICraftCheckCraftScepter(oSpellTarget,oCaster);
break;
case BASE_ITEM_MUNDANE_HERB :
// -------------------------------------------------
@@ -2922,7 +3114,12 @@ int GetMagicalArtisanFeat(int nCraftingFeat)
{
nReturn = FEAT_MAGICAL_ARTISAN_CREATE_INFUSION;
break;
}
}
case FEAT_CRAFT_SCEPTER:
{
nReturn = FEAT_MAGICAL_ARTISAN_CRAFT_SCEPTER;
break;
}
default:
{
if(DEBUG) DoDebug("GetMagicalArtisanFeat: invalid crafting feat");

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
@@ -697,6 +694,7 @@ if(nItem == BASE_ITEM_BASTARDSWORD
|| nItem == BASE_ITEM_SICKLE
|| nItem == BASE_ITEM_TWOBLADEDSWORD
|| nItem == BASE_ITEM_CLUB
|| nItem == BASE_ITEM_CRAFTED_SCEPTER
|| nItem == BASE_ITEM_DAGGER
|| nItem == BASE_ITEM_DIREMACE
|| nItem == BASE_ITEM_HEAVYFLAIL
@@ -729,6 +727,7 @@ if(nItem == BASE_ITEM_BASTARDSWORD
|| nItem == BASE_ITEM_ELVEN_THINBLADE
|| nItem == BASE_ITEM_ELVEN_COURTBLADE
|| nItem == BASE_ITEM_CRAFTED_STAFF
|| nItem == BASE_ITEM_CRAFTED_SCEPTER
|| nItem == 300 //CEP Trident
|| nItem == 303 //CEP Sai
|| nItem == 304 //CEP nunchaku
@@ -1612,31 +1611,140 @@ int IPGetDamageBonusConstantFromNumber(int nNumber)
// oOld - Item equipped before polymorphing (source for item props)
// oNew - Item equipped after polymorphing (target for item props)
// bWeapon - Must be set TRUE when oOld is a weapon.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE)
{
if (GetIsObjectValid(oOld) && GetIsObjectValid(oNew))
{
itemproperty ip = GetFirstItemProperty(oOld);
while (GetIsItemPropertyValid(ip))
{
if (bWeapon)
{
if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) )
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
}
else
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
ip = GetNextItemProperty(oOld);
// Invalid source/target
if (!GetIsObjectValid(oOld) || !GetIsObjectValid(oNew))
return;
// Determine possessor
object oPC = GetItemPossessor(oOld);
if (!GetIsObjectValid(oPC))
oPC = GetItemPossessor(oNew);
}
}
if (!GetIsObjectValid(oPC))
{
if (DEBUG) DoDebug("IPWS: Unable to determine item possessor");
return;
}
// Determine glove state once
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
// Weapon ranged mismatch = do nothing (intent is no partial copy)
if (bWeapon && GetWeaponRanged(oOld) != GetWeaponRanged(oNew))
{
if (DEBUG) DoDebug("IPWS: Weapon ranged mismatch <20> skipping all IP copy");
return;
}
// Begin property copy
itemproperty ip = GetFirstItemProperty(oOld);
while (GetIsItemPropertyValid(ip))
{
int nType = GetItemPropertyType(ip);
// If copying from gloves and monk gloves are active
if (bMonkGloves
&& (nType == ITEM_PROPERTY_DAMAGE_BONUS
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP))
{
// Always apply glove damage IPs
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
ip = GetNextItemProperty(oOld);
continue;
}
// Normal weapon pass
if (bWeapon)
{
// If monk gloves active ? skip ALL weapon damage IPs
if (bMonkGloves
&& (nType == ITEM_PROPERTY_DAMAGE_BONUS
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP))
{
ip = GetNextItemProperty(oOld);
continue;
}
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
}
else
{
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
}
ip = GetNextItemProperty(oOld);
}
}
/* // ----------------------------------------------------------------------------
// GZ, Sept. 30 2003
// Special Version of Copy Item Properties for use with greater wild shape
// oOld - Item equipped before polymorphing (source for item props)
// oNew - Item equipped after polymorphing (target for item props)
// bWeapon - Must be set TRUE when oOld is a weapon.
// ----------------------------------------------------------------------------
void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE)
{
if (!GetIsObjectValid(oOld) || !GetIsObjectValid(oNew))
return;
object oPC = GetItemPossessor(oOld);
if (!GetIsObjectValid(oPC))
{
oPC = GetItemPossessor(oNew);
}
if (!GetIsObjectValid(oPC))
{
if (DEBUG) DoDebug("IPWS: Unable to determine item possessor");
return;
}
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
itemproperty ip = GetFirstItemProperty(oOld);
while (GetIsItemPropertyValid(ip))
{
if (bWeapon)
{
// Gloves override weapon damage <20> skip weapon damage properties
if (bMonkGloves)
{
int nType = GetItemPropertyType(ip);
// skip damage props
if (nType == ITEM_PROPERTY_DAMAGE_BONUS
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)
{
if (DEBUG) DoDebug("IPWS: SKIPPED weapon damage IP");
}
else
{
if (DEBUG) DoDebug("IPWS: Applied non-damage weapon IP");
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
}
}
else if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) )
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
}
else
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
ip = GetNextItemProperty(oOld);
}
} */
// ----------------------------------------------------------------------------
// Returns the current enhancement bonus of a weapon (+1 to +20), 0 if there is
// no enhancement bonus. You can test for a specific type of enhancement bonus
@@ -2018,4 +2126,6 @@ int IPOnHitSaveDC(int nSaveDC)
if (nSaveDC > 26) nIPBonus = IP_CONST_ONHIT_SAVEDC_26;
return nIPBonus;
} */
} */
//:: void main(){}

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

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

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
@@ -786,69 +788,12 @@ int GetIsPsionicCharacter(object oCreature)
GetHasFeat(FEAT_KALASHTAR_PP, oCreature) ||
GetHasFeat(FEAT_NATPSIONIC_1, oCreature) ||
GetHasFeat(FEAT_NATPSIONIC_2, oCreature) ||
GetHasFeat(FEAT_NATPSIONIC_3, oCreature)
GetHasFeat(FEAT_NATPSIONIC_3, oCreature) ||
IsHiddenTalent(oCreature)
// Racial psionicity signifying feats go here
);
}
int IsHiddenTalent(object oPC = OBJECT_SELF)
{
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC) ||
//GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC))
{
return TRUE;
}
else
{
return FALSE;
}
}
void LocalCleanExtraFists(object oCreature)
{
int iIsCWeap, iIsEquip;
@@ -985,6 +930,48 @@ int PracticedManifesting(object oManifester, int iManifestingClass, int iManifes
int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVALID, int nMaxPowerLevel = FALSE)
{
// Handle POWER_LIST_MISC (Hidden Talent) powers
// Check if this is a power list call
int nPowerType = GetLocalInt(oManifester, "PRC_UsePowerList");
if(nSpecificClass == CLASS_TYPE_INVALID && nPowerType == POWER_LIST_MISC)
{
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: CLASS_TYPE_INVALID + POWER_LIST_MISC found!");
// Check if character has psionic class levels
int nPsionLevel = GetLevelByClass(CLASS_TYPE_PSION, oManifester);
int nPsywarLevel = GetLevelByClass(CLASS_TYPE_PSYWAR, oManifester);
int nWilderLevel = GetLevelByClass(CLASS_TYPE_WILDER, oManifester);
int nWarmindLevel = GetLevelByClass(CLASS_TYPE_WARMIND, oManifester);
int nFistOfZuokenLevel = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oManifester);
int nPsychicRogueLevel = GetLevelByClass(CLASS_TYPE_PSYCHIC_ROGUE, oManifester);
// If no psionic levels, use Charisma-based calculation (treat as 1st level)
if(nPsionLevel + nPsywarLevel + nWilderLevel + nWarmindLevel +
nFistOfZuokenLevel + nPsychicRogueLevel == 0)
{
// Hidden Talent: considered 1st-level manifester, but must have CHA 11+
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: Hidden Talent found!");
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
return 1;
else
return 0; // Cannot manifest without CHA 11+
}
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: nSpecificClass=" + IntToString(nSpecificClass) +
", nPowerType=" + IntToString(nPowerType));
// Has psionic levels - return highest manifester level
int nHighest = 0;
if(nPsionLevel > 0) nHighest = GetManifesterLevel(oManifester, CLASS_TYPE_PSION);
if(nPsywarLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_PSYWAR));
if(nWilderLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_WILDER));
if(nWarmindLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_WARMIND));
if(nFistOfZuokenLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_FIST_OF_ZUOKEN));
if(nPsychicRogueLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_PSYCHIC_ROGUE));
return nHighest;
}
int nLevel;
int nAdjust = GetLocalInt(oManifester, PRC_CASTERLEVEL_ADJUSTMENT);
nAdjust -= GetLocalInt(oManifester, "WoLManifPenalty");
@@ -1049,17 +1036,27 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
DelayCommand(1.0, DeleteLocalInt(oManifester, PRC_CASTERLEVEL_OVERRIDE));
nLevel = GetLocalInt(oManifester, PRC_CASTERLEVEL_OVERRIDE);
}
else if(GetManifestingClass(oManifester) != CLASS_TYPE_INVALID)
{
//Gets the manifesting class
int nManifestingClass = GetManifestingClass(oManifester);
if(DEBUG) DoDebug("Manifesting Class #2: " + IntToString(nManifestingClass), oManifester);
nLevel = GetLevelByClass(nManifestingClass, oManifester);
// Add levels from +ML PrCs only for the first manifesting class
nLevel += GetPsionicPRCLevels(oManifester, nManifestingClass);
//nLevel += nManifestingClass == GetPrimaryPsionicClass(oManifester) ? GetPsionicPRCLevels(oManifester) : 0;
}
else if(GetManifestingClass(oManifester) != CLASS_TYPE_INVALID)
{
//Gets the manifesting class
int nManifestingClass = GetManifestingClass(oManifester);
if(DEBUG) DoDebug("Manifesting Class #2: " + IntToString(nManifestingClass), oManifester);
nLevel = GetLevelByClass(nManifestingClass, oManifester);
// Add levels from +ML PrCs only for the first manifesting class
nLevel += GetPsionicPRCLevels(oManifester, nManifestingClass);
// CHECK: If this is Hidden Talent and character has no levels, set to 1
if(nLevel == 0 && GetLocalInt(oManifester, "PRC_UsePowerList") == TRUE &&
GetLocalInt(oManifester, "PRC_PowerListType") == POWER_LIST_MISC)
{
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
{
if(DEBUG) DoDebug("GetManifesterLevel: Hidden Talent with no psionic levels, returning 1");
nLevel = 1;
}
}
// Psionic vestiges are tucked in here to override things.
// This assumes that there will never be a psion with this spell effect manifesting things
if (nManifestingClass == CLASS_TYPE_PSION && GetHasSpellEffect(VESTIGE_ARETE, oManifester) && !nMaxPowerLevel)
@@ -1085,7 +1082,37 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
// if(DEBUG) DoDebug("Level gotten via GetLevelByClass: " + IntToString(nLevel), oManifester);
}
// If you have a primary psionic class and no manifester level yet, get levels based on that
// If you have a primary psionic class and no manifester level yet, get levels based on that
if (GetPrimaryPsionicClass(oManifester) && nLevel == 0)
{
int nClass = GetPrimaryPsionicClass(oManifester);
nLevel = GetLevelByClass(nClass, oManifester);
nLevel += GetPsionicPRCLevels(oManifester, nClass);
nLevel += PracticedManifesting(oManifester, nClass, nLevel);
}
// If everything else fails, check for Hidden Talent before returning 0
if(nLevel == 0)
{
// Check if this is a Hidden Talent power
if(GetLocalInt(oManifester, "PRC_UsePowerList") == POWER_LIST_MISC)
{
// Hidden Talent: manifester level is 1 if they have CHA 11+
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
{
if(DEBUG) DoDebug("GetManifesterLevel: Hidden Talent character, returning level 1");
return 1;
}
}
if(DEBUG) DoDebug("Failed to get manifester level for creature " + DebugObject2Str(oManifester) + ", using first class slot");
//else WriteTimestampedLogEntry("Failed to get manifester level for creature " + DebugObject2Str(oManifester) + ", using first class slot");
return 0;
}
/* // If you have a primary psionic class and no manifester level yet, get levels based on that
if (GetPrimaryPsionicClass(oManifester) && nLevel == 0)
{
int nClass = GetPrimaryPsionicClass(oManifester);
@@ -1102,7 +1129,7 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
return 0;
}
*/
// The bonuses inside only apply to normal manifestation
if(!GetLocalInt(oManifester, PRC_IS_PSILIKE))
@@ -1665,4 +1692,225 @@ int GetMaxPowerLevel(object oManifester)
int nMax = StringToInt(Get2DACache(sFile, "MaxPowerLevel", nLevel));
if (DEBUG) DoDebug("GetMaxPowerLevel is "+IntToString(nMax));
return nMax;
}
}
//////////////////////////////////////////////////////
/* START HIDDEN TALENT */
//////////////////////////////////////////////////////
int IsHiddenTalent(object oPC = OBJECT_SELF)
{
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC) ||
//GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC))
{
return TRUE;
}
else
{
return FALSE;
}
}
int GetHiddenTalentPowerFromFeat(int nFeatID)
{
// Map Hidden Talent feats to their corresponding power IDs
// Using the same mappings as GetIsHiddenTalentPower()
if(nFeatID == FEAT_HIDDEN_TALENT_BIOFEEDBACK) return POWER_BIOFEEDBACK;
if(nFeatID == FEAT_HIDDEN_TALENT_BITE_WOLF) return POWER_BITE_WOLF;
if(nFeatID == FEAT_HIDDEN_TALENT_BOLT) return POWER_BOLT;
if(nFeatID == FEAT_HIDDEN_TALENT_BURST) return POWER_BURST;
if(nFeatID == FEAT_HIDDEN_TALENT_CALLTOMIND) return POWER_CALLTOMIND;
if(nFeatID == FEAT_HIDDEN_TALENT_CALL_WEAPONRY) return POWER_CALL_WEAPONRY;
if(nFeatID == FEAT_HIDDEN_TALENT_CHAMELEON) return POWER_CHAMELEON;
if(nFeatID == FEAT_HIDDEN_TALENT_CLAWS_BEAST) return POWER_CLAWS_BEAST;
if(nFeatID == FEAT_HIDDEN_TALENT_COMPRESSION) return POWER_COMPRESSION;
if(nFeatID == FEAT_HIDDEN_TALENT_CONCEALTHOUGHT) return POWER_CONCEALTHOUGHT;
if(nFeatID == FEAT_HIDDEN_TALENT_CREATESOUND) return POWER_CREATESOUND;
if(nFeatID == FEAT_HIDDEN_TALENT_CRYSTALSHARD) return POWER_CRYSTALSHARD;
if(nFeatID == FEAT_HIDDEN_TALENT_DAZE) return POWER_DAZE;
if(nFeatID == FEAT_HIDDEN_TALENT_DECELERATION) return POWER_DECELERATION;
if(nFeatID == FEAT_HIDDEN_TALENT_DEFPRECOG) return POWER_DEFPRECOG;
if(nFeatID == FEAT_HIDDEN_TALENT_DEMORALIZE) return POWER_DEMORALIZE;
if(nFeatID == FEAT_HIDDEN_TALENT_DISABLE) return POWER_DISABLE;
if(nFeatID == FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH)return POWER_DISSIPATINGTOUCH;
if(nFeatID == FEAT_HIDDEN_TALENT_DISTRACT) return POWER_DISTRACT;
if(nFeatID == FEAT_HIDDEN_TALENT_ELFSIGHT) return POWER_ELFSIGHT;
if(nFeatID == FEAT_HIDDEN_TALENT_EMPATHY) return POWER_EMPATHY;
if(nFeatID == FEAT_HIDDEN_TALENT_EMPTYMIND) return POWER_EMPTYMIND;
if(nFeatID == FEAT_HIDDEN_TALENT_ENTANGLE) return POWER_ENTANGLE;
if(nFeatID == FEAT_HIDDEN_TALENT_EXPANSION) return POWER_EXPANSION;
if(nFeatID == FEAT_HIDDEN_TALENT_FARHAND) return POWER_FARHAND;
if(nFeatID == FEAT_HIDDEN_TALENT_FORCESCREEN) return POWER_FORCESCREEN;
if(nFeatID == FEAT_HIDDEN_TALENT_GREASE) return POWER_GREASE;
if(nFeatID == FEAT_HIDDEN_TALENT_HAMMER) return POWER_HAMMER;
if(nFeatID == FEAT_HIDDEN_TALENT_INERTIALARMOUR) return POWER_INERTIALARMOUR;
if(nFeatID == FEAT_HIDDEN_TALENT_MATTERAGITATION) return POWER_MATTERAGITATION;
if(nFeatID == FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW) return POWER_METAPHYSICAL_CLAW;
if(nFeatID == FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON) return POWER_METAPHYSICAL_WEAPON;
if(nFeatID == FEAT_HIDDEN_TALENT_MINDTHRUST) return POWER_MINDTHRUST;
if(nFeatID == FEAT_HIDDEN_TALENT_MYLIGHT) return POWER_MYLIGHT;
if(nFeatID == FEAT_HIDDEN_TALENT_OFFPRECOG) return POWER_OFFPRECOG;
if(nFeatID == FEAT_HIDDEN_TALENT_OFFPRESC) return POWER_OFFPRESC;
if(nFeatID == FEAT_HIDDEN_TALENT_PREVENOM) return POWER_PREVENOM;
if(nFeatID == FEAT_HIDDEN_TALENT_PREVENOM_WEAPON) return POWER_PREVENOM_WEAPON;
if(nFeatID == FEAT_HIDDEN_TALENT_SKATE) return POWER_SKATE;
if(nFeatID == FEAT_HIDDEN_TALENT_STOMP) return POWER_STOMP;
if(nFeatID == FEAT_HIDDEN_TALENT_SYNESTHETE) return POWER_SYNESTHETE;
if(nFeatID == FEAT_HIDDEN_TALENT_TELEMPATHICPRO) return POWER_TELEMPATHICPRO;
if(nFeatID == FEAT_HIDDEN_TALENT_THICKSKIN) return POWER_THICKSKIN;
if(nFeatID == FEAT_HIDDEN_TALENT_VIGOR) return POWER_VIGOR;
if(nFeatID == FEAT_HIDDEN_TALENT_GRIP_IRON) return POWER_GRIP_IRON;
return -1; // Not found
}
int GetHiddenTalentCount(object oPC = OBJECT_SELF)
{
int nCount = 0;
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC)) nCount++;
//if (GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC))nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC)) nCount++;
return nCount;
}
int GetIsHiddenTalentPower(object oPC, int nPower)
{
// Check each Hidden Talent feat to see if it grants this power
if(nPower == POWER_BIOFEEDBACK && GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC)) return TRUE;
if(nPower == POWER_BITE_WOLF && GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC)) return TRUE;
if(nPower == POWER_BOLT && GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC)) return TRUE;
if(nPower == POWER_BURST && GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC)) return TRUE;
if(nPower == POWER_CALLTOMIND && GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC)) return TRUE;
if(nPower == POWER_CALL_WEAPONRY && GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC)) return TRUE;
if(nPower == POWER_CHAMELEON && GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC)) return TRUE;
if(nPower == POWER_CLAWS_BEAST && GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC)) return TRUE;
if(nPower == POWER_COMPRESSION && GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC)) return TRUE;
if(nPower == POWER_CONCEALTHOUGHT && GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC)) return TRUE;
if(nPower == POWER_CREATESOUND && GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC)) return TRUE;
if(nPower == POWER_CRYSTALSHARD && GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC)) return TRUE;
if(nPower == POWER_DAZE && GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC)) return TRUE;
if(nPower == POWER_DECELERATION && GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC)) return TRUE;
if(nPower == POWER_DEFPRECOG && GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC)) return TRUE;
if(nPower == POWER_DEMORALIZE && GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC)) return TRUE;
if(nPower == POWER_DISABLE && GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC)) return TRUE;
if(nPower == POWER_DISSIPATINGTOUCH && GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC)) return TRUE;
if(nPower == POWER_DISTRACT && GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC)) return TRUE;
if(nPower == POWER_ELFSIGHT && GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC)) return TRUE;
if(nPower == POWER_EMPATHY && GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC)) return TRUE;
if(nPower == POWER_EMPTYMIND && GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC)) return TRUE;
//if(nPower == POWER_ENERGYRAY && GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) return TRUE;
if(nPower == POWER_ENTANGLE && GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC)) return TRUE;
if(nPower == POWER_EXPANSION && GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC)) return TRUE;
if(nPower == POWER_FARHAND && GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC)) return TRUE;
if(nPower == POWER_FORCESCREEN && GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC)) return TRUE;
if(nPower == POWER_GREASE && GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC)) return TRUE;
if(nPower == POWER_HAMMER && GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC)) return TRUE;
if(nPower == POWER_INERTIALARMOUR && GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC)) return TRUE;
if(nPower == POWER_MATTERAGITATION && GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC)) return TRUE;
if(nPower == POWER_METAPHYSICAL_CLAW && GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC)) return TRUE;
if(nPower == POWER_METAPHYSICAL_WEAPON && GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC)) return TRUE;
if(nPower == POWER_MINDTHRUST && GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC)) return TRUE;
if(nPower == POWER_MYLIGHT && GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC)) return TRUE;
if(nPower == POWER_OFFPRECOG && GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC)) return TRUE;
if(nPower == POWER_OFFPRESC && GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC)) return TRUE;
if(nPower == POWER_PREVENOM && GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC)) return TRUE;
if(nPower == POWER_PREVENOM_WEAPON && GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC)) return TRUE;
if(nPower == POWER_SKATE && GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC)) return TRUE;
if(nPower == POWER_STOMP && GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC)) return TRUE;
if(nPower == POWER_SYNESTHETE && GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC)) return TRUE;
if(nPower == POWER_TELEMPATHICPRO && GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC)) return TRUE;
if(nPower == POWER_THICKSKIN && GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC)) return TRUE;
if(nPower == POWER_VIGOR && GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC)) return TRUE;
if(nPower == POWER_GRIP_IRON && GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC)) return TRUE;
return FALSE;
}

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

@@ -572,7 +572,11 @@ int GetMaxPowerCount(object oCreature, int nList)
int GetHasPower(int nPower, object oCreature = OBJECT_SELF)
{
if((GetLevelByClass(CLASS_TYPE_PSION, oCreature)
// Check MISC list first (for Hidden Talent and similar feats)
if(GetHasFeat(GetClassFeatFromPower(nPower, CLASS_TYPE_INVALID), oCreature))
return TRUE;
if((GetLevelByClass(CLASS_TYPE_PSION, oCreature)
&& GetHasFeat(GetClassFeatFromPower(nPower, CLASS_TYPE_PSION), oCreature)
) ||
(GetLevelByClass(CLASS_TYPE_PSYWAR, oCreature)

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.
@@ -692,10 +694,28 @@ void _UsePowerAux(object oManifester, object oMfToken, int nSpellId,
struct manifestation EvaluateManifestation(object oManifester, object oTarget, struct power_augment_profile pap, int nMetaPsiFlags)
{
/* Get some data */
//:: Handle Hidden Talent
int nSpellID = PRCGetSpellId();
int bIsHiddenTalent = GetIsHiddenTalentPower(oManifester, nSpellID);
if(bIsHiddenTalent)
{
SetLocalInt(oManifester, "PRC_UsePowerList", TRUE);
SetLocalInt(oManifester, "PRC_PowerListType", POWER_LIST_MISC);
}
/* Get some data */
int bIgnoreConstraints = (DEBUG) ? GetLocalInt(oManifester, PRC_DEBUG_IGNORE_CONSTRAINTS) : FALSE;
// Manifester-related stuff
int nManifesterLevel = GetManifesterLevel(oManifester);
//int nManifesterLevel = GetManifesterLevel(oManifester);
int nManifesterLevel;
if(bIsHiddenTalent)
{
nManifesterLevel = GetManifesterLevel(oManifester, CLASS_TYPE_INVALID);
}
else
{
nManifesterLevel = GetManifesterLevel(oManifester);
}
int nPowerLevel = GetPowerLevel(oManifester);
int nClass = GetManifestingClass(oManifester);
int nWildSurge = GetWildSurge(oManifester);
@@ -714,6 +734,8 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
manif.nManifesterLevel = nManifesterLevel;
manif.nSpellID = PRCGetSpellId();
// Run an ability score check to see if the manifester can manifest the power at all
if (bIsPsiLike)
{
@@ -767,7 +789,9 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
//If the manifester does not have enough points before hostile modifiers, cancel power
if(manif.nPPCost > nManifesterPP && !bIsPsiLike && !bIgnoreConstraints)
{
FloatingTextStrRefOnCreature(16826412, oManifester, FALSE); // "You do not have enough Power Points to manifest this power"
// DEBUG: show why the cost over cap branch triggered
FloatingTextStringOnCreature("DEBUG: manif.nManifesterLevel=" + IntToString(manif.nManifesterLevel) + " manif.nPPCost=" + IntToString(manif.nPPCost) +" PRC_UsePowerList=" + IntToString(GetLocalInt(manif.oManifester, "PRC_UsePowerList")), manif.oManifester, FALSE);
FloatingTextStrRefOnCreature(16826412, oManifester, FALSE); // "You do not have enough Power Points to manifest this power"
manif.bCanManifest = FALSE;
}
// The manifester has enough power points that they would be able to use the power, barring extra costs

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

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

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

@@ -2902,7 +2902,7 @@ int WandEquipped(object oCaster, object oSpellCastItem)
int nType = GetBaseItemType(oSpellCastItem);
if(nType == BASE_ITEM_MAGICWAND || nType == BASE_ITEM_ENCHANTED_WAND) // Has to be a wand, obv
if(nType == BASE_ITEM_MAGICWAND || nType == BASE_ITEM_ENCHANTED_WAND || nType == BASE_ITEM_CRAFTED_SCEPTER) // Has to be a wand, obv
{
if(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCaster) == oSpellCastItem || GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCaster) == oSpellCastItem) // Needs to be equipped
{
@@ -2910,7 +2910,7 @@ int WandEquipped(object oCaster, object oSpellCastItem)
}
else
{
FloatingTextStringOnCreature("You must equip a wand to cast from it.", oCaster, FALSE);
FloatingTextStringOnCreature("You must equip this item to cast from it.", oCaster, FALSE);
return FALSE; // It's a wand not equipped
}
}

View File

@@ -1078,7 +1078,7 @@
"Mod_Name": {
"type": "cexolocstring",
"value": {
"0": "Lord of Terror [CCOH-PRC8-CEP3]"
"0": "Lord of Terror [PRC8-CEP3]"
}
},
"Mod_OnAcquirItem": {
@@ -1135,7 +1135,7 @@
},
"Mod_OnPlrGuiEvt": {
"type": "resref",
"value": ""
"value": "prc_onplayergui"
},
"Mod_OnPlrLvlUp": {
"type": "resref",

View File

@@ -11090,7 +11090,7 @@
"__struct_id": 0,
"CR": {
"type": "float",
"value": 17.0
"value": 16.0
},
"FACTION": {
"type": "cexostring",
@@ -19955,7 +19955,7 @@
"__struct_id": 0,
"CR": {
"type": "float",
"value": 0.3333
"value": 84.0
},
"FACTION": {
"type": "cexostring",