Update for PRC 4.1.10a 2023/02/20

Update for PRC 4.1.10a 2023/02/20

+ Jaysyn's latest PnP changes.
This commit is contained in:
Jaysyn904
2023-02-20 19:23:13 -05:00
parent 6c305aecc5
commit 6a6a8d56ac
42 changed files with 3670 additions and 2577 deletions

View File

@@ -0,0 +1,83 @@
//::///////////////////////////////////////////////
//:: Forest Master: Deep Roots
//:: prc_fm_deeproots.nss
//:://////////////////////////////////////////////
/*
Deep Roots (Su): Beginning at 8th level, once per day the forest
master may sink roots into the ground in any natural surface
place that can support at least some vegetation. While rooted, the
forest master gains fast healing 5, but has an effective Dexterity
score of 1 and may not move from the spot in which he stands.
*/
//:://////////////////////////////////////////////
//:: Created By: Jaysyn
//:: Created On: 20230107
//:://////////////////////////////////////////////
void main()
{
//:: Declare major variables
object oPC = OBJECT_SELF;
object oArea = GetArea(oPC);
int bDeepRoots = GetLocalInt(oPC, "DeepRootsActive");
int iNatural = GetIsAreaNatural(oArea);
int iSurface = GetIsAreaAboveGround(oArea);
effect eRoots = EffectCutsceneImmobilize();
effect eRegen = EffectRegenerate(4, 6.0f);
effect eEntangle = EffectVisualEffect(VFX_DUR_ENTANGLE);
effect eLink;
effect eEffect;
//:: Deep Roots only works where trees can grow.
if ((!iNatural) || (!iSurface))
{
SendMessageToPC(oPC, "You must be outdoors on fertile ground for this ability to function.");
return;
}
if (bDeepRoots)
{
//:: End & remove Deep Roots
eEffect = GetFirstEffect(oPC);
while(GetIsEffectValid(eEffect))
{
if(GetEffectTag(eEffect) == "FM_DeepRoots")
{
RemoveEffect(oPC, eEffect);
}
eEffect = GetNextEffect(oPC);
}
SetLocalInt(oPC, "DeepRootsActive", 0);
return;
}
//:: Link & tag effects
eLink = EffectLinkEffects(eRoots, eRegen);
eLink = EffectLinkEffects(eLink, eEntangle);
eLink = SupernaturalEffect(eLink);
eLink = TagEffect(eLink, "FM_DeepRoots");
//:: Clear the effect to be safe and prevent stacking
effect eCheckEffect = GetFirstEffect(oPC);
while (GetIsEffectValid(eCheckEffect))
{
if (GetEffectTag(eCheckEffect) == "FM_DeepRoots")
{
RemoveEffect(oPC, eCheckEffect);
}
eCheckEffect = GetNextEffect(oPC);
}
//:: Apply effects & set int var
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oPC);
SetLocalInt(oPC, "DeepRootsActive", 1);
}

View File

