Archived Spellman's Project content. Added missing Diamond Dragon stat feats. Hospitaler's should be able to take Extra Turning. Dodge proxies should allow entry into Champion of Corellon. Mounted Combat is a prereq for Champion of Corellon. Only Clerics have Domain reqs to enter Morninglord. Verdant Lord was missing BAB 4 entry requirement. Diamond Dragons don't get spellcraft. Re-added Korobokuru race. Added .ltr tables for Korobokuru. Capped Blood in the Water at +20. Capped Pearl of Black Doubt at +20. Added json_GetFirstKnownSpell() and json_GetNextKnownSpell(). Updated all old NWNx functions to work with NWNxEE. Added new switch to enable optional PRCX / NWNxEE shims. Commented out ConvoCC switches on inc_switch_setup.nss Diamond Dragon's stat increases are intrinsic when using NWNxEE. Forsaker's stat increases are intrinsic when using NWNxEE. Vow of Poverty's stat increases are intrinsic when using NWNxEE. Cloud Dragon summon should be Neutral Good. Fixed Verdant Lord's regen. Fixed Forest Master's regen. Morninglord's Creative Fire should affect Alchemy. Added yes/no dialog when choosing Vow of Poverty bonus Exalted Feats. Racial natural AC should be intrinsic when NWNxEE is enabled. Transcendent Vitality's CON bonus is intrinsic when NWNxEE is enabled.
586 lines
20 KiB
Plaintext
586 lines
20 KiB
Plaintext
//:://////////////////////////////////////////////
|
|
//:: Associate include
|
|
//:: prc_inc_assoc.nss
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
This file contains various functions for animal
|
|
companions and familiars
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
|
|
#include "inc_npc"
|
|
#include "inc_nwnx_funcs"
|
|
#include "shd_inc_shdfunc"
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function prototypes */
|
|
//////////////////////////////////////////////////
|
|
|
|
//adds associate as a henchman
|
|
void AddAssociate(object oMaster, object oAssociate);
|
|
|
|
//removes associate with unsummon vfx
|
|
void DestroyAssociate(object oAssociate);
|
|
|
|
//applies fiendiosh template
|
|
void ApplyFiendishTemplate(object oCompanion, object oCompSkin);
|
|
|
|
//applies exalted companion bonuses
|
|
void ApplyExaltedCompanion(object oCompanion, object oCompSkin);
|
|
|
|
//applies blightspawned properties
|
|
void ApplyIllmaster(object oCompanion, object oCompSkin);
|
|
|
|
//applies pseudonatural template
|
|
void ApplyPseudonatural(object oFamiliar, object oFamSkin);
|
|
|
|
//applies pnp familiar bonuses
|
|
void ApplyPnPFamiliarProperties(object oPC, object oFamiliar);
|
|
|
|
//sets up animal companion natural weapons using following scheme:
|
|
/*
|
|
Damage
|
|
Lvl Claw Bite
|
|
1 1d3 1d6
|
|
6 1d4 1d8
|
|
12 1d6 1d10
|
|
19 1d8 2d6
|
|
27 1d10 2d8
|
|
36 1d12 2d10
|
|
|
|
enhancement bonus
|
|
(Lvl - 15) / 5
|
|
*/
|
|
void SetNaturalWeaponDamage(object oCompanion, int nLvlMod = 0);
|
|
|
|
void UnsummonCompanions(object oPC);
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Constants */
|
|
//////////////////////////////////////////////////
|
|
|
|
const int DISEASE_TALONAS_BLIGHT = 52;
|
|
|
|
//associate numbers as nTH parameter in GetAssociateNPC()
|
|
const int NPC_BIOWARE_COMPANION = 1; //'original' bioware familiar/companion returned by GetAssociate()
|
|
const int NPC_HENCHMAN_COMPANION = 2; //bioware familiar/companion added as hanchman
|
|
//ASSOCIATE_TYPE_FAMILIAR
|
|
const int NPC_PNP_FAMILIAR = 3;
|
|
const int NPC_BONDED_FAMILIAR = 4;
|
|
const int NPC_DN_FAMILIAR = 5;
|
|
const int NPC_MS_ELEMENTAL = 6;
|
|
//ASSOCIATE_TYPE_ANIMALCOMPANION
|
|
const int NPC_SHAMAN_COMPANION = 3;
|
|
const int NPC_UR_COMPANION = 4;
|
|
//ASSOCIATE_TYPE_SUMMONED
|
|
const int NPC_DARK_COMPANION = 2;
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function definitions */
|
|
//////////////////////////////////////////////////
|
|
|
|
void AddAssociate(object oMaster, object oAssociate)
|
|
{
|
|
int nMaxHenchmen = GetMaxHenchmen();
|
|
SetMaxHenchmen(99);
|
|
AddHenchman(oMaster, oAssociate);
|
|
SetMaxHenchmen(nMaxHenchmen);
|
|
}
|
|
|
|
void DestroyAssociate(object oAssociate)
|
|
{
|
|
AssignCommand(oAssociate, SetIsDestroyable(TRUE));
|
|
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), GetLocation(oAssociate));
|
|
DestroyObject(oAssociate);
|
|
}
|
|
|
|
void CleanProperties(object oItem)
|
|
{
|
|
itemproperty ip = GetFirstItemProperty(oItem);
|
|
while(GetIsItemPropertyValid(ip))
|
|
{
|
|
RemoveItemProperty(oItem, ip);
|
|
ip = GetNextItemProperty(oItem);
|
|
}
|
|
}
|
|
|
|
void ApplyFiendishTemplate(object oTarget, object oCompSkin)
|
|
{
|
|
int nHD = GetHitDice(oTarget);
|
|
effect eDR;
|
|
int nResist;
|
|
|
|
if (nHD >= 12)
|
|
{
|
|
eDR = EffectDamageReduction(10, DAMAGE_POWER_PLUS_THREE);
|
|
nResist = 20;
|
|
}
|
|
else if (12 > nHD && nHD >= 8)
|
|
{
|
|
eDR = EffectDamageReduction(5, DAMAGE_POWER_PLUS_TWO);
|
|
nResist = 15;
|
|
}
|
|
else if (8 > nHD && nHD >= 4)
|
|
{
|
|
eDR = EffectDamageReduction(5, DAMAGE_POWER_PLUS_ONE);
|
|
nResist = 10;
|
|
}
|
|
else if (4 > nHD)
|
|
{
|
|
nResist = 5;
|
|
}
|
|
|
|
effect eFire = EffectDamageResistance(DAMAGE_TYPE_FIRE, nResist);
|
|
effect eCold = EffectDamageResistance(DAMAGE_TYPE_COLD, nResist);
|
|
effect eVis = EffectUltravision();
|
|
effect eLink = EffectLinkEffects(eDR, eFire);
|
|
eLink = EffectLinkEffects(eLink, eCold);
|
|
eLink = EffectLinkEffects(eLink, eVis);
|
|
eLink = SupernaturalEffect(eLink);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oTarget);
|
|
|
|
itemproperty ipIP = PRCItemPropertyBonusFeat(FEAT_TEMPLATE_FIENDISH_SMITE_GOOD);
|
|
IPSafeAddItemProperty(oCompSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
|
|
|
if(GetAlignmentGoodEvil(oTarget) != ALIGNMENT_EVIL)
|
|
AdjustAlignment(oTarget, ALIGNMENT_EVIL, 80, FALSE);
|
|
|
|
SetSubRace(oTarget, "Undead (Extraplanar)");
|
|
|
|
SetLocalInt(oTarget, "FiendishTemplate", 1);
|
|
|
|
}
|
|
|
|
|
|
void ApplyExaltedCompanion(object oCompanion, object oCompSkin)
|
|
{
|
|
int nHD = GetHitDice(oCompanion);
|
|
effect eDR;
|
|
int nResist;
|
|
|
|
if (nHD >= 12)
|
|
{
|
|
eDR = EffectDamageReduction(10, DAMAGE_POWER_PLUS_THREE);
|
|
nResist = 20;
|
|
}
|
|
else if (12 > nHD && nHD >= 8)
|
|
{
|
|
eDR = EffectDamageReduction(5, DAMAGE_POWER_PLUS_TWO);
|
|
nResist = 15;
|
|
}
|
|
else if (8 > nHD && nHD >= 4)
|
|
{
|
|
eDR = EffectDamageReduction(5, DAMAGE_POWER_PLUS_ONE);
|
|
nResist = 10;
|
|
}
|
|
else if (4 > nHD)
|
|
{
|
|
nResist = 5;
|
|
}
|
|
|
|
effect eAcid = EffectDamageResistance(DAMAGE_TYPE_ACID, nResist);
|
|
effect eCold = EffectDamageResistance(DAMAGE_TYPE_COLD, nResist);
|
|
effect eElec = EffectDamageResistance(DAMAGE_TYPE_ELECTRICAL, nResist);
|
|
effect eVis = EffectUltravision();
|
|
effect eLink = EffectLinkEffects(eDR, eAcid);
|
|
eLink = EffectLinkEffects(eLink, eCold);
|
|
eLink = EffectLinkEffects(eLink, eElec);
|
|
eLink = EffectLinkEffects(eLink, eVis);
|
|
eLink = SupernaturalEffect(eLink);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oCompanion);
|
|
|
|
itemproperty ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_TEMPLATE_CELESTIAL_SMITE_EVIL);
|
|
IPSafeAddItemProperty(oCompSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
|
|
|
if(GetAlignmentGoodEvil(oCompanion) != ALIGNMENT_GOOD)
|
|
AdjustAlignment(oCompanion, ALIGNMENT_GOOD, 80, FALSE);
|
|
|
|
SetLocalInt(oCompanion, "CelestialTemplate", 1);
|
|
}
|
|
|
|
void ApplyPseudonatural(object oFamiliar, object oFamSkin)
|
|
{
|
|
if(GetLocalInt(oFamiliar, "PseudonaturalTemplate"))
|
|
return;
|
|
|
|
int nHD = GetHitDice(oFamiliar);
|
|
int nResist;
|
|
effect eDR;
|
|
if (nHD >= 12)
|
|
{
|
|
eDR = EffectDamageReduction(10, DAMAGE_POWER_PLUS_THREE);
|
|
nResist = 20;
|
|
}
|
|
else if (12 > nHD && nHD >= 8)
|
|
{
|
|
eDR = EffectDamageReduction(5, DAMAGE_POWER_PLUS_TWO);
|
|
nResist = 15;
|
|
}
|
|
else if (8 > nHD && nHD >= 4)
|
|
{
|
|
eDR = EffectDamageReduction(5, DAMAGE_POWER_PLUS_ONE);
|
|
nResist = 10;
|
|
}
|
|
else if (4 > nHD)
|
|
{
|
|
nResist = 5;
|
|
}
|
|
|
|
effect eAcid = EffectDamageResistance(DAMAGE_TYPE_ACID, nResist);
|
|
effect eElec = EffectDamageResistance(DAMAGE_TYPE_ELECTRICAL, nResist);
|
|
effect eAC = EffectACIncrease(1,AC_NATURAL_BONUS);
|
|
effect eLink = EffectLinkEffects(eDR, eAcid);
|
|
eLink = EffectLinkEffects(eLink, eElec);
|
|
eLink = EffectLinkEffects(eLink, eAC);
|
|
eLink = SupernaturalEffect(eLink);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oFamiliar);
|
|
|
|
// itemproperty ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_TEMPLATE_PSEUDONATURAL_TRUESTRIKE);
|
|
// IPSafeAddItemProperty(oFamSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
|
|
|
SetLocalInt(oFamiliar, "PseudonaturalTemplate", 1);
|
|
}
|
|
|
|
void ApplyIllmaster(object oCompanion, object oCompSkin)
|
|
{
|
|
//Give the companion permanent Str +4, Con +2, Wis -2, and Cha -2
|
|
if(GetPRCSwitch(PRC_NWNXEE_ENABLED))
|
|
{
|
|
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_STRENGTH, 4);
|
|
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_CONSTITUTION, 2);
|
|
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_WISDOM, -2);
|
|
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_CHARISMA, -2);
|
|
}
|
|
else
|
|
{
|
|
string sFlag = "Illmaster";
|
|
SetCompositeBonus(oCompSkin, sFlag, 4, ITEM_PROPERTY_ABILITY_BONUS, IP_CONST_ABILITY_STR);
|
|
SetCompositeBonus(oCompSkin, sFlag, 2, ITEM_PROPERTY_ABILITY_BONUS, IP_CONST_ABILITY_CON);
|
|
SetCompositeBonus(oCompSkin, sFlag, 2, ITEM_PROPERTY_DECREASED_ABILITY_SCORE, IP_CONST_ABILITY_WIS);
|
|
SetCompositeBonus(oCompSkin, sFlag, 2, ITEM_PROPERTY_DECREASED_ABILITY_SCORE, IP_CONST_ABILITY_CHA);
|
|
}
|
|
|
|
//Set PLANT immunities and add low light vision
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertySpellImmunitySpecific(IP_CONST_IMMUNITYSPELL_CHARM_PERSON), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertySpellImmunitySpecific(IP_CONST_IMMUNITYSPELL_DOMINATE_PERSON), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertySpellImmunitySpecific(IP_CONST_IMMUNITYSPELL_HOLD_PERSON), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertySpellImmunitySpecific(IP_CONST_IMMUNITYSPELL_MASS_CHARM), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_MINDSPELLS), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_POISON), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_PARALYSIS), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_CRITICAL_HITS), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_DISEASE), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_BACKSTAB), oCompSkin);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, PRCItemPropertyBonusFeat(FEAT_LOWLIGHTVISION), oCompSkin);
|
|
|
|
//Compute the DC for this companion's blight touch
|
|
int iHD = GetHitDice(oCompanion);
|
|
int iCons = GetAbilityModifier(ABILITY_CONSTITUTION, oCompanion);
|
|
int iDC = 10 + (iHD / 2) + iCons;
|
|
//Create the onhit item property for causing the blight touch disease
|
|
itemproperty ipBlightTouch = ItemPropertyOnHitProps(IP_CONST_ONHIT_DISEASE, IPOnHitSaveDC(iDC), DISEASE_TALONAS_BLIGHT);
|
|
//Get the companion's creature weapons
|
|
object oBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oCompanion);
|
|
object oLClaw = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oCompanion);
|
|
object oRClaw = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oCompanion);
|
|
//Apply blight touch to each weapon
|
|
if (GetIsObjectValid(oBite))
|
|
IPSafeAddItemProperty(oBite, ipBlightTouch);
|
|
if (GetIsObjectValid(oLClaw))
|
|
IPSafeAddItemProperty(oLClaw, ipBlightTouch);
|
|
if (GetIsObjectValid(oRClaw))
|
|
IPSafeAddItemProperty(oRClaw, ipBlightTouch);
|
|
|
|
//Adjust alignment to Neutral Evil
|
|
if(GetAlignmentLawChaos(oCompanion) != ALIGNMENT_NEUTRAL)
|
|
AdjustAlignment(oCompanion, ALIGNMENT_NEUTRAL, 50, FALSE);
|
|
if (GetAlignmentGoodEvil(oCompanion) != ALIGNMENT_EVIL)
|
|
AdjustAlignment(oCompanion, ALIGNMENT_EVIL, 80, FALSE);
|
|
}
|
|
|
|
void WinterWolfProperties(object oCompanion, int nLevel)
|
|
{
|
|
int iStr = nLevel >= 30 ? (nLevel-30)/2 : (nLevel-4)/2;
|
|
int iDex = nLevel >= 30 ? (nLevel-31)/2 : (nLevel-5)/2;
|
|
|
|
object oCreR = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oCompanion);
|
|
|
|
if(GetPRCSwitch(PRC_NWNXEE_ENABLED))
|
|
{
|
|
if(iStr > 0)
|
|
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_STRENGTH, iStr);
|
|
if(iDex > 0)
|
|
PRC_Funcs_ModAbilityScore(oCompanion, ABILITY_DEXTERITY, iStr);
|
|
}
|
|
else
|
|
{
|
|
if(iStr > 0)
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAbilityBonus(IP_CONST_ABILITY_STR, iStr), oCreR);
|
|
if(iDex > 0)
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAbilityBonus(IP_CONST_ABILITY_DEX, iDex), oCreR);
|
|
}
|
|
|
|
int nBonusDmg;
|
|
|
|
if(nLevel > 24)
|
|
nBonusDmg = IP_CONST_DAMAGEBONUS_1d12;
|
|
else if(nLevel > 16)
|
|
nBonusDmg = IP_CONST_DAMAGEBONUS_1d10;
|
|
else if(nLevel > 7)
|
|
nBonusDmg = IP_CONST_DAMAGEBONUS_1d8;
|
|
else
|
|
nBonusDmg = IP_CONST_DAMAGEBONUS_1d6;
|
|
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, nBonusDmg), oCreR);
|
|
//winter wolf properties
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyDamageVulnerability(IP_CONST_DAMAGETYPE_FIRE, IP_CONST_DAMAGEVULNERABILITY_50_PERCENT), oCreR);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyDamageImmunity(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEIMMUNITY_100_PERCENT), oCreR);
|
|
|
|
int iMax, i;
|
|
int coneAbi = nLevel / 5;
|
|
switch(coneAbi)
|
|
{
|
|
case 1 : iMax = 7; break;
|
|
case 2 : iMax = 6; break;
|
|
case 3 : iMax = 5; break;
|
|
case 4 : iMax = 4; break;
|
|
case 5 : iMax = 3; break;
|
|
case 6 : iMax = 2; break;
|
|
case 7 : iMax = 1; break;
|
|
}
|
|
|
|
if(iMax > 0)
|
|
{
|
|
for(i = 1; i <= iMax; i++)
|
|
DecrementRemainingSpellUses(oCompanion, 230);
|
|
}
|
|
}
|
|
|
|
void ApplyPnPFamiliarProperties(object oPC, object oFam)
|
|
{
|
|
int nNWNxEE = GetPRCSwitch(PRC_NWNXEE_ENABLED);
|
|
int nPRCx = GetPRCSwitch(PRC_PRCX_ENABLED);
|
|
int bFuncs = (nNWNxEE && nPRCx);
|
|
|
|
effect eBonus;
|
|
|
|
//get familiar level
|
|
int nFamLevel = GetLevelByClass(CLASS_TYPE_WIZARD, oPC)
|
|
+ GetLevelByClass(CLASS_TYPE_SORCERER, oPC)
|
|
+ GetLevelByClass(CLASS_TYPE_WITCH, oPC)
|
|
+ GetLevelByClass(CLASS_TYPE_ALIENIST, oPC)
|
|
+ GetLevelByClass(CLASS_TYPE_HEXBLADE, oPC)
|
|
+ GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oPC);
|
|
|
|
if (GetHasFeat(FEAT_SHADOW_FAMILIAR, oPC)) nFamLevel = GetLevelByTypeArcane(oPC) + GetShadowcasterLevel(oPC); // For the purpose of determining familiar abilities that depend on your arcane caster level,
|
|
// your levels in all classes that allow you to cast mysteries or arcane spells stack
|
|
|
|
//scaling bonuses
|
|
int nAdjustLevel = nFamLevel - GetHitDice(oFam);
|
|
int n;
|
|
for(n = 1; nAdjustLevel >= n; n++)
|
|
LevelUpHenchman(oFam, CLASS_TYPE_INVALID, TRUE);
|
|
|
|
int nACBonus = nFamLevel / 2;
|
|
int nIntBonus = nFamLevel / 2;
|
|
int nSRBonus = nFamLevel > 11 ? nFamLevel + 5 : 0;
|
|
|
|
//saving throws
|
|
int nSaveRefBonus = GetReflexSavingThrow(oPC) - GetReflexSavingThrow(oFam);
|
|
int nSaveFortBonus = GetFortitudeSavingThrow(oPC) - GetFortitudeSavingThrow(oFam);
|
|
int nSaveWillBonus = GetWillSavingThrow(oPC) - GetWillSavingThrow(oFam);
|
|
|
|
int nHPBonus;
|
|
|
|
if(bFuncs)
|
|
{
|
|
nHPBonus = GetMaxHitPoints(oPC) / 2;
|
|
|
|
int i, nBonus;
|
|
for(i = 0; i < GetPRCSwitch(FILE_END_SKILLS); i++)
|
|
{
|
|
nBonus = GetSkillRank(i, oPC) - GetSkillRank(i, oFam);
|
|
if(nBonus > 0)
|
|
PRC_Funcs_ModSkill(oFam, i, nBonus);
|
|
}
|
|
|
|
PRC_Funcs_SetBaseNaturalAC(oFam, PRC_Funcs_GetBaseNaturalAC(oFam) + nACBonus);
|
|
PRC_Funcs_ModAbilityScore(oFam, ABILITY_INTELLIGENCE, nIntBonus);
|
|
PRC_Funcs_ModSavingThrowBonus(oFam, SAVING_THROW_REFLEX, nSaveRefBonus);
|
|
PRC_Funcs_ModSavingThrowBonus(oFam, SAVING_THROW_FORT, nSaveFortBonus);
|
|
PRC_Funcs_ModSavingThrowBonus(oFam, SAVING_THROW_WILL, nSaveWillBonus);
|
|
PRC_Funcs_SetMaxHitPoints(oFam, nHPBonus);
|
|
PRC_Funcs_SetCurrentHitPoints(oFam, nHPBonus);
|
|
}
|
|
else
|
|
{
|
|
//temporary HP for the moment, have to think of a better idea later
|
|
nHPBonus = (GetMaxHitPoints(oPC) / 2) - GetMaxHitPoints(oFam);
|
|
|
|
int i, nBonus;
|
|
for(i = 0; i < GetPRCSwitch(FILE_END_SKILLS); i++)
|
|
{
|
|
nBonus = GetSkillRank(i, oPC) - GetSkillRank(i, oFam);
|
|
eBonus = EffectLinkEffects(eBonus, EffectSkillIncrease(i, nBonus));
|
|
}
|
|
|
|
eBonus = EffectLinkEffects(eBonus, EffectACIncrease(nACBonus, AC_NATURAL_BONUS));
|
|
eBonus = EffectLinkEffects(eBonus, EffectAbilityIncrease(ABILITY_INTELLIGENCE, nIntBonus));
|
|
eBonus = EffectLinkEffects(eBonus, EffectSavingThrowIncrease(SAVING_THROW_REFLEX, nSaveRefBonus));
|
|
eBonus = EffectLinkEffects(eBonus, EffectSavingThrowIncrease(SAVING_THROW_FORT, nSaveFortBonus));
|
|
eBonus = EffectLinkEffects(eBonus, EffectSavingThrowIncrease(SAVING_THROW_WILL, nSaveWillBonus));
|
|
eBonus = EffectLinkEffects(eBonus, EffectTemporaryHitpoints(nHPBonus));
|
|
}
|
|
|
|
int nABBonus = GetBaseAttackBonus(oPC) - GetBaseAttackBonus(oFam);
|
|
int nAttacks = (GetBaseAttackBonus(oPC)/5)+1;
|
|
if(nAttacks > 5)
|
|
nAttacks = 5;
|
|
SetBaseAttackBonus(nAttacks, oFam);
|
|
|
|
//effect doing
|
|
if(nSRBonus > 0) eBonus = EffectLinkEffects(eBonus, EffectSpellResistanceIncrease(nSRBonus));
|
|
eBonus = EffectLinkEffects(eBonus, EffectAttackIncrease(nABBonus));
|
|
//skills were linked earlier
|
|
eBonus = SupernaturalEffect(eBonus);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eBonus, oFam);
|
|
}
|
|
|
|
void CheckIsValidFamiliar(object oMaster, effect eBonus)
|
|
{
|
|
object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR);
|
|
object oFamToken = GetItemPossessedBy(oMaster, "prc_pnp_familiar");
|
|
|
|
if(GetIsObjectValid(oFam))
|
|
{
|
|
if(!GetIsDead(oFam))
|
|
{
|
|
DelayCommand(30.0, CheckIsValidFamiliar(oMaster, eBonus));
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(GetIsObjectValid(oFamToken))
|
|
{
|
|
DelayCommand(30.0, CheckIsValidFamiliar(oMaster, eBonus));
|
|
return;
|
|
}
|
|
}
|
|
|
|
RemoveEffect(oMaster, eBonus);
|
|
}
|
|
|
|
effect GetMasterBonus(int nFamiliarType)
|
|
{
|
|
effect eBonus;
|
|
string sFile = "prc_familiar";
|
|
string sTemp = Get2DACache(sFile, "BONUS", nFamiliarType);
|
|
int nParam1 = StringToInt(Get2DACache(sFile, "PARAM1", nFamiliarType));
|
|
int nParam2 = StringToInt(Get2DACache(sFile, "PARAM2", nFamiliarType));
|
|
|
|
if(sTemp == "sk")
|
|
eBonus = EffectSkillIncrease(nParam1, nParam2);
|
|
else if(sTemp == "sv")
|
|
eBonus = EffectSavingThrowIncrease(nParam1, nParam2);
|
|
else if(sTemp == "hp")
|
|
eBonus = EffectTemporaryHitpoints(nParam1);
|
|
|
|
return eBonus;
|
|
}
|
|
|
|
int GetCompanionBaseDamage(int nLevel, int bBite)
|
|
{
|
|
int nBite, nClaw;
|
|
if(nLevel > 35)
|
|
{
|
|
nBite = IP_CONST_MONSTERDAMAGE_2d10;
|
|
nClaw = IP_CONST_MONSTERDAMAGE_1d12;
|
|
}
|
|
else if(nLevel > 26)
|
|
{
|
|
nBite = IP_CONST_MONSTERDAMAGE_2d8;
|
|
nClaw = IP_CONST_MONSTERDAMAGE_1d10;
|
|
}
|
|
else if(nLevel > 18)
|
|
{
|
|
nBite = IP_CONST_MONSTERDAMAGE_2d6;
|
|
nClaw = IP_CONST_MONSTERDAMAGE_1d8;
|
|
}
|
|
else if(nLevel > 11)
|
|
{
|
|
nBite = IP_CONST_MONSTERDAMAGE_1d10;
|
|
nClaw = IP_CONST_MONSTERDAMAGE_1d6;
|
|
}
|
|
else if(nLevel > 5)
|
|
{
|
|
nBite = IP_CONST_MONSTERDAMAGE_1d8;
|
|
nClaw = IP_CONST_MONSTERDAMAGE_1d4;
|
|
}
|
|
else
|
|
{
|
|
nBite = IP_CONST_MONSTERDAMAGE_1d6;
|
|
nClaw = IP_CONST_MONSTERDAMAGE_1d3;
|
|
}
|
|
|
|
if(bBite)
|
|
return nBite;
|
|
|
|
return nClaw;
|
|
}
|
|
|
|
void SetNaturalWeaponDamage(object oCompanion, int nLvlMod = 0)
|
|
{
|
|
int nLevel = GetHitDice(oCompanion);
|
|
nLevel += nLvlMod;
|
|
int Enh = (nLevel - 15) / 5;
|
|
int nDamage;
|
|
|
|
//Get the companion's creature weapons
|
|
object oBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oCompanion);
|
|
object oLClaw = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oCompanion);
|
|
object oRClaw = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oCompanion);
|
|
|
|
//Apply properties to each weapon
|
|
if(GetIsObjectValid(oBite))
|
|
{
|
|
CleanProperties(oBite);
|
|
nDamage = GetCompanionBaseDamage(nLevel, TRUE);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyMonsterDamage(nDamage), oBite);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAttackBonus(Enh), oBite);
|
|
}
|
|
if(GetIsObjectValid(oLClaw))
|
|
{
|
|
CleanProperties(oLClaw);
|
|
nDamage = GetCompanionBaseDamage(nLevel, FALSE);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyMonsterDamage(nDamage), oLClaw);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAttackBonus(Enh), oLClaw);
|
|
}
|
|
if(GetIsObjectValid(oRClaw))
|
|
{
|
|
CleanProperties(oRClaw);
|
|
nDamage = GetCompanionBaseDamage(nLevel, FALSE);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyMonsterDamage(nDamage), oRClaw);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAttackBonus(Enh), oRClaw);
|
|
}
|
|
}
|
|
|
|
void UnsummonCompanions(object oPC)
|
|
{
|
|
int i;
|
|
object oAsso;
|
|
for(i = 1; i <= 5; i++)
|
|
{
|
|
oAsso = GetAssociateNPC(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC, i);
|
|
if(GetIsObjectValid(oAsso))
|
|
DestroyAssociate(oAsso);
|
|
}
|
|
for(i = 1; i <= 5; i++)
|
|
{
|
|
oAsso = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, i);
|
|
if(GetIsObjectValid(oAsso))
|
|
DestroyAssociate(oAsso);
|
|
}
|
|
}
|
|
|
|
//:: void main(){} |