PRC8/nwn/nwnprc/trunk/include/prc_inc_function.nss
Jaysyn904 4fb9f2783b Disabled Hidden Talent until it's actually finished
Disabled Hidden Talent until it's actually finished.  Fixed a few typos & some formatting.
2025-02-07 19:11:46 -05:00

2046 lines
89 KiB
Plaintext

//::///////////////////////////////////////////////
//:: [PRC Feat Router]
//:: [prc_inc_function.nss]
//:://////////////////////////////////////////////
//:: This file serves as a hub for the various
//:: PRC passive feat functions. If you need to
//:: add passive feats for a new PRC, link them here.
//::
//:: This file also contains a few multi-purpose
//:: PRC functions that need to be included in several
//:: places, ON DIFFERENT PRCS. Make local include files
//:: for any functions you use ONLY on ONE PRC.
//:://////////////////////////////////////////////
//:: Created By: Aaon Graywolf
//:: Created On: Dec 19, 2003
//:://////////////////////////////////////////////
//:: Updated for 8 class slots by Jaysyn 2024/02/05
//--------------------------------------------------------------------------
// This is the "event" that is called to re-evalutate PRC bonuses. Currently
// it is fired by OnEquip, OnUnequip and OnLevel. If you want to move any
// classes into this event, just copy the format below. Basically, this function
// is meant to keep the code looking nice and clean by routing each class's
// feats to their own self-contained script
//--------------------------------------------------------------------------
//:: Test Void
//void main (){}
//////////////////////////////////////////////////
/* Constants */
//////////////////////////////////////////////////
const int TEMPLATE_SLA_START = 16304;
const int TEMPLATE_SLA_END = 16400;
const string PRC_ScrubPCSkin_Generation = "PRC_ScrubPCSkin_Generation";
const string PRC_EvalPRCFeats_Generation = "PRC_EvalPRCFeats_Generation";
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
void EvalPRCFeats(object oPC);
int BlastInfidelOrFaithHeal(object oCaster, object oTarget, int iEnergyType, int iDisplayFeedback);
void ScrubPCSkin(object oPC, object oSkin);
void DeletePRCLocalInts(object oSkin);
void DelayedAddIPFeats(int nExpectedGeneration, object oPC);
void DelayedReApplyUnhealableAbilityDamage(int nExpectedGeneration, object oPC);
int nbWeaponFocus(object oPC);
//////////////////////////////////////////////////
/* Includes */
//////////////////////////////////////////////////
// Minimalist includes
#include "prc_inc_util"
#include "prc_inc_spells"
#include "prc_inc_stunfist"
#include "inc_nwnx_funcs"
#include "prc_template_con"
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
void DeleteCharacterData(object oPC)
{
DeletePersistantLocalString(oPC, "PRC_Class_Script1");
DeletePersistantLocalString(oPC, "PRC_Class_Script2");
DeletePersistantLocalString(oPC, "PRC_Class_Script3");
DeletePersistantLocalString(oPC, "PRC_Class_Script4");
DeletePersistantLocalString(oPC, "PRC_Class_Script5");
DeletePersistantLocalString(oPC, "PRC_Class_Script6");
DeletePersistantLocalString(oPC, "PRC_Class_Script7");
DeletePersistantLocalString(oPC, "PRC_Class_Script8");
DeletePersistantLocalInt(oPC, "PRC_Class_Data");
}
void SetupCharacterData(object oPC)
{
// iData format:
// 0x01 - run alternate magic system setup
// 0x02 - add new metamagic feats for spontaneous casters
// 0x04 - run reduced arcane spell failure check
// use bitwise to combine flags
int i, iData, iShifting;
for(i = 1; i <= 8; i++)
{
int nClassType = GetClassByPosition(i, oPC);
if(nClassType != CLASS_TYPE_INVALID)
{
string sScript;
switch(nClassType)
{
case CLASS_TYPE_ABJURANT_CHAMPION: sScript = "prc_abchamp"; break;
case CLASS_TYPE_ACOLYTE: sScript = "prc_acolyte"; break;
case CLASS_TYPE_ALIENIST: sScript = "prc_alienist"; break;
case CLASS_TYPE_ARCANE_DUELIST: sScript = "prc_arcduel"; break;
case CLASS_TYPE_ARCHIVIST: sScript = "prc_archivist"; iData |= 0x01; break;
case CLASS_TYPE_ASSASSIN: iData |= 0x03; break;
case CLASS_TYPE_BAELNORN: sScript = "prc_baelnorn"; break;
case CLASS_TYPE_BARD: iData |= 0x07; break;
case CLASS_TYPE_BATTLESMITH: sScript = "prc_battlesmith"; break;
case CLASS_TYPE_BEGUILER: iData |= 0x03; break;
case CLASS_TYPE_BINDER: sScript = "bnd_binder"; break;
case CLASS_TYPE_BFZ: sScript = "prc_bfz"; break;
case CLASS_TYPE_BLACK_BLOOD_CULTIST: sScript = "prc_bbc"; break;
case CLASS_TYPE_BLACKGUARD: sScript = "prc_blackguard"; break;
case CLASS_TYPE_BLADESINGER: sScript = "prc_bladesinger"; iData |= 0x04; break;
case CLASS_TYPE_BLIGHTLORD: sScript = "prc_blightlord"; break;
case CLASS_TYPE_BLOODCLAW_MASTER: sScript = "tob_bloodclaw"; break;
case CLASS_TYPE_BONDED_SUMMONNER: sScript = "prc_bondedsumm"; break;
case CLASS_TYPE_CELEBRANT_SHARESS: iData |= 0x03; break;
case CLASS_TYPE_CHILD_OF_NIGHT: sScript = "shd_childnight"; break;
case CLASS_TYPE_COC: sScript = "prc_coc"; break;
case CLASS_TYPE_COMBAT_MEDIC: sScript = "prc_cbtmed"; break;
case CLASS_TYPE_CONTEMPLATIVE: sScript = "prc_contemplate"; break;
case CLASS_TYPE_CRUSADER: sScript = "tob_crusader"; iData |= 0x01; break;
case CLASS_TYPE_CULTIST_SHATTERED_PEAK: sScript = "prc_shatterdpeak"; break;
case CLASS_TYPE_CW_SAMURAI: sScript = "prc_cwsamurai"; break;
case CLASS_TYPE_DEEPSTONE_SENTINEL: sScript = "tob_deepstone"; break;
case CLASS_TYPE_DIAMOND_DRAGON: sScript = "psi_diadra"; break;
case CLASS_TYPE_DISC_BAALZEBUL: sScript = "prc_baalzebul"; break;
case CLASS_TYPE_DISCIPLE_OF_ASMODEUS: sScript = "prc_discasmodeus"; break;
case CLASS_TYPE_DISCIPLE_OF_MEPH: sScript = "prc_discmeph"; break;
case CLASS_TYPE_DISPATER: sScript = "prc_dispater"; break;
case CLASS_TYPE_DRAGON_DEVOTEE: sScript = "prc_dragdev"; break;
case CLASS_TYPE_DRAGON_DISCIPLE: sScript = "prc_dradis"; break;
case CLASS_TYPE_DRAGON_SHAMAN: sScript = "prc_dragonshaman"; break;
case CLASS_TYPE_DRAGONFIRE_ADEPT: sScript = "inv_drgnfireadpt"; iData |= 0x01; break;
case CLASS_TYPE_DREAD_NECROMANCER: sScript = "prc_dreadnecro"; iData |= 0x03; break;
case CLASS_TYPE_DRUID: iShifting = TRUE; break;
case CLASS_TYPE_DRUNKEN_MASTER: sScript = "prc_drunk"; break;
case CLASS_TYPE_DUELIST: sScript = "prc_duelist"; break;
case CLASS_TYPE_DUSKBLADE: sScript = "prc_duskblade"; iData |= 0x03; break;
case CLASS_TYPE_ENLIGHTENEDFIST: sScript = "prc_enlfis"; break;
case CLASS_TYPE_ELEMENTAL_SAVANT: sScript = "prc_elemsavant"; break;
case CLASS_TYPE_ETERNAL_BLADE: sScript = "tob_eternalblade"; break;
case CLASS_TYPE_FACTOTUM: sScript = "prc_factotum"; break;
case CLASS_TYPE_FAVOURED_SOUL: sScript = "prc_favouredsoul"; iData |= 0x03; break;
case CLASS_TYPE_FIST_OF_ZUOKEN: sScript = "psi_zuoken"; iData |= 0x01; break;
case CLASS_TYPE_FOCHLUCAN_LYRIST: sScript = "prc_fochlyr"; break;
case CLASS_TYPE_FOE_HUNTER: sScript = "prc_foe_hntr"; break;
case CLASS_TYPE_FORESTMASTER: sScript = "prc_forestmaster"; break;
case CLASS_TYPE_FORSAKER: sScript = "prc_forsaker"; break;
case CLASS_TYPE_FRE_BERSERKER: sScript = "prc_frebzk"; break;
case CLASS_TYPE_FROSTRAGER: sScript = "prc_frostrager"; break;
case CLASS_TYPE_FROST_MAGE: sScript = "prc_frostmage"; break;
case CLASS_TYPE_HALFLING_WARSLINGER: sScript = "prc_warsling"; break;
case CLASS_TYPE_HARPER: iData |= 0x03; break;
case CLASS_TYPE_HEARTWARDER: sScript = "prc_heartwarder"; break;
case CLASS_TYPE_HENSHIN_MYSTIC: sScript = "prc_henshin"; break;
case CLASS_TYPE_HEXBLADE: iData |= 0x03; break;
case CLASS_TYPE_HEXTOR: sScript = "prc_hextor"; break;
case CLASS_TYPE_IAIJUTSU_MASTER: sScript = "prc_iaijutsu_mst"; break;
case CLASS_TYPE_INCARNATE: sScript = "moi_incarnate"; break;
case CLASS_TYPE_INCARNUM_BLADE: sScript = "moi_iblade"; break;
case CLASS_TYPE_INITIATE_DRACONIC: sScript = "prc_initdraconic"; break;
case CLASS_TYPE_IRONMIND: sScript = "psi_ironmind"; break;
case CLASS_TYPE_IRONSOUL_FORGEMASTER: sScript = "moi_ironsoul"; break;
case CLASS_TYPE_JADE_PHOENIX_MAGE: sScript = "tob_jadephoenix"; break;
case CLASS_TYPE_JUDICATOR: sScript = "prc_judicator"; break;
case CLASS_TYPE_JUSTICEWW: iData |= 0x03; break;
case CLASS_TYPE_KNIGHT: sScript = "prc_knight"; break;
case CLASS_TYPE_KNIGHT_CHALICE: sScript = "prc_knghtch"; break;
case CLASS_TYPE_KNIGHT_WEAVE: iData |= 0x03; break;
case CLASS_TYPE_KNIGHT_SACRED_SEAL: sScript = "bnd_kss"; break;
case CLASS_TYPE_LASHER: sScript = "prc_lasher"; break;
case CLASS_TYPE_LEGENDARY_DREADNOUGHT: sScript = "prc_legendread"; break;
case CLASS_TYPE_LICH: sScript = "pnp_lich_level"; break;
case CLASS_TYPE_MAGEKILLER: sScript = "prc_magekill"; break;
case CLASS_TYPE_MASTER_HARPER: sScript = "prc_masterh"; break;
case CLASS_TYPE_MASTER_OF_NINE: sScript = "tob_masterofnine"; break;
case CLASS_TYPE_MASTER_OF_SHADOW: sScript = "shd_mastershadow"; break;
case CLASS_TYPE_MIGHTY_CONTENDER_KORD: sScript = "prc_contendkord"; break;
case CLASS_TYPE_MORNINGLORD: sScript = "prc_morninglord"; break;
case CLASS_TYPE_NIGHTSHADE: sScript = "prc_nightshade"; break;
case CLASS_TYPE_NINJA: sScript = "prc_ninjca"; break;
case CLASS_TYPE_OLLAM: sScript = "prc_ollam"; break;
case CLASS_TYPE_OOZEMASTER: sScript = "prc_oozemstr"; break;
case CLASS_TYPE_ORDER_BOW_INITIATE: sScript = "prc_ootbi"; break;
case CLASS_TYPE_PEERLESS: sScript = "prc_peerless"; break;
case CLASS_TYPE_PNP_SHIFTER : iShifting = TRUE; break;
case CLASS_TYPE_PRC_EYE_OF_GRUUMSH: sScript = "prc_eog"; break;
case CLASS_TYPE_PSION: iData |= 0x01; break;
case CLASS_TYPE_PSYWAR: iData |= 0x01; break;
case CLASS_TYPE_PSYCHIC_ROGUE: sScript = "psi_psyrogue"; iData |= 0x01; break;
case CLASS_TYPE_PYROKINETICIST: sScript = "psi_pyro"; break;
case CLASS_TYPE_RAGE_MAGE: iData |= 0x04; break;
case CLASS_TYPE_REAPING_MAULER : sScript = "prc_reapmauler"; break;
case CLASS_TYPE_RUBY_VINDICATOR: sScript = "tob_rubyknight"; break;
case CLASS_TYPE_RUNESCARRED: sScript = "prc_runescarred"; break;
case CLASS_TYPE_SACREDFIST: sScript = "prc_sacredfist"; break;
case CLASS_TYPE_SANCTIFIED_MIND: sScript = "psi_sancmind"; break;
case CLASS_TYPE_SAPPHIRE_HIERARCH: sScript = "moi_sapphire"; break;
case CLASS_TYPE_SCOUT: sScript = "prc_scout"; break;
case CLASS_TYPE_SERENE_GUARDIAN: sScript = "prc_sereneguard"; break;
case CLASS_TYPE_SHADOW_ADEPT: sScript = "prc_shadowadept"; break;
case CLASS_TYPE_SHADOWCASTER: sScript = "shd_shadowcaster"; iData |= 0x01; break;
case CLASS_TYPE_SHADOWSMITH: iData |= 0x01; break;
case CLASS_TYPE_SHADOW_SUN_NINJA: sScript = "tob_shadowsun"; break;
case CLASS_TYPE_SHADOWBLADE: sScript = "prc_sb_shdstlth"; break;
case CLASS_TYPE_SHADOWMIND: sScript = "psi_shadowmind"; break;
case CLASS_TYPE_SHADOWBANE_STALKER: sScript = "prc_shadstalker"; break;
case CLASS_TYPE_SHADOW_THIEF_AMN: sScript = "prc_amn"; break;
case CLASS_TYPE_SHAMAN: sScript = "prc_shaman"; break;
case CLASS_TYPE_SHINING_BLADE: sScript = "prc_sbheir"; break;
case CLASS_TYPE_SHOU: sScript = "prc_shou"; break;
case CLASS_TYPE_SKULLCLAN_HUNTER: sScript = "prc_skullclan"; break;
case CLASS_TYPE_SLAYER_OF_DOMIEL: sScript = "prc_slayerdomiel"; break;
case CLASS_TYPE_SOHEI: sScript = "prc_sohei"; break;
case CLASS_TYPE_SOLDIER_OF_LIGHT: sScript = "prc_soldoflight"; break;
case CLASS_TYPE_SORCERER: iData |= 0x03; break;
case CLASS_TYPE_SOULBORN: sScript = "moi_soulborn"; break;
case CLASS_TYPE_SOUL_EATER: iShifting = TRUE; break;
case CLASS_TYPE_SOULKNIFE: sScript = "psi_sk_clseval"; break;
case CLASS_TYPE_SPELLSWORD: sScript = "prc_spellswd"; iData |= 0x04; break;
case CLASS_TYPE_SPINEMELD_WARRIOR: sScript = "moi_spinemeld"; break;
case CLASS_TYPE_STORMLORD: sScript = "prc_stormlord"; break;
case CLASS_TYPE_SUBLIME_CHORD: sScript = "prc_schord"; iData |= 0x03; break;
case CLASS_TYPE_SUEL_ARCHANAMACH: iData |= 0x03; break;
case CLASS_TYPE_SWASHBUCKLER: sScript = "prc_swashbuckler"; break;
case CLASS_TYPE_SWIFT_WING: sScript = "prc_swiftwing"; break;
case CLASS_TYPE_SWORDSAGE: sScript = "tob_swordsage"; iData |= 0x01; break;
case CLASS_TYPE_TALON_OF_TIAMAT: sScript = "prc_talontiamat"; break;
case CLASS_TYPE_TEMPEST: sScript = "prc_tempest"; break;
case CLASS_TYPE_TEMPUS: sScript = "prc_battletempus"; break;
case CLASS_TYPE_TENEBROUS_APOSTATE: sScript = "bnd_tenebrous"; break;
case CLASS_TYPE_THAYAN_KNIGHT: sScript = "prc_thayknight"; break;
case CLASS_TYPE_THRALL_OF_GRAZZT_A: sScript = "tog"; break;
case CLASS_TYPE_THRALLHERD: sScript = "psi_thrallherd"; break;
case CLASS_TYPE_TOTEMIST: sScript = "moi_totemist"; break;
case CLASS_TYPE_TOTEM_RAGER: sScript = "moi_totemrager"; break;
case CLASS_TYPE_TRUENAMER: sScript = "true_truenamer"; iData |= 0x01; break;
case CLASS_TYPE_VASSAL: sScript = "prc_vassal"; break;
case CLASS_TYPE_VIGILANT: sScript = "prc_vigilant"; break;
case CLASS_TYPE_WARBLADE: sScript = "tob_warblade"; iData |= 0x01; break;
case CLASS_TYPE_WARCHIEF: sScript = "prc_warchief"; break;
case CLASS_TYPE_WARFORGED_JUGGERNAUT: sScript = "prc_juggernaut"; break;
case CLASS_TYPE_WARLOCK: sScript = "inv_warlock"; iData |= 0x01; break;
case CLASS_TYPE_WARMAGE: iData |= 0x03; break;
case CLASS_TYPE_WARMIND: sScript = "psi_warmind"; iData |= 0x01; break;
case CLASS_TYPE_WEREWOLF: sScript = "prc_werewolf"; break;
case CLASS_TYPE_WILDER: iData |= 0x01; break;
// Races that can cast spells
case CLASS_TYPE_DRAGON: iData |= 0x03; break;
case CLASS_TYPE_SHAPECHANGER: iData |= 0x03; break;
case CLASS_TYPE_OUTSIDER: iData |= 0x03; break;
case CLASS_TYPE_ABERRATION: iData |= 0x03; break;
case CLASS_TYPE_MONSTROUS: iData |= 0x03; break;
case CLASS_TYPE_FEY: iData |= 0x03; break;
}
if(sScript != "")
SetPersistantLocalString(oPC, "PRC_Class_Script"+IntToString(i), sScript);
}
if (DEBUG) DoDebug("SetupCharacterData Class: " + IntToString(nClassType));
if (DEBUG) DoDebug("SetupCharacterData Data: " + IntToString(iData));
}
if(iData)
SetPersistantLocalInt(oPC, "PRC_Class_Data", iData);
if(iShifting)
SetPersistantLocalInt(oPC, "PRC_UNI_SHIFT_SCRIPT", 1);
//Setup class info for onleveldown script
int nCharData = ((GetClassByPosition(8, oPC) & 0xFF) << 56) |
((GetClassByPosition(7, oPC) & 0xFF) << 48) |
((GetClassByPosition(6, oPC) & 0xFF) << 40) |
((GetClassByPosition(5, oPC) & 0xFF) << 32) |
((GetClassByPosition(4, oPC) & 0xFF) << 24) |
((GetClassByPosition(3, oPC) & 0xFF) << 16) |
((GetClassByPosition(2, oPC) & 0xFF) << 8) |
(GetClassByPosition(1, oPC) & 0xFF);
SetPersistantLocalInt(oPC, "PRC_Character_Data", nCharData);
}
void DelayedExecuteScript(int nExpectedGeneration, string sScriptName, object oPC)
{
if (nExpectedGeneration != GetLocalInt(oPC, PRC_EvalPRCFeats_Generation))
{
//Generation has changed, so don't apply the effect
return;
}
ExecuteScript(sScriptName, oPC);
}
void DelayedReApplyUnhealableAbilityDamage(int nExpectedGeneration, object oPC)
{
if (nExpectedGeneration != GetLocalInt(oPC, PRC_ScrubPCSkin_Generation))
{
//Generation has changed, so don't apply the effect
return;
}
ReApplyUnhealableAbilityDamage(oPC);
}
int ToBFeats(object oPC)
{
if(GetHasFeat(FEAT_SHADOW_BLADE, oPC) ||
GetHasFeat(FEAT_RAPID_ASSAULT, oPC) ||
GetHasFeat(FEAT_DESERT_WIND_DODGE, oPC) ||
GetHasFeat(FEAT_DESERT_FIRE, oPC) ||
GetHasFeat(FEAT_IRONHEART_AURA, oPC) ||
GetHasFeat(FEAT_SHADOW_TRICKSTER, oPC) ||
GetHasFeat(FEAT_WHITE_RAVEN_DEFENSE, oPC) ||
GetHasFeat(FEAT_DEVOTED_BULWARK, oPC) ||
GetHasFeat(FEAT_SNAP_KICK, oPC) ||
GetHasFeat(FEAT_THREE_MOUNTAINS, oPC) ||
GetHasFeat(FEAT_VAE_SCHOOL, oPC) ||
GetHasFeat(FEAT_INLINDL_SCHOOL, oPC) ||
GetHasFeat(FEAT_XANIQOS_SCHOOL, oPC) ||
GetHasFeat(FEAT_SHIELD_WALL, oPC) ||
GetHasFeat(FEAT_CROSSBOW_SNIPER, oPC) ||
GetHasFeat(FEAT_CRESCENT_MOON, oPC) ||
GetHasFeat(FEAT_QUICK_STAFF, oPC) ||
GetHasFeat(FEAT_BEAR_FANG, oPC) ||
GetHasFeat(FEAT_IMPROVED_RAPID_SHOT, oPC) ||
GetHasFeat(FEAT_DIRE_FLAIL_SMASH, oPC) ||
GetHasFeat(FEAT_SHIELD_SPECIALIZATION_LIGHT, oPC) ||
GetHasFeat(FEAT_SHIELD_SPECIALIZATION_HEAVY, oPC) ||
GetHasFeat(FEAT_FOCUSED_SHIELD, oPC) ||
GetHasFeat(FEAT_SHIELDMATE, oPC) ||
GetHasFeat(FEAT_IMPROVED_SHIELDMATE, oPC) ||
GetHasFeat(FEAT_SHIELDED_CASTING, oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_DESERT_WIND , oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_DEVOTED_SPIRIT, oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_DIAMOND_MIND , oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_IRON_HEART , oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_SETTING_SUN , oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_SHADOW_HAND , oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_STONE_DRAGON , oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_TIGER_CLAW , oPC) ||
GetHasFeat(FEAT_BLADE_MEDITATION_WHITE_RAVEN , oPC) ||
GetRacialType(oPC) == RACIAL_TYPE_RETH_DEKALA ||
GetRacialType(oPC) == RACIAL_TYPE_HADRIMOI)
return TRUE;
return FALSE;
}
void EvalPRCFeats(object oPC)
{
// Player is currently making character in ConvoCC
// don't run EvalPRCFeats() yet
if(oPC == GetLocalObject(GetModule(), "ccc_active_pc"))
return;
int nGeneration = PRC_NextGeneration(GetLocalInt(oPC, PRC_EvalPRCFeats_Generation));
if (DEBUG > 1) DoDebug("EvalPRCFeats Generation: " + IntToString(nGeneration));
SetLocalInt(oPC, PRC_EvalPRCFeats_Generation, nGeneration);
//permanent ability changes
if(GetPRCSwitch(PRC_NWNX_FUNCS))
ExecuteScript("prc_nwnx_funcs", oPC);
//Add IP Feats to the hide
DelayCommand(0.0f, DelayedAddIPFeats(nGeneration, oPC));
// If there is a bonus domain, it will always be in the first slot, so just check that.
// It also runs things that clerics with those domains need
if (GetPersistantLocalInt(oPC, "PRCBonusDomain1") > 0 || GetLevelByClass(CLASS_TYPE_CLERIC, oPC) || GetLevelByClass(CLASS_TYPE_SHAMAN, oPC))
DelayCommand(0.1f, ExecuteScript("prc_domain_skin", oPC));
// special add atk bonus equal to Enhancement
ExecuteScript("ft_sanctmartial", oPC);
//hook in the weapon size restrictions script
//ExecuteScript("prc_restwpnsize", oPC);
//Route the event to the appropriate class specific scripts
int i, iData;
string sScript;
for (i = 1; i <= 8; i++)
{
sScript = GetPersistantLocalString(oPC, "PRC_Class_Script"+IntToString(i));
if(sScript != "")
{
if (DEBUG) DoDebug("PRC_Class_Script: "+sScript);
ExecuteScript(sScript, oPC);
}
}
iData = GetPersistantLocalInt(oPC, "PRC_Class_Data");
// Handle alternate caster types gaining new stuff
if(iData & 0x01)
ExecuteScript("prc_amagsys_gain", oPC);
// Add ip feats for spontaneous casters using metamagic
if(iData & 0x02)
ExecuteScript("prc_metamagic", oPC);
// Handle classes with reduced arcane spell failure
if(iData & 0x04)
ExecuteScript("prc_reducedasf", oPC);
if(GetPersistantLocalInt(oPC, "PRC_UNI_SHIFT_SCRIPT"))
//Executing shifter-related stuff like this has these advantages:
//1) All races and classes that need it can get it without a different script needing to be created for each.
//2) PCs with shifter-related stuff from multiple classes or races don't run the same functions multiple times.
ExecuteScript("prc_uni_shift", oPC);
// Templates
//these go here so feats can be reused
ExecuteScript("prc_templates", oPC);
// Feats
//these are here so if templates add them the if check runs after the template was applied
ExecuteScript("prc_feats", oPC);
if (ToBFeats(oPC))
ExecuteScript("tob_feats", oPC);
if (GetIsIncarnumUser(oPC) || GetRacialType(oPC) == RACIAL_TYPE_JAEBRIN)
ExecuteScript("moi_events", oPC);
if (GetIsBinder(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
if(GetPRCSwitch(PRC_CRAFTING_BASE_ITEMS))
DelayCommand(0.5f, ExecuteScript("prc_crftbaseitms", oPC));
// Add the teleport management feats.
// 2005.11.03: Now added to all base classes on 1st level - Ornedan
// ExecuteScript("prc_tp_mgmt_eval", oPC);
// Size changes. Removed due to double-dipping most size adjustments
//ExecuteScript("prc_size", oPC);
// Speed changes
// The local int is for when items are requipped too quickly and this script bugs out
if (!GetLocalInt(oPC, "PRCSpeedDelay"))
{
ExecuteScript("prc_speed", oPC);
SetLocalInt(oPC, "PRCSpeedDelay", TRUE);
DelayCommand(0.15, DeleteLocalInt(oPC, "PRCSpeedDelay"));
}
// ACP system
if((GetIsPC(oPC) &&
(GetPRCSwitch(PRC_ACP_MANUAL) ||
GetPRCSwitch(PRC_ACP_AUTOMATIC)
)
) ||
(!GetIsPC(oPC) &&
GetPRCSwitch(PRC_ACP_NPC_AUTOMATIC)
)
)
ExecuteScript("acp_auto", oPC);
// this is handled inside the PRC Options conversation now.
/* // Epic spells
if((GetCasterLvl(CLASS_TYPE_CLERIC, oPC) >= 21 ||
GetCasterLvl(CLASS_TYPE_DRUID, oPC) >= 21 ||
GetCasterLvl(CLASS_TYPE_SORCERER, oPC) >= 21 ||
GetCasterLvl(CLASS_TYPE_FAVOURED_SOUL, oPC) >= 21 ||
GetCasterLvl(CLASS_TYPE_HEALER, oPC) >= 21 ||
GetCasterLvl(CLASS_TYPE_WIZARD, oPC) >= 21
) &&
!GetHasFeat(FEAT_EPIC_SPELLCASTING_REST, oPC)
)
{
IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_FEAT_EPIC_REST), 0.0f,
X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}*/
// Miscellaneous
ExecuteScript("prc_sneak_att", oPC);
ExecuteScript("race_skin", oPC);
ExecuteScript("prc_mithral", oPC);
if(GetPRCSwitch(PRC_ENFORCE_RACIAL_APPEARANCE) && GetIsPC(oPC))
ExecuteScript("race_appear", oPC);
//Reserve Feats
if(!GetLocalInt(oPC, "ReserveFeatsRunning"))
{
if(GetHasFeat(FEAT_HOLY_WARRIOR, oPC) ||
GetHasFeat(FEAT_MYSTIC_BACKLASH, oPC) ||
GetHasFeat(FEAT_ACIDIC_SPLATTER, oPC) ||
GetHasFeat(FEAT_FIERY_BURST, oPC) ||
GetHasFeat(FEAT_STORM_BOLT, oPC) ||
GetHasFeat(FEAT_WINTERS_BLAST, oPC) ||
GetHasFeat(FEAT_CLAP_OF_THUNDER, oPC) ||
GetHasFeat(FEAT_SICKENING_GRASP, oPC) ||
GetHasFeat(FEAT_TOUCH_OF_HEALING, oPC) ||
GetHasFeat(FEAT_DIMENSIONAL_JAUNT, oPC) ||
GetHasFeat(FEAT_CLUTCH_OF_EARTH, oPC) ||
GetHasFeat(FEAT_BORNE_ALOFT, oPC) ||
GetHasFeat(FEAT_PROTECTIVE_WARD, oPC) ||
GetHasFeat(FEAT_SHADOW_VEIL, oPC) ||
GetHasFeat(FEAT_SUNLIGHT_EYES, oPC) ||
GetHasFeat(FEAT_TOUCH_OF_DISTRACTION, oPC) ||
GetHasFeat(FEAT_UMBRAL_SHROUD, oPC) ||
GetHasFeat(FEAT_CHARNEL_MIASMA, oPC) ||
GetHasFeat(FEAT_DROWNING_GLANCE, oPC) ||
GetHasFeat(FEAT_INVISIBLE_NEEDLE, oPC) ||
GetHasFeat(FEAT_SUMMON_ELEMENTAL, oPC) ||
GetHasFeat(FEAT_DIMENSIONAL_REACH, oPC) ||
GetHasFeat(FEAT_HURRICANE_BREATH, oPC) ||
GetHasFeat(FEAT_MINOR_SHAPESHIFT, oPC) ||
GetHasFeat(FEAT_FACECHANGER, oPC))
{
ExecuteScript("prc_reservefeat", oPC);
}
}
/*if(// Psionics
GetLevelByClass(CLASS_TYPE_PSION, oPC) ||
GetLevelByClass(CLASS_TYPE_WILDER, oPC) ||
GetLevelByClass(CLASS_TYPE_PSYWAR, oPC) ||
GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oPC) ||
GetLevelByClass(CLASS_TYPE_WARMIND, oPC) ||
// New spellbooks
GetLevelByClass(CLASS_TYPE_BARD, oPC) ||
GetLevelByClass(CLASS_TYPE_SORCERER, oPC) ||
GetLevelByClass(CLASS_TYPE_SUEL_ARCHANAMACH, oPC) ||
GetLevelByClass(CLASS_TYPE_FAVOURED_SOUL, oPC) ||
GetLevelByClass(CLASS_TYPE_MYSTIC, oPC) ||
GetLevelByClass(CLASS_TYPE_HEXBLADE, oPC) ||
GetLevelByClass(CLASS_TYPE_DUSKBLADE, oPC) ||
GetLevelByClass(CLASS_TYPE_WARMAGE, oPC) ||
GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER,oPC) ||
GetLevelByClass(CLASS_TYPE_JUSTICEWW, oPC) ||
GetLevelByClass(CLASS_TYPE_WITCH, oPC) ||
GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oPC) ||
GetLevelByClass(CLASS_TYPE_ARCHIVIST, oPC) ||
GetLevelByClass(CLASS_TYPE_BEGUILER, oPC) ||
GetLevelByClass(CLASS_TYPE_HARPER, oPC) ||
GetLevelByClass(CLASS_TYPE_TEMPLAR, oPC) ||
// Truenaming
GetLevelByClass(CLASS_TYPE_TRUENAMER, oPC) ||
// Tome of Battle
GetLevelByClass(CLASS_TYPE_CRUSADER, oPC) ||
GetLevelByClass(CLASS_TYPE_SWORDSAGE, oPC) ||
GetLevelByClass(CLASS_TYPE_WARBLADE, oPC) ||
// Invocations
GetLevelByClass(CLASS_TYPE_DRAGONFIRE_ADEPT, oPC) ||
GetLevelByClass(CLASS_TYPE_WARLOCK, oPC) ||
// Racial casters
(GetLevelByClass(CLASS_TYPE_OUTSIDER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
)
{
DelayCommand(1.0, DelayedExecuteScript(nGeneration, "prc_amagsys_gain", oPC));
//add selectable metamagic feats for spontaneous spellcasters
ExecuteScript("prc_metamagic", oPC);
}*/
// Gathers all the calls to UnarmedFists & Feats to one place.
// Must be after all evaluationscripts that need said functions.
//if(GetLocalInt(oPC, "CALL_UNARMED_FEATS") || GetLocalInt(oPC, "CALL_UNARMED_FISTS")) // ExecuteScript() is pretty expensive, do not run it needlessly - 20060702, Ornedan
ExecuteScript("unarmed_caller", oPC);
// Gathers all the calls to SetBaseAttackBonus() to one place
// Must be after all evaluationscripts that need said function.
ExecuteScript("prc_bab_caller", oPC);
// Classes an invoker can take
if( GetLevelByClass(CLASS_TYPE_ABJURANT_CHAMPION, oPC) ||
GetLevelByClass(CLASS_TYPE_ACOLYTE, oPC) ||
GetLevelByClass(CLASS_TYPE_ANIMA_MAGE, oPC) ||
GetLevelByClass(CLASS_TYPE_ARCTRICK, oPC) ||
GetLevelByClass(CLASS_TYPE_BLOOD_MAGUS, oPC) ||
GetLevelByClass(CLASS_TYPE_DISCIPLE_OF_ASMODEUS, oPC) ||
GetLevelByClass(CLASS_TYPE_ENLIGHTENEDFIST, oPC) ||
GetLevelByClass(CLASS_TYPE_MAESTER, oPC) ||
GetLevelByClass(CLASS_TYPE_TALON_OF_TIAMAT, oPC) ||
GetLevelByClass(CLASS_TYPE_UNSEEN_SEER, oPC) ||
GetLevelByClass(CLASS_TYPE_VIRTUOSO, oPC) ||
GetLevelByClass(CLASS_TYPE_WILD_MAGE, oPC))
{
//Arcane caster first class position, take arcane
if(GetFirstArcaneClassPosition(oPC) == 1)
SetLocalInt(oPC, "INV_Caster", 1);
//Invoker first class position. take invoker
else if(GetClassByPosition(1, oPC) == CLASS_TYPE_WARLOCK || GetClassByPosition(1, oPC) == CLASS_TYPE_DRAGONFIRE_ADEPT)
SetLocalInt(oPC, "INV_Caster", 2);
//Non arcane first class position, invoker second. Take invoker
else if(GetFirstArcaneClassPosition(oPC) ==0 && (GetClassByPosition(2, oPC) == CLASS_TYPE_WARLOCK || GetClassByPosition(2, oPC) == CLASS_TYPE_DRAGONFIRE_ADEPT))
SetLocalInt(oPC, "INV_Caster", 2);
//last class would be Non-invoker first class position, arcane second position. take arcane.
else
SetLocalInt(oPC, "INV_Caster", 1);
//:: Set arcane or invocation bonus caster levels
if ( GetLevelByClass(CLASS_TYPE_ABJURANT_CHAMPION, oPC) > 0 &&
GetHasFeat(FEAT_ABCHAMP_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_ACOLYTE, oPC) > 0 &&
GetHasFeat(FEAT_AOTS_NONE, oPC) || GetHasFeat(FEAT_AOTS_MYSTERY_SHADOWCASTER, oPC) || GetHasFeat(FEAT_AOTS_MYSTERY_SHADOWSMITH, oPC))
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_ANIMA_MAGE, oPC) > 0 &&
GetHasFeat(FEAT_ANIMA_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_ARCTRICK, oPC) > 0 &&
GetHasFeat(FEAT_ARCTRICK_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_BLOOD_MAGUS, oPC) > 0 &&
GetHasFeat(FEAT_BLDMAGUS_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_DISCIPLE_OF_ASMODEUS, oPC) > 0 &&
GetHasFeat(FEAT_ASMODEUS_NONE, oPC) || GetHasFeat(FEAT_ASMODEUS_MYSTERY_SHADOWCASTER, oPC) || GetHasFeat(FEAT_ASMODEUS_MYSTERY_SHADOWSMITH, oPC))
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_ENLIGHTENEDFIST, oPC) > 0 &&
GetHasFeat(FEAT_ENLIGHTENEDFIST_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_MAESTER, oPC) > 0 &&
GetHasFeat(FEAT_MAESTER_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_TALON_OF_TIAMAT, oPC) > 0 &&
GetHasFeat(FEAT_TIAMAT_NONE, oPC) || GetHasFeat(FEAT_TIAMAT_MYSTERY_SHADOWCASTER, oPC) || GetHasFeat(FEAT_TIAMAT_MYSTERY_SHADOWSMITH, oPC))
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_UNSEEN_SEER, oPC) > 0 &&
GetHasFeat(FEAT_UNSEEN_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_VIRTUOSO, oPC) > 0 &&
GetHasFeat(FEAT_VIRTUOSO_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
if ( GetLevelByClass(CLASS_TYPE_WILD_MAGE, oPC) > 0 &&
GetHasFeat(FEAT_WILDMAGE_NONE, oPC) )
{
SetLocalInt(oPC, "INV_Caster", 1);
}
else
{
SetLocalInt(oPC, "INV_Caster", 2);
}
/* //Arcane caster first class position, take arcane
if(GetFirstArcaneClassPosition(oPC) == 1)
SetLocalInt(oPC, "INV_Caster", 1);
//Invoker first class position. take invoker
else if(GetClassByPosition(1, oPC) == CLASS_TYPE_WARLOCK || GetClassByPosition(1, oPC) == CLASS_TYPE_DRAGONFIRE_ADEPT)
SetLocalInt(oPC, "INV_Caster", 2);
//Non arcane first class position, invoker second. Take invoker
else if(GetFirstArcaneClassPosition(oPC) ==0 && (GetClassByPosition(2, oPC) == CLASS_TYPE_WARLOCK || GetClassByPosition(2, oPC) == CLASS_TYPE_DRAGONFIRE_ADEPT))
SetLocalInt(oPC, "INV_Caster", 2);
//last class would be Non-invoker first class position, arcane second position. take arcane.
else
SetLocalInt(oPC, "INV_Caster", 1); */
}
}
void DelayedAddIPFeats(int nExpectedGeneration, object oPC)
{
if (nExpectedGeneration != GetLocalInt(oPC, PRC_EvalPRCFeats_Generation))
{
//Generation has changed, so don't apply the effect
return;
}
object oSkin = GetPCSkin(oPC);
//Horse menu
AddSkinFeat(FEAT_HORSE_MENU, 40, oSkin, oPC);
// Switch convo feat
//Now everyone gets it at level 1, but just to be on the safe side
AddSkinFeat(FEAT_OPTIONS_CONVERSATION, 229, oSkin, oPC);
//PnP familiars
if(GetHasFeat(FEAT_SUMMON_FAMILIAR, oPC) && GetPRCSwitch(PRC_PNP_FAMILIARS))
IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_PNP_FAMILIAR), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
else if(!GetHasFeat(FEAT_SUMMON_FAMILIAR, oPC) || !GetPRCSwitch(PRC_PNP_FAMILIARS))
RemoveItemProperty(oSkin, ItemPropertyBonusFeat(IP_CONST_PNP_FAMILIAR));
//PnP Spell Schools
if(GetPRCSwitch(PRC_PNP_SPELL_SCHOOLS)
&& GetLevelByClass(CLASS_TYPE_WIZARD, oPC)
&& !GetIsPolyMorphedOrShifted(oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_GENERAL, oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_ABJURATION, oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_CONJURATION, oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_DIVINATION, oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_ENCHANTMENT, oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_EVOCATION, oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_ILLUSION, oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_NECROMANCY, oPC)
&& !GetHasFeat(FEAT_PNP_SPELL_SCHOOL_TRANSMUTATION, oPC)
//&& !PRCGetHasEffect(EFFECT_TYPE_POLYMORPH, oPC) //so it doesnt pop up on polymorphing
//&& !GetLocalInt(oSkin, "nPCShifted") //so it doenst pop up on shifting
)
{
if(GetXP(oPC))// ConvoCC compatibility fix
ExecuteScript("prc_pnp_shcc_s", oPC);
}
/*//Arcane Archer old imbue arrow
if(GetLevelByClass(CLASS_TYPE_ARCANE_ARCHER, oPC) >= 2
&& !GetHasFeat(FEAT_PRESTIGE_IMBUE_ARROW, oPC)
&& GetPRCSwitch(PRC_PNP_SPELL_SCHOOLS))
{
//add the old feat to the hide
IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_FEAT_FEAT_PRESTIGE_IMBUE_ARROW), 0.0f,
X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}*/
//handle PnP sling switch
if(GetPRCSwitch(PRC_PNP_SLINGS))
{
if(GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC)) == BASE_ITEM_SLING)
IPSafeAddItemProperty(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC),
ItemPropertyMaxRangeStrengthMod(20),
999999.9);
}
}
void TemplateSLAs(object oPC)
{
int i;
for(i = TEMPLATE_SLA_START; i <= TEMPLATE_SLA_END; i++)
{
DeleteLocalInt(oPC, "TemplateSLA_"+IntToString(i));
}
}
void DeletePRCLocalInts(object oSkin)
{
// This will get rid of any SetCompositeAttackBonus LocalInts:
object oPC = GetItemPossessor(oSkin);
DeleteLocalInt(oPC, "CompositeAttackBonusR");
DeleteLocalInt(oPC, "CompositeAttackBonusL");
//Do not use DelayCommand for this--it's too dangerous:
//if SetCompositeAttackBonus is called at the wrong time the result will be incorrect.
DeleteNamedComposites(oPC, "PRC_ComAttBon");
// PRCGetClassByPosition and PRCGetLevelByPosition cleanup
// not needed now that GetClassByPosition() works for custom classes
// DeleteLocalInt(oPC, "PRC_ClassInPos1");
// DeleteLocalInt(oPC, "PRC_ClassInPos2");
// DeleteLocalInt(oPC, "PRC_ClassInPos3");
// DeleteLocalInt(oPC, "PRC_ClassLevelInPos1");
// DeleteLocalInt(oPC, "PRC_ClassLevelInPos2");
// DeleteLocalInt(oPC, "PRC_ClassLevelInPos3");
//persistant local token object cache
//looks like logging off then back on without the server rebooting breaks it
//I guess because the token gets a new ID, but the local still points to the old one
DeleteLocalObject(oPC, "PRC_HideTokenCache");
DeleteLocalInt(oSkin, "PRC_ArcaneSpellFailure");
DeleteLocalInt(oPC, "PRC_SwiftActionUsed");
DeleteLocalInt(oPC, "PRC_MoveActionUsed");
// In order to work with the PRC system we need to delete some locals for each
// PRC that has a hide
//Do not use DelayCommand for this--it's too dangerous:
//if SetCompositeBonus is called between the time EvalPRCFeats removes item properties
//and the time this delayed command is executed, the result will be incorrect.
//Since this error case actually happens frequently with any delay here, just don't do it.
DeleteNamedComposites(oSkin, "PRC_CBon");
if (DEBUG) DoDebug("Clearing class flags");
// Elemental Savants
DeleteLocalInt(oSkin,"ElemSavantResist");
DeleteLocalInt(oSkin,"ElemSavantPerfection");
DeleteLocalInt(oSkin,"ElemSavantImmMind");
DeleteLocalInt(oSkin,"ElemSavantImmParal");
DeleteLocalInt(oSkin,"ElemSavantImmSleep");
// HeartWarder
DeleteLocalInt(oSkin,"FeyType");
// OozeMaster
DeleteLocalInt(oSkin,"IndiscernibleCrit");
DeleteLocalInt(oSkin,"IndiscernibleBS");
DeleteLocalInt(oSkin,"OneOozeMind");
DeleteLocalInt(oSkin,"OneOozePoison");
// Storm lord
DeleteLocalInt(oSkin,"StormLResElec");
// Spell sword
DeleteLocalInt(oSkin,"SpellswordSFBonusNormal");
DeleteLocalInt(oSkin,"SpellswordSFBonusEpic");
// Acolyte of the skin
DeleteLocalInt(oSkin,"AcolyteSymbBonus");
DeleteLocalInt(oSkin,"AcolyteResistanceCold");
DeleteLocalInt(oSkin,"AcolyteResistanceFire");
DeleteLocalInt(oSkin,"AcolyteResistanceAcid");
DeleteLocalInt(oSkin,"AcolyteResistanceElectric");
// Battleguard of Tempus
DeleteLocalInt(oSkin,"FEAT_WEAP_TEMPUS");
// Bonded Summoner
DeleteLocalInt(oSkin,"BondResEle");
DeleteLocalInt(oSkin,"BondSubType");
// Disciple of Meph
DeleteLocalInt(oSkin,"DiscMephResist");
DeleteLocalInt(oSkin,"DiscMephGlove");
// Initiate of Draconic Mysteries
DeleteLocalInt(oSkin,"IniSR");
DeleteLocalInt(oSkin,"IniStunStrk");
// Man at Arms
DeleteLocalInt(oSkin,"ManArmsCore");
// Telflammar Shadowlord
DeleteLocalInt(oSkin,"ShaDiscorp");
// Vile Feats
DeleteLocalInt(oSkin,"DeformGaunt");
DeleteLocalInt(oSkin,"DeformObese");
// Sneak Attack
DeleteLocalInt(oSkin,"RogueSneakDice");
DeleteLocalInt(oSkin,"BlackguardSneakDice");
// Sacred Fist
DeleteLocalInt(oSkin,"SacFisMv");
// Minstrel
DeleteLocalInt(oSkin,"MinstrelSFBonus"); /// @todo Make ASF reduction compositable
// Nightshade
DeleteLocalInt(oSkin,"ImmuNSWeb");
DeleteLocalInt(oSkin,"ImmuNSPoison");
// Soldier of Light
DeleteLocalInt(oSkin,"ImmuPF");
// Ultimate Ranger
DeleteLocalInt(oSkin,"URImmu");
// Thayan Knight
DeleteLocalInt(oSkin,"ThayHorror");
DeleteLocalInt(oSkin,"ThayZulkFave");
DeleteLocalInt(oSkin,"ThayZulkChamp");
// Black Flame Zealot
DeleteLocalInt(oSkin,"BFZHeart");
// Henshin Mystic
DeleteLocalInt(oSkin,"Happo");
DeleteLocalInt(oSkin,"HMInvul");
//Blightlord
DeleteLocalInt(oSkin, "WntrHeart");
DeleteLocalInt(oSkin, "BlightBlood");
// Contemplative
DeleteLocalInt(oSkin, "ContempDisease");
DeleteLocalInt(oSkin, "ContempPoison");
DeleteLocalInt(oSkin, "ContemplativeDR");
DeleteLocalInt(oSkin, "ContemplativeSR");
// Dread Necromancer
DeleteLocalInt(oSkin, "DNDamageResist");
// Warsling Sniper
DeleteLocalInt(oPC, "CanRicochet");
// Blood Magus
DeleteLocalInt(oSkin, "ThickerThanWater");
// Feats
DeleteLocalInt(oPC, "ForceOfPersonalityWis");
DeleteLocalInt(oPC, "ForceOfPersonalityCha");
DeleteLocalInt(oPC, "InsightfulReflexesInt");
DeleteLocalInt(oPC, "InsightfulReflexesDex");
DeleteLocalInt(oSkin, "TactileTrapsmithSearchIncrease");
DeleteLocalInt(oSkin, "TactileTrapsmithDisableIncrease");
DeleteLocalInt(oSkin, "TactileTrapsmithSearchDecrease");
DeleteLocalInt(oSkin, "TactileTrapsmithDisableDecrease");
// Warmind
DeleteLocalInt(oSkin, "EnduringBody");
// Ironmind
DeleteLocalInt(oSkin, "IronMind_DR");
// Suel Archanamach
DeleteLocalInt(oSkin, "SuelArchanamachSpellFailure");
// Favoured Soul
DeleteLocalInt(oSkin, "FavouredSoulResistElementAcid");
DeleteLocalInt(oSkin, "FavouredSoulResistElementCold");
DeleteLocalInt(oSkin, "FavouredSoulResistElementElec");
DeleteLocalInt(oSkin, "FavouredSoulResistElementFire");
DeleteLocalInt(oSkin, "FavouredSoulResistElementSonic");
DeleteLocalInt(oSkin, "FavouredSoulDR");
// Domains
DeleteLocalInt(oSkin, "StormDomainPower");
// Skullclan Hunter
DeleteLocalInt(oSkin, "SkullClanFear");
DeleteLocalInt(oSkin, "SkullClanDisease");
DeleteLocalInt(oSkin, "SkullClanProtectionEvil");
DeleteLocalInt(oSkin, "SkullClanSwordLight");
DeleteLocalInt(oSkin, "SkullClanParalysis");
DeleteLocalInt(oSkin, "SkullClanAbilityDrain");
DeleteLocalInt(oSkin, "SkullClanLevelDrain");
// Sohei
DeleteLocalInt(oSkin, "SoheiDamageResist");
// Dragon Disciple
DeleteLocalInt(oPC, "DragonDiscipleBreathWeaponUses");
//Dragon Shaman
DeleteLocalInt(oPC, "DragonShamanTotem");
//Warblade
DeleteLocalInt(oSkin, "PRC_WEAPON_APTITUDE_APPLIED");
//Shifter(PnP)
DeleteLocalInt(oSkin, "PRC_SHIFTER_TEMPLATE_APPLIED");
DeleteLocalInt(oPC, "ScoutFreeMove");
DeleteLocalInt(oPC, "ScoutFastMove");
DeleteLocalInt(oPC, "ScoutBlindsight");
//Truenamer
// Called elsewhere now
/*int UtterID;
for(UtterID = 3526; UtterID <= 3639; UtterID++) // All utterances
DeleteLocalInt(oPC, "PRC_LawOfResistance" + IntToString(UtterID));
for(UtterID = 3418; UtterID <= 3431; UtterID++) // Syllable of Detachment to Word of Heaven, Greater
DeleteLocalInt(oPC, "PRC_LawOfResistance" + IntToString(UtterID));*/
//Invocations
DeleteLocalInt(oPC, "ChillingFogLock");
//Endure Exposure wearing off
array_delete(oPC, "BreathProtected");
DeleteLocalInt(oPC, "DragonWard");
//Scry on Familiar
DeleteLocalInt(oPC, "Scry_Familiar");
// Undead HD
DeleteLocalInt(oPC, "PRCUndeadHD");
DeleteLocalInt(oPC, "PRCUndeadFSPen");
//Template Spell-Like Abilities
DelayCommand(0.5f, TemplateSLAs(oPC));
// future PRCs Go below here
}
void ScrubPCSkin(object oPC, object oSkin)
{
int nGeneration = PRC_NextGeneration(GetLocalInt(oPC, PRC_ScrubPCSkin_Generation));
if (DEBUG > 1) DoDebug("ScrubPCSkin Generation: " + IntToString(nGeneration));
SetLocalInt(oPC, PRC_ScrubPCSkin_Generation, nGeneration);
int iCode = GetHasFeat(FEAT_SF_CODE,oPC);
int ipType, st;
if(!(/*GetIsPolyMorphedOrShifted(oPC) || */GetIsObjectValid(GetMaster(oPC))))
{
itemproperty ip = GetFirstItemProperty(oSkin);
while(GetIsItemPropertyValid(ip))
{
// Insert Logic here to determine if we spare a property
ipType = GetItemPropertyType(ip);
if(ipType == ITEM_PROPERTY_BONUS_FEAT)
{
// Check for specific Bonus Feats
// Reference iprp_feats.2da
st = GetItemPropertySubType(ip);
// Spare 400 through 570 and 398 -- epic spells & spell effects
//also spare the new spellbook feats (1000-12000 & 17701-24704
//also spare the psionic, trunaming, tob, invocation feats (12000-16000)
// spare template, tob stuff (16300-17700)
// changed by fluffyamoeba so that iprp weapon specialization, dev crit, epic weapon focus, epic weapon spec
// overwhelming crit and weapon of choice are no longer skipped.
if ((st < 400 || st > 570)
&& st != 102 //:: ACP Feats
&& st != 586 //:: ACP Feats
&& st != 587 //:: ACP Feats
&& st != 398
&& (st < 1000 || st > 13520)
//&& (st < 1000 || st > 13999)
//&& (st < 14501 || st > 15999)
&& (st < 16300 || st > 24704)
&& (st < 223 || st > 226) // draconic feats
&& (st < 229 || st > 249) // Pnp spellschool feats and PRC options feat (231-249 & 229)
&& st != 259 // 259 - psionic focus
&& (st < 141 || st > 200) // 141 - shadowmaster shades, 142-151 bonus domains casting feats, 152 - 200 bonus domain powers
&& st != 26000 // Bullybasher Giant Bearing
&& ( (st == IP_CONST_FEAT_PRC_POWER_ATTACK_QUICKS_RADIAL ||
st == IP_CONST_FEAT_POWER_ATTACK_SINGLE_RADIAL ||
st == IP_CONST_FEAT_POWER_ATTACK_FIVES_RADIAL) ? // Remove the PRC Power Attack radials if the character no longer has Power Attack
!GetHasFeat(FEAT_POWER_ATTACK, oPC) :
TRUE // If the feat is not relevant to this clause, always pass
)
)
RemoveItemProperty(oSkin, ip);
}
else if(ipType == ITEM_PROPERTY_BONUS_SPELL_SLOT_OF_LEVEL_N)
{
//bonus spellslots code here
//st = GetItemPropertySubType(ip);
RemoveItemProperty(oSkin, ip);
}
else
RemoveItemProperty(oSkin, ip);
// Get the next property
ip = GetNextItemProperty(oSkin);
}
}
if(iCode)
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(381),oSkin);
// Schedule restoring the unhealable ability damage
DelayCommand(0.1f, DelayedReApplyUnhealableAbilityDamage(nGeneration, oPC));
// Remove all natural weapons too
// ClearNaturalWeapons(oPC);
// Done this way to remove prc_inc_natweap and prc_inc_combat from the include
// Should help with compile speeds and the like
//array_delete(oPC, "ARRAY_NAT_SEC_WEAP_RESREF");
//array_delete(oPC, "ARRAY_NAT_PRI_WEAP_RESREF");
//array_delete(oPC, "ARRAY_NAT_PRI_WEAP_ATTACKS");
}
int BlastInfidelOrFaithHeal(object oCaster, object oTarget, int iEnergyType, int iDisplayFeedback)
{
//Don't bother doing anything if iEnergyType isn't either positive/negative energy
if(iEnergyType != DAMAGE_TYPE_POSITIVE && iEnergyType != DAMAGE_TYPE_NEGATIVE)
return FALSE;
//If the target is undead and damage type is negative
//or if the target is living and damage type is positive
//then we're healing. Otherwise, we're harming.
int iTombTainted = GetHasFeat(FEAT_TOMB_TAINTED_SOUL, oTarget) && GetAlignmentGoodEvil(oTarget) != ALIGNMENT_GOOD;
int iHeal = ( iEnergyType == DAMAGE_TYPE_NEGATIVE && (MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD || iTombTainted)) ||
( iEnergyType == DAMAGE_TYPE_POSITIVE && MyPRCGetRacialType(oTarget) != RACIAL_TYPE_UNDEAD && !iTombTainted);
int iRetVal = FALSE;
int iAlignDif = CompareAlignment(oCaster, oTarget);
string sFeedback = "";
if(iHeal){
if((GetHasFeat(FEAT_FAITH_HEALING, oCaster) && iAlignDif < 2)){
iRetVal = TRUE;
sFeedback = "Faith Healing";
}
}
else{
if((GetHasFeat(FEAT_BLAST_INFIDEL, oCaster) && iAlignDif >= 2)){
iRetVal = TRUE;
sFeedback = "Blast Infidel";
}
}
if(iDisplayFeedback) FloatingTextStringOnCreature(sFeedback, oCaster);
return iRetVal;
}
int GetShiftingFeats(object oPC)
{
int nNumFeats;
nNumFeats = GetHasFeat(FEAT_BEASTHIDE_ELITE, oPC)
+ GetHasFeat(FEAT_DREAMSIGHT_ELITE, oPC)
+ GetHasFeat(FEAT_GOREBRUTE_ELITE, oPC)
+ GetHasFeat(FEAT_LONGSTRIDE_ELITE, oPC)
+ GetHasFeat(FEAT_LONGTOOTH_ELITE, oPC)
+ GetHasFeat(FEAT_RAZORCLAW_ELITE, oPC)
+ GetHasFeat(FEAT_WILDHUNT_ELITE, oPC)
+ GetHasFeat(FEAT_EXTRA_SHIFTER_TRAIT, oPC)
+ GetHasFeat(FEAT_HEALING_FACTOR, oPC)
+ GetHasFeat(FEAT_SHIFTER_AGILITY, oPC)
+ GetHasFeat(FEAT_SHIFTER_DEFENSE, oPC)
+ GetHasFeat(FEAT_GREATER_SHIFTER_DEFENSE, oPC)
+ GetHasFeat(FEAT_SHIFTER_FEROCITY, oPC)
+ GetHasFeat(FEAT_SHIFTER_INSTINCTS, oPC)
+ GetHasFeat(FEAT_SHIFTER_SAVAGERY, oPC);
return nNumFeats;
}
//Including DelayedApplyEffectToObject here because it is often used in conjunction with EvalPRCFeats and I don't know a better place to put it
void DelayedApplyEffectToObject(int nExpectedGeneration, int nCurrentGeneration, int nDuration, effect eEffect, object oTarget, float fDuration)
{
if (nExpectedGeneration != nCurrentGeneration)
{
//Generation has changed, so don't apply the effect
return;
}
ApplyEffectToObject(nDuration, eEffect, oTarget, fDuration);
}
//Including DelayedApplyEffectToObject here because it is often used in conjunction with EvalPRCFeats and I don't know a better place to put it
void DelayApplyEffectToObject(float fDelay, string sGenerationName, int nDuration, effect eEffect, object oTarget, float fDuration = 0.0f)
{
/*
There are a couple of problems that can arise in code that removes and reapplies effects;
this function helps deal with those problems. One example of a typical place where these problems
frequently arise is in the class scripts called by the EvalPRCFeats function.
The first problem is that when code removes and immediately reapplies a series of effects,
some of those effects may not actually be reapplied. This is because the RemoveEffect() function
doesn't actually remove an effect, it marks it to be removed later--when the currently running
script finishes. If any of the effects we reapply matches one of the effects marked to be
removed, that reapplied effect will be removed when the currently running script finishes
and so will be unexpectedly missing. To illustrate:
1) We start with effect A and B.
2) The application function is called; it removes all effects and reapplies effects B and C.
3) The actual removal happens when the script ends: effect A and B are removed.
End result: we have only effect C instead of the expected B and C.
The solution to this is to reapply the effects later using DelayCommand().
This introduces a new problem. If the function that removes and reapplies the effects is called
multiple times quickly, it can queue up a series of delayed applications. This causes two problems:
if the data on which the effects are calculated changes, the earlier delayed applications can
apply effects that should no longer be used, but they are anyway because the delayed code doesn't
know this. To illustrate:
1) The application function is called; it removes all effects, schedules delayed application of effect A.
2) The application function is called again; it removes all effects, schedules delayed application of effect B.
3) Delayed application of effect A occurs.
4) Delayed application of effect B occurs.
End result: we have both effect A and B instead of the expected result, B alone.
Another problem is that we can end up with multiple copies of the same effect.
If this happens enough, it can cause "Effect List overflow" errors. Also, if the effect stacks
with itself, this gives a greater bonus or penalty than it should. To illustrate:
1) The application function is called; it removes all effects, schedules delayed application of effect C.
2) The application function is called; it removes all effects, schedules delayed application of effect C.
3) Delayed application of effect C occurs.
4) Delayed application of effect C occurs.
End result: we have effect C twice instead of just once.
The solution is to both these problems is for the application function to increment an integer each time it
is called and to pass this to the delayed application function. The delayed application actually happens only
if the generation when it runs is the same as the generation when it was scheduled. To illustrate:
1) We start with effect A and B applied.
2) The application function is called: it increments generation to 2, schedules delayed application of effect B and C.
3) The application function is called: it increments generation to 3, schedules delayed application of effect C.
4) The generation 2 delayed application function executes: it sees that the current generation is 3 and simply exits, doing nothing.
5) The generation 3 delayed application function executes: it sees that the current generation is 3, so it applies effect C.
End result: we have one copy of effect C, which is what we wanted.
*/
if (fDelay < 0.0f || GetStringLength(sGenerationName) == 0)
{
ApplyEffectToObject(nDuration, eEffect, oTarget, fDuration);
}
else
{
int nExpectedGeneration = GetLocalInt(oTarget, sGenerationName); //This gets the generation now
DelayCommand(
fDelay,
DelayedApplyEffectToObject(
nExpectedGeneration,
GetLocalInt(oTarget, sGenerationName), //This is delayed by the DelayCommand, so it gets the generation when DelayedApplyEffectToObject is actually executed
nDuration,
eEffect,
oTarget,
fDuration
)
);
}
}
//Including DelayedAddItemProperty here to keep it with DelayedApplyEffectToObject, though more properly it should probably be in inc_item_props.nss
void DelayedAddItemProperty(int nExpectedGeneration, int nCurrentGeneration, int nDurationType, itemproperty ipProperty, object oItem, float fDuration)
{
if (nExpectedGeneration != nCurrentGeneration)
{
//Generation has changed, so don't apply the effect
return;
}
AddItemProperty(nDurationType, ipProperty, oItem, fDuration);
}
//Including DelayAddItemProperty here to keep it with DelayApplyEffectToObject, though more properly it should probably be in inc_item_props.nss
void DelayAddItemProperty(float fDelay, object oGenerationHolder, string sGenerationName, int nDurationType, itemproperty ipProperty, object oItem, float fDuration = 0.0f)
{
/*
There are a couple of problems that can arise in code that removes and reapplies item properties;
this function helps deal with those problems. One example of a typical place where these problems
frequently arise is in the class scripts called by the EvalPRCFeats function.
The first problem is that when code removes and immediately reapplies a series of item properties,
some of those properties may not actually be reapplied. This is because the RemoveItemProperty() function
doesn't actually remove a property, it marks it to be removed later--when the currently running
script finishes. If any of the properties we reapply matches one of the properties marked to be
removed, that reapplied property will be removed when the currently running script finishes
and so will be unexpectedly missing. To illustrate:
1) We start with properties A and B.
2) The application function is called; it removes all properties and reapplies properties B and C.
3) The actual removal happens when the script ends: property A and B are removed.
End result: we have only property C instead of the expected B and C.
The solution to this is to reapply the properties later using DelayCommand().
This introduces a new problem. If the function that removes and reapplies the properties is called
multiple times quickly, it can queue up a series of delayed applications. This causes two problems:
if the data on which the properties are calculated changes, the earlier delayed applications can
apply properties that should no longer be used, but they are anyway because the delayed code doesn't
know this. To illustrate:
1) The application function is called; it removes all properties, schedules delayed application of property A.
2) The application function is called again; it removes all properties, schedules delayed application of property B.
3) Delayed application of property A occurs.
4) Delayed application of property B occurs.
End result: we have both property A and B instead of the expected result, B alone.
Another problem is that we can end up with multiple copies of the same property.
If this happens enough, it can cause "Effect List overflow" errors. Also, if the property stacks
with itself, this gives a greater bonus or penalty than it should. To illustrate:
1) The application function is called; it removes all properties, schedules delayed application of property C.
2) The application function is called; it removes all properties, schedules delayed application of property C.
3) Delayed application of property C occurs.
4) Delayed application of property C occurs.
End result: we have property C twice instead of just once.
The solution is to both these problems is for the application function to increment an integer each time it
is called and to pass this to the delayed application function. The delayed application actually happens only
if the generation when it runs is the same as the generation when it was scheduled. To illustrate:
1) We start with property A and B applied.
2) The application function is called: it increments generation to 2, schedules delayed application of property B and C.
3) The application function is called: it increments generation to 3, schedules delayed application of property C.
4) The generation 2 delayed application function executes: it sees that the current generation is 3 and simply exits, doing nothing.
5) The generation 3 delayed application function executes: it sees that the current generation is 3, so it applies property C.
End result: we have one copy of property C, which is what we wanted.
*/
if (fDelay < 0.0f || GetStringLength(sGenerationName) == 0)
{
AddItemProperty(nDurationType, ipProperty, oItem, fDuration);
}
else
{
int nExpectedGeneration = GetLocalInt(oGenerationHolder, sGenerationName); //This gets the generation now
DelayCommand(
fDelay,
DelayedAddItemProperty(
nExpectedGeneration,
GetLocalInt(oGenerationHolder, sGenerationName), //This is delayed by the DelayCommand, so it gets the generation when DelayedAddItemProperty is actually executed
nDurationType,
ipProperty,
oItem,
fDuration
)
);
}
}
void FeatUsePerDay(object oPC, int iFeat, int iAbiMod = ABILITY_CHARISMA, int iMod = 0, int iMin = 1)
{
if(!GetHasFeat(iFeat,oPC))
return;
int iAbi = GetAbilityModifier(iAbiMod, oPC);
iAbi = (iAbi > 0) ? iAbi : 0;
if (iAbiMod == -1) iAbi = 0;
iAbi += iMod;
if(iAbi < iMin)
iAbi = iMin;
while(GetHasFeat(iFeat, oPC))
DecrementRemainingFeatUses(oPC, iFeat);
while(iAbi)
{
IncrementRemainingFeatUses(oPC, iFeat);
iAbi--;
}
}
void DomainUses(object oPC)
{
int nUses;
if(!GetHasFeat(FEAT_BONUS_DOMAIN_STRENGTH, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_STRENGTH_DOMAIN_POWER))
{
nUses = GetLevelByClass(CLASS_TYPE_MIGHTY_CONTENDER_KORD, oPC) ? GetAbilityModifier(ABILITY_STRENGTH, oPC) : 1;
FeatUsePerDay(oPC, FEAT_STRENGTH_DOMAIN_POWER, -1, nUses);
}
if(GetHasFeat(FEAT_BONUS_DOMAIN_SUN, oPC) && GetLevelByClass(CLASS_TYPE_MYSTIC, oPC) && PRC_Funcs_GetFeatKnown(oPC, FEAT_SUN_DOMAIN_POWER))
{
nUses = GetHasFeat(FEAT_EXTRA_TURNING, oPC) ? 7 : 3;
FeatUsePerDay(oPC, FEAT_SUN_DOMAIN_POWER, ABILITY_CHARISMA, nUses);
}
else if(!GetHasFeat(FEAT_BONUS_DOMAIN_SUN, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_SUN_DOMAIN_POWER))
FeatUsePerDay(oPC, FEAT_SUN_DOMAIN_POWER, -1, 1);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_BLIGHTBRINGER, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_DOMAIN_POWER_BLIGHTBRINGER))
FeatUsePerDay(oPC, FEAT_DOMAIN_POWER_BLIGHTBRINGER, ABILITY_CHARISMA, 3);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_AIR, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_AIR_DOMAIN_POWER))
FeatUsePerDay(oPC, FEAT_AIR_DOMAIN_POWER, ABILITY_CHARISMA, 3);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_EARTH, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_EARTH_DOMAIN_POWER))
FeatUsePerDay(oPC, FEAT_EARTH_DOMAIN_POWER, ABILITY_CHARISMA, 3);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_FIRE, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_FIRE_DOMAIN_POWER))
FeatUsePerDay(oPC, FEAT_FIRE_DOMAIN_POWER, ABILITY_CHARISMA, 3);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_WATER, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_WATER_DOMAIN_POWER))
FeatUsePerDay(oPC, FEAT_WATER_DOMAIN_POWER, ABILITY_CHARISMA, 3);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_SLIME, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_DOMAIN_POWER_SLIME))
FeatUsePerDay(oPC, FEAT_DOMAIN_POWER_SLIME, ABILITY_CHARISMA, 3);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_SPIDER, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_DOMAIN_POWER_SPIDER))
FeatUsePerDay(oPC, FEAT_DOMAIN_POWER_SPIDER, ABILITY_CHARISMA, 3);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_SCALEYKIND, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_DOMAIN_POWER_SCALEYKIND))
FeatUsePerDay(oPC, FEAT_DOMAIN_POWER_SCALEYKIND, ABILITY_CHARISMA, 3);
if(!GetHasFeat(FEAT_BONUS_DOMAIN_PLANT, oPC) || PRC_Funcs_GetFeatKnown(oPC, FEAT_PLANT_DOMAIN_POWER))
FeatUsePerDay(oPC, FEAT_PLANT_DOMAIN_POWER, ABILITY_CHARISMA, 3);
}
void MephlingBreath(object oPC) //:: Mephlings
{
if(!GetHasFeat(FEAT_MEPHLING_BREATH, oPC))
return;
int nMephBreath = ((1 + GetHitDice(oPC)) / 4);
FeatUsePerDay(oPC, FEAT_MEPHLING_BREATH, -1, nMephBreath);
}
void FeatAlaghar(object oPC)
{
int iAlagharLevel = GetLevelByClass(CLASS_TYPE_ALAGHAR, oPC);
if (!iAlagharLevel) return;
int iClangStrike = iAlagharLevel/3;
int iClangMight = (iAlagharLevel - 1)/3;
int iRockburst = (iAlagharLevel + 2)/4;
FeatUsePerDay(oPC, FEAT_CLANGEDDINS_STRIKE, -1, iClangStrike);
FeatUsePerDay(oPC, FEAT_CLANGEDDINS_MIGHT, -1, iClangMight);
FeatUsePerDay(oPC, FEAT_ALAG_ROCKBURST, -1, iRockburst);
}
void FeatDiabolist(object oPC)
{
int Diabol = GetLevelByClass(CLASS_TYPE_DIABOLIST, oPC);
if (!Diabol) return;
int iUse = (Diabol + 3)/3;
FeatUsePerDay(oPC,FEAT_DIABOL_DIABOLISM_1,-1,iUse);
FeatUsePerDay(oPC,FEAT_DIABOL_DIABOLISM_2,-1,iUse);
FeatUsePerDay(oPC,FEAT_DIABOL_DIABOLISM_3,-1,iUse);
}
void FeatNinja (object oPC)
{
int iNinjaLevel = GetLevelByClass(CLASS_TYPE_NINJA, oPC);
// Ascetic Stalker
if (GetHasFeat(FEAT_ASCETIC_STALKER, oPC))
iNinjaLevel += GetLevelByClass(CLASS_TYPE_MONK, oPC);
// Martial Stalker
if (GetHasFeat(FEAT_MARTIAL_STALKER, oPC))
iNinjaLevel += GetLevelByClass(CLASS_TYPE_FIGHTER, oPC);
if (!iNinjaLevel) return;
int nUsesLeft = iNinjaLevel / 2;
if (nUsesLeft < 1)
nUsesLeft = 1;
// Expanded Ki Pool
if (GetHasFeat(FEAT_EXPANDED_KI_POOL, oPC)) nUsesLeft += 3;
FeatUsePerDay(oPC, FEAT_KI_POWER, ABILITY_WISDOM, nUsesLeft);
FeatUsePerDay(oPC, FEAT_GHOST_STEP, ABILITY_WISDOM, nUsesLeft);
FeatUsePerDay(oPC, FEAT_GHOST_STRIKE, ABILITY_WISDOM, nUsesLeft);
FeatUsePerDay(oPC, FEAT_GHOST_WALK, ABILITY_WISDOM, nUsesLeft);
FeatUsePerDay(oPC, FEAT_KI_DODGE, ABILITY_WISDOM, nUsesLeft);
SetLocalInt(oPC, "prc_ninja_ki", nUsesLeft);
}
void BarbarianRage(object oPC)
{
if(!GetHasFeat(FEAT_BARBARIAN_RAGE, oPC)) return;
int nUses = (GetLevelByClass(CLASS_TYPE_BARBARIAN, oPC) + GetLevelByClass(CLASS_TYPE_BLACK_BLOOD_CULTIST, oPC) + GetLevelByClass(CLASS_TYPE_PRC_EYE_OF_GRUUMSH, oPC)) / 4 + 1;
nUses += (GetLevelByClass(CLASS_TYPE_RAGE_MAGE, oPC) + 2) / 5;
nUses += (GetLevelByClass(CLASS_TYPE_BATTLERAGER, oPC) + 1) / 2;
nUses += (GetLevelByClass(CLASS_TYPE_CELEBRANT_SHARESS, oPC) + 2) / 4;
nUses += GetLevelByClass(CLASS_TYPE_RUNESCARRED, oPC) ? ((GetLevelByClass(CLASS_TYPE_RUNESCARRED, oPC) / 4) + 1) : 0;
nUses += (GetLevelByClass(CLASS_TYPE_TOTEM_RAGER, oPC) + 4) / 6;
if(GetHasFeat(FEAT_EXTRA_RAGE, oPC)) nUses += 2;
FeatUsePerDay(oPC, FEAT_BARBARIAN_RAGE, -1, nUses);
FeatUsePerDay(oPC, FEAT_GREATER_RAGE, -1, nUses);
if(GetLevelByClass(CLASS_TYPE_RAGE_MAGE, oPC) > 0)
{
if(GetLevelByClass(CLASS_TYPE_RAGE_MAGE, oPC) > 9)
nUses = 3;
else if(GetLevelByClass(CLASS_TYPE_RAGE_MAGE, oPC) > 4)
nUses = 2;
else
nUses = 1;
FeatUsePerDay(oPC, FEAT_SPELL_RAGE, -1, nUses);
}
}
void BardSong(object oPC)
{
// This is used to set the number of bardic song uses per day, as bardic PrCs can increase it
// or other classes can grant it on their own
if(!GetHasFeat(FEAT_BARD_SONGS, oPC)) return;
int nTotal = GetLevelByClass(CLASS_TYPE_BARD, oPC);
nTotal += GetLevelByClass(CLASS_TYPE_DIRGESINGER, oPC);
nTotal += GetLevelByClass(CLASS_TYPE_VIRTUOSO, oPC);
nTotal += GetLevelByClass(CLASS_TYPE_FOCHLUCAN_LYRIST, oPC);
nTotal += GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oPC) / 2;
if(GetHasFeat(FEAT_EXTRA_MUSIC, oPC)) nTotal += 4;
FeatUsePerDay(oPC, FEAT_BARD_SONGS, -1, nTotal);
}
void FeatVirtuoso(object oPC)
{
int iVirtuosoLevel = GetLevelByClass(CLASS_TYPE_VIRTUOSO, oPC);
if (!iVirtuosoLevel) return;
int nUses = GetLevelByClass(CLASS_TYPE_BARD, oPC) + iVirtuosoLevel;
if(GetHasFeat(FEAT_EXTRA_MUSIC, oPC)) nUses += 4;
SetPersistantLocalInt(oPC, "Virtuoso_Performance_Uses", nUses);
int nFeat;
for(nFeat = FEAT_VIRTUOSO_SUSTAINING_SONG; nFeat <= FEAT_VIRTUOSO_PERFORMANCE; nFeat++)
{
FeatUsePerDay(oPC, nFeat, -1, nUses);
}
}
void HexCurse(object oPC)
{
int iHexLevel = GetLevelByClass(CLASS_TYPE_HEXBLADE, oPC);
if (!iHexLevel) return;
//Hexblade's Curse
int nUses = (iHexLevel + 3) / 4; // every 4 levels get 1 more use
FeatUsePerDay(oPC, FEAT_HEXCURSE, ABILITY_CHARISMA, nUses);
//Swift Cast
if(iHexLevel > 13)
nUses = (iHexLevel + 2) / 4;
else if(iHexLevel > 10)
nUses = 3;
else if(iHexLevel > 7)
nUses = 2;
else if(iHexLevel > 5)
nUses = 1;
else
nUses = 0;
FeatUsePerDay(oPC, FEAT_SWIFT_CAST, -1, nUses);
}
void FeatShadowblade(object oPC)
{
int iShadowLevel = GetLevelByClass(CLASS_TYPE_SHADOWBLADE, oPC);
if (!iShadowLevel) return;
FeatUsePerDay(oPC, FEAT_UNERRING_STRIKE, -1, iShadowLevel);
FeatUsePerDay(oPC, FEAT_UNEXPECTED_STRIKE, -1, iShadowLevel);
FeatUsePerDay(oPC, FEAT_EPHEMERAL_WEAPON, -1, iShadowLevel);
FeatUsePerDay(oPC, FEAT_SHADOWY_STRIKE, -1, iShadowLevel);
FeatUsePerDay(oPC, FEAT_FAR_SHADOW, -1, iShadowLevel);
}
void FeatNoble(object oPC)
{
int iNobleLevel = GetLevelByClass(CLASS_TYPE_NOBLE, oPC);
if (!iNobleLevel) return;
int nBonus = 0;
if (iNobleLevel >= 17) nBonus = 5;
else if (iNobleLevel >= 13) nBonus = 4;
else if (iNobleLevel >= 9) nBonus = 3;
else if (iNobleLevel >= 5) nBonus = 2;
else if (iNobleLevel >= 2) nBonus = 1;
FeatUsePerDay(oPC, FEAT_NOBLE_CONFIDENCE, -1, nBonus);
nBonus = (iNobleLevel - 11) / 3 + 1;
FeatUsePerDay(oPC, FEAT_NOBLE_GREATNESS, -1, nBonus);
}
void DarkKnowledge(object oPC)
{
int iArchivistLevel = GetLevelByClass(CLASS_TYPE_ARCHIVIST, oPC);
if(!iArchivistLevel) return;
int nUses = (iArchivistLevel / 3) + 3;
FeatUsePerDay(oPC, FEAT_DK_TACTICS, -1, nUses);
FeatUsePerDay(oPC, FEAT_DK_PUISSANCE, -1, nUses);
FeatUsePerDay(oPC, FEAT_DK_FOE, -1, nUses);
FeatUsePerDay(oPC, FEAT_DK_DREADSECRET, -1, nUses);
FeatUsePerDay(oPC, FEAT_DK_FOREKNOWLEDGE, -1, nUses);
}
void FeatImbueArrow(object oPC)
{
if(GetPRCSwitch(PRC_USE_NEW_IMBUE_ARROW))
FeatUsePerDay(oPC, FEAT_PRESTIGE_IMBUE_ARROW, -1, 0, 0);
}
void DragonDisciple(object oPC)
{
if(!GetHasFeat(FEAT_DRAGON_DIS_BREATH, oPC))
return;
//Dragon Disciples that do not possess any breath weapon
if(GetHasFeat(FEAT_CHIANG_LUNG_DRAGON, oPC)
|| GetHasFeat(FEAT_PAN_LUNG_DRAGON, oPC)
|| GetHasFeat(FEAT_SHEN_LUNG_DRAGON, oPC)
|| GetHasFeat(FEAT_TUN_MI_LUNG_DRAGON, oPC)
|| GetHasFeat(FEAT_YU_LUNG_DRAGON, oPC))
DecrementRemainingFeatUses(oPC, FEAT_DRAGON_DIS_BREATH);
}
void Warlock(object oPC)
{
if(GetHasFeat(FEAT_FIENDISH_RESILIENCE, oPC))
{
//Add daily Uses of Fiendish Resilience for epic warlock
if(GetHasFeat(FEAT_EPIC_FIENDISH_RESILIENCE_I, oPC))
{
int nFeatAmt = 0;
int bDone = FALSE;
while(!bDone)
{
if(nFeatAmt >= 9)
bDone = TRUE;
else if(GetHasFeat(FEAT_EPIC_FIENDISH_RESILIENCE_II + nFeatAmt, oPC))
nFeatAmt++;
else
bDone = TRUE;
}
nFeatAmt++;
FeatUsePerDay(oPC, FEAT_FIENDISH_RESILIENCE, -1, nFeatAmt);
}
else
FeatUsePerDay(oPC, FEAT_FIENDISH_RESILIENCE, -1, 1);
}
//Hellfire infusion
int nCha = GetAbilityModifier(ABILITY_CHARISMA, oPC);
FeatUsePerDay(oPC, FEAT_HELLFIRE_INFUSION, -1, nCha);
//Eldritch Spellweave
nCha += 3;
FeatUsePerDay(oPC, FEAT_ELDRITCH_SPELLWEAVE, -1, nCha);
}
void KotMC(object oPC)
{
int iKotMCLevel = GetLevelByClass(CLASS_TYPE_KNIGHT_MIDDLECIRCLE, oPC);
if(!iKotMCLevel) return;
int nUses = iKotMCLevel / 3;
FeatUsePerDay(oPC, FEAT_KOTMC_TRUE_STRIKE, -1, nUses);
}
void Templar(object oPC)
{
if(!GetHasFeat(FEAT_SECULAR_AUTHORITY, oPC)) return;
int nTemplar = GetLevelByClass(CLASS_TYPE_TEMPLAR, oPC);
int nUses = nTemplar + ((GetHitDice(oPC) - nTemplar) / 4);
FeatUsePerDay(oPC, FEAT_SECULAR_AUTHORITY, -1, nUses);
}
void FeatRacial(object oPC)
{
//Shifter bonus shifting uses
int nRace = GetRacialType(oPC);
if(nRace == RACIAL_TYPE_SHIFTER)
{
int nShiftFeats = GetShiftingFeats(oPC);
int nBonusShiftUses = (nShiftFeats / 2) + 1;
FeatUsePerDay(oPC, FEAT_SHIFTER_SHIFTING, -1, nBonusShiftUses);
}
else if(nRace == RACIAL_TYPE_FORESTLORD_ELF)
{
int nUses = GetHitDice(oPC) / 5 + 1;
FeatUsePerDay(oPC, FEAT_FORESTLORD_TREEWALK, -1, nUses);
}
}
void CombatMedic(object oPC)
{
int iCombMed = GetLevelByClass(CLASS_TYPE_COMBAT_MEDIC, oPC);
if(!iCombMed) return;
FeatUsePerDay(oPC, FEAT_HEALING_KICKER_1, ABILITY_WISDOM, iCombMed);
FeatUsePerDay(oPC, FEAT_HEALING_KICKER_2, ABILITY_WISDOM, iCombMed);
FeatUsePerDay(oPC, FEAT_HEALING_KICKER_3, ABILITY_WISDOM, iCombMed);
}
void MasterOfShrouds(object oPC)
{
if(!GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oPC)) return;
FeatUsePerDay(oPC, FEAT_MOS_UNDEAD_1, ABILITY_CHARISMA, 3);
FeatUsePerDay(oPC, FEAT_MOS_UNDEAD_2, ABILITY_CHARISMA, 3);
FeatUsePerDay(oPC, FEAT_MOS_UNDEAD_3, ABILITY_CHARISMA, 3);
FeatUsePerDay(oPC, FEAT_MOS_UNDEAD_4, ABILITY_CHARISMA, 3);
}
void SLAUses(object oPC)
{
if(!GetHasFeat(FEAT_SPELL_LIKE_ABILITY_1, oPC)) return;
FeatUsePerDay(oPC, FEAT_SPELL_LIKE_ABILITY_1, -1, GetPersistantLocalInt(oPC, "PRC_SLA_Uses_1"));
FeatUsePerDay(oPC, FEAT_SPELL_LIKE_ABILITY_2, -1, GetPersistantLocalInt(oPC, "PRC_SLA_Uses_2"));
FeatUsePerDay(oPC, FEAT_SPELL_LIKE_ABILITY_3, -1, GetPersistantLocalInt(oPC, "PRC_SLA_Uses_3"));
FeatUsePerDay(oPC, FEAT_SPELL_LIKE_ABILITY_4, -1, GetPersistantLocalInt(oPC, "PRC_SLA_Uses_4"));
FeatUsePerDay(oPC, FEAT_SPELL_LIKE_ABILITY_5, -1, GetPersistantLocalInt(oPC, "PRC_SLA_Uses_5"));
}
void ShadowShieldUses(object oPC)
{
if(!GetHasFeat(FEAT_SA_SHIELDSHADOW, oPC)) return;
FeatUsePerDay(oPC, FEAT_SA_SHIELDSHADOW, -1, GetPrCAdjustedCasterLevelByType(TYPE_ARCANE, oPC));
}
void BlighterFeats(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_BLIGHTER, oPC);
if(0 >= nClass) return;
if (nClass == 3)
FeatUsePerDay(oPC, FEAT_UNDEAD_WILD_SHAPE, -1, 1);
else if (nClass == 4)
FeatUsePerDay(oPC, FEAT_UNDEAD_WILD_SHAPE, -1, 2);
else if (nClass == 5)
{
FeatUsePerDay(oPC, FEAT_UNDEAD_WILD_SHAPE, -1, 2);
FeatUsePerDay(oPC, FEAT_CONTAGIOUS_TOUCH, -1, 1);
}
else if (nClass == 6)
{
FeatUsePerDay(oPC, FEAT_UNDEAD_WILD_SHAPE, -1, 3);
FeatUsePerDay(oPC, FEAT_CONTAGIOUS_TOUCH, -1, 1);
}
else if (nClass == 7)
{
FeatUsePerDay(oPC, FEAT_UNDEAD_WILD_SHAPE, -1, 3);
FeatUsePerDay(oPC, FEAT_CONTAGIOUS_TOUCH, -1, 2);
}
else if (nClass == 8)
{
FeatUsePerDay(oPC, FEAT_UNDEAD_WILD_SHAPE, -1, 4);
FeatUsePerDay(oPC, FEAT_CONTAGIOUS_TOUCH, -1, 2);
}
else if (nClass == 9)
{
FeatUsePerDay(oPC, FEAT_UNDEAD_WILD_SHAPE, -1, 4);
FeatUsePerDay(oPC, FEAT_CONTAGIOUS_TOUCH, -1, 3);
}
else
{
FeatUsePerDay(oPC, FEAT_UNDEAD_WILD_SHAPE, -1, 5);
FeatUsePerDay(oPC, FEAT_CONTAGIOUS_TOUCH, -1, 3);
}
}
void MysteryFeats(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_CHILD_OF_NIGHT, oPC);
if(nClass > 0)
{
if (nClass >= 10)
FeatUsePerDay(oPC, FEAT_CLOAK_SHADOWS, -1, 2);
else if (nClass >= 6)
FeatUsePerDay(oPC, FEAT_CLOAK_SHADOWS, -1, 3);
else
FeatUsePerDay(oPC, FEAT_CLOAK_SHADOWS, -1, 1);
if (nClass >= 7)
FeatUsePerDay(oPC, FEAT_DANCING_SHADOWS, -1, 2);
else
FeatUsePerDay(oPC, FEAT_DANCING_SHADOWS, -1, 1);
}
nClass = GetLevelByClass(CLASS_TYPE_NOCTUMANCER, oPC);
if(nClass > 0)
{
if (nClass >= 8)
FeatUsePerDay(oPC, FEAT_INNATE_COUNTERSPELL, -1, 3);
else if (nClass >= 5)
FeatUsePerDay(oPC, FEAT_INNATE_COUNTERSPELL, -1, 2);
else
FeatUsePerDay(oPC, FEAT_INNATE_COUNTERSPELL, -1, 1);
}
nClass = GetLevelByClass(CLASS_TYPE_SHADOWSMITH, oPC);
if(nClass > 0)
{
FeatUsePerDay(oPC, FEAT_TOUCH_SHADOW , -1, nClass);
FeatUsePerDay(oPC, FEAT_SHROUD_SHADOW , -1, nClass);
FeatUsePerDay(oPC, FEAT_SHADOW_CRAFT , -1, nClass/2);
FeatUsePerDay(oPC, FEAT_ARMOR_SHADOW , -1, nClass/2);
FeatUsePerDay(oPC, FEAT_ARMOR_SHADOW_Q, -1, nClass/2);
}
}
void WildMage(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_WILD_MAGE, oPC);
if(nClass > 0)
{
if (nClass >= 8)
FeatUsePerDay(oPC, FEAT_WILD_MAGE_RANDOM_DEFLECTOR, -1, 2);
else if (nClass >= 5)
FeatUsePerDay(oPC, FEAT_WILD_MAGE_RANDOM_DEFLECTOR, -1, 3);
else
FeatUsePerDay(oPC, FEAT_WILD_MAGE_RANDOM_DEFLECTOR, -1, 1);
}
}
void Factotum(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_FACTOTUM, oPC);
if(nClass > 0)
{
if (nClass >= 20)
{
FeatUsePerDay(oPC, FEAT_OPPORTUNISTIC_PIETY_TURN, ABILITY_WISDOM, 0, 6);
FeatUsePerDay(oPC, FEAT_OPPORTUNISTIC_PIETY_HEAL, ABILITY_WISDOM, 0, 6);
}
else if (nClass >= 15)
{
FeatUsePerDay(oPC, FEAT_OPPORTUNISTIC_PIETY_TURN, ABILITY_WISDOM, 0, 5);
FeatUsePerDay(oPC, FEAT_OPPORTUNISTIC_PIETY_HEAL, ABILITY_WISDOM, 0, 5);
}
else if (nClass >= 10)
{
FeatUsePerDay(oPC, FEAT_OPPORTUNISTIC_PIETY_TURN, ABILITY_WISDOM, 0, 4);
FeatUsePerDay(oPC, FEAT_OPPORTUNISTIC_PIETY_HEAL, ABILITY_WISDOM, 0, 4);
}
else
{
FeatUsePerDay(oPC, FEAT_OPPORTUNISTIC_PIETY_TURN, ABILITY_WISDOM, 0, 3);
FeatUsePerDay(oPC, FEAT_OPPORTUNISTIC_PIETY_HEAL, ABILITY_WISDOM, 0, 3);
}
}
}
void Sharess(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_CELEBRANT_SHARESS, oPC);
if(nClass > 0)
{
FeatUsePerDay(oPC, FEAT_CELEBRANT_SHARESS_FASCINATE , -1, 0, nClass);
FeatUsePerDay(oPC, FEAT_CELEBRANT_SHARESS_CONFUSE , -1, 0, nClass);
FeatUsePerDay(oPC, FEAT_CELEBRANT_SHARESS_DOMINATE , -1, 0, nClass);
}
}
void SoulbornDefense(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_SOULBORN, oPC);
if(nClass > 0)
{
if (nClass >= 37)
FeatUsePerDay(oPC, FEAT_SHARE_INCARNUM_DEFENSE, -1, 0, 8);
else if (nClass >= 33)
FeatUsePerDay(oPC, FEAT_SHARE_INCARNUM_DEFENSE, -1, 0, 7);
else if (nClass >= 29)
FeatUsePerDay(oPC, FEAT_SHARE_INCARNUM_DEFENSE, -1, 0, 6);
else if (nClass >= 25)
FeatUsePerDay(oPC, FEAT_SHARE_INCARNUM_DEFENSE, -1, 0, 5);
else if (nClass >= 21)
FeatUsePerDay(oPC, FEAT_SHARE_INCARNUM_DEFENSE, -1, 0, 4);
else if (nClass >= 17)
FeatUsePerDay(oPC, FEAT_SHARE_INCARNUM_DEFENSE, -1, 0, 3);
else if (nClass >= 13)
FeatUsePerDay(oPC, FEAT_SHARE_INCARNUM_DEFENSE, -1, 0, 2);
else
FeatUsePerDay(oPC, FEAT_SHARE_INCARNUM_DEFENSE, -1, 0, 1);
}
}
void TotemistReshape(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_TOTEMIST, oPC);
if(nClass > 0)
{
if (nClass >= 40)
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 9);
else if (nClass >= 36)
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 8);
else if (nClass >= 32)
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 7);
else if (nClass >= 28)
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 6);
else if (nClass >= 24)
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 5);
else if (nClass >= 20)
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 4);
else if (nClass >= 16)
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 3);
else if (nClass >= 12)
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 2);
else
FeatUsePerDay(oPC, FEAT_REBIND_TOTEM_SOULMELD, -1, 0, 1);
}
}
void CWSamurai(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_CW_SAMURAI, oPC);
if(nClass > 0)
{
if (nClass >= 17)
FeatUsePerDay(oPC, FEAT_KIAI_SMITE, -1, 0, 4);
else if (nClass >= 12)
FeatUsePerDay(oPC, FEAT_KIAI_SMITE, -1, 0, 3);
else if (nClass >= 7)
FeatUsePerDay(oPC, FEAT_KIAI_SMITE, -1, 0, 2);
else
FeatUsePerDay(oPC, FEAT_KIAI_SMITE, -1, 0, 1);
}
}
void CrusaderSmite(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_CRUSADER, oPC);
if(nClass > 0)
{
if (nClass >= 18)
FeatUsePerDay(oPC, FEAT_CRUSADER_SMITE, -1, 0, 2);
else
FeatUsePerDay(oPC, FEAT_CRUSADER_SMITE, -1, 0, 1);
}
}
void AnimaMage(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_ANIMA_MAGE, oPC);
if(nClass > 0)
{
if (nClass >= 9)
FeatUsePerDay(oPC, FEAT_ANIMA_VESTIGE_METAMAGIC, -1, 0, 3);
else if (nClass >= 7)
FeatUsePerDay(oPC, FEAT_ANIMA_VESTIGE_METAMAGIC, -1, 0, 2);
else
FeatUsePerDay(oPC, FEAT_ANIMA_VESTIGE_METAMAGIC, -1, 0, 1);
}
}
void FeatSpecialUsePerDay(object oPC)
{
FeatUsePerDay(oPC, FEAT_WWOC_WIDEN_SPELL, ABILITY_CHARISMA, GetLevelByClass(CLASS_TYPE_WAR_WIZARD_OF_CORMYR, oPC));
FeatUsePerDay(oPC, FEAT_FIST_DAL_QUOR_STUNNING_STRIKE, -1, GetLevelByClass(CLASS_TYPE_FIST_DAL_QUOR, oPC));
FeatUsePerDay(oPC, FEAT_AD_FALSE_KEENNESS, -1, GetLevelByClass(CLASS_TYPE_ARCANE_DUELIST, oPC));
FeatUsePerDay(oPC, FEAT_LASHER_STUNNING_SNAP, -1, GetLevelByClass(CLASS_TYPE_LASHER, oPC));
FeatUsePerDay(oPC, FEAT_AD_BLUR, -1, GetLevelByClass(CLASS_TYPE_ARCANE_DUELIST, oPC));
FeatUsePerDay(oPC, FEAT_SHADOW_RIDE, -1, GetLevelByClass(CLASS_TYPE_CRINTI_SHADOW_MARAUDER, oPC));
FeatUsePerDay(oPC, FEAT_SHADOWJUMP, -1, GetLevelByClass(CLASS_TYPE_SHADOWLORD, oPC));
FeatUsePerDay(oPC, FEAT_SHADOWBANE_SMITE, -1, (GetLevelByClass(CLASS_TYPE_SHADOWBANE_INQUISITOR, oPC)+2)/4);
FeatUsePerDay(oPC, FEAT_INCARNUM_RADIANCE, -1, (GetLevelByClass(CLASS_TYPE_INCARNATE, oPC)+2)/5);
FeatUsePerDay(oPC, FEAT_RAPID_MELDSHAPING, -1, (GetLevelByClass(CLASS_TYPE_INCARNATE, oPC)+1)/6);
FeatUsePerDay(oPC, FEAT_SMITE_OPPOSITION, -1, (GetLevelByClass(CLASS_TYPE_SOULBORN, oPC)+5)/5);
FeatUsePerDay(oPC, FEAT_SMITE_CHAOS, -1, (GetLevelByClass(CLASS_TYPE_SAPPHIRE_HIERARCH, oPC)+2)/3);
FeatUsePerDay(oPC, FEAT_INCANDESCENT_OVERLOAD, -1, (GetLevelByClass(CLASS_TYPE_INCANDESCENT_CHAMPION, oPC)-1)/3);
FeatUsePerDay(oPC, FEAT_NECROCARNATE_SOULSHIELD, -1, GetLevelByClass(CLASS_TYPE_NECROCARNATE, oPC)/2);
FeatUsePerDay(oPC, FEAT_SCION_DANTALION_SCHOLARSHIP, -1, GetLevelByClass(CLASS_TYPE_SCION_DANTALION, oPC));
FeatUsePerDay(oPC, FEAT_SMITE_GOOD_ALIGN, -1, (GetLevelByClass(CLASS_TYPE_FISTRAZIEL, oPC)+1)/2);
FeatUsePerDay(oPC, FEAT_FIST_OF_IRON, ABILITY_WISDOM, 3);
FeatUsePerDay(oPC, FEAT_SMITE_UNDEAD, ABILITY_CHARISMA, 3);
FeatUsePerDay(oPC, FEAT_COC_WRATH, ABILITY_CHARISMA, 3);
FeatUsePerDay(oPC, FEAT_KILLOREN_ASPECT_D, ABILITY_CHARISMA);
FeatUsePerDay(oPC, FEAT_AVENGING_STRIKE, ABILITY_CHARISMA, 0, 1);
FeatUsePerDay(oPC, FEAT_INCARNUM_BLADE_REBIND, ABILITY_CONSTITUTION, 1);
FeatUsePerDay(oPC, FEAT_WITCHBORN_INTEGUMENT, ABILITY_CONSTITUTION, 1);
FeatUsePerDay(oPC, FEAT_LIPS_RAPTUR);
FeatUsePerDay(oPC, FEAT_COMMAND_SPIDERS, ABILITY_CHARISMA, 3);
FeatUsePerDay(oPC, FEAT_FM_FOREST_DOMINION, ABILITY_CHARISMA, 3);
FeatDiabolist(oPC);
FeatAlaghar(oPC);
ShadowShieldUses(oPC);
CombatMedic(oPC);
FeatNinja(oPC);
FeatNoble(oPC);
MasterOfShrouds(oPC);
HexCurse(oPC);
FeatRacial(oPC);
FeatShadowblade(oPC);
SoulbornDefense(oPC);
int nDread = GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oPC);
if (nDread >= 1)
{//:: Enervating Touch
if (nDread >= 17)
{
FeatUsePerDay(oPC, FEAT_DN_ENERVATING_TOUCH, -1, nDread);
}
else
{
FeatUsePerDay(oPC, FEAT_DN_ENERVATING_TOUCH, -1, nDread/2);
}
}
if (nDread >= 3)
{//:: Negative Energy Burst
int NegBurstUses = 0;
if (nDread >= 8)
{
// Gains 1 more daily use of Negative Energy Burst every 5 levels after 3rd
int additionalUses = (nDread - 3) / 5;
NegBurstUses += 1 + additionalUses;
FeatUsePerDay(oPC, FEAT_DN_NEG_NRG_BURST, -1, NegBurstUses);
}
else if (nDread >= 3)
{
// Dread Necromancer gains 1 use at level 3
NegBurstUses += 1;
FeatUsePerDay(oPC, FEAT_DN_NEG_NRG_BURST, -1, NegBurstUses);
}
}
if (nDread >= 7)
{//:: Scabrous Touch
int ScabUses = 0;
// Gains 1 more daily use every 5 levels after 21
if (nDread >= 26)
{
int additionalUses = (nDread - 21) / 5;
ScabUses += 4 + additionalUses;
FeatUsePerDay(oPC, FEAT_DN_SCABROUS_TOUCH, -1, ScabUses);
}
// Epic Dread Necromancer gains 1 more daily use at level 21
else if (nDread >= 21)
{
ScabUses += 4;
FeatUsePerDay(oPC, FEAT_DN_SCABROUS_TOUCH, -1, ScabUses);
}
else if (nDread >= 16)
{
ScabUses += 3;
FeatUsePerDay(oPC, FEAT_DN_SCABROUS_TOUCH, -1, ScabUses);
}
else if (nDread >= 11)
{
ScabUses += 2;
FeatUsePerDay(oPC, FEAT_DN_SCABROUS_TOUCH, -1, ScabUses);
}
else
{
ScabUses += 1;
FeatUsePerDay(oPC, FEAT_DN_SCABROUS_TOUCH, -1, ScabUses);
}
}
SLAUses(oPC);
DomainUses(oPC);
BardSong(oPC);
BarbarianRage(oPC);
FeatVirtuoso(oPC);
ResetExtraStunfistUses(oPC);
DarkKnowledge(oPC);
FeatImbueArrow(oPC);
DragonDisciple(oPC);
Warlock(oPC);
KotMC(oPC);
Templar(oPC);
BlighterFeats(oPC);
MysteryFeats(oPC);
WildMage(oPC);
Factotum(oPC);
Sharess(oPC);
TotemistReshape(oPC);
CWSamurai(oPC);
CrusaderSmite(oPC);
AnimaMage(oPC);
MephlingBreath(oPC);
}