@@ -0,0 +1,250 @@
//::///////////////////////////////////////////////
//:: Forest Dominion
//:: prc_fm_forestdom.nss
//:://////////////////////////////////////////////
/*
At 2nd level, the forest master gains the ability to rebuke or command plants
as an evil cleric can rebuke or command undead. His effective level for this
ability is his class level, and he may use it a number of times perday equal
to 3 + his Charisma modifier. If he already has this ability because he is a
cleric with the Plant domain, these levels stack with his cleric levels and
vice versa.
*/
//:://////////////////////////////////////////////
//:: Modified:
//:: 20040101 by Cole Kleinschmit: for use as Command Spiders.
//:: 22021020 by Jaysyn: Fixed to actually work on all spiders.
//:: 20230107 by Jaysyn: for use as Command Plants.
#include "prc_class_const"
#include "prc_alterations"
int CheckTargetName(object oTarget, string sName);
int GetIsPlant(object oCreature, int nAppearance);
int CanCommand(int nClassLevel, int nTargetHD)
{
int nSlots = GetLocalInt(OBJECT_SELF, "wb_clr_comm_slots");
int nNew = nSlots+nTargetHD;
//FloatingTextStringOnCreature("The variable is " + IntToString(nSlots), OBJECT_SELF);
if(nClassLevel >= nNew)
{
return TRUE;
}
return FALSE;
}
void AddCommand(int nTargetHD)
{
int nSlots = GetLocalInt(OBJECT_SELF, "wb_clr_comm_slots");
SetLocalInt(OBJECT_SELF, "wb_clr_comm_slots", nSlots + nTargetHD);
}
void SubCommand(int nTargetHD)
{
int nSlots = GetLocalInt(OBJECT_SELF, "wb_clr_comm_slots");
SetLocalInt(OBJECT_SELF, "wb_clr_comm_slots", nSlots - nTargetHD);
}
void RebukePlant(int nTurnLevel, int nTurnHD, int nPlants, int nClassLevel)
{
//Gets all creatures in a 20m radius around the caster and rebukes them or not. If the creatures
//HD are 1/2 or less of the nClassLevel then the creature is commanded (dominated).
int nCnt = 1;
int nHD, nRacial, nHDCount, bValid, nDamage;
nHDCount = 0;
effect eVis = EffectVisualEffect(VFX_IMP_PULSE_NEGATIVE);
effect eVisTurn = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DOMINATED);
effect eDamage;
effect eTurned = EffectCutsceneParalyze();
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
effect eLink = EffectLinkEffects(eVisTurn, eTurned);
eLink = EffectLinkEffects(eLink, eDur);
effect eDeath = SupernaturalEffect(EffectCutsceneDominated());
effect eDomin = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_NEGATIVE);
effect eDeathLink = EffectLinkEffects(eDeath, eDomin);
effect eImpactVis = EffectVisualEffect(VFX_FNF_LOS_EVIL_30);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpactVis, GetLocation(OBJECT_SELF));
//Get nearest enemy within 20m (60ft)
//Why are you using GetNearest instead of GetFirstObjectInShape
// Because ability description says "gets closest first" :P
object oTarget = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC , OBJECT_SELF, nCnt);
int nTargetAppearance = GetAppearanceType(oTarget);
while(GetIsObjectValid(oTarget) && nHDCount < nTurnHD && GetDistanceToObject(oTarget) <= 20.0)
{
if(!GetIsFriend(oTarget))
{
nHD = GetHitDice(oTarget) + GetTurnResistanceHD(oTarget);
if(nHD <= nTurnLevel && nHD <= (nTurnHD - nHDCount))
{
//:: Check for correct turning target.
if(GetIsPlant(oTarget, nTargetAppearance))
{
bValid = TRUE;
//debug
SpeakString("Plant Found");
}
//Apply results of the turn
if( bValid == TRUE)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
//if(IntToFloat(nClassLevel)/2.0 >= IntToFloat(nHD))
//{
if((nClassLevel/2) >= nHD && CanCommand(nClassLevel, nHD))
{
//Fire cast spell at event for the specified target
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_FM_FORESTDOMINION));
//Destroy the target
DelayCommand(0.1f, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDeathLink, oTarget, RoundsToSeconds(nClassLevel + 5)));
//AssignCommand(oTarget, ClearAllActions());
//SetIsTemporaryFriend(oTarget, OBJECT_SELF, TRUE, RoundsToSeconds(nClassLevel + 5));
AddCommand(nHD);
DelayCommand(RoundsToSeconds(nClassLevel + 5), SubCommand(nHD));
//debug
SpeakString("Commanding Plant");
}
else
{
//Turn the target
//Fire cast spell at event for the specified target
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_FM_FORESTDOMINION));
//AssignCommand(oTarget, ActionMoveAwayFromObject(OBJECT_SELF, TRUE));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nClassLevel + 5));
//debug
SpeakString("Rebuking Plant");
}
nHDCount = nHDCount + nHD;
}
}
bValid = FALSE;
}
nCnt++;
oTarget = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF, nCnt);
}
}
void main()
{
//:: Declare major variables
int nFMLevel = GetLevelByClass(CLASS_TYPE_FORESTMASTER);
int nCleric = GetLevelByClass(CLASS_TYPE_CLERIC);
int nShaman = GetLevelByClass(CLASS_TYPE_SHAMAN);
int nTotalLevel;
//:: Check for Plant Domain & adust turning & class level.
int nPlants = GetHasFeat(FEAT_PLANT_DOMAIN_POWER);
if (nPlants)
{
nTotalLevel = nFMLevel + nCleric + nShaman;
}
else
{
nTotalLevel = nFMLevel;
}
int nTurnLevel = nTotalLevel;
int nClassLevel = nTotalLevel;
//:: Make a turning check roll
int nChrMod = GetAbilityModifier(ABILITY_CHARISMA);
int nTurnCheck = d20() + nChrMod; //:: The roll to apply to the max HD of plants that can be commanded --> nTurnLevel
int nTurnHD = d6(2) + nChrMod + nClassLevel; //:: The number of HD of plants that can be commanded.
//:: Determine the maximum HD of the plants that can be commanded.
if(nTurnCheck <= 0)
{
nTurnLevel -= 4;
}
else if(nTurnCheck >= 1 && nTurnCheck <= 3)
{
nTurnLevel -= 3;
}
else if(nTurnCheck >= 4 && nTurnCheck <= 6)
{
nTurnLevel -= 2;
}
else if(nTurnCheck >= 7 && nTurnCheck <= 9)
{
nTurnLevel -= 1;
}
else if(nTurnCheck >= 10 && nTurnCheck <= 12)
{
//:: Stays the same
}
else if(nTurnCheck >= 13 && nTurnCheck <= 15)
{
nTurnLevel += 1;
}
else if(nTurnCheck >= 16 && nTurnCheck <= 18)
{
nTurnLevel += 2;
}
else if(nTurnCheck >= 19 && nTurnCheck <= 21)
{
nTurnLevel += 3;
}
else if(nTurnCheck >= 22)
{
nTurnLevel += 4;
}
RebukePlant(nTurnLevel, nTurnHD, nPlants, nClassLevel);
}
int GetIsPlant(object oTarget, int nAppearance)
{
//:: No actual plants in vanilla NWN
return (nAppearance == 1001 //:: [CEP3] Twig Blight* (Erendril)
|| nAppearance == 1053 //:: [CEP3] Fungus: Shrieker 1* (Lathspell)
|| nAppearance == 1055 //:: [CEP3] Myconid* (Schazzwozzer)
|| nAppearance == 1056 //:: [CEP3] Myconid: Sprout* (Schazzwozzer)
|| nAppearance == 1057 //:: [CEP3] Myconid: Elder* (Schazzwozzer)
|| nAppearance == 1060 //:: [CEP3] Vegepygmy* (Lathspell)
|| nAppearance == 1061 //:: [CEP3] Thorny* (Lathspell)
|| nAppearance == 1062 //:: [CEP3] Vegepygmy: Thorny Rider T* (Lathspell)
|| nAppearance == 1063 //:: [CEP3] Vegepygmy: Thorny Rider* (Lathspell)
|| nAppearance == 1064 //:: [CEP3] Vegepygmy: Thorny Rider V* (Lathspell)
|| nAppearance == 1492 //:: [CEP3] Treant 1* (DLA Team)
|| nAppearance == 1496 //:: [CEP3] Assassin Vine: Horizontal* (ShadowM)
|| nAppearance == 1497 //:: [CEP3] Assassin Vine: Vertical* (ShadowM)
|| nAppearance == 2597 //:: [CEP3] Treant: Small*
|| nAppearance == 3049 //:: [CEP3] Pumpkin* (CEP-Barry_1066)
|| nAppearance == 3397 //:: [CEP3] Fungus: Mold: Brown* (CCP)
|| nAppearance == 3398 //:: [CEP3] Fungus: Mold: Yellow* (CCP)
|| nAppearance == 3399 //:: [CEP3] Fungus: Shrieker 2* (CCP)
|| nAppearance == 3400 //:: [CEP3] Fungus: Violet* (CCP)
|| nAppearance == 3471 //:: [CEP3] Shambling Mound 1* (CCP)
|| nAppearance == 3480 //:: [CEP3] Strangle Weed* (CCP)
|| nAppearance == 3492 //:: [CEP3] Treant 2* [WoW] (CCP)
|| nAppearance == 3893 //:: [CEP3] Shambling Mound 2* (Hardpoints)
|| nAppearance == 6409 //:: [CEP3] Fungus: Shrieker* (The Amethyst Dragon)
|| nAppearance == 6410 //:: [CEP3] Fungus: Violet Fungus* (The Amethyst Dragon)
|| nAppearance == 6417 //:: [CEP3] Treant: Wild Woods* (The Amethyst Dragon)
|| nAppearance == 6437 //:: [CEP3] Forrestal: Runner* (CCC-Cestus Dei)
|| nAppearance == 6438 //:: [CEP3] Forrestal: Strider* (CCC-Cestus Dei)
|| nAppearance == 6439 //:: [CEP3] Forrestal: Walkabout* (CCC-Cestus Dei)
|| nAppearance == 6440 //:: [CEP3] Forrestal: Elder* (CCC-Cestus Dei)
|| nAppearance == 6441 //:: [CEP3] Forrestal: Dreamwalker* (CCC-Cestus Dei)
|| nAppearance == 6468 //:: [CEP3] Topiary Guardian: Bear* (The Amethyst Dragon)
|| nAppearance == 6469 //:: [CEP3] Topiary Guardian: Boar* (The Amethyst Dragon)
|| nAppearance == 6470 //:: [CEP3] Topiary Guardian: Deer* (The Amethyst Dragon)
|| nAppearance == 6471 //:: [CEP3] Topiary Guardian: Lion* (The Amethyst Dragon)
|| nAppearance == 6472 //:: [CEP3] Topiary Guardian: Triceratops* (The Amethyst Dragon)
|| nAppearance == 6473 //:: [CEP3] Topiary Guardian: Wolf* (The Amethyst Dragon)
|| nAppearance == 6474 //:: [CEP3] Topiary Guardian: Horse* (The Amethyst Dragon)
|| nAppearance == 6475 //:: [CEP3] Topiary Guardian: Woman* (The Amethyst Dragon)
|| (MyPRCGetRacialType(oTarget) == RACIAL_TYPE_PLANT));
}

View File

@@ -0,0 +1,109 @@
//::///////////////////////////////////////////////
//:: Forest Master: Shocking Great Mallet
//:: prc_fm_icy_mal.nss
//:://////////////////////////////////////////////
/*
Beginning at 2nd level, a forest master begins to awaken magical abilities
within the wood and metal that make up his maul. Any maul used by a forest
master is treated as if it were a +2 maul with either the frost or shock
property (the forest master decides each round whether the weapons extra damage
is cold or electricity). If the weapon has additional abilities (such as
defending), these abilities still apply, and if the weapon has an enhancement
bonus better than +2 the higher of the two bonuses is used. The maul does not
gain these abilities if it is not wielded by the forest master. At 6th-level,
the forest masters maul acts as a +2 icy burst or +2 shocking burst weapon,
with the forest master deciding each round what effect the weapon has. At 9th
level, the forest masters maul acts as a +3 mighty cleaving weapon in addition
to its other properties (including its icy burst or shocking burst ability).
*/
//:://////////////////////////////////////////////
//:: Created By: Jaysyn
//:: Created On: 20230106
//:://////////////////////////////////////////////
#include "prc_alterations"
void main()
{
//:: Declare major variables
object oPC = OBJECT_SELF;
int iFMLevel = GetLevelByClass(CLASS_TYPE_FORESTMASTER, oPC);
itemproperty ipIP;
//:: Find a maul
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
int bHasMaul = (GetBaseItemType(oItem) == BASE_ITEM_MAUL);
//:: Need a maul
if(!bHasMaul)
{
FloatingTextStringOnCreature(GetStringByStrRef(16548+0x01000000), oPC, FALSE);
}
//:: Remove the Cleave or Great Cleave bonus feat from the maul being unequipped
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_BONUS_FEAT, DURATION_TYPE_TEMPORARY, IP_CONST_FEAT_GREAT_CLEAVE);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_BONUS_FEAT, DURATION_TYPE_TEMPORARY, IP_CONST_FEAT_CLEAVE);
//:: Remove Great Mallet damage bonuses from maul being unequipped
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_DAMAGE_BONUS, DURATION_TYPE_TEMPORARY, IP_CONST_DAMAGETYPE_ELECTRICAL);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_DAMAGE_BONUS, DURATION_TYPE_TEMPORARY, IP_CONST_DAMAGETYPE_COLD);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_ENHANCEMENT_BONUS, DURATION_TYPE_TEMPORARY);
//:: Setup damage bonuses
if (iFMLevel >= 9)
{
if (GetHasFeat(FEAT_GREAT_CLEAVE,oPC))
{
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d8);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(3);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
else if (GetHasFeat(FEAT_CLEAVE, oPC))
{
ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_GREAT_CLEAVE);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d8);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(3);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
else
{
ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_CLEAVE);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d8);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(3);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
}
else if (iFMLevel < 9 && iFMLevel > 5)
{
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d8);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(2);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
else
{
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d6);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(2);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
}

View File

@@ -0,0 +1,108 @@
//::///////////////////////////////////////////////
//:: Forest Master: Shocking Great Mallet
//:: prc_fm_shock_mal.nss
//:://////////////////////////////////////////////
/*
Beginning at 2nd level, a forest master begins to awaken magical abilities
within the wood and metal that make up his maul. Any maul used by a forest
master is treated as if it were a +2 maul with either the frost or shock
property (the forest master decides each round whether the weapons extra damage
is cold or electricity). If the weapon has additional abilities (such as
defending), these abilities still apply, and if the weapon has an enhancement
bonus better than +2 the higher of the two bonuses is used. The maul does not
gain these abilities if it is not wielded by the forest master. At 6th-level,
the forest masters maul acts as a +2 icy burst or +2 shocking burst weapon,
with the forest master deciding each round what effect the weapon has. At 9th
level, the forest masters maul acts as a +3 mighty cleaving weapon in addition
to its other properties (including its icy burst or shocking burst ability).
*/
//:://////////////////////////////////////////////
//:: Created By: Jaysyn
//:: Created On: 20230106
//:://////////////////////////////////////////////
#include "prc_alterations"
void main()
{
//:: Declare major variables
object oPC = OBJECT_SELF;
int iFMLevel = GetLevelByClass(CLASS_TYPE_FORESTMASTER, oPC);
itemproperty ipIP;
//:: Find a maul
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
int bHasMaul = (GetBaseItemType(oItem) == BASE_ITEM_MAUL);
//:: Need a maul
if(!bHasMaul)
{
FloatingTextStringOnCreature(GetStringByStrRef(16548+0x01000000), oPC, FALSE);
}
//:: Remove the Cleave or Great Cleave bonus feat from the maul being unequipped
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_BONUS_FEAT, DURATION_TYPE_TEMPORARY, IP_CONST_FEAT_GREAT_CLEAVE);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_BONUS_FEAT, DURATION_TYPE_TEMPORARY, IP_CONST_FEAT_CLEAVE);
//:: Remove Great Mallet damage bonuses from maul being unequipped
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_DAMAGE_BONUS, DURATION_TYPE_TEMPORARY, IP_CONST_DAMAGETYPE_ELECTRICAL);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_DAMAGE_BONUS, DURATION_TYPE_TEMPORARY, IP_CONST_DAMAGETYPE_COLD);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_ENHANCEMENT_BONUS, DURATION_TYPE_TEMPORARY);
//:: Setup damage bonuses
if (iFMLevel >= 9)
{
if (GetHasFeat(FEAT_GREAT_CLEAVE,oPC))
{
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d8);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(3);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
else if (GetHasFeat(FEAT_CLEAVE, oPC))
{
ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_GREAT_CLEAVE);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d8);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(3);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
else
{
ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_CLEAVE);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d8);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(3);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
}
else if (iFMLevel < 9 && iFMLevel > 5)
{
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d8);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(2);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
else
{
ipIP = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d6);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyEnhancementBonus(2);
IPSafeAddItemProperty(oItem, ipIP, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
}

View File

@@ -0,0 +1,131 @@
//::///////////////////////////////////////////////
//:: [Forest Master setup script]
//:: [prc_forestmaster.nss]
//:: [Jaysyn 20230106]
//::///////////////////////////////////////////////
#include "prc_inc_combat"
void main()
{
//:: Declare major variables
object oPC = OBJECT_SELF;
object oSkin = GetPCSkin(oPC);
object oItem = GetPCItemLastUnequipped();
int nFMLevel = GetLevelByClass(CLASS_TYPE_FORESTMASTER, oPC);
int nEvent = GetRunningEvent();
effect eEffect;
itemproperty ipIP;
//:: We aren't being called from onPlayerUnequipItem event, instead from the PRCEvalFeats
if(nEvent == FALSE)
{
// :: Hook in the events
if(DEBUG) DoDebug("Forest Master: Adding eventhooks");
AddEventScript(oPC, EVENT_ONPLAYERUNEQUIPITEM, "prc_forestmaster", TRUE, FALSE);
}
//:: We're being called from the onPlayerUnequipItem eventhook, so check or skip
if(nEvent == EVENT_ONPLAYERUNEQUIPITEM)
{
//:: Remove Great Mallet damage bonuses from maul being unequipped
int bHadMaul = (GetBaseItemType(oItem) == BASE_ITEM_MAUL);
if(bHadMaul)
{
//:: Remove the Cleave or Great Cleave bonus feat from the maul being unequipped
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_BONUS_FEAT, DURATION_TYPE_TEMPORARY, IP_CONST_FEAT_GREAT_CLEAVE);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_BONUS_FEAT, DURATION_TYPE_TEMPORARY, IP_CONST_FEAT_CLEAVE);
//:: Remove Great Mallet damage bonuses from maul being unequipped
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_DAMAGE_BONUS, DURATION_TYPE_TEMPORARY, IP_CONST_DAMAGETYPE_ELECTRICAL);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_DAMAGE_BONUS, DURATION_TYPE_TEMPORARY, IP_CONST_DAMAGETYPE_COLD);
IPRemoveMatchingItemProperties(oItem, ITEM_PROPERTY_ENHANCEMENT_BONUS, DURATION_TYPE_TEMPORARY);
}
}
//:: End if - Running OnPlayerUnequipItem event
//:: Setup Oak Strength ////////////////////////////////////////////////////////
/* Oak Strength (Ex): Beginning at 4th level, the forest master gains a +2
bonus to Strength and the ability to make slam attacks. A Small creatures
slam attack deals 1d4 points of damage, one from a Medium-size creature
deals 1d6 points of damage, and a Large forest masters slam attack deals
1d8 points of damage. Slam attacks are natural weapon attacks and do not
provoke an attack of opportunity from the defender. A forest master can
select Improved Critical (slam), Weapon Focus (slam), and (if a fighter of
4th level or higher) Weapon Specialization (slam). Upon gaining this
ability, the forest masters hair takes on a green, leafy appearance. */
//::////////////////////////////////////////////////////////////////////////////
if (nFMLevel >= 4)
{
string sResRef;
int nHair;
int nHairSet = GetLocalInt(oPC, "FM_HAIR_INT");
int nSize = PRCGetCreatureSize(oPC)+1;
//primary weapon
sResRef = "prc_warf_slam_";
sResRef += GetAffixForSize(nSize);
AddNaturalPrimaryWeapon(oPC, sResRef, 2);
if (!nHairSet)
{
switch (Random(6))
{
case 0: {nHair = 30; break;}
case 1: {nHair = 31; break;}
case 2: {nHair = 49 ; break;}
case 3: {nHair = 106; break;}
case 4: {nHair = 107; break;}
case 5: {nHair = 152; break;}
case 6: {nHair = 153; break;}
}
SetColor(oPC, COLOR_CHANNEL_HAIR, nHair);
SetLocalInt(oPC, "FM_HAIR_INT", nHair);
}
}
//:: Setup Oakheart ///////////////////////////////////////////////////////////////
/* Oakheart (Ex): Upon reaching 7th level, a forest masters body becomes a
thing of wood and leaf rather than meat and bone. His type changes to plant.
As such, he is immune to mind-affecting effects, poison, sleep, paralysis,
stunning, and polymorphing. He is not subject to critical hits or sneak
attacks. However, the forest master becomes vulnerable to fire, and suffers
double damage from fire attacks if he fails a Reflex saving throw, or half
damage if he succeeds. */
//::///////////////////////////////////////////////////////////////////////////////
if (nFMLevel >= 7)
{
effect eNoStun = EffectImmunity(IMMUNITY_TYPE_STUN);
eNoStun = SupernaturalEffect(eNoStun);
eNoStun = ExtraordinaryEffect(eNoStun);
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eNoStun, oPC));
//:: These are handled via cls_feat_formast.2da
/* ipIP =ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_PARALYSIS);
IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE);
ipIP =ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_POISON);
IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE);
ipIP =ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_MINDSPELLS);
IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE);
ipIP =ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_CRITICAL_HITS);
IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE); */
ipIP =ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_BACKSTAB);
IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE);
ipIP = ItemPropertyDamageVulnerability(DAMAGE_TYPE_FIRE, IP_CONST_DAMAGEVULNERABILITY_50_PERCENT);
IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE);
}
} //:: End

View File

@@ -142,7 +142,7 @@ void UpdateIPs(object oItem)
else if(nClass == CLASS_TYPE_WIZARD || nClass == CLASS_TYPE_SORCERER)
bAdd = RealSpellToSpellbookID(CLASS_TYPE_SORCERER, nSpellID) == -1 ? FALSE : TRUE;
else if(nClass == CLASS_TYPE_CLERIC)
bAdd = RealSpellToSpellbookID(CLASS_TYPE_MYSTIC, nSpellID) == -1 ? FALSE : TRUE;
bAdd = Get2DACache("Spells", "Cleric", nSpellID) == "" ? FALSE : TRUE;
else
bAdd = RealSpellToSpellbookID(nClass, nSpellID) == -1 ? FALSE : TRUE;