Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
1619 lines
64 KiB
Plaintext
1619 lines
64 KiB
Plaintext
/*
|
|
Class functions.
|
|
This scripts holds all functions used for classes in includes.
|
|
This prevents us from having one include for each class or set of classes.
|
|
|
|
Stratovarius
|
|
*/
|
|
|
|
//:: Updated for .35 by Jaysyn 2023/03/10
|
|
|
|
////////////////Begin Generic////////////////
|
|
|
|
// Function Definitions:
|
|
|
|
// Include Files:
|
|
#include "prc_inc_spells"
|
|
//#include "prc_alterations"
|
|
//#include "prcsp_engine"
|
|
//#include "prc_inc_function"
|
|
//#include "prc_x2_itemprop"
|
|
//#include "prc_class_const"
|
|
//#include "prc_feat_const"
|
|
//#include "prc_ipfeat_const"
|
|
//#include "inc_utility"
|
|
//
|
|
//#include "pnp_shft_poly"
|
|
//#include "x2_inc_spellhook"
|
|
//#include "prc_inc_combat"
|
|
//#include "prc_inc_sp_tch"
|
|
|
|
////////////////End Generic////////////////
|
|
|
|
////////////////Begin Drunken Master//////////////////////
|
|
|
|
|
|
// Function Definitions:
|
|
|
|
// Searches oPC's inventory and finds the first valid alcoholic beverage container
|
|
// (empty) and returns TRUE if a proper container was found. This function takes
|
|
// action and returns a boolean.
|
|
int UseBottle(object oPC);
|
|
|
|
// Searches oPC's inventory for an alcoholic beverage and if one is found it's
|
|
// destroyed and replaced by an empty container. This function is only used in
|
|
// the Breath of Fire spell script.
|
|
int UseAlcohol(object oPC = OBJECT_SELF);
|
|
|
|
// Removes all Alcohol effects for oTarget. Used in B o Flame.
|
|
void RemoveAlcoholEffects(object oTarget = OBJECT_SELF);
|
|
|
|
// Creates an empty bottle on oPC.
|
|
// sTag: the tag of the alcoholic beverage used (ale, spirits, wine)
|
|
void CreateBottleOnObject(object oPC, string sTag);
|
|
|
|
|
|
// Applies Drunk Like a Demno effects
|
|
void DrunkLikeDemon();
|
|
|
|
// Add the non-drunken master drinking effects.
|
|
void MakeDrunk(int nSpellID);
|
|
|
|
// Have the drunken master say one of 6 phrases.
|
|
void DrunkenMasterSpeakString();
|
|
|
|
// Creates an empty bottle on oPC.
|
|
// nBeverage: the spell id of the alcoholic beverage used (ale, spirits, wine)
|
|
void DrunkenMasterCreateEmptyBottle(int nSpellID);
|
|
|
|
// Determines the DC needed to save against the cast spell-like ability
|
|
// replace PRCGetSaveDC
|
|
int GetSpellDCSLA(object oCaster, int iSpelllvl,int iAbi = ABILITY_WISDOM);
|
|
|
|
void DoArchmageHeirophantSLA(object oPC, object oTarget, location lTarget, int nSLAID);
|
|
|
|
// Functions:
|
|
int UseBottle(object oPC)
|
|
{
|
|
object oItem = GetFirstItemInInventory(oPC);
|
|
//search oPC for a bottle:
|
|
string sTag;
|
|
while(oItem != OBJECT_INVALID)
|
|
{
|
|
sTag = GetTag(oItem);
|
|
if(sTag == "NW_IT_THNMISC001"
|
|
|| sTag == "NW_IT_THNMISC002"
|
|
|| sTag == "NW_IT_THNMISC003"
|
|
|| sTag == "NW_IT_THNMISC004")
|
|
{
|
|
SetPlotFlag(oItem, FALSE);
|
|
DestroyObject(oItem);
|
|
return TRUE;
|
|
}
|
|
else
|
|
oItem = GetNextItemInInventory();
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int UseAlcohol(object oPC = OBJECT_SELF)
|
|
{
|
|
object oItem = GetFirstItemInInventory(oPC);
|
|
//search oPC for alcohol:
|
|
string sTag = GetTag(oItem);
|
|
while(oItem != OBJECT_INVALID)
|
|
{
|
|
if(sTag == "NW_IT_MPOTION021"
|
|
|| sTag == "NW_IT_MPOTION022"
|
|
|| sTag == "NW_IT_MPOTION023"
|
|
|| sTag == "DragonsBreath")
|
|
{
|
|
SetPlotFlag(oItem, FALSE);
|
|
if(GetItemStackSize(oItem) > 1)
|
|
{
|
|
SetItemStackSize(oItem, GetItemStackSize(oItem) - 1);
|
|
// Create an Empty Bottle:
|
|
CreateBottleOnObject(oPC, sTag);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
DestroyObject(oItem);
|
|
// Create an Empty Bottle:
|
|
CreateBottleOnObject(oPC, sTag);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
oItem = GetNextItemInInventory();
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void CreateBottleOnObject(object oPC, string sTag)
|
|
{
|
|
if(sTag == "NW_IT_MPOTION021") // Ale
|
|
{
|
|
CreateItemOnObject("nw_it_thnmisc002", oPC);
|
|
}
|
|
else if(sTag == "NW_IT_MPOTION022") // Spirits
|
|
{
|
|
CreateItemOnObject("nw_it_thnmisc003", oPC);
|
|
}
|
|
else if(sTag == "NW_IT_MPOTION023") // Wine
|
|
{
|
|
CreateItemOnObject("nw_it_thnmisc004", oPC);
|
|
}
|
|
else // Other beverage
|
|
{
|
|
CreateItemOnObject("nw_it_thnmisc001", oPC);
|
|
}
|
|
}
|
|
|
|
int GetIsDrunk(object oTarget = OBJECT_SELF)
|
|
{
|
|
return GetHasSpellEffect(406, oTarget)
|
|
|| GetHasSpellEffect(407, oTarget)
|
|
|| GetHasSpellEffect(408, oTarget);
|
|
}
|
|
|
|
void RemoveAlcoholEffects(object oTarget = OBJECT_SELF)
|
|
{
|
|
PRCRemoveSpellEffects(406, OBJECT_SELF, oTarget);
|
|
PRCRemoveSpellEffects(407, OBJECT_SELF, oTarget);
|
|
PRCRemoveSpellEffects(408, OBJECT_SELF, oTarget);
|
|
}
|
|
|
|
void DrunkenRage()
|
|
{
|
|
float fDuration = GetLevelByClass(CLASS_TYPE_DRUNKEN_MASTER) > 9 ? HoursToSeconds(3) : HoursToSeconds(1);
|
|
|
|
effect eLink = EffectLinkEffects(EffectAbilityIncrease(ABILITY_STRENGTH, 4), EffectAbilityIncrease(ABILITY_CONSTITUTION, 4));
|
|
eLink = EffectLinkEffects(eLink, EffectSavingThrowIncrease(SAVING_THROW_WILL, 2));
|
|
eLink = EffectLinkEffects(eLink, EffectACDecrease(2));
|
|
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_BLUR));
|
|
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_AURA_FIRE));
|
|
eLink = ExtraordinaryEffect(eLink);
|
|
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, OBJECT_SELF, fDuration);
|
|
|
|
FloatingTextStringOnCreature("Drunken Rage Activated", OBJECT_SELF);
|
|
}
|
|
|
|
void DrunkLikeDemon()
|
|
{
|
|
// A Drunken Master has had a drink. Add effects:
|
|
effect eLink = EffectLinkEffects(EffectAbilityIncrease(ABILITY_STRENGTH, 1), EffectAbilityIncrease(ABILITY_CONSTITUTION, 1));
|
|
eLink = EffectLinkEffects(eLink, EffectAbilityDecrease(ABILITY_WISDOM, 1));
|
|
eLink = EffectLinkEffects(eLink, EffectAbilityDecrease(ABILITY_INTELLIGENCE, 1));
|
|
eLink = EffectLinkEffects(eLink, EffectAbilityDecrease(ABILITY_DEXTERITY, 1));
|
|
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_BLUR));
|
|
|
|
//run checks to see if Dex Modifier will be changed:
|
|
if(!(GetAbilityModifier(ABILITY_DEXTERITY) % 2))
|
|
{
|
|
//restore AC, Ref save and Tumble to previous values
|
|
eLink = EffectLinkEffects(eLink, EffectACIncrease(1));
|
|
eLink = EffectLinkEffects(eLink, EffectSavingThrowIncrease(SAVING_THROW_REFLEX, 1));
|
|
eLink = EffectLinkEffects(eLink, EffectSkillIncrease(SKILL_TUMBLE, 1));
|
|
}
|
|
eLink = ExtraordinaryEffect(eLink);
|
|
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, OBJECT_SELF, HoursToSeconds(1));
|
|
|
|
FloatingTextStringOnCreature("You are Drunk Like a Demon", OBJECT_SELF);
|
|
}
|
|
|
|
void MakeDrunk(int nSpellID)
|
|
{
|
|
if(Random(100) < 40)
|
|
AssignCommand(OBJECT_SELF, ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING));
|
|
else
|
|
AssignCommand(OBJECT_SELF, ActionPlayAnimation(ANIMATION_LOOPING_PAUSE_DRUNK));
|
|
|
|
int nPoints;
|
|
switch(nSpellID)
|
|
{
|
|
case 406: nPoints = 1; break;//Ale
|
|
case 407: nPoints = 2; break;//Wine
|
|
case 408: nPoints = 3; break;//Spirits
|
|
}
|
|
|
|
//ApplyAbilityDamage(oTarget, ABILITY_INTELLIGENCE, nPoints, DURATION_TYPE_TEMPORARY, TRUE, 60.0);
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(EffectAbilityDecrease(ABILITY_INTELLIGENCE, nPoints)), OBJECT_SELF, 60.0);
|
|
AssignCommand(OBJECT_SELF, ActionSpeakStringByStrRef(10499));
|
|
}
|
|
|
|
void DrunkenMasterSpeakString()
|
|
{
|
|
switch(d6())
|
|
{
|
|
case 1: AssignCommand(OBJECT_SELF, ActionSpeakString("Now that's the stuff!")); break;
|
|
case 2: AssignCommand(OBJECT_SELF, ActionSpeakString("That one really hit the spot!")); break;
|
|
case 3: AssignCommand(OBJECT_SELF, ActionSpeakString("That should keep me warm!")); break;
|
|
case 4: AssignCommand(OBJECT_SELF, ActionSpeakString("Good stuff!")); break;
|
|
case 5: AssignCommand(OBJECT_SELF, ActionSpeakString("Bless the Wine Gods!")); break;
|
|
case 6: AssignCommand(OBJECT_SELF, ActionSpeakString("Just what I needed!")); break;
|
|
}
|
|
}
|
|
|
|
void DrunkenMasterCreateEmptyBottle(int nSpellID)
|
|
{
|
|
switch(nSpellID)
|
|
{
|
|
case 406: CreateItemOnObject("nw_it_thnmisc002", OBJECT_SELF); break;//Ale
|
|
case 407: CreateItemOnObject("nw_it_thnmisc004", OBJECT_SELF); break;//Wine
|
|
case 408: CreateItemOnObject("nw_it_thnmisc003", OBJECT_SELF); break;//Spirits
|
|
default: CreateItemOnObject("nw_it_thnmisc001", OBJECT_SELF); break;//Other
|
|
}
|
|
}
|
|
|
|
////////////////End Drunken Master//////////////////
|
|
|
|
////////////////Begin Samurai//////////////////
|
|
|
|
// This function is probably utterly broken: the match found variable is not reset in the loop and the returned value will be equal to the last match - Ornedan
|
|
int GetPropertyValue(object oWeapon, int iType, int iSubType = -1, int bDebug = FALSE);
|
|
|
|
int GetPropertyValue(object oWeapon, int iType, int iSubType = -1, int bDebug = FALSE)
|
|
{
|
|
int bReturn = -1;
|
|
if(oWeapon == OBJECT_INVALID){return FALSE;}
|
|
int bMatch = FALSE;
|
|
if (GetItemHasItemProperty(oWeapon, iType))
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("It has the property."));}
|
|
itemproperty ip = GetFirstItemProperty(oWeapon);
|
|
while(GetIsItemPropertyValid(ip))
|
|
{
|
|
if(GetItemPropertyType(ip) == iType)
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("Again..."));}
|
|
bMatch = TRUE;
|
|
if (iSubType > -1)
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("Subtype Required."));}
|
|
if(GetItemPropertySubType(ip) != iSubType)
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("Subtype wrong."));}
|
|
bMatch = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("Subtype Correct."));}
|
|
}
|
|
}
|
|
}
|
|
if (bMatch)
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("Match found."));}
|
|
if (GetItemPropertyCostTableValue(ip) > -1)
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("Cost value found, returning."));}
|
|
bReturn = GetItemPropertyCostTableValue(ip);
|
|
}
|
|
else
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("No cost value for property, returning TRUE."));}
|
|
bReturn = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(bDebug){AssignCommand(GetFirstPC(), SpeakString("Match not found."));}
|
|
}
|
|
ip = GetNextItemProperty(oWeapon);
|
|
}
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
void WeaponUpgradeVisual();
|
|
|
|
object GetSamuraiToken(object oSamurai);
|
|
|
|
void WeaponUpgradeVisual()
|
|
{
|
|
object oPC = GetPCSpeaker();
|
|
int iCost = GetLocalInt(oPC, "CODI_SAM_WEAPON_COST");
|
|
object oToken = GetSamuraiToken(oPC);
|
|
int iToken = StringToInt(GetTag(oToken));
|
|
int iGold = GetGold(oPC);
|
|
if(iGold + iToken < iCost)
|
|
{
|
|
SendMessageToPC(oPC, "You sense the gods are angered!");
|
|
AdjustAlignment(oPC, ALIGNMENT_CHAOTIC, 25, FALSE);
|
|
object oWeapon = GetItemPossessedBy(oPC, "codi_sam_mw");
|
|
DestroyObject(oWeapon);
|
|
return;
|
|
}
|
|
else if(iToken <= iCost)
|
|
{
|
|
iCost = iCost - iToken;
|
|
DestroyObject(oToken);
|
|
TakeGoldFromCreature(iCost, oPC, TRUE);
|
|
}
|
|
else if (iToken > iCost)
|
|
{
|
|
object oNewToken = CopyObject(oToken, GetLocation(oPC), oPC, IntToString(iToken - iCost));
|
|
DestroyObject(oToken);
|
|
}
|
|
effect eVis = EffectVisualEffect(VFX_FNF_DISPEL_DISJUNCTION);
|
|
AssignCommand(oPC, ClearAllActions());
|
|
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_LOOPING_MEDITATE,1.0,6.0));
|
|
AssignCommand(oPC, ActionPlayAnimation(ANIMATION_FIREFORGET_VICTORY2));
|
|
DelayCommand(0.1, SetCommandable(FALSE, oPC));
|
|
DelayCommand(6.5, SetCommandable(TRUE, oPC));
|
|
DelayCommand(5.0,ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, GetLocation(oPC)));
|
|
}
|
|
|
|
object GetSamuraiToken(object oSamurai)
|
|
{
|
|
object oItem = GetFirstItemInInventory(oSamurai);
|
|
while(oItem != OBJECT_INVALID)
|
|
{
|
|
if(GetResRef(oItem) == "codi_sam_token")
|
|
{
|
|
return oItem;
|
|
}
|
|
oItem = GetNextItemInInventory(oSamurai);
|
|
}
|
|
return OBJECT_INVALID;
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////End Samurai//////////////////
|
|
|
|
////////////////Begin Vile Feat//////////////////
|
|
|
|
|
|
int Vile_Feat(int iTypeWeap)
|
|
{
|
|
switch(iTypeWeap)
|
|
{
|
|
case BASE_ITEM_BASTARDSWORD: return GetHasFeat(FEAT_VILE_MARTIAL_BASTARDSWORD);
|
|
case BASE_ITEM_BATTLEAXE: return GetHasFeat(FEAT_VILE_MARTIAL_BATTLEAXE);
|
|
case BASE_ITEM_CLUB: return GetHasFeat(FEAT_VILE_MARTIAL_CLUB);
|
|
case BASE_ITEM_DAGGER: return GetHasFeat(FEAT_VILE_MARTIAL_DAGGER);
|
|
case BASE_ITEM_DART: return GetHasFeat(FEAT_VILE_MARTIAL_DART);
|
|
case BASE_ITEM_DIREMACE: return GetHasFeat(FEAT_VILE_MARTIAL_DIREMACE);
|
|
case BASE_ITEM_DOUBLEAXE: return GetHasFeat(FEAT_VILE_MARTIAL_DOUBLEAXE);
|
|
case BASE_ITEM_DWARVENWARAXE: return GetHasFeat(FEAT_VILE_MARTIAL_DWAXE);
|
|
case BASE_ITEM_GREATAXE: return GetHasFeat(FEAT_VILE_MARTIAL_GREATAXE);
|
|
case BASE_ITEM_GREATSWORD: return GetHasFeat(FEAT_VILE_MARTIAL_GREATSWORD);
|
|
case BASE_ITEM_HALBERD: return GetHasFeat(FEAT_VILE_MARTIAL_HALBERD);
|
|
case BASE_ITEM_HANDAXE: return GetHasFeat(FEAT_VILE_MARTIAL_HANDAXE);
|
|
case BASE_ITEM_HEAVYCROSSBOW: return GetHasFeat(FEAT_VILE_MARTIAL_HEAVYCROSSBOW);
|
|
case BASE_ITEM_HEAVYFLAIL: return GetHasFeat(FEAT_VILE_MARTIAL_HEAVYFLAIL);
|
|
case BASE_ITEM_KAMA: return GetHasFeat(FEAT_VILE_MARTIAL_KAMA);
|
|
case BASE_ITEM_KATANA: return GetHasFeat(FEAT_VILE_MARTIAL_KATANA);
|
|
case BASE_ITEM_KUKRI: return GetHasFeat(FEAT_VILE_MARTIAL_KUKRI);
|
|
case BASE_ITEM_LIGHTCROSSBOW: return GetHasFeat(FEAT_VILE_MARTIAL_LIGHTCROSSBOW);
|
|
case BASE_ITEM_LIGHTFLAIL: return GetHasFeat(FEAT_VILE_MARTIAL_LIGHTFLAIL);
|
|
case BASE_ITEM_LIGHTHAMMER: return GetHasFeat(FEAT_VILE_MARTIAL_LIGHTHAMMER);
|
|
case BASE_ITEM_LIGHTMACE: return GetHasFeat(FEAT_VILE_MARTIAL_MACE);
|
|
case BASE_ITEM_LONGBOW: return GetHasFeat(FEAT_VILE_MARTIAL_LONGBOW);
|
|
case BASE_ITEM_LONGSWORD: return GetHasFeat(FEAT_VILE_MARTIAL_LONGSWORD);
|
|
case BASE_ITEM_MORNINGSTAR: return GetHasFeat(FEAT_VILE_MARTIAL_MORNINGSTAR);
|
|
case BASE_ITEM_QUARTERSTAFF: return GetHasFeat(FEAT_VILE_MARTIAL_QUARTERSTAFF);
|
|
case BASE_ITEM_RAPIER: return GetHasFeat(FEAT_VILE_MARTIAL_RAPIER);
|
|
case BASE_ITEM_SCIMITAR: return GetHasFeat(FEAT_VILE_MARTIAL_SCIMITAR);
|
|
case BASE_ITEM_SCYTHE: return GetHasFeat(FEAT_VILE_MARTIAL_SCYTHE);
|
|
case BASE_ITEM_SHORTBOW: return GetHasFeat(FEAT_VILE_MARTIAL_SHORTBOW);
|
|
case BASE_ITEM_SHORTSPEAR: return GetHasFeat(FEAT_VILE_MARTIAL_SPEAR);
|
|
case BASE_ITEM_SHORTSWORD: return GetHasFeat(FEAT_VILE_MARTIAL_SHORTSWORD);
|
|
case BASE_ITEM_SHURIKEN: return GetHasFeat(FEAT_VILE_MARTIAL_SHURIKEN);
|
|
case BASE_ITEM_SLING: return GetHasFeat(FEAT_VILE_MARTIAL_SLING);
|
|
case BASE_ITEM_SICKLE: return GetHasFeat(FEAT_VILE_MARTIAL_SICKLE);
|
|
case BASE_ITEM_TWOBLADEDSWORD: return GetHasFeat(FEAT_VILE_MARTIAL_TWOBLADED);
|
|
case BASE_ITEM_WARHAMMER: return GetHasFeat(FEAT_VILE_MARTIAL_WARHAMMER);
|
|
case BASE_ITEM_WHIP: return GetHasFeat(FEAT_VILE_MARTIAL_WHIP);
|
|
case BASE_ITEM_TRIDENT: return GetHasFeat(FEAT_VILE_MARTIAL_TRIDENT);
|
|
|
|
//new items
|
|
case BASE_ITEM_ELVEN_LIGHTBLADE: return (GetHasFeat(FEAT_VILE_MARTIAL_SHORTSWORD) || GetHasFeat(FEAT_VILE_MARTIAL_RAPIER));
|
|
case BASE_ITEM_ELVEN_THINBLADE: return (GetHasFeat(FEAT_VILE_MARTIAL_LONGSWORD) || GetHasFeat(FEAT_VILE_MARTIAL_RAPIER));
|
|
case BASE_ITEM_ELVEN_COURTBLADE: return GetHasFeat(FEAT_VILE_MARTIAL_GREATSWORD);
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
////////////////End Vile Feat//////////////////
|
|
|
|
////////////////Begin Soul Inc//////////////////
|
|
|
|
const int IPRP_CONST_ONHIT_DURATION_5_PERCENT_1_ROUNDS = 20;
|
|
|
|
int Sanctify_Feat(int iTypeWeap)
|
|
{
|
|
switch(iTypeWeap)
|
|
{
|
|
case BASE_ITEM_BASTARDSWORD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_BASTARDSWORD);
|
|
case BASE_ITEM_BATTLEAXE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_BATTLEAXE);
|
|
case BASE_ITEM_CLUB: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_CLUB);
|
|
case BASE_ITEM_DAGGER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DAGGER);
|
|
case BASE_ITEM_DART: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DART);
|
|
case BASE_ITEM_DIREMACE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DIREMACE);
|
|
case BASE_ITEM_DOUBLEAXE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DOUBLEAXE);
|
|
case BASE_ITEM_DWARVENWARAXE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DWAXE);
|
|
case BASE_ITEM_GREATAXE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_GREATAXE);
|
|
case BASE_ITEM_GREATSWORD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_GREATSWORD);
|
|
case BASE_ITEM_HALBERD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_HALBERD);
|
|
case BASE_ITEM_HANDAXE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_HANDAXE);
|
|
case BASE_ITEM_HEAVYCROSSBOW: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_HEAVYCROSSBOW);
|
|
case BASE_ITEM_HEAVYFLAIL: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_HEAVYFLAIL);
|
|
case BASE_ITEM_KAMA: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_KAMA);
|
|
case BASE_ITEM_KATANA: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_KATANA);
|
|
case BASE_ITEM_KUKRI: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_KUKRI);
|
|
case BASE_ITEM_LIGHTCROSSBOW: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_LIGHTCROSSBOW);
|
|
case BASE_ITEM_LIGHTFLAIL: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_LIGHTFLAIL);
|
|
case BASE_ITEM_LIGHTHAMMER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_LIGHTHAMMER);
|
|
case BASE_ITEM_LIGHTMACE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_MACE);
|
|
case BASE_ITEM_LONGBOW: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_LONGBOW);
|
|
case BASE_ITEM_LONGSWORD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_LONGSWORD);
|
|
case BASE_ITEM_MORNINGSTAR: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_MORNINGSTAR);
|
|
case BASE_ITEM_QUARTERSTAFF: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_QUARTERSTAFF);
|
|
case BASE_ITEM_RAPIER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_RAPIER);
|
|
case BASE_ITEM_SCIMITAR: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SCIMITAR);
|
|
case BASE_ITEM_SCYTHE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SCYTHE);
|
|
case BASE_ITEM_SHORTBOW: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SHORTBOW);
|
|
case BASE_ITEM_SHORTSPEAR: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SPEAR);
|
|
case BASE_ITEM_SHORTSWORD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SHORTSWORD);
|
|
case BASE_ITEM_SHURIKEN: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SHURIKEN);
|
|
case BASE_ITEM_SLING: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SLING);
|
|
case BASE_ITEM_SICKLE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SICKLE);
|
|
case BASE_ITEM_TWOBLADEDSWORD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_TWOBLADED);
|
|
case BASE_ITEM_WARHAMMER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_WARHAMMER);
|
|
case BASE_ITEM_WHIP: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_WHIP);
|
|
case BASE_ITEM_TRIDENT: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_TRIDENT);
|
|
|
|
//new items
|
|
case BASE_ITEM_ELVEN_LIGHTBLADE: return (GetHasFeat(FEAT_SANCTIFY_MARTIAL_SHORTSWORD) || GetHasFeat(FEAT_SANCTIFY_MARTIAL_RAPIER));
|
|
case BASE_ITEM_ELVEN_THINBLADE: return (GetHasFeat(FEAT_SANCTIFY_MARTIAL_LONGSWORD) || GetHasFeat(FEAT_SANCTIFY_MARTIAL_RAPIER));
|
|
case BASE_ITEM_ELVEN_COURTBLADE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_GREATSWORD);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int DamageConv(int iMonsDmg)
|
|
{
|
|
|
|
switch(iMonsDmg)
|
|
{
|
|
case IP_CONST_MONSTERDAMAGE_1d4: return 1;
|
|
case IP_CONST_MONSTERDAMAGE_1d6: return 2;
|
|
case IP_CONST_MONSTERDAMAGE_1d8: return 3;
|
|
case IP_CONST_MONSTERDAMAGE_1d10: return 4;
|
|
case IP_CONST_MONSTERDAMAGE_1d12: return 5;
|
|
case IP_CONST_MONSTERDAMAGE_1d20: return 6;
|
|
|
|
case IP_CONST_MONSTERDAMAGE_2d4: return 10;
|
|
case IP_CONST_MONSTERDAMAGE_2d6: return 11;
|
|
case IP_CONST_MONSTERDAMAGE_2d8: return 12;
|
|
case IP_CONST_MONSTERDAMAGE_2d10: return 13;
|
|
case IP_CONST_MONSTERDAMAGE_2d12: return 14;
|
|
case IP_CONST_MONSTERDAMAGE_2d20: return 15;
|
|
|
|
case IP_CONST_MONSTERDAMAGE_3d4: return 20;
|
|
case IP_CONST_MONSTERDAMAGE_3d6: return 21;
|
|
case IP_CONST_MONSTERDAMAGE_3d8: return 22;
|
|
case IP_CONST_MONSTERDAMAGE_3d10: return 23;
|
|
case IP_CONST_MONSTERDAMAGE_3d12: return 24;
|
|
case IP_CONST_MONSTERDAMAGE_3d20: return 25;
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ConvMonsterDmg(int iMonsDmg)
|
|
{
|
|
|
|
switch(iMonsDmg)
|
|
{
|
|
case 1: return IP_CONST_MONSTERDAMAGE_1d4;
|
|
case 2: return IP_CONST_MONSTERDAMAGE_1d6;
|
|
case 3: return IP_CONST_MONSTERDAMAGE_1d8;
|
|
case 4: return IP_CONST_MONSTERDAMAGE_1d10;
|
|
case 5: return IP_CONST_MONSTERDAMAGE_1d12;
|
|
case 6: return IP_CONST_MONSTERDAMAGE_1d20;
|
|
case 10: return IP_CONST_MONSTERDAMAGE_2d4;
|
|
case 11: return IP_CONST_MONSTERDAMAGE_2d6;
|
|
case 12: return IP_CONST_MONSTERDAMAGE_2d8;
|
|
case 13: return IP_CONST_MONSTERDAMAGE_2d10;
|
|
case 14: return IP_CONST_MONSTERDAMAGE_2d12;
|
|
case 15: return IP_CONST_MONSTERDAMAGE_2d20;
|
|
case 20: return IP_CONST_MONSTERDAMAGE_3d4;
|
|
case 21: return IP_CONST_MONSTERDAMAGE_3d6;
|
|
case 22: return IP_CONST_MONSTERDAMAGE_3d8;
|
|
case 23: return IP_CONST_MONSTERDAMAGE_3d10;
|
|
case 24: return IP_CONST_MONSTERDAMAGE_3d12;
|
|
case 25: return IP_CONST_MONSTERDAMAGE_3d20;
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int MonsterDamage(object oItem)
|
|
{
|
|
int iBonus;
|
|
int iTemp;
|
|
itemproperty ip = GetFirstItemProperty(oItem);
|
|
while(GetIsItemPropertyValid(ip))
|
|
{
|
|
if(GetItemPropertyType(ip) == ITEM_PROPERTY_MONSTER_DAMAGE)
|
|
{
|
|
iTemp = GetItemPropertyCostTableValue(ip);
|
|
iBonus = iTemp > iBonus ? iTemp : iBonus;
|
|
}
|
|
ip = GetNextItemProperty(oItem);
|
|
}
|
|
|
|
return iBonus;
|
|
}
|
|
|
|
int FeatIniDmg(object oItem)
|
|
{
|
|
itemproperty ip = GetFirstItemProperty(oItem);
|
|
while (GetIsItemPropertyValid(ip))
|
|
{
|
|
if(GetItemPropertyType(ip) == ITEM_PROPERTY_BONUS_FEAT)
|
|
{
|
|
if(GetItemPropertySubType(ip) == IP_CONST_FEAT_WeapFocCreature)
|
|
return 1;
|
|
}
|
|
ip = GetNextItemProperty(oItem);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void AddIniDmg(object oPC)
|
|
{
|
|
|
|
int bUnarmedDmg = GetHasFeat(FEAT_INCREASE_DAMAGE1, oPC)
|
|
+ GetHasFeat(FEAT_INCREASE_DAMAGE2, oPC);
|
|
|
|
if(!bUnarmedDmg)
|
|
return;
|
|
|
|
object oCweapB = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
|
|
object oCweapL = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
|
|
object oCweapR = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
|
|
|
|
int iDmg;
|
|
int iConv;
|
|
int iStr = GetAbilityModifier(ABILITY_STRENGTH, oPC);
|
|
int iWis = GetAbilityModifier(ABILITY_WISDOM, oPC);
|
|
iWis = iWis > iStr ? iWis : 0;
|
|
|
|
|
|
/*if(GetHasFeat(FEAT_INTUITIVE_ATTACK, oPC))
|
|
{
|
|
SetCompositeBonusT(oCweapB,"",iWis,ITEM_PROPERTY_ATTACK_BONUS);
|
|
SetCompositeBonusT(oCweapL,"",iWis,ITEM_PROPERTY_ATTACK_BONUS);
|
|
SetCompositeBonusT(oCweapR,"",iWis,ITEM_PROPERTY_ATTACK_BONUS);
|
|
}
|
|
if (GetHasFeat(FEAT_RAVAGEGOLDENICE, oPC))
|
|
{
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_RAVAGEGOLDENICE,2),oCweapB,9999.0);
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_RAVAGEGOLDENICE,2),oCweapL,9999.0);
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_RAVAGEGOLDENICE,2),oCweapR,9999.0);
|
|
}*/
|
|
|
|
|
|
if ( oCweapB != OBJECT_INVALID && !FeatIniDmg(oCweapB))
|
|
{
|
|
iDmg = MonsterDamage(oCweapB);
|
|
iConv = DamageConv(iDmg) + bUnarmedDmg;
|
|
iConv = (iConv > 6 && iConv < 10) ? 6 : iConv;
|
|
iConv = (iConv > 15 && iConv < 20) ? 15 : iConv;
|
|
iConv = (iConv > 25) ? 25 : iConv;
|
|
iConv = ConvMonsterDmg(iConv);
|
|
TotalAndRemoveProperty(oCweapB,ITEM_PROPERTY_MONSTER_DAMAGE,-1);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyMonsterDamage(iConv),oCweapB);
|
|
//AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapFocCreature),oCweapB);
|
|
IPSafeAddItemProperty(oCweapB, PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapFocCreature), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
|
}
|
|
if ( oCweapL != OBJECT_INVALID && !FeatIniDmg(oCweapL))
|
|
{
|
|
iDmg = MonsterDamage(oCweapL);
|
|
iConv = DamageConv(iDmg) + bUnarmedDmg;
|
|
iConv = (iConv > 6 && iConv < 10) ? 6 : iConv;
|
|
iConv = (iConv > 15 && iConv < 20) ? 15 : iConv;
|
|
iConv = (iConv > 25) ? 25 : iConv;
|
|
iConv = ConvMonsterDmg(iConv);
|
|
TotalAndRemoveProperty(oCweapL,ITEM_PROPERTY_MONSTER_DAMAGE,-1);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyMonsterDamage(iConv),oCweapL);
|
|
//AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapFocCreature),oCweapL);
|
|
IPSafeAddItemProperty(oCweapL, PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapFocCreature), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
|
}
|
|
if ( oCweapR != OBJECT_INVALID && !FeatIniDmg(oCweapR))
|
|
{
|
|
iDmg = MonsterDamage(oCweapR);
|
|
iConv = DamageConv(iDmg) + bUnarmedDmg;
|
|
iConv = (iConv > 6 && iConv < 10) ? 6 : iConv;
|
|
iConv = (iConv > 15 && iConv < 20) ? 15 : iConv;
|
|
iConv = (iConv > 25) ? 25 : iConv;
|
|
iConv = ConvMonsterDmg(iConv);
|
|
TotalAndRemoveProperty(oCweapR,ITEM_PROPERTY_MONSTER_DAMAGE,-1);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyMonsterDamage(iConv),oCweapR);
|
|
//AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapFocCreature),oCweapR);
|
|
IPSafeAddItemProperty(oCweapR, PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapFocCreature), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
|
}
|
|
}
|
|
|
|
void AddCriti(object oPC,object oSkin,int ip_feat_crit,int nFeat)
|
|
{
|
|
// Do not add multiple instances of the same bonus feat iprop, it lags the game
|
|
AddSkinFeat(nFeat, ip_feat_crit, oSkin, oPC);
|
|
}
|
|
|
|
void ImpCrit(object oPC,object oSkin)
|
|
{
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_BASTARD_SWORD, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_BASTARD_SWORD, FEAT_IMPROVED_CRITICAL_BASTARD_SWORD);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_BATTLE_AXE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_BATTLE_AXE, FEAT_IMPROVED_CRITICAL_BATTLE_AXE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_CLUB, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_CLUB, FEAT_IMPROVED_CRITICAL_CLUB);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_DAGGER, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_DAGGER, FEAT_IMPROVED_CRITICAL_DAGGER);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_DART, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_DART, FEAT_IMPROVED_CRITICAL_DART);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_DIRE_MACE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_DIRE_MACE, FEAT_IMPROVED_CRITICAL_DIRE_MACE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_DOUBLE_AXE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_DOUBLE_AXE, FEAT_IMPROVED_CRITICAL_DOUBLE_AXE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_DWAXE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_DWAXE, FEAT_IMPROVED_CRITICAL_DWAXE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_GREAT_AXE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_GREAT_AXE, FEAT_IMPROVED_CRITICAL_GREAT_AXE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_GREAT_SWORD, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_GREAT_SWORD, FEAT_IMPROVED_CRITICAL_GREAT_SWORD);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_HALBERD, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_HALBERD, FEAT_IMPROVED_CRITICAL_HALBERD);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_HAND_AXE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_HAND_AXE, FEAT_IMPROVED_CRITICAL_HAND_AXE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_HEAVY_CROSSBOW, FEAT_IMPROVED_CRITICAL_HEAVY_CROSSBOW);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_FLAIL, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_HEAVY_FLAIL, FEAT_IMPROVED_CRITICAL_HEAVY_FLAIL);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_KAMA, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_KAMA, FEAT_IMPROVED_CRITICAL_KAMA);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_KATANA, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_KATANA, FEAT_IMPROVED_CRITICAL_KATANA);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_KUKRI, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_KUKRI, FEAT_IMPROVED_CRITICAL_KUKRI);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_LIGHT_CROSSBOW, FEAT_IMPROVED_CRITICAL_LIGHT_CROSSBOW);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_FLAIL, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_LIGHT_FLAIL, FEAT_IMPROVED_CRITICAL_LIGHT_FLAIL);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_HAMMER, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_LIGHT_HAMMER, FEAT_IMPROVED_CRITICAL_LIGHT_HAMMER);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_MACE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_LIGHT_MACE, FEAT_IMPROVED_CRITICAL_LIGHT_MACE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_LONG_SWORD, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_LONG_SWORD, FEAT_IMPROVED_CRITICAL_LONG_SWORD);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_LONGBOW, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_LONGBOW, FEAT_IMPROVED_CRITICAL_LONGBOW);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_MORNING_STAR, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_MORNING_STAR, FEAT_IMPROVED_CRITICAL_MORNING_STAR);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_RAPIER, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_RAPIER, FEAT_IMPROVED_CRITICAL_RAPIER);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_SCIMITAR, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_SCIMITAR, FEAT_IMPROVED_CRITICAL_SCIMITAR);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_SCYTHE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_SCYTHE, FEAT_IMPROVED_CRITICAL_SCYTHE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_SHORT_SWORD, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_SHORT_SWORD, FEAT_IMPROVED_CRITICAL_SHORT_SWORD);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_SHORTBOW, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_SHORTBOW, FEAT_IMPROVED_CRITICAL_SHORTBOW);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_SHURIKEN, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_SHURIKEN, FEAT_IMPROVED_CRITICAL_SHURIKEN);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_SICKLE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_SICKLE, FEAT_IMPROVED_CRITICAL_SICKLE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_SLING, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_SLING, FEAT_IMPROVED_CRITICAL_SLING);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_SPEAR, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_SPEAR, FEAT_IMPROVED_CRITICAL_SPEAR);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_STAFF, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_STAFF, FEAT_IMPROVED_CRITICAL_STAFF);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_THROWING_AXE, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_THROWING_AXE, FEAT_IMPROVED_CRITICAL_THROWING_AXE);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_TWO_BLADED_SWORD, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_TWO_BLADED_SWORD, FEAT_IMPROVED_CRITICAL_TWO_BLADED_SWORD);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_WAR_HAMMER, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_WAR_HAMMER, FEAT_IMPROVED_CRITICAL_WAR_HAMMER);
|
|
if(GetHasFeat(FEAT_WEAPON_FOCUS_WHIP, oPC)) AddCriti(oPC, oSkin, IP_CONST_FEAT_IMPROVED_CRITICAL_WHIP, FEAT_IMPROVED_CRITICAL_WHIP);
|
|
|
|
}
|
|
|
|
////////////////End Soul Inc//////////////////
|
|
|
|
////////////////Begin Martial Strike//////////////////
|
|
|
|
void MartialStrike()
|
|
{
|
|
object oItem;
|
|
object oPC = OBJECT_SELF;
|
|
|
|
int iEquip=GetLocalInt(oPC,"ONEQUIP");
|
|
int iType;
|
|
|
|
if (iEquip==2)
|
|
{
|
|
|
|
if (!GetHasFeat(FEAT_HOLY_MARTIAL_STRIKE)) return;
|
|
|
|
oItem=GetItemLastEquipped();
|
|
iType= GetBaseItemType(oItem);
|
|
|
|
switch (iType)
|
|
{
|
|
case BASE_ITEM_BOLT:
|
|
case BASE_ITEM_BULLET:
|
|
case BASE_ITEM_ARROW:
|
|
iType=GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND));
|
|
break;
|
|
case BASE_ITEM_SHORTBOW:
|
|
case BASE_ITEM_LONGBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_ARROWS);
|
|
break;
|
|
case BASE_ITEM_LIGHTCROSSBOW:
|
|
case BASE_ITEM_HEAVYCROSSBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BOLTS);
|
|
break;
|
|
case BASE_ITEM_SLING:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BULLETS);
|
|
break;
|
|
}
|
|
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_EVIL,IP_CONST_DAMAGETYPE_DIVINE,IP_CONST_DAMAGEBONUS_2d6),oItem,9999.0);
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyVisualEffect(ITEM_VISUAL_HOLY),oItem,9999.0);
|
|
SetLocalInt(oItem,"MartialStrik",1);
|
|
}
|
|
else if (iEquip==1)
|
|
{
|
|
oItem=GetItemLastUnequipped();
|
|
iType= GetBaseItemType(oItem);
|
|
|
|
switch (iType)
|
|
{
|
|
case BASE_ITEM_BOLT:
|
|
case BASE_ITEM_BULLET:
|
|
case BASE_ITEM_ARROW:
|
|
iType=GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND));
|
|
break;
|
|
case BASE_ITEM_SHORTBOW:
|
|
case BASE_ITEM_LONGBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_ARROWS);
|
|
break;
|
|
case BASE_ITEM_LIGHTCROSSBOW:
|
|
case BASE_ITEM_HEAVYCROSSBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BOLTS);
|
|
break;
|
|
case BASE_ITEM_SLING:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BULLETS);
|
|
break;
|
|
}
|
|
|
|
if ( GetLocalInt(oItem,"MartialStrik"))
|
|
{
|
|
RemoveSpecificProperty(oItem,ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP,IP_CONST_ALIGNMENTGROUP_EVIL,IP_CONST_DAMAGEBONUS_2d6, 1,"",IP_CONST_DAMAGETYPE_DIVINE,DURATION_TYPE_TEMPORARY);
|
|
RemoveSpecificProperty(oItem,ITEM_PROPERTY_VISUALEFFECT,ITEM_VISUAL_HOLY,-1,1,"",-1,DURATION_TYPE_TEMPORARY);
|
|
DeleteLocalInt(oItem,"MartialStrik");
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if (!GetHasFeat(FEAT_HOLY_MARTIAL_STRIKE)) return;
|
|
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);
|
|
iType= GetBaseItemType(oItem);
|
|
|
|
switch (iType)
|
|
{
|
|
case BASE_ITEM_BOLT:
|
|
case BASE_ITEM_BULLET:
|
|
case BASE_ITEM_ARROW:
|
|
iType=GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND));
|
|
break;
|
|
case BASE_ITEM_SHORTBOW:
|
|
case BASE_ITEM_LONGBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_ARROWS);
|
|
break;
|
|
case BASE_ITEM_LIGHTCROSSBOW:
|
|
case BASE_ITEM_HEAVYCROSSBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BOLTS);
|
|
break;
|
|
case BASE_ITEM_SLING:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BULLETS);
|
|
break;
|
|
}
|
|
|
|
if (!GetLocalInt(oItem,"MartialStrik"))
|
|
{
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_EVIL,IP_CONST_DAMAGETYPE_DIVINE,IP_CONST_DAMAGEBONUS_2d6),oItem,9999.0);
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyVisualEffect(ITEM_VISUAL_HOLY),oItem,9999.0);
|
|
SetLocalInt(oItem,"MartialStrik",1);
|
|
}
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
|
|
iType= GetBaseItemType(oItem);
|
|
if ( !GetLocalInt(oItem,"MartialStrik"))
|
|
{
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_EVIL,IP_CONST_DAMAGETYPE_DIVINE,IP_CONST_DAMAGEBONUS_2d6),oItem,9999.0);
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyVisualEffect(ITEM_VISUAL_HOLY),oItem,9999.0);
|
|
SetLocalInt(oItem,"MartialStrik",1);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void UnholyStrike()
|
|
{
|
|
object oItem;
|
|
object oPC = OBJECT_SELF;
|
|
|
|
int iEquip=GetLocalInt(oPC,"ONEQUIP");
|
|
int iType;
|
|
|
|
if (iEquip==2)
|
|
{
|
|
|
|
if (!GetHasFeat(FEAT_UNHOLY_STRIKE)) return;
|
|
|
|
oItem=GetItemLastEquipped();
|
|
iType= GetBaseItemType(oItem);
|
|
|
|
switch (iType)
|
|
{
|
|
case BASE_ITEM_BOLT:
|
|
case BASE_ITEM_BULLET:
|
|
case BASE_ITEM_ARROW:
|
|
iType=GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND));
|
|
break;
|
|
case BASE_ITEM_SHORTBOW:
|
|
case BASE_ITEM_LONGBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_ARROWS);
|
|
break;
|
|
case BASE_ITEM_LIGHTCROSSBOW:
|
|
case BASE_ITEM_HEAVYCROSSBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BOLTS);
|
|
break;
|
|
case BASE_ITEM_SLING:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BULLETS);
|
|
break;
|
|
}
|
|
|
|
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_GOOD,IP_CONST_DAMAGETYPE_DIVINE,IP_CONST_DAMAGEBONUS_2d6),oItem,9999.0);
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyVisualEffect(ITEM_VISUAL_EVIL),oItem,9999.0);
|
|
SetLocalInt(oItem,"UnholyStrik",1);
|
|
}
|
|
else if (iEquip==1)
|
|
{
|
|
oItem=GetItemLastUnequipped();
|
|
iType= GetBaseItemType(oItem);
|
|
|
|
switch (iType)
|
|
{
|
|
case BASE_ITEM_BOLT:
|
|
case BASE_ITEM_BULLET:
|
|
case BASE_ITEM_ARROW:
|
|
iType=GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND));
|
|
break;
|
|
case BASE_ITEM_SHORTBOW:
|
|
case BASE_ITEM_LONGBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_ARROWS);
|
|
break;
|
|
case BASE_ITEM_LIGHTCROSSBOW:
|
|
case BASE_ITEM_HEAVYCROSSBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BOLTS);
|
|
break;
|
|
case BASE_ITEM_SLING:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BULLETS);
|
|
break;
|
|
}
|
|
|
|
if ( GetLocalInt(oItem,"UnholyStrik"))
|
|
{
|
|
RemoveSpecificProperty(oItem,ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP,IP_CONST_ALIGNMENTGROUP_GOOD,IP_CONST_DAMAGEBONUS_2d6, 1,"",IP_CONST_DAMAGETYPE_DIVINE,DURATION_TYPE_TEMPORARY);
|
|
RemoveSpecificProperty(oItem,ITEM_PROPERTY_VISUALEFFECT,ITEM_VISUAL_EVIL,-1,1,"",-1,DURATION_TYPE_TEMPORARY);
|
|
DeleteLocalInt(oItem,"UnholyStrik");
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if (!GetHasFeat(FEAT_UNHOLY_STRIKE)) return;
|
|
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);
|
|
iType= GetBaseItemType(oItem);
|
|
|
|
switch (iType)
|
|
{
|
|
case BASE_ITEM_BOLT:
|
|
case BASE_ITEM_BULLET:
|
|
case BASE_ITEM_ARROW:
|
|
iType=GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND));
|
|
break;
|
|
case BASE_ITEM_SHORTBOW:
|
|
case BASE_ITEM_LONGBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_ARROWS);
|
|
break;
|
|
case BASE_ITEM_LIGHTCROSSBOW:
|
|
case BASE_ITEM_HEAVYCROSSBOW:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BOLTS);
|
|
break;
|
|
case BASE_ITEM_SLING:
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_BULLETS);
|
|
break;
|
|
}
|
|
|
|
if (!GetLocalInt(oItem,"UnholyStrik"))
|
|
{
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_GOOD,IP_CONST_DAMAGETYPE_DIVINE,IP_CONST_DAMAGEBONUS_2d6),oItem,9999.0);
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyVisualEffect(ITEM_VISUAL_EVIL),oItem,9999.0);
|
|
SetLocalInt(oItem,"UnholyStrik",1);
|
|
}
|
|
oItem=GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
|
|
iType= GetBaseItemType(oItem);
|
|
if ( !GetLocalInt(oItem,"UnholyStrik"))
|
|
{
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_GOOD,IP_CONST_DAMAGETYPE_DIVINE,IP_CONST_DAMAGEBONUS_2d6),oItem,9999.0);
|
|
AddItemProperty(DURATION_TYPE_TEMPORARY,ItemPropertyVisualEffect(ITEM_VISUAL_EVIL),oItem,9999.0);
|
|
SetLocalInt(oItem,"UnholyStrik",1);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
////////////////End Martial Strike//////////////////
|
|
|
|
////////////////Begin Soldier of Light Spells//////////////////
|
|
/* As far as I can tell, not used at all - Ornedan
|
|
void spellsCureMod(int nCasterLvl ,int nDamage, int nMaxExtraDamage, int nMaximized, int vfx_impactHurt, int vfx_impactHeal, int nSpellID)
|
|
{
|
|
//Declare major variables
|
|
object oTarget = PRCGetSpellTargetObject();
|
|
int nHeal;
|
|
int nMetaMagic = PRCGetMetaMagicFeat();
|
|
effect eVis = EffectVisualEffect(vfx_impactHurt);
|
|
effect eVis2 = EffectVisualEffect(vfx_impactHeal);
|
|
effect eHeal, eDam;
|
|
|
|
int nExtraDamage = nCasterLvl; // * figure out the bonus damage
|
|
if (nExtraDamage > nMaxExtraDamage)
|
|
{
|
|
nExtraDamage = nMaxExtraDamage;
|
|
}
|
|
// * if low or normal difficulty is treated as MAXIMIZED
|
|
if(GetIsPC(oTarget) && GetGameDifficulty() < GAME_DIFFICULTY_CORE_RULES)
|
|
{
|
|
nDamage = nMaximized + nExtraDamage;
|
|
}
|
|
else
|
|
{
|
|
nDamage = nDamage + nExtraDamage;
|
|
}
|
|
|
|
|
|
//Make metamagic checks
|
|
int iBlastFaith = BlastInfidelOrFaithHeal(OBJECT_SELF, oTarget, DAMAGE_TYPE_POSITIVE, TRUE);
|
|
if (nMetaMagic & METAMAGIC_MAXIMIZE || iBlastFaith)
|
|
{
|
|
nDamage = nMaximized + nExtraDamage;
|
|
// * if low or normal difficulty then MAXMIZED is doubled.
|
|
if(GetIsPC(OBJECT_SELF) && GetGameDifficulty() < GAME_DIFFICULTY_CORE_RULES)
|
|
{
|
|
nDamage = nDamage + nExtraDamage;
|
|
}
|
|
}
|
|
if (nMetaMagic & METAMAGIC_EMPOWER || GetHasFeat(FEAT_HEALING_DOMAIN_POWER))
|
|
{
|
|
nDamage = nDamage + (nDamage/2);
|
|
}
|
|
|
|
|
|
if (MyPRCGetRacialType(oTarget) != RACIAL_TYPE_UNDEAD)
|
|
{
|
|
//Figure out the amount of damage to heal
|
|
nHeal = nDamage;
|
|
//Set the heal effect
|
|
eHeal = EffectHeal(nHeal);
|
|
//Apply heal effect and VFX impact
|
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget);
|
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis2, oTarget);
|
|
//Fire cast spell at event for the specified target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpellID, FALSE));
|
|
|
|
|
|
}
|
|
//Check that the target is undead
|
|
else
|
|
{
|
|
int nTouch = PRCDoMeleeTouchAttack(oTarget);;
|
|
if (nTouch > 0)
|
|
{
|
|
if(!GetIsReactionTypeFriendly(oTarget))
|
|
{
|
|
//Fire cast spell at event for the specified target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpellID));
|
|
if (!PRCDoResistSpell(OBJECT_SELF, oTarget,nCasterLvl+add_spl_pen(OBJECT_SELF)))
|
|
{
|
|
eDam = EffectDamage(nDamage,DAMAGE_TYPE_NEGATIVE);
|
|
//Apply the VFX impact and effects
|
|
DelayCommand(1.0, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
////////////////End Soldier of Light Spells//////////////////
|
|
|
|
////////////////Begin Master Harper Instruments//////////////////
|
|
|
|
void ActiveModeCIMM(object oTarget)
|
|
{
|
|
if(!GetLocalInt(oTarget,"use_CIMM") )
|
|
{
|
|
string sScript = GetModuleOverrideSpellscript();
|
|
if (sScript != "mh_spell_at_inst")
|
|
{
|
|
SetLocalString(OBJECT_SELF,"temp_spell_at_inst",sScript);
|
|
SetLocalString(OBJECT_SELF, "PRC_OVERRIDE_SPELLSCRIPT", "mh_spell_at_inst");
|
|
}
|
|
SetLocalInt(OBJECT_SELF,"nb_spell_at_inst",GetLocalInt(OBJECT_SELF,"nb_spell_at_inst")+1);
|
|
FloatingTextStrRefOnCreature(16825240,oTarget);
|
|
SetLocalInt(oTarget,"use_CIMM",TRUE);
|
|
}
|
|
}
|
|
|
|
void UnactiveModeCIMM(object oTarget)
|
|
{
|
|
if(GetLocalInt(oTarget,"use_CIMM") )
|
|
{
|
|
string sScript = GetModuleOverrideSpellscript();
|
|
SetLocalInt(OBJECT_SELF,"nb_spell_at_inst",GetLocalInt(OBJECT_SELF,"nb_spell_at_inst")-1);
|
|
if (sScript == "mh_spell_at_inst" && GetLocalInt(OBJECT_SELF,"nb_spell_at_inst") == 0)
|
|
{
|
|
SetLocalString(OBJECT_SELF, "PRC_OVERRIDE_SPELLSCRIPT", GetLocalString(OBJECT_SELF,"temp_spell_at_inst"));
|
|
GetLocalString(OBJECT_SELF,"temp_spell_at_inst");
|
|
SetLocalString(OBJECT_SELF,"temp_spell_at_inst","");
|
|
}
|
|
FloatingTextStrRefOnCreature(16825241,oTarget);
|
|
SetLocalInt(oTarget,"use_CIMM",FALSE);
|
|
}
|
|
}
|
|
|
|
////////////////End Master Harper Instruments//////////////////
|
|
|
|
////////////////Begin Minstrel of the Edge//////////////////
|
|
|
|
// Goes a bit further than RemoveSpellEffects -- makes sure to remove ALL effects
|
|
// made by the Singer+Song.
|
|
void RemoveSongEffects(int iSong, object oCaster, object oTarget)
|
|
{
|
|
effect eCheck = GetFirstEffect(oTarget);
|
|
while (GetIsEffectValid(eCheck))
|
|
{
|
|
if (GetEffectCreator(eCheck) == oCaster && GetEffectSpellId(eCheck) == iSong)
|
|
RemoveEffect(oTarget, eCheck);
|
|
eCheck = GetNextEffect(oTarget);
|
|
}
|
|
}
|
|
|
|
// Stores a Song recipient to the PC as a local variable, and creates a list by using
|
|
// an index variable.
|
|
void StoreSongRecipient(object oRecipient, object oSinger, int iSongID, int iDuration = 0)
|
|
{
|
|
int iSlot = GetLocalInt(oSinger, "SONG_SLOT");
|
|
int iIndex = GetLocalInt(oSinger, "SONG_INDEX_" + IntToString(iSlot)) + 1;
|
|
string sIndex = "SONG_INDEX_" + IntToString(iSlot);
|
|
string sRecip = "SONG_RECIPIENT_" + IntToString(iIndex) + "_" + IntToString(iSlot);
|
|
string sSong = "SONG_IN_USE_" + IntToString(iSlot);
|
|
|
|
// Store the recipient into the current used slot
|
|
SetLocalObject(oSinger, sRecip, oRecipient);
|
|
|
|
// Store the song information
|
|
SetLocalInt(oSinger, sSong, iSongID);
|
|
|
|
// Store the index of creatures we're on
|
|
SetLocalInt(oSinger, sIndex, iIndex);
|
|
}
|
|
|
|
// Removes all effects given by the previous song from all creatures who recieved it.
|
|
// Now allows for two "slots", which means you can perform two songs at a time.
|
|
void RemoveOldSongEffects(object oSinger, int iSongID)
|
|
{
|
|
object oCreature;
|
|
int iSlotNow = GetLocalInt(oSinger, "SONG_SLOT");
|
|
int iSlot;
|
|
int iNumRecip;
|
|
int iSongInUse;
|
|
int iIndex;
|
|
string sIndex;
|
|
string sRecip;
|
|
string sSong;
|
|
|
|
if (GetHasFeat(FEAT_MINSTREL_GREATER_MINSTREL_SONG, oSinger))
|
|
{
|
|
// If you use the same song twice in a row you
|
|
// should deal with the same slot again...
|
|
if (GetLocalInt(oSinger, "SONG_IN_USE_" + IntToString(iSlotNow)) == iSongID)
|
|
iSlot = iSlotNow;
|
|
// Otherwise, we should toggle between slot "1" and slot "0"
|
|
else
|
|
iSlot = (iSlotNow == 1) ? 0 : 1;
|
|
}
|
|
else
|
|
{
|
|
iSlot = 0;
|
|
}
|
|
|
|
// Save the toggle we're on for later.
|
|
SetLocalInt(oSinger, "SONG_SLOT", iSlot);
|
|
|
|
// Find the proper variable names based on slot
|
|
sIndex = "SONG_INDEX_" + IntToString(iSlot);
|
|
sSong = "SONG_IN_USE_" + IntToString(iSlot);
|
|
|
|
// Store the local variables into script variables
|
|
iNumRecip = GetLocalInt(oSinger, sIndex);
|
|
iSongInUse = GetLocalInt(oSinger, sSong);
|
|
|
|
// Reset the local variables
|
|
SetLocalInt(oSinger, sIndex, 0);
|
|
SetLocalInt(oSinger, sSong, 0);
|
|
|
|
// Removes any effects from the caster first
|
|
RemoveSongEffects(iSongInUse, oSinger, oSinger);
|
|
|
|
// Removes any effects from the recipients
|
|
for (iIndex = 1 ; iIndex <= iNumRecip ; iIndex++)
|
|
{
|
|
sRecip = "SONG_RECIPIENT_" + IntToString(iIndex) + "_" + IntToString(iSlot);
|
|
oCreature = GetLocalObject(oSinger, sRecip);
|
|
|
|
RemoveSongEffects(iSongInUse, oSinger, oCreature);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////End Minstrel of the Edge//////////////////
|
|
|
|
////////////////Begin Arcane Duelist//////////////////
|
|
|
|
void FlurryEffects(object oPC)
|
|
{
|
|
effect Effect1 = EffectModifyAttacks(1);
|
|
effect Effect2 = EffectAttackDecrease(2, ATTACK_BONUS_MISC);
|
|
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, Effect1, oPC, RoundsToSeconds(10));
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, Effect2, oPC, RoundsToSeconds(10));
|
|
|
|
}
|
|
|
|
void CheckCombatDexAttack(object oPC)
|
|
{
|
|
//object oPC = GetLocalObject(OBJECT_SELF, "PC_IN_COMBAT_WITH_DEXATTACK_ON");
|
|
int iCombat = GetIsInCombat(oPC);
|
|
object oWeapon = GetLocalObject(oPC, "CHOSEN_WEAPON");
|
|
|
|
if(iCombat == TRUE && GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC) == oWeapon)
|
|
{
|
|
DelayCommand(6.0, CheckCombatDexAttack(oPC));
|
|
}
|
|
else
|
|
{
|
|
FloatingTextStringOnCreature("Dexterous Attack Mode Deactivated", oPC, FALSE);
|
|
effect eEffects = GetFirstEffect(oPC);
|
|
while (GetIsEffectValid(eEffects))
|
|
{
|
|
|
|
if (GetEffectType(eEffects) == EFFECT_TYPE_ATTACK_INCREASE && GetEffectSpellId(eEffects) == 1761) // dextrous attack
|
|
{
|
|
RemoveEffect(oPC, eEffects);
|
|
}
|
|
|
|
eEffects = GetNextEffect(oPC);
|
|
}
|
|
DeleteLocalObject(OBJECT_SELF, "PC_IN_COMBAT_WITH_DEXATTACK_ON");
|
|
}
|
|
}
|
|
|
|
void SPMakeAttack(object oTarget, object oImage)
|
|
{
|
|
int iDead = GetIsDead(oTarget);
|
|
|
|
if(iDead == FALSE)
|
|
{
|
|
PrintString("TARGET AINT DEAD");
|
|
DelayCommand(6.0, SPMakeAttack(oTarget, oImage));
|
|
AssignCommand(oImage, ActionAttack(oTarget, FALSE));
|
|
}
|
|
if(iDead == TRUE)
|
|
{
|
|
PrintString("TARGET BE DEAD AS A DOORNAIL");
|
|
DestroyObject(oImage, 0.0);
|
|
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3), GetLocation(oImage), 0.0);
|
|
}
|
|
|
|
}
|
|
|
|
////////////////End Arcane Duelist//////////////////
|
|
|
|
////////////////Begin Corpsecrafter//////////////
|
|
|
|
void CorpseCrafter(object oPC, object oSummon)
|
|
{
|
|
// Hijacking this function because it's already in the right places
|
|
if (GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oPC) >= 8)
|
|
{
|
|
if (DEBUG) DoDebug("Corpsecrafter: Dread Necro");
|
|
int nHD = GetHitDice(oSummon);
|
|
effect eHP = EffectTemporaryHitpoints(nHD * 2);
|
|
effect eStr = EffectAbilityIncrease(ABILITY_STRENGTH, 4);
|
|
effect eDex = EffectAbilityIncrease(ABILITY_DEXTERITY, 4);
|
|
eHP = SupernaturalEffect(eHP);
|
|
eStr = SupernaturalEffect(EffectLinkEffects(eStr, eDex));
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHP, oSummon);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eStr, oSummon);
|
|
}
|
|
if (GetHasFeat(FEAT_CORPSECRAFTER, oPC))
|
|
{
|
|
if (DEBUG) DoDebug("Corpsecrafter: Corpsecrafter");
|
|
int nHD = GetHitDice(oSummon);
|
|
effect eHP = EffectTemporaryHitpoints(nHD * 2);
|
|
effect eStr = EffectAbilityIncrease(ABILITY_STRENGTH, 4);
|
|
eHP = SupernaturalEffect(eHP);
|
|
eStr = SupernaturalEffect(eStr);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eHP, oSummon);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eStr, oSummon);
|
|
}
|
|
if (GetHasFeat(FEAT_BOLSTER_RESISTANCE, oPC))
|
|
{
|
|
if (DEBUG) DoDebug("Corpsecrafter: Bolster Resistance");
|
|
effect eTurn = EffectTurnResistanceIncrease(4);
|
|
eTurn = SupernaturalEffect(eTurn);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eTurn, oSummon);
|
|
}
|
|
if (GetHasFeat(FEAT_DEADLY_CHILL, oPC))
|
|
{
|
|
if (DEBUG) DoDebug("Corpsecrafter: Deadly Chill");
|
|
effect eChill = EffectDamageIncrease(DAMAGE_BONUS_1d6, DAMAGE_TYPE_COLD);
|
|
eChill = SupernaturalEffect(eChill);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eChill, oSummon);
|
|
}
|
|
if (GetHasFeat(FEAT_HARDENED_FLESH, oPC))
|
|
{
|
|
if (DEBUG) DoDebug("Corpsecrafter: Hardened Flesh");
|
|
effect eAC = EffectACIncrease(2);
|
|
eAC = SupernaturalEffect(eAC);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eAC, oSummon);
|
|
}
|
|
if (GetHasFeat(FEAT_NIMBLE_BONES, oPC))
|
|
{
|
|
if (DEBUG) DoDebug("Corpsecrafter: Nimble Bones");
|
|
object oSkin = GetPCSkin(oPC);
|
|
itemproperty iInit = PRCItemPropertyBonusFeat(IP_CONST_FEAT_IMPROVED_INIT);
|
|
//AddItemProperty(DURATION_TYPE_PERMANENT, iInit, oSkin);
|
|
IPSafeAddItemProperty(oSkin, iInit, 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
|
|
|
// Speed boost, average speed is 30 feet, so a 10 foot boost is a 33% boost
|
|
effect eSpeed = EffectMovementSpeedIncrease(33);
|
|
eSpeed = SupernaturalEffect(eSpeed);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSpeed, oSummon);
|
|
}
|
|
if (GetHasFeat(FEAT_DESTRUCTION_RETRIBUTION, oPC))
|
|
{
|
|
if (DEBUG) DoDebug("Corpsecrafter: Destruction Retribution");
|
|
SetLocalInt(oSummon, "DestructionRetribution", TRUE);
|
|
}
|
|
}
|
|
|
|
////////////////Begin Ninja//////////////
|
|
|
|
void Ninja_DecrementKi (object oPC, int iExcept = -1)
|
|
{
|
|
if (iExcept != FEAT_KI_POWER)
|
|
DecrementRemainingFeatUses(oPC, FEAT_KI_POWER);
|
|
if (iExcept != FEAT_GHOST_STEP)
|
|
DecrementRemainingFeatUses(oPC, FEAT_GHOST_STEP);
|
|
if (iExcept != FEAT_GHOST_STRIKE)
|
|
DecrementRemainingFeatUses(oPC, FEAT_GHOST_STRIKE);
|
|
if (iExcept != FEAT_GHOST_WALK)
|
|
DecrementRemainingFeatUses(oPC, FEAT_GHOST_WALK);
|
|
if (iExcept != FEAT_KI_DODGE)
|
|
DecrementRemainingFeatUses(oPC, FEAT_KI_DODGE);
|
|
// for testing only
|
|
SetLocalInt(oPC, "prc_ninja_ki", GetLocalInt(oPC, "prc_ninja_ki") - 1);
|
|
ExecuteScript("prc_ninjca", oPC);
|
|
}
|
|
|
|
int Ninja_AbilitiesEnabled (object oPC)
|
|
{
|
|
object oLefthand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
|
|
|
|
if (GetBaseAC(GetItemInSlot(INVENTORY_SLOT_CHEST, oPC)) > 0 ||
|
|
GetBaseItemType(oLefthand) == BASE_ITEM_SMALLSHIELD ||
|
|
GetBaseItemType(oLefthand) == BASE_ITEM_LARGESHIELD ||
|
|
GetBaseItemType(oLefthand) == BASE_ITEM_TOWERSHIELD)
|
|
return FALSE;
|
|
// all Ki powers will not function when encumbered
|
|
if (GetIsEncumbered(oPC))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
////////////////End Ninja//////////////
|
|
|
|
////////////////Begin Virtuoso//////////////
|
|
|
|
//Decrements the daily uses of Virtuoso Performance by the
|
|
// correct amount, returns FALSE if there are insufficient
|
|
// uses remaining to use the current feat
|
|
int VirtuosoPerformanceDecrement(object oPC, int nSpellID)
|
|
{
|
|
int nDecrement = 0;
|
|
int nDifference = 1122; //hack, difference in number between feat and spell 2da lines
|
|
switch(nSpellID)
|
|
{
|
|
case SPELL_VIRTUOSO_SUSTAINING_SONG:
|
|
case SPELL_VIRTUOSO_CALUMNY:
|
|
case SPELL_VIRTUOSO_GREATER_CALUMNY: nDecrement = 1; break;
|
|
|
|
case SPELL_VIRTUOSO_MINDBENDING_MELODY:
|
|
case SPELL_VIRTUOSO_MAGICAL_MELODY:
|
|
case SPELL_VIRTUOSO_REVEALING_MELODY: nDecrement = 2; break;
|
|
|
|
case SPELL_VIRTUOSO_SHARP_NOTE:
|
|
case SPELL_VIRTUOSO_JARRING_SONG:
|
|
case SPELL_VIRTUOSO_SONG_OF_FURY: nDecrement = 3; break;
|
|
}
|
|
if(!nDecrement) return FALSE; //sanity check
|
|
int nUses = GetPersistantLocalInt(oPC, "Virtuoso_Performance_Uses");
|
|
if(nUses >= nDecrement)
|
|
{
|
|
SetPersistantLocalInt(oPC, "Virtuoso_Performance_Uses", nUses - nDecrement);
|
|
int nFeat, nDec;
|
|
for(nFeat = FEAT_VIRTUOSO_SUSTAINING_SONG; nFeat <= FEAT_VIRTUOSO_PERFORMANCE; nFeat++)
|
|
{
|
|
nDec = nDecrement;
|
|
if(nFeat == (nSpellID + nDifference))
|
|
nDec--; //already decremented once by being used
|
|
for(; nDec > 0; nDec--)
|
|
DecrementRemainingFeatUses(oPC, nFeat);
|
|
}
|
|
return TRUE;
|
|
}
|
|
else
|
|
{ //refund feat use :P
|
|
IncrementRemainingFeatUses(oPC, nSpellID + nDifference);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
////////////////End Virtuoso//////////////
|
|
|
|
|
|
///////////////Archmage & Heirophant SLAs ///////////
|
|
|
|
void DoArchmageHeirophantSLA(object oPC, object oTarget, location lTarget, int nSLAID)
|
|
{
|
|
int nSLAFeatID = -1; //feat ID of the SLA in use
|
|
int nSLASpellID = -1;//spell ID of the SLA in use NOT THE SPELL BEING CAST
|
|
//get the SLAFeatID
|
|
int SLA_ID;
|
|
switch(SLA_ID)
|
|
{
|
|
case 1: nSLAFeatID = FEAT_SPELL_LIKE_ABILITY_1; break;
|
|
case 2: nSLAFeatID = FEAT_SPELL_LIKE_ABILITY_2; break;
|
|
case 3: nSLAFeatID = FEAT_SPELL_LIKE_ABILITY_3; break;
|
|
case 4: nSLAFeatID = FEAT_SPELL_LIKE_ABILITY_4; break;
|
|
case 5: nSLAFeatID = FEAT_SPELL_LIKE_ABILITY_5; break;
|
|
}
|
|
//get the spellID of the spell your trying to cast
|
|
//+1 offset for unassigned
|
|
int nSpellID = GetPersistantLocalInt(oPC, "PRC_SLA_SpellID_"+IntToString(nSLAID))-1;
|
|
//test if already stored
|
|
if(nSpellID == -1)
|
|
{
|
|
//not stored
|
|
FloatingTextStringOnCreature("This SLA has not been stored yet\nThe next spell you cast will be assigned to this SLA", oPC);
|
|
SetLocalInt(oPC, "PRC_SLA_Store", nSLAID);
|
|
DelayCommand(18.0,
|
|
DeleteLocalInt(oPC, "PRC_SLA_Store"));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
//stored, recast it
|
|
int nSpellClass = GetPersistantLocalInt(oPC, "PRC_SLA_Class_"+IntToString(nSLAID));
|
|
int nMetamagic = GetPersistantLocalInt(oPC, "PRC_SLA_Meta_"+IntToString(nSLAID));
|
|
int nSpellLevel = PRCGetSpellLevelForClass(nSpellID, nSpellClass);
|
|
int nBaseDC = 10 + nSpellLevel + GetDCAbilityModForClass(nSpellClass, oPC);
|
|
//since this is targetted using a generic feat,
|
|
//make sure were within range and target is valid for this spell
|
|
//get current distance
|
|
/*string sRange = Get2DACache("spells", "Range", nSpellID);
|
|
float fDist;
|
|
if(GetIsObjectValid(oTarget))
|
|
fDist = GetDistanceToObject(oTarget);
|
|
else
|
|
fDist = GetDistanceBetweenLocations(GetLocation(oPC), lTarget);
|
|
//check distance is allowed
|
|
if(fDist < 0.0
|
|
|| (sRange == "T" && fDist > 2.25)
|
|
|| (sRange == "S" && fDist > 8.0 )
|
|
|| (sRange == "M" && fDist > 20.0 )
|
|
|| (sRange == "L" && fDist > 40.0 )
|
|
)
|
|
{
|
|
//out of range
|
|
FloatingTextStringOnCreature("You are out of range", oPC);
|
|
//replace the useage
|
|
IncrementRemainingFeatUses(oPC, nSLAFeatID);
|
|
//end the script
|
|
return;
|
|
}*/
|
|
//check object type
|
|
int nTargetType = HexToInt(Get2DACache("spells", "TargetType", nSpellID));
|
|
/*
|
|
# 0x01 = 1 = Self
|
|
# 0x02 = 2 = Creature
|
|
# 0x04 = 4 = Area/Ground
|
|
# 0x08 = 8 = Items
|
|
# 0x10 = 16 = Doors
|
|
# 0x20 = 32 = Placeables
|
|
*/
|
|
int nCaster = nTargetType & 1;
|
|
int nCreature = nTargetType & 2;
|
|
int nLocation = nTargetType & 4;
|
|
int nItem = nTargetType & 8;
|
|
int nDoor = nTargetType & 16;
|
|
int nPlaceable = nTargetType & 32;
|
|
int nTargetValid = TRUE;
|
|
//test targetting self
|
|
if(oTarget == OBJECT_SELF)
|
|
{
|
|
if(!nCaster)
|
|
{
|
|
nTargetValid = FALSE;
|
|
FloatingTextStringOnCreature("You cannot target yourself", oPC);
|
|
}
|
|
}
|
|
//test targetting others
|
|
else if(GetIsObjectValid(oTarget))
|
|
{
|
|
switch(GetObjectType(oTarget))
|
|
{
|
|
case OBJECT_TYPE_CREATURE:
|
|
if(!nCreature)
|
|
{
|
|
nTargetValid = FALSE;
|
|
FloatingTextStringOnCreature("You cannot target creatures", oPC);
|
|
}
|
|
break;
|
|
case OBJECT_TYPE_ITEM:
|
|
if(!nItem)
|
|
{
|
|
nTargetValid = FALSE;
|
|
FloatingTextStringOnCreature("You cannot target items", oPC);
|
|
}
|
|
break;
|
|
case OBJECT_TYPE_DOOR:
|
|
if(!nDoor)
|
|
{
|
|
nTargetValid = FALSE;
|
|
FloatingTextStringOnCreature("You cannot target doors", oPC);
|
|
}
|
|
break;
|
|
case OBJECT_TYPE_PLACEABLE:
|
|
if(!nPlaceable)
|
|
{
|
|
nTargetValid = FALSE;
|
|
FloatingTextStringOnCreature("You cannot target placeables", oPC);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
//test if can target a location
|
|
else if(GetIsObjectValid(GetAreaFromLocation(lTarget)))
|
|
{
|
|
if(!nLocation)
|
|
{
|
|
nTargetValid = FALSE;
|
|
FloatingTextStringOnCreature("You cannot target locations", oPC);
|
|
}
|
|
}
|
|
//target was not valid, abort
|
|
if(!nTargetValid)
|
|
{
|
|
//replace the useage
|
|
IncrementRemainingFeatUses(oPC, nSLAFeatID);
|
|
//end the script
|
|
return;
|
|
}
|
|
//actually cast it at this point
|
|
//note that these are instant-spells, so we have to add the animation part too
|
|
/*if(GetIsObjectValid(oTarget))
|
|
ActionCastFakeSpellAtObject(nSpellID, oTarget);
|
|
else
|
|
ActionCastFakeSpellAtLocation(nSpellID, lTarget);*/
|
|
ActionDoCommand(ActionCastSpell(nSpellID, 0, nBaseDC, 0, nMetamagic, nSpellClass, 0, 0, OBJECT_INVALID, FALSE));
|
|
}
|
|
}
|
|
|
|
/////////////// End Archmage & Heirophant SLAs ///////////
|
|
|
|
////////////////////////Alienist//////////////////////////
|
|
int GetPhobia(object oPC)
|
|
{
|
|
int nPhobia = GetPersistantLocalInt(oPC, "Alienist_Phobia");
|
|
if(nPhobia < 1)
|
|
{
|
|
nPhobia = Random(16) + 1;
|
|
SetPersistantLocalInt(oPC, "Alienist_Phobia", nPhobia);
|
|
}
|
|
return nPhobia;
|
|
}
|
|
|
|
int GetPhobiaRace(int nPhobia)
|
|
{
|
|
switch(nPhobia)
|
|
{
|
|
case 1: return RACIAL_TYPE_ABERRATION;
|
|
case 2: return RACIAL_TYPE_ANIMAL;
|
|
case 3: return RACIAL_TYPE_BEAST;
|
|
case 4: return RACIAL_TYPE_CONSTRUCT;
|
|
case 5: return RACIAL_TYPE_DRAGON;
|
|
case 6: return RACIAL_TYPE_HUMANOID_GOBLINOID;
|
|
case 7: return RACIAL_TYPE_HUMANOID_MONSTROUS;
|
|
case 8: return RACIAL_TYPE_HUMANOID_ORC;
|
|
case 9: return RACIAL_TYPE_HUMANOID_REPTILIAN;
|
|
case 10: return RACIAL_TYPE_ELEMENTAL;
|
|
case 11: return RACIAL_TYPE_FEY;
|
|
case 12: return RACIAL_TYPE_GIANT;
|
|
case 13: return RACIAL_TYPE_MAGICAL_BEAST;
|
|
case 14: return RACIAL_TYPE_SHAPECHANGER;
|
|
case 15: return RACIAL_TYPE_UNDEAD;
|
|
case 16: return RACIAL_TYPE_VERMIN;
|
|
}
|
|
return -1;//error
|
|
}
|
|
|
|
int GetPhobiaFeat(int nPhobia)
|
|
{
|
|
switch(nPhobia)
|
|
{
|
|
case 1: return IP_CONST_PHOBIA_ABERRATION;
|
|
case 2: return IP_CONST_PHOBIA_ANIMAL;
|
|
case 3: return IP_CONST_PHOBIA_BEAST;
|
|
case 4: return IP_CONST_PHOBIA_CONSTRUCT;
|
|
case 5: return IP_CONST_PHOBIA_DRAGON;
|
|
case 6: return IP_CONST_PHOBIA_GOBLINOID;
|
|
case 7: return IP_CONST_PHOBIA_MONSTROUS;
|
|
case 8: return IP_CONST_PHOBIA_ORC;
|
|
case 9: return IP_CONST_PHOBIA_REPTILIAN;
|
|
case 10: return IP_CONST_PHOBIA_ELEMENTAL;
|
|
case 11: return IP_CONST_PHOBIA_FEY;
|
|
case 12: return IP_CONST_PHOBIA_GIANT;
|
|
case 13: return IP_CONST_PHOBIA_MAGICAL_BEAST;
|
|
case 14: return IP_CONST_PHOBIA_SHAPECHANGER;
|
|
case 15: return IP_CONST_PHOBIA_UNDEAD;
|
|
case 16: return IP_CONST_PHOBIA_VERMIN;
|
|
}
|
|
return -1;//error
|
|
}
|
|
|
|
/////////////////////DragonSong Lyrist////////////////////////
|
|
|
|
void RemoveOldSongs(object oPC)
|
|
{
|
|
if(GetHasSpellEffect(SPELL_DSL_SONG_STRENGTH, oPC)) PRCRemoveEffectsFromSpell(oPC, SPELL_DSL_SONG_STRENGTH);
|
|
if(GetHasSpellEffect(SPELL_DSL_SONG_COMPULSION, oPC)) PRCRemoveEffectsFromSpell(oPC, SPELL_DSL_SONG_COMPULSION);
|
|
if(GetHasSpellEffect(SPELL_DSL_SONG_SPEED, oPC)) PRCRemoveEffectsFromSpell(oPC, SPELL_DSL_SONG_SPEED);
|
|
if(GetHasSpellEffect(SPELL_DSL_SONG_FEAR, oPC)) PRCRemoveEffectsFromSpell(oPC, SPELL_DSL_SONG_FEAR);
|
|
if(GetHasSpellEffect(SPELL_DSL_SONG_HEALING, oPC)) PRCRemoveEffectsFromSpell(oPC, SPELL_DSL_SONG_HEALING);
|
|
}
|
|
|
|
|
|
// Eldritch Theurge class requires arcane spellcasting and eldritch blast.
|
|
// If a character is an Eldritch Theruge we know that she must have levels in Warlock
|
|
// since in NWN character can have max 3 classes. We also know that Eldritch Theurge
|
|
// is at positon 3 (unless player is cheating).
|
|
// So we just need to check the third class.
|
|
|
|
//:: [PRC .35] This function will require marker feats
|
|
int GetETArcaneClass(object oPC)
|
|
{
|
|
int nClass = GetClassByPosition(1, oPC);
|
|
if(nClass == CLASS_TYPE_WARLOCK)
|
|
nClass = GetClassByPosition(2, oPC);
|
|
return nClass;
|
|
}
|
|
|