Files
PRC8/nwn/nwnprc/trunk/scripts/ft_vowofpoverty.nss
Jaysyn904 a62073c871 2026/04/29 Early update
Fixed targeting for Claws of the Savage.
Updated VFX for Landshark Boots.
Made GetTotalUsableEssentia respect Incandescent Overload.
Added the rest of the old CEP2 weapons to prc_x2_itemprop.
Fixed DoCone() to allow skipping SR checks.
Fixed Blast of Flame to not have an SR check.
Fixed Lightining Guantlet's Hand bind to add electrical damage to melee weapon, once per round.
Vow of Poverty now allows Shield of Thought.
Cloudkill now obeys poison immunity
True Resurrection should work on any PC as well as any NPC in your party.
2026-04-29 00:41:13 -04:00

594 lines
27 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Name Vow of Poverty
//:: FileName ft_vowofpoverty.nss
//:: Created By: Fencas
//:: Created On: 2024-12-02
//:: Based On: Stratovarius' Forsaker
//:://////////////////////////////////////////////
#include "prc_inc_combat"
#include "inc_dynconv"
#include "prc_class_const"
#include "prc_inc_clsfunc"
#include "prc_alterations"
#include "NW_I0_GENERIC"
#include "nw_i0_spells"
#include "inc_persist_loca"
#include "inc_nwnx_funcs"
effect VoPDamage(int nTotalEnhancement)
{
effect eDamage;
if (nTotalEnhancement>=15) eDamage = EffectDamageIncrease(DAMAGE_BONUS_15,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=14) eDamage = EffectDamageIncrease(DAMAGE_BONUS_14,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=13) eDamage = EffectDamageIncrease(DAMAGE_BONUS_13,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=12) eDamage = EffectDamageIncrease(DAMAGE_BONUS_12,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=11) eDamage = EffectDamageIncrease(DAMAGE_BONUS_11,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=10) eDamage = EffectDamageIncrease(DAMAGE_BONUS_10,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=9) eDamage = EffectDamageIncrease(DAMAGE_BONUS_9,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=8) eDamage = EffectDamageIncrease(DAMAGE_BONUS_8,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=7) eDamage = EffectDamageIncrease(DAMAGE_BONUS_7,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=6) eDamage = EffectDamageIncrease(DAMAGE_BONUS_6,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=5) eDamage = EffectDamageIncrease(DAMAGE_BONUS_5,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=4) eDamage = EffectDamageIncrease(DAMAGE_BONUS_4,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=3) eDamage = EffectDamageIncrease(DAMAGE_BONUS_3,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=2) eDamage = EffectDamageIncrease(DAMAGE_BONUS_2,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
else if (nTotalEnhancement>=1) eDamage = EffectDamageIncrease(DAMAGE_BONUS_1,DAMAGE_TYPE_BLUDGEONING || DAMAGE_TYPE_SLASHING || DAMAGE_TYPE_PIERCING);
return eDamage;
}
void ConvertVoPFeatsToNWNxEE(object oPC)
{
if (GetPersistantLocalInt(oPC, "VoP_NWNxEE_Feats_Converted")) return;
if (!GetHasFeat(FEAT_VOWOFPOVERTY, oPC)) return;
// Remove any lingering VoP feat effects
effect eLoop = GetFirstEffect(oPC);
while (GetIsEffectValid(eLoop))
{
string sTag = GetEffectTag(eLoop);
if (GetStringLeft(sTag, 7) == "VoPFeat")
RemoveEffect(oPC, eLoop);
eLoop = GetNextEffect(oPC);
}
// Reapply intrinsic feats for each stored VoPFeatID entry
int i = 1;
string sKey;
while (GetPersistantLocalInt(oPC, "VoPFeatID" + IntToString(i)))
{
int nFeatID = StringToInt(Get2DAString("prc_vop_feats", "FeatIndex", i - 1));
if (nFeatID > 0)
{
PRC_Funcs_AddFeat(oPC, nFeatID);
}
i++;
}
SetPersistantLocalInt(oPC, "VoP_NWNxEE_Feats_Converted", TRUE);
}
void ConvertVoPToNWNxEE(object oPC)
{
if (GetPersistantLocalInt(oPC, "VoP_NWNxEE_Converted")) return;
if (!GetHasFeat(FEAT_VOWOFPOVERTY, oPC)) return;
int nLevel = GetCharacterLevel(oPC) - GetPersistantLocalInt(oPC, "VoPLevel1") + 1;
object oSkin = GetPCSkin(oPC);
int i;
// Remove existing VoP ability item properties
for (i = 0; i < 6; i++)
{
RemoveSpecificProperty(oSkin, ITEM_PROPERTY_ABILITY_BONUS, i, -1, 1, "VoPBoostStat"+IntToString(i), -1, DURATION_TYPE_PERMANENT);
}
// Reapply intrinsic bonuses for each stored VoPBoost
for (i = 1; i <= nLevel; i++)
{
int nStored = GetPersistantLocalInt(oPC, "VoPBoost"+IntToString(i));
if (nStored >= 10)
{
int stat = nStored - 10;
int value = 2 * (1 + (nLevel - i) / 4);
PRC_Funcs_ModAbilityScore(oPC, stat, value);
}
}
SetPersistantLocalInt(oPC, "VoP_NWNxEE_Converted", TRUE);
}
#include "prc_feat_const"
#include "prc_inc_function"
const string VOP_TAG = "VoP";
// Helper: add a VoP-tagged property to the skin
void AddVoPProperty(object oSkin, itemproperty ip)
{
ip = TagItemProperty(ip, VOP_TAG);
IPSafeAddItemProperty(oSkin, ip, 0.0f, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE);
}
// Remove all VoP-tagged properties from an item
void RemoveVoPProperties(object oItem)
{
itemproperty ip = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(ip))
{
if (GetItemPropertyTag(ip) == VOP_TAG)
RemoveItemProperty(oItem, ip);
ip = GetNextItemProperty(oItem);
}
}
void main()
{
int nEvent = GetRunningEvent();
if (DEBUG) DoDebug("ft_vowofpoverty running, event: " + IntToString(nEvent));
object oPC;
switch (nEvent)
{
case EVENT_ITEM_ONHIT: oPC = OBJECT_SELF; break;
case EVENT_ONPLAYEREQUIPITEM: oPC = GetItemLastEquippedBy(); break;
case EVENT_ONPLAYERUNEQUIPITEM: oPC = GetItemLastUnequippedBy(); break;
case EVENT_ONHEARTBEAT: oPC = OBJECT_SELF; break;
default: oPC = OBJECT_SELF;
}
object oItem;
object oSkin = GetPCSkin(oPC);
int nLevel = GetCharacterLevel(oPC) - GetPersistantLocalInt(oPC, "VoPLevel1") + 1;
int nACArmor = 4 + nLevel / 3;
int nACDeflection = nLevel / 6;
int nACNatural = nLevel / 8;
int nRegen = 1 + (nLevel - 17) / 7;
int nDR = 5 * (1 + (nLevel - 10) / 9);
int nER = (10 * (1 + (nLevel - 13) / 7)) - 5;
int nResist = 0;
if (nLevel >= 17) nResist = 1 + (nLevel - 7) / 5;
else if (nLevel >= 13) nResist = 2;
else if (nLevel >= 7) nResist = 1;
int nForsakerBonus = GetLevelByClass(CLASS_TYPE_FORSAKER, oPC) / 2;
int nSlot, nLevelCheck, nExaltedStrike, nTotalEnhancement;
if (nLevel >= 10) nExaltedStrike = 1 + (nLevel - 7) / 3;
else if (nLevel >= 4) nExaltedStrike = 1;
if (nForsakerBonus >= nExaltedStrike) nTotalEnhancement = nForsakerBonus;
else nTotalEnhancement = nExaltedStrike;
// EvalPRCFeats pass
if (nEvent == FALSE)
{
if (GetPRCSwitch("PRC_NWNXEE_ENABLED") && GetPRCSwitch("PRC_PRCX_ENABLED"))
ConvertVoPToNWNxEE(oPC);
if (GetPRCSwitch("PRC_NWNXEE_ENABLED") && GetPRCSwitch("PRC_PRCX_ENABLED"))
ConvertVoPFeatsToNWNxEE(oPC);
for (nLevelCheck = 1; nLevelCheck <= nLevel; nLevelCheck++)
{
if (!GetPersistantLocalInt(oPC, "VoPBoost" + IntToString(nLevelCheck)) && (nLevelCheck - (nLevelCheck / 4) * 4 == 3) && (nLevelCheck >= 7) && (nLevelCheck <= 27))
{
AssignCommand(oPC, ClearAllActions(TRUE));
SetPersistantLocalInt(oPC, "VoPBoostCheck", nLevelCheck);
StartDynamicConversation("ft_vowpoverty_ab", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
}
if (GetPersistantLocalInt(oPC, "VoPBoost" + IntToString(nLevelCheck)) >= 10)
{
int stat = GetPersistantLocalInt(oPC, "VoPBoost" + IntToString(nLevelCheck)) - 10;
int value = 2 * (1 + (nLevel - nLevelCheck) / 4);
if (GetPRCSwitch("PRC_NWNXEE_ENABLED") && GetPRCSwitch("PRC_PRCX_ENABLED"))
{
string sKey = "VoP_EE_Boost_" + IntToString(stat);
int nLastApplied = GetPersistantLocalInt(oPC, sKey);
int nDelta = value - nLastApplied;
if (nDelta > 0)
{
PRC_Funcs_ModAbilityScore(oPC, stat, nDelta);
SetPersistantLocalInt(oPC, sKey, value);
}
}
else
{
// Fallback: add tagged ability bonus to skin
itemproperty ip = ItemPropertyAbilityBonus(stat, value);
AddVoPProperty(oSkin, ip);
}
}
if (!GetPersistantLocalInt(oPC, "VoPFeat" + IntToString(nLevelCheck)) && (nLevelCheck - (nLevelCheck / 2) * 2 == 0))
{
AssignCommand(oPC, ClearAllActions(TRUE));
SetPersistantLocalInt(oPC, "VoPFeatCheck", nLevelCheck);
StartDynamicConversation("ft_vowpoverty_ft", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
}
}
// AC Armor (effect)
ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectACIncrease(nACArmor, AC_ARMOUR_ENCHANTMENT_BONUS)), oPC);
// Deflection (effect)
ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectACIncrease(nACDeflection, AC_DEFLECTION_BONUS)), oPC);
// Resistance (itemproperty, tagged)
if (nLevel >= 7)
{
itemproperty ip = ItemPropertyBonusSavingThrow(SAVING_THROW_ALL, nResist);
AddVoPProperty(oSkin, ip);
}
// Natural Armor (effect)
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ExtraordinaryEffect(EffectACIncrease(nACNatural, AC_NATURAL_BONUS)), oPC);
// DR (effect)
if (nLevel >= 10) ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDamageReduction(nDR, nTotalEnhancement)), oPC);
// Energy resistances (effects)
if (nLevel >= 13)
{
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_ACID, nER, 0, FALSE), oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_COLD, nER, 0, FALSE), oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_ELECTRICAL, nER, 0, FALSE), oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_FIRE, nER, 0, FALSE), oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_SONIC, nER, 0, FALSE), oPC);
}
// Freedom of Movement (tagged)
if (nLevel >= 14)
{
itemproperty ip = ItemPropertyFreeAction();
AddVoPProperty(oSkin, ip);
}
// Regeneration (tagged)
if (nLevel >= 17)
{
itemproperty ip = ItemPropertyRegeneration(nRegen);
AddVoPProperty(oSkin, ip);
}
// True Seeing (tagged)
if (nLevel >= 18)
{
itemproperty ip = ItemPropertyTrueSeeing();
AddVoPProperty(oSkin, ip);
}
// Exalted Strike (effect, already tagged)
effect eEffect1 = EffectAttackIncrease(nTotalEnhancement);
effect eEffect2 = VoPDamage(nTotalEnhancement);
effect eLink = EffectLinkEffects(eEffect1, eEffect2);
eLink = SupernaturalEffect(eLink);
eLink = TagEffect(eLink, "EffectExaltedStrike");
effect eCheckEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eCheckEffect))
{
if (GetEffectTag(eCheckEffect) == "EffectExaltedStrike") RemoveEffect(oPC, eCheckEffect);
eCheckEffect = GetNextEffect(oPC);
}
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oPC);
// Enforce vow: unequip prohibited items
for (nSlot = 0; nSlot < 13; nSlot++)
{
oItem = GetItemInSlot(nSlot, oPC);
if (!(GetTag(oItem) == "xp1_mystrashand")
&& !(GetTag(oItem) == "H2_SenseiAmulet")
&& !(GetResRef(oItem) == "prc_sk_mblade_bs")
&& !(GetResRef(oItem) == "prc_sk_mblade_th")
&& !(GetResRef(oItem) == "prc_sk_mblade_ss")
&& !(GetResRef(oItem) == "psi_sk_tshield_0")
&& !(GetResRef(oItem) == "prc_sk_mblade_ls"))
{
if ((GetIsItemPropertyValid(GetFirstItemProperty(oItem)) && !(GetItemPropertyTag(GetFirstItemProperty(oItem)) == "Tag_PRC_OnHitKeeper")
&& !(nSlot == 4 || nSlot == 5))
|| (nSlot == 1 && GetBaseAC(oItem) >= 1)
|| (nSlot == 5 && (GetBaseItemType(oItem) == BASE_ITEM_SMALLSHIELD
|| GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD
|| GetBaseItemType(oItem) == BASE_ITEM_TOWERSHIELD)))
{
AssignCommand(oPC, ClearAllActions(TRUE));
AssignCommand(oPC, ActionUnequipItem(oItem));
FloatingTextStringOnCreature(GetName(oItem) + " would break your vow!", oPC, FALSE);
}
}
}
// Register unequip hook
AddEventScript(oPC, EVENT_ONPLAYERUNEQUIPITEM, "ft_vowofpoverty", TRUE, FALSE);
}
// OnEquip: enforce vow for equipped weapons
else if (nEvent == EVENT_ONPLAYEREQUIPITEM)
{
oItem = GetPCItemLastEquipped();
int iWeaponAllowed = (GetBaseItemType(oItem) == BASE_ITEM_CLUB
|| GetBaseItemType(oItem) == BASE_ITEM_DAGGER
|| GetBaseItemType(oItem) == BASE_ITEM_DART
|| GetBaseItemType(oItem) == BASE_ITEM_HEAVYCROSSBOW
|| GetBaseItemType(oItem) == BASE_ITEM_LIGHTCROSSBOW
|| GetBaseItemType(oItem) == BASE_ITEM_LIGHTMACE
|| GetBaseItemType(oItem) == BASE_ITEM_MORNINGSTAR
|| GetBaseItemType(oItem) == BASE_ITEM_QUARTERSTAFF
|| GetBaseItemType(oItem) == BASE_ITEM_SICKLE
|| GetBaseItemType(oItem) == BASE_ITEM_SLING
|| GetBaseItemType(oItem) == BASE_ITEM_SHORTSPEAR
|| GetBaseItemType(oItem) == BASE_ITEM_BOLT
|| GetBaseItemType(oItem) == BASE_ITEM_GOAD
|| GetBaseItemType(oItem) == BASE_ITEM_KATAR
|| GetBaseItemType(oItem) == BASE_ITEM_HEAVY_MACE
|| GetBaseItemType(oItem) == BASE_ITEM_BULLET);
int iMagic = 0;
itemproperty eCheckIP = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(eCheckIP))
{
if (!(GetItemPropertyTag(eCheckIP) == "Sanctify1")
&& !(GetItemPropertyTag(eCheckIP) == "Sanctify2")
&& !(GetItemPropertyTag(eCheckIP) == "Sanctify3")
&& !(GetItemPropertyTag(eCheckIP) == "Sanctify4"))
iMagic = 1;
eCheckIP = GetNextItemProperty(oItem);
}
if (!(GetTag(oItem) == "xp1_mystrashand")
&& !(GetTag(oItem) == "H2_SenseiAmulet")
&& !(GetResRef(oItem) == "prc_sk_mblade_bs")
&& !(GetResRef(oItem) == "prc_sk_mblade_th")
&& !(GetResRef(oItem) == "prc_sk_mblade_ss")
&& !(GetResRef(oItem) == "psi_sk_tshield_0")
&& !(GetResRef(oItem) == "prc_sk_mblade_ls"))
{
if ((IPGetIsMeleeWeapon(oItem) || GetWeaponRanged(oItem)) && (iMagic || !iWeaponAllowed))
{
if (!(GetBaseItemType(oItem) == BASE_ITEM_SLING && GetItemPropertyType(GetFirstItemProperty(oItem)) == ITEM_PROPERTY_MIGHTY))
{
AssignCommand(oPC, ClearAllActions(TRUE));
AssignCommand(oPC, ActionUnequipItem(oItem));
FloatingTextStringOnCreature(GetName(oItem) + " would break your vow!", oPC, FALSE);
}
}
}
}
// OnUnequip: remove VoP-tagged properties from the unequipped item
else if (nEvent == EVENT_ONPLAYERUNEQUIPITEM)
{
oItem = GetPCItemLastUnequipped();
if (IPGetIsMeleeWeapon(oItem) || GetWeaponRanged(oItem))
RemoveVoPProperties(oItem);
}
}
/* void main()
{
int nEvent = GetRunningEvent();
if(DEBUG) DoDebug("prc_forsaker running, event: " + IntToString(nEvent));
// Get the PC. This is event-dependent
object oPC;
switch(nEvent)
{
case EVENT_ITEM_ONHIT: oPC = OBJECT_SELF; break;
case EVENT_ONPLAYEREQUIPITEM: oPC = GetItemLastEquippedBy(); break;
case EVENT_ONPLAYERUNEQUIPITEM: oPC = GetItemLastUnequippedBy(); break;
case EVENT_ONHEARTBEAT: oPC = OBJECT_SELF; break;
default:
oPC = OBJECT_SELF;
}
object oItem;
object oArmor;
object oShield;
object oSkin = GetPCSkin(oPC);
int nLevel = GetCharacterLevel(oPC)-GetPersistantLocalInt(oPC,"VoPLevel1")+1;
int nACArmor = 4+nLevel/3;
int nACDeflection = nLevel/6;
int nACNatural = nLevel/8;
int nRegen = 1+(nLevel-17)/7;
int nDR = 5*(1+(nLevel-10)/9);
int nER = (10*(1+(nLevel-13)/7))-5;
int nResist = 0;//Resistance (Ex): At 7th level, an ascetic gains a +1 resistance bonus on all saving throws. This bonus increases to +2 at 13th level, and to +3 at 17th level.
if (nLevel >= 17) nResist = 1 + (nLevel - 7) / 5;
else if (nLevel >= 13) nResist = 2;
else if (nLevel >= 7) nResist = 1;
int nForsakerBonus = GetLevelByClass(CLASS_TYPE_FORSAKER, oPC)/2;
int nSlot, nLevelCheck, nExaltedStrike, nTotalEnhancement;
//Enhancement bonus for unarmed damage and weapons; consider the bigger, Forsaker or VoP
if(nLevel>=10) nExaltedStrike = 1+(nLevel-7)/3;
else if(nLevel>=4) nExaltedStrike = 1;
if(nForsakerBonus>=nExaltedStrike) nTotalEnhancement = nForsakerBonus;
else nTotalEnhancement = nExaltedStrike;
// We aren't being called from any event, instead from EvalPRCFeats
if(nEvent == FALSE)
{
if (GetPRCSwitch("PRC_NWNXEE_ENABLED") && GetPRCSwitch("PRC_PRCX_ENABLED"))
ConvertVoPToNWNxEE(oPC);
if (GetPRCSwitch("PRC_NWNXEE_ENABLED") && GetPRCSwitch("PRC_PRCX_ENABLED"))
ConvertVoPFeatsToNWNxEE(oPC);
//Check if level up bonus has already been chosen and given for any of past VoP levels
for(nLevelCheck=1; nLevelCheck <= nLevel; nLevelCheck++)
{
//Call stat boost dialogue for level 7 and each 4 levels after that
if (!GetPersistantLocalInt(oPC, "VoPBoost"+IntToString(nLevelCheck)) && (nLevelCheck-(nLevelCheck/4)*4 == 3) && (nLevelCheck >= 7) && (nLevelCheck <= 27))
{
AssignCommand(oPC, ClearAllActions(TRUE));
SetPersistantLocalInt(oPC,"VoPBoostCheck",nLevelCheck);
StartDynamicConversation("ft_vowpoverty_ab", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
}
//Applying stat boosts
if(GetPersistantLocalInt(oPC, "VoPBoost"+IntToString(nLevelCheck)) >= 10)
{
int stat = GetPersistantLocalInt(oPC, "VoPBoost"+IntToString(nLevelCheck)) - 10;
int value = 2 * (1 + (nLevel - nLevelCheck) / 4);
if (GetPRCSwitch("PRC_NWNXEE_ENABLED") && GetPRCSwitch("PRC_PRCX_ENABLED"))
{
// Track last applied intrinsic bonus per ability to avoid stacking
string sKey = "VoP_EE_Boost_" + IntToString(stat);
int nLastApplied = GetPersistantLocalInt(oPC, sKey);
int nDelta = value - nLastApplied;
if (nDelta > 0)
{
PRC_Funcs_ModAbilityScore(oPC, stat, nDelta);
SetPersistantLocalInt(oPC, sKey, value);
}
}
else
{
// Fallback to item property on skin (overwrites, so safe to run each level)
SetCompositeBonus(oSkin, "VoPBoostStat"+IntToString(stat), value, ITEM_PROPERTY_ABILITY_BONUS, stat);
}
}
//:: Applying stat boosts
// if(GetPersistantLocalInt(oPC, "VoPBoost"+IntToString(nLevelCheck)) >= 10)
// {
// int stat = GetPersistantLocalInt(oPC, "VoPBoost"+IntToString(nLevelCheck)) - 10;
// int value = 2 * (1 + (nLevel - nLevelCheck) / 4);
// SetCompositeBonus(oSkin, "VoPBoostStat"+IntToString(stat), value, ITEM_PROPERTY_ABILITY_BONUS, stat);
// }
//Call exalted feat for each even level
if (!GetPersistantLocalInt(oPC, "VoPFeat"+IntToString(nLevelCheck)) && (nLevelCheck-(nLevelCheck/2)*2 == 0))
{
AssignCommand(oPC, ClearAllActions(TRUE));
SetPersistantLocalInt(oPC,"VoPFeatCheck",nLevelCheck);
StartDynamicConversation("ft_vowpoverty_ft", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
}
}
//AC Armor +4 on 1st, then +1 each 3 levels
ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectACIncrease(nACArmor, AC_ARMOUR_ENCHANTMENT_BONUS)), oPC);
//Deflection Armor +1 each 6 levels
ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectACIncrease(nACDeflection, AC_DEFLECTION_BONUS)), oPC);
//Resistance (Ex): At 7th level, an ascetic gains a +1 resistance bonus on all saving throws. This bonus increases to +2 at 13th level, and to +3 at 17th level.
if (nLevel>=7)
{
SetCompositeBonus(oSkin, "VoPResist", nResist, ITEM_PROPERTY_SAVING_THROW_BONUS, SAVING_THROW_ALL);
}
//Natural Armor +1 each 8 levels
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ExtraordinaryEffect(EffectACIncrease(nACNatural, AC_NATURAL_BONUS)), oPC);
//DR 5/Enhancement starting 10, +5 each 9 levels
if (nLevel >= 10) ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectDamageReduction(nDR,nTotalEnhancement)),oPC);
//Energy resistance 5 for acid, cold ,electrical, fire and sonic on 13th, than +10 each 7 levels
if (nLevel>=13)
{
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_ACID, nER, 0, FALSE), oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_COLD, nER, 0, FALSE), oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_ELECTRICAL, nER, 0, FALSE), oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_FIRE, nER, 0, FALSE), oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectDamageResistance(DAMAGE_TYPE_SONIC, nER, 0, FALSE), oPC);
}
//Freedom of Movement at 14th
if (nLevel>=14) IPSafeAddItemProperty(oSkin, ItemPropertyFreeAction(), 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, TRUE, TRUE);
//Regeneration 1 at 17th, +1 at each 7 levels
if (nLevel>=17) SetCompositeBonus(oSkin, "VoPFH", nRegen, ITEM_PROPERTY_REGENERATION);
//True Seeing at 18th
if (nLevel>=18) IPSafeAddItemProperty(oSkin, ItemPropertyTrueSeeing(), 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, TRUE, TRUE);
// Exalted Strike - only applies to weapons or unarmed
effect eEffect1 = EffectAttackIncrease(nTotalEnhancement);
effect eEffect2 = VoPDamage(nTotalEnhancement);
effect eLink = EffectLinkEffects(eEffect1,eEffect2);
eLink = SupernaturalEffect(eLink);
eLink = TagEffect(eLink, "EffectExaltedStrike");
//Remove any prior bonus to avoid duplication
effect eCheckEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eCheckEffect))
{
if(GetEffectTag(eCheckEffect) == "EffectExaltedStrike") RemoveEffect(oPC, eCheckEffect);
eCheckEffect = GetNextEffect(oPC);
}
//Give player the bonus, regardless of the weapon
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oPC);
// For some reason, EVENT_ONPLAYEREQUIPITEM just works with weapons, so it is better to check all other items for magic elsewhere
for (nSlot=0; nSlot < 13; nSlot++) //All but creatures slots
{
oItem=GetItemInSlot(nSlot, oPC);
if (!(GetTag(oItem) == "xp1_mystrashand")
&& !(GetTag(oItem) == "H2_SenseiAmulet")
&& !(GetResRef(oItem) == "prc_sk_mblade_bs")
&& !(GetResRef(oItem) == "prc_sk_mblade_th")
&& !(GetResRef(oItem) == "prc_sk_mblade_ss")
&& !(GetResRef(oItem) == "prc_sk_mblade_ls"))
{
if((GetIsItemPropertyValid(GetFirstItemProperty(oItem)) && !(GetItemPropertyTag(GetFirstItemProperty(oItem)) == "Tag_PRC_OnHitKeeper")
&& !(nSlot == 4 || nSlot == 5)) //Check if it is magical (all items but on the hands)
|| (nSlot == 1 && GetBaseAC(oItem) >= 1) //Check if it is an armor (AC>0)
|| (nSlot == 5 && GetBaseItemType(oItem) == BASE_ITEM_SMALLSHIELD || //Check if it is a shield
GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD ||
GetBaseItemType(oItem) == BASE_ITEM_TOWERSHIELD))
{
AssignCommand(oPC, ClearAllActions(TRUE));
AssignCommand(oPC, ActionUnequipItem(oItem));
FloatingTextStringOnCreature(GetName(oItem)+" would break your vow!", oPC, FALSE);
}
}
}
//Remove bonus from unequiped weapons
oItem = GetPCItemLastUnequipped();
if(IPGetIsMeleeWeapon(oItem) || GetWeaponRanged(oItem)) IPRemoveAllItemProperties(oItem, DURATION_TYPE_TEMPORARY);
AddEventScript(oPC, EVENT_SCRIPT_MODULE_ON_EQUIP_ITEM, "ft_vowofpoverty", TRUE, FALSE);
}
// We are called from the OnPlayerUnEquipItem eventhook. Remove OnHitCast: Unique Power from oPC's weapon
else if(nEvent == EVENT_SCRIPT_MODULE_ON_EQUIP_ITEM)
{
oItem = GetPCItemLastEquipped();
int iWeaponAllowed = GetBaseItemType(oItem) == BASE_ITEM_CLUB
|| GetBaseItemType(oItem) == BASE_ITEM_DAGGER
|| GetBaseItemType(oItem) == BASE_ITEM_DART
|| GetBaseItemType(oItem) == BASE_ITEM_HEAVYCROSSBOW
|| GetBaseItemType(oItem) == BASE_ITEM_LIGHTCROSSBOW
|| GetBaseItemType(oItem) == BASE_ITEM_LIGHTMACE
|| GetBaseItemType(oItem) == BASE_ITEM_MORNINGSTAR
|| GetBaseItemType(oItem) == BASE_ITEM_QUARTERSTAFF
|| GetBaseItemType(oItem) == BASE_ITEM_SICKLE
|| GetBaseItemType(oItem) == BASE_ITEM_SLING
|| GetBaseItemType(oItem) == BASE_ITEM_SHORTSPEAR
|| GetBaseItemType(oItem) == BASE_ITEM_BOLT
|| GetBaseItemType(oItem) == BASE_ITEM_GOAD
|| GetBaseItemType(oItem) == BASE_ITEM_KATAR
|| GetBaseItemType(oItem) == BASE_ITEM_HEAVY_MACE
|| GetBaseItemType(oItem) == BASE_ITEM_BULLET;
//Check if the magic is JUST Sanctify
int iMagic = 0;
itemproperty eCheckIP = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(eCheckIP))
{
if(!(GetItemPropertyTag(eCheckIP) == "Sanctify1") && !(GetItemPropertyTag(eCheckIP) == "Sanctify2") && !(GetItemPropertyTag(eCheckIP) == "Sanctify3")
&& !(GetItemPropertyTag(eCheckIP) == "Sanctify4")) iMagic = 1;
eCheckIP = GetNextItemProperty(oItem);
}
if (!(GetTag(oItem) == "xp1_mystrashand")
&& !(GetTag(oItem) == "H2_SenseiAmulet")
&& !(GetResRef(oItem) == "prc_sk_mblade_bs")
&& !(GetResRef(oItem) == "prc_sk_mblade_th")
&& !(GetResRef(oItem) == "prc_sk_mblade_ss")
&& !(GetResRef(oItem) == "prc_sk_mblade_ls"))
{
if((IPGetIsMeleeWeapon(oItem) || GetWeaponRanged(oItem)) && (iMagic || !iWeaponAllowed)) //Check if weapon is magical or not on allowed list
{
if(!(GetBaseItemType(oItem) == BASE_ITEM_SLING && GetItemPropertyType(GetFirstItemProperty(oItem)) == ITEM_PROPERTY_MIGHTY)) //Allow Mighty Bonus on Slings
{
AssignCommand(oPC, ClearAllActions(TRUE));
AssignCommand(oPC, ActionUnequipItem(oItem));
FloatingTextStringOnCreature(GetName(oItem)+" would break your vow!", oPC, FALSE);
}
}
}
}
} */