Updated AMS marker feats. Removed arcane & divine marker feats. Updated Dread Necromancer for epic progression. Updated weapon baseitem models. Updated new weapons for crafting & npc equip. Updated prefix. Updated release archive.
1620 lines
64 KiB
Plaintext
1620 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
|
|
*/
|
|
|
|
|
|
|
|
////////////////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.
|
|
int GetETArcaneClass(object oPC)
|
|
{
|
|
|
|
int nClass = GetPrimaryArcaneClass(oPC);
|
|
|
|
/* int nClass = GetClassByPosition(1, oPC);
|
|
if(nClass == CLASS_TYPE_WARLOCK)
|
|
nClass = GetClassByPosition(2, oPC); */
|
|
return nClass;
|
|
}
|
|
|