669 lines
26 KiB
Plaintext
669 lines
26 KiB
Plaintext
//::///////////////////////////////////////////////
|
|
//:: x2_i0_spells
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Expansion 2 and above include file for spells
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Andrew Nobbs
|
|
//:: Created On: Nov 2002
|
|
//:: Updated On: 2003/09/10 - Georg Zoeller
|
|
//:://////////////////////////////////////////////
|
|
#include "x2_inc_itemprop"
|
|
#include "x0_i0_spells"
|
|
|
|
//------------------------------------------------------------------------------
|
|
// GZ: These constants are used with for the AOE behavior AI
|
|
//------------------------------------------------------------------------------
|
|
const int X2_SPELL_AOEBEHAVIOR_FLEE = 0;
|
|
const int X2_SPELL_AOEBEHAVIOR_IGNORE = 1;
|
|
const int X2_SPELL_AOEBEHAVIOR_GUST = 2;
|
|
const int X2_SPELL_AOEBEHAVIOR_DISPEL_L = SPELL_LESSER_DISPEL;
|
|
const int X2_SPELL_AOEBEHAVIOR_DISPEL_N = SPELL_DISPEL_MAGIC;
|
|
const int X2_SPELL_AOEBEHAVIOR_DISPEL_G = SPELL_GREATER_DISPELLING;
|
|
const int X2_SPELL_AOEBEHAVIOR_DISPEL_M = SPELL_MORDENKAINENS_DISJUNCTION;
|
|
const int X2_SPELL_AOEBEHAVIOR_DISPEL_C = 727;
|
|
|
|
|
|
// * Will pass back a linked effect for all of the bad tide of battle effects.
|
|
effect CreateBadTideEffectsLink();
|
|
// * Will pass back a linked effect for all of the good tide of battle effects.
|
|
effect CreateGoodTideEffectsLink();
|
|
// * Passes in the slashing weapon type
|
|
int GetSlashingWeapon(object oItem);
|
|
// * Passes in the melee weapon type
|
|
int GetMeleeWeapon(object oItem);
|
|
// * Passes in if the item is magical or not.
|
|
int GetIsMagicalItem(object oItem);
|
|
// * Passes back the stat bonus of the characters magical stat, if any.
|
|
int GetIsMagicStatBonus(object oCaster);
|
|
|
|
// * Save DC against Epic Spells is the relevant ability score of the caster
|
|
// * + 20. The hightest ability score of the casting relevants is 99.99% identical
|
|
// * with the one that is used for casting, so we just take it.
|
|
// * if used by a placeable, it is equal to the placeables WILL save field.
|
|
int GetEpicSpellSaveDC(object oCaster);
|
|
|
|
// * Hub function for the epic barbarian feats that upgrade rage. Call from
|
|
// * the end of the barbarian rage spellscript
|
|
void CheckAndApplyEpicRageFeats(int nRounds);
|
|
|
|
// * Checks the character for the thundering rage feat and will apply temporary massive critical
|
|
// * to the worn weapons
|
|
// * called by CheckAndApplyEpicRageFeats(
|
|
void CheckAndApplyThunderingRage(int nRounds);
|
|
|
|
// * Checks and runs Rerrifying Rage feat
|
|
// * called by CheckAndApplyEpicRageFeats(
|
|
void CheckAndApplyTerrifyingRage(int nRounds);
|
|
|
|
|
|
// * Do a mind blast
|
|
// nDC - DC of the Save to resist
|
|
// nRounds - Rounds the stun effect holds
|
|
// fRange - Range of the EffectCone
|
|
void DoMindBlast(int nDC, int nDuration, float fRange);
|
|
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: CreateBadTideEffectsLink
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Creates the linked bad effects for Battletide.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
effect CreateBadTideEffectsLink()
|
|
{
|
|
//Declare major variables
|
|
effect eSaves = EffectSavingThrowDecrease(SAVING_THROW_ALL, 2);
|
|
effect eAttack = EffectAttackDecrease(2);
|
|
effect eDamage = EffectDamageDecrease(2);
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
|
|
//Link the effects
|
|
effect eLink = EffectLinkEffects(eAttack, eDamage);
|
|
eLink = EffectLinkEffects(eLink, eSaves);
|
|
eLink = EffectLinkEffects(eLink, eDur);
|
|
|
|
return eLink;
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: CreateGoodTideEffectsLink
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Creates the linked good effects for Battletide.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
effect CreateGoodTideEffectsLink()
|
|
{
|
|
//Declare major variables
|
|
effect eSaves = EffectSavingThrowIncrease(SAVING_THROW_ALL, 2);
|
|
effect eAttack = EffectAttackIncrease(2);
|
|
effect eDamage = EffectDamageIncrease(2);
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
|
|
//Link the effects
|
|
effect eLink = EffectLinkEffects(eAttack, eDamage);
|
|
eLink = EffectLinkEffects(eLink, eSaves);
|
|
eLink = EffectLinkEffects(eLink, eDur);
|
|
|
|
return eLink;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// AN, 2003
|
|
// Returns TRUE if oItem is a slashing weapon
|
|
//------------------------------------------------------------------------------
|
|
int GetSlashingWeapon(object oItem)
|
|
{
|
|
//Declare major variables
|
|
int nItem = GetBaseItemType(oItem);
|
|
|
|
if((nItem == BASE_ITEM_BASTARDSWORD) ||
|
|
(nItem == BASE_ITEM_BATTLEAXE) ||
|
|
(nItem == BASE_ITEM_DOUBLEAXE) ||
|
|
(nItem == BASE_ITEM_GREATAXE) ||
|
|
(nItem == BASE_ITEM_GREATSWORD) ||
|
|
(nItem == BASE_ITEM_HALBERD) ||
|
|
(nItem == BASE_ITEM_HANDAXE) ||
|
|
(nItem == BASE_ITEM_KAMA) ||
|
|
(nItem == BASE_ITEM_KATANA) ||
|
|
(nItem == BASE_ITEM_KUKRI) ||
|
|
(nItem == BASE_ITEM_LONGSWORD)||
|
|
(nItem == BASE_ITEM_SCIMITAR)||
|
|
(nItem == BASE_ITEM_SCYTHE)||
|
|
(nItem == BASE_ITEM_SICKLE)||
|
|
(nItem == BASE_ITEM_TWOBLADEDSWORD) ||
|
|
(nItem == BASE_ITEM_DWARVENWARAXE) ||
|
|
(nItem == BASE_ITEM_THROWINGAXE) ||
|
|
(nItem == BASE_ITEM_WHIP)
|
|
|
|
)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// AN, 2003
|
|
// Returns TRUE if oItem is a ranged weapon
|
|
//------------------------------------------------------------------------------
|
|
int GetIsRangedWeapon(object oItem)
|
|
{
|
|
// GZ: replaced if statement with engine function
|
|
return GetWeaponRanged(oItem);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// AN, 2003
|
|
// Returns TRUE, if oItem is a melee weapon
|
|
//------------------------------------------------------------------------------
|
|
int GetMeleeWeapon(object oItem)
|
|
{
|
|
//Declare major variables
|
|
int nItem = GetBaseItemType(oItem);
|
|
|
|
if((nItem == BASE_ITEM_BASTARDSWORD) ||
|
|
(nItem == BASE_ITEM_BATTLEAXE) ||
|
|
(nItem == BASE_ITEM_DOUBLEAXE) ||
|
|
(nItem == BASE_ITEM_GREATAXE) ||
|
|
(nItem == BASE_ITEM_GREATSWORD) ||
|
|
(nItem == BASE_ITEM_HALBERD) ||
|
|
(nItem == BASE_ITEM_HANDAXE) ||
|
|
(nItem == BASE_ITEM_KAMA) ||
|
|
(nItem == BASE_ITEM_KATANA) ||
|
|
(nItem == BASE_ITEM_KUKRI) ||
|
|
(nItem == BASE_ITEM_LONGSWORD) ||
|
|
(nItem == BASE_ITEM_SCIMITAR) ||
|
|
(nItem == BASE_ITEM_SCYTHE) ||
|
|
(nItem == BASE_ITEM_SICKLE) ||
|
|
(nItem == BASE_ITEM_TWOBLADEDSWORD) ||
|
|
(nItem == BASE_ITEM_CLUB) ||
|
|
(nItem == BASE_ITEM_DAGGER) ||
|
|
(nItem == BASE_ITEM_DIREMACE) ||
|
|
(nItem == BASE_ITEM_HEAVYFLAIL) ||
|
|
(nItem == BASE_ITEM_LIGHTFLAIL) ||
|
|
(nItem == BASE_ITEM_LIGHTHAMMER) ||
|
|
(nItem == BASE_ITEM_LIGHTMACE) ||
|
|
(nItem == BASE_ITEM_MORNINGSTAR) ||
|
|
(nItem == BASE_ITEM_QUARTERSTAFF) ||
|
|
(nItem == BASE_ITEM_RAPIER) ||
|
|
(nItem == BASE_ITEM_SHORTSPEAR) ||
|
|
(nItem == BASE_ITEM_SHORTSWORD) ||
|
|
(nItem == BASE_ITEM_WARHAMMER) ||
|
|
(nItem == BASE_ITEM_WHIP) ||
|
|
(nItem == BASE_ITEM_DWARVENWARAXE))
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// AN, 2003
|
|
// Returns TRUE if oItem has any item property that classifies it as magical item
|
|
//------------------------------------------------------------------------------
|
|
int GetIsMagicalItem(object oItem)
|
|
{
|
|
//Declare major variables
|
|
int nProperty;
|
|
|
|
if((GetItemHasItemProperty(oItem, ITEM_PROPERTY_ABILITY_BONUS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_AC_BONUS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_AC_BONUS_VS_ALIGNMENT_GROUP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_AC_BONUS_VS_DAMAGE_TYPE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_AC_BONUS_VS_RACIAL_GROUP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_AC_BONUS_VS_SPECIFIC_ALIGNMENT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ATTACK_BONUS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ATTACK_BONUS_VS_ALIGNMENT_GROUP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ATTACK_BONUS_VS_RACIAL_GROUP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ATTACK_BONUS_VS_SPECIFIC_ALIGNMENT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_BASE_ITEM_WEIGHT_REDUCTION)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_BONUS_FEAT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_CAST_SPELL)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DAMAGE_BONUS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DAMAGE_REDUCTION)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DAMAGE_RESISTANCE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DAMAGE_VULNERABILITY)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DARKVISION)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DECREASED_ABILITY_SCORE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DECREASED_AC)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DECREASED_DAMAGE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DECREASED_ENHANCEMENT_MODIFIER)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DECREASED_SAVING_THROWS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DECREASED_SAVING_THROWS_SPECIFIC)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_DECREASED_SKILL_MODIFIER)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ENHANCED_CONTAINER_REDUCED_WEIGHT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ENHANCEMENT_BONUS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_ALIGNMENT_GROUP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_RACIAL_GROUP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_SPECIFIC_ALIGNEMENT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_EXTRA_MELEE_DAMAGE_TYPE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_EXTRA_RANGED_DAMAGE_TYPE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_FREEDOM_OF_MOVEMENT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_HASTE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_HOLY_AVENGER)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_IMMUNITY_MISCELLANEOUS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_IMMUNITY_SPELL_SCHOOL)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_IMPROVED_EVASION)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_KEEN)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_LIGHT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_MASSIVE_CRITICALS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_MIGHTY)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_MIND_BLANK)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_MONSTER_DAMAGE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_NO_DAMAGE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ON_HIT_PROPERTIES)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ON_MONSTER_HIT)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_POISON)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_REGENERATION)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_REGENERATION_VAMPIRIC)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_SAVING_THROW_BONUS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_SAVING_THROW_BONUS_SPECIFIC)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_SKILL_BONUS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_SPELL_RESISTANCE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_THIEVES_TOOLS)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_TRAP)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_TRUE_SEEING)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_TURN_RESISTANCE)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_UNLIMITED_AMMUNITION)) ||
|
|
(GetItemHasItemProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL))
|
|
)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: GetIsMagicStatBonus
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Returns the modifier from the ability
|
|
score that matters for this caster
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
int GetIsMagicStatBonus(object oCaster)
|
|
{
|
|
//Declare major variables
|
|
int nClass;
|
|
int nAbility;
|
|
|
|
if(nClass = GetLevelByClass(CLASS_TYPE_WIZARD, oCaster))
|
|
{
|
|
if(nClass > 0)
|
|
{
|
|
nAbility = ABILITY_INTELLIGENCE;
|
|
}
|
|
}
|
|
if(nClass = GetLevelByClass(CLASS_TYPE_BARD, oCaster) || GetLevelByClass(CLASS_TYPE_SORCERER, oCaster))
|
|
{
|
|
if(nClass > 0)
|
|
{
|
|
nAbility = ABILITY_CHARISMA;
|
|
}
|
|
}
|
|
else if(nClass = GetLevelByClass(CLASS_TYPE_CLERIC, oCaster) || GetLevelByClass(CLASS_TYPE_DRUID, oCaster)
|
|
|| GetLevelByClass(CLASS_TYPE_PALADIN, oCaster) || GetLevelByClass(CLASS_TYPE_RANGER, oCaster))
|
|
{
|
|
if(nClass > 0)
|
|
{
|
|
nAbility = ABILITY_WISDOM;
|
|
}
|
|
}
|
|
|
|
return GetAbilityModifier(nAbility, oCaster);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// GZ, 2003-07-09
|
|
// Hub function for the epic barbarian feats that upgrade rage. Call from
|
|
// the end of the barbarian rage spellscript
|
|
//------------------------------------------------------------------------------
|
|
void CheckAndApplyEpicRageFeats(int nRounds)
|
|
{
|
|
CheckAndApplyThunderingRage(nRounds);
|
|
CheckAndApplyTerrifyingRage(nRounds);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// GZ, 2003-07-09
|
|
// If the character calling this function from a spellscript has the thundering
|
|
// rage feat, his weapons are upgraded to deafen and cause 2d6 points of massive
|
|
// criticals
|
|
//------------------------------------------------------------------------------
|
|
void CheckAndApplyThunderingRage(int nRounds)
|
|
{
|
|
if (GetHasFeat(988, OBJECT_SELF))
|
|
{
|
|
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND);
|
|
|
|
if (GetIsObjectValid(oWeapon))
|
|
{
|
|
IPSafeAddItemProperty(oWeapon, ItemPropertyMassiveCritical(IP_CONST_DAMAGEBONUS_2d6), RoundsToSeconds(nRounds), X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE,TRUE);
|
|
IPSafeAddItemProperty(oWeapon, ItemPropertyVisualEffect(ITEM_VISUAL_SONIC), RoundsToSeconds(nRounds), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
|
|
IPSafeAddItemProperty(oWeapon, ItemPropertyOnHitProps(IP_CONST_ONHIT_DEAFNESS,IP_CONST_ONHIT_SAVEDC_20,IP_CONST_ONHIT_DURATION_25_PERCENT_3_ROUNDS), RoundsToSeconds(nRounds), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
|
|
}
|
|
|
|
oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND);
|
|
|
|
if (GetIsObjectValid(oWeapon) )
|
|
{
|
|
IPSafeAddItemProperty(oWeapon, ItemPropertyMassiveCritical(IP_CONST_DAMAGEBONUS_2d6), RoundsToSeconds(nRounds), X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE,TRUE);
|
|
IPSafeAddItemProperty(oWeapon,ItemPropertyVisualEffect(ITEM_VISUAL_SONIC), RoundsToSeconds(nRounds), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// GZ, 2003-07-09
|
|
// If the character calling this function from a spellscript has the terrifying
|
|
// rage feat, he gets an aura of fear for the specified duration
|
|
// The saving throw against this fear is a check opposed to the character's
|
|
// intimidation skill
|
|
//------------------------------------------------------------------------------
|
|
void CheckAndApplyTerrifyingRage(int nRounds)
|
|
{
|
|
if (GetHasFeat(989, OBJECT_SELF))
|
|
{
|
|
effect eAOE = EffectAreaOfEffect(AOE_MOB_FEAR,"x2_s2_terrage_A", "","");
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eAOE,OBJECT_SELF,RoundsToSeconds(nRounds));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
//Keith Warner
|
|
// Do a mind blast
|
|
// nHitDice - HitDice/Caster Level of the creator
|
|
// nDC - DC of the Save to resist
|
|
// nRounds - Rounds the stun effect holds
|
|
// fRange - Range of the EffectCone
|
|
//------------------------------------------------------------------------------
|
|
void DoMindBlast(int nDC, int nDuration, float fRange)
|
|
{
|
|
int nStunTime;
|
|
float fDelay;
|
|
|
|
location lTargetLocation = GetSpellTargetLocation();
|
|
object oTarget;
|
|
effect eCone;
|
|
effect eVis = EffectVisualEffect(VFX_IMP_SONIC);
|
|
|
|
oTarget = GetFirstObjectInShape(SHAPE_SPELLCONE, fRange, lTargetLocation, TRUE);
|
|
|
|
while(GetIsObjectValid(oTarget))
|
|
{
|
|
int nApp = GetAppearanceType(oTarget);
|
|
int bImmune = FALSE;
|
|
//----------------------------------------------------------------------
|
|
// Hack to make mind flayers immune to their psionic attacks...
|
|
//----------------------------------------------------------------------
|
|
if (nApp == 413 ||nApp== 414 || nApp == 415)
|
|
{
|
|
bImmune = TRUE;
|
|
}
|
|
|
|
if(spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE,OBJECT_SELF) && oTarget != OBJECT_SELF && !bImmune )
|
|
{
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
|
fDelay = GetDistanceBetween(OBJECT_SELF, oTarget)/20;
|
|
// already stunned
|
|
if (GetHasSpellEffect(GetSpellId(),oTarget))
|
|
{
|
|
// only affects the targeted object
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_STUN), oTarget);
|
|
int nDamage;
|
|
if (GetLevelByClass(CLASS_TYPE_SHIFTER,OBJECT_SELF)>0)
|
|
{
|
|
nDamage = d6(GetLevelByClass(CLASS_TYPE_SHIFTER,OBJECT_SELF)/3);
|
|
}
|
|
else
|
|
{
|
|
nDamage = d6(GetHitDice(OBJECT_SELF)/2);
|
|
}
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage), oTarget);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_BIGBYS_FORCEFUL_HAND), oTarget);
|
|
}
|
|
else if (WillSave(oTarget, nDC) < 1)
|
|
{
|
|
//Calculate the length of the stun
|
|
nStunTime = nDuration;
|
|
//Set stunned effect
|
|
eCone = EffectStunned();
|
|
//Apply the VFX impact and effects
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eCone, oTarget, RoundsToSeconds(nStunTime)));
|
|
}
|
|
}
|
|
//Get next target in spell area
|
|
oTarget = GetNextObjectInShape(SHAPE_SPELLCONE, fRange, lTargetLocation, TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
// * Gelatinous Cube Paralyze attack
|
|
int DoCubeParalyze(object oTarget, object oSource, int nSaveDC = 26)
|
|
{
|
|
if (GetIsImmune(oTarget,IMMUNITY_TYPE_PARALYSIS) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (FortitudeSave(oTarget,nSaveDC, SAVING_THROW_TYPE_POISON,oSource) == 0)
|
|
{
|
|
effect ePara = EffectParalyze();
|
|
effect eDur = EffectVisualEffect(VFX_DUR_PARALYZED);
|
|
ePara = EffectLinkEffects(eDur,ePara);
|
|
ePara = EffectLinkEffects(EffectVisualEffect(VFX_DUR_FREEZE_ANIMATION),ePara);
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,ePara,oTarget,RoundsToSeconds(3+d3())); // not 3 d6, thats not fun
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
effect eSave = EffectVisualEffect(VFX_IMP_FORTITUDE_SAVING_THROW_USE);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT,eSave,oTarget);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// GZ: Gel. Cube special abilities
|
|
// --------------------------------------------------------------------------------
|
|
void EngulfAndDamage(object oTarget, object oSource)
|
|
{
|
|
|
|
if (ReflexSave(oTarget, 13 + GetHitDice(oSource) - 4, SAVING_THROW_TYPE_NONE,oSource) == 0)
|
|
{
|
|
|
|
FloatingTextStrRefOnCreature(84610,oTarget); // * Engulfed
|
|
int nDamage = d6(10);
|
|
|
|
effect eDamage = EffectDamage(nDamage, DAMAGE_TYPE_ACID);
|
|
effect eVis = EffectVisualEffect(VFX_IMP_ACID_S);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oTarget);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT,eVis,oTarget);
|
|
if (!GetIsImmune(oTarget,IMMUNITY_TYPE_PARALYSIS) )
|
|
{
|
|
if (DoCubeParalyze(oTarget,oSource,16))
|
|
{
|
|
FloatingTextStrRefOnCreature(84609,oTarget);
|
|
}
|
|
}
|
|
|
|
} else
|
|
{
|
|
effect eSave = EffectVisualEffect(VFX_IMP_REFLEX_SAVE_THROW_USE);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT,eSave,oTarget);
|
|
}
|
|
|
|
|
|
}
|
|
// --------------------------------------------------------------------------------
|
|
// Georg Zoeller, 2003-09-19
|
|
// Save DC against Epic Spells is the relevant ability score of the caster
|
|
// + 20. The hightest ability score of the casting relevants is 99.99% identical
|
|
// with the one that is used for casting, so we just take it.
|
|
// if used by a placeable, it is equal to the placeables WILL save field.
|
|
// --------------------------------------------------------------------------------
|
|
int GetEpicSpellSaveDC(object oCaster)
|
|
{
|
|
|
|
// * Placeables use their WILL Save field as caster level
|
|
if (GetObjectType(oCaster) == OBJECT_TYPE_PLACEABLE)
|
|
{
|
|
return GetWillSavingThrow(oCaster);
|
|
}
|
|
|
|
int nWis = GetAbilityModifier(ABILITY_WISDOM,oCaster);
|
|
int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE,oCaster);
|
|
int nCha = GetAbilityModifier(ABILITY_CHARISMA,oCaster);
|
|
|
|
int nHigh = nWis;
|
|
if (nHigh < nInt)
|
|
{
|
|
nHigh = nInt;
|
|
}
|
|
if (nHigh < nCha)
|
|
{
|
|
nHigh = nCha;
|
|
}
|
|
int nRet = 20 + nHigh;
|
|
return nRet;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// GZ: Sept 2003
|
|
// Determines the optimal behavior against AoESpell nSpellId for a NPC
|
|
// use in OnSpellCastAt
|
|
// --------------------------------------------------------------------------------
|
|
int GetBestAOEBehavior(int nSpellID)
|
|
{
|
|
if (nSpellID == SPELL_GREASE)
|
|
{
|
|
if (spellsIsFlying(OBJECT_SELF))
|
|
return X2_SPELL_AOEBEHAVIOR_IGNORE;
|
|
}
|
|
|
|
if (GetHasSpell(SPELL_GUST_OF_WIND) == TRUE)
|
|
return X2_SPELL_AOEBEHAVIOR_GUST;
|
|
|
|
if (GetModuleSwitchValue(MODULE_SWITCH_DISABLE_AI_DISPEL_AOE) == 0 )
|
|
{
|
|
if (d100() > GetLocalInt(GetModule(),MODULE_VAR_AI_NO_DISPEL_AOE_CHANCE))
|
|
{
|
|
if (GetHasSpell(SPELL_LESSER_DISPEL) == TRUE)
|
|
return X2_SPELL_AOEBEHAVIOR_DISPEL_L;
|
|
if (GetHasSpell(SPELL_DISPEL_MAGIC) == TRUE)
|
|
return X2_SPELL_AOEBEHAVIOR_DISPEL_N;
|
|
if (GetHasSpell(SPELL_GREATER_DISPELLING) == TRUE)
|
|
return X2_SPELL_AOEBEHAVIOR_DISPEL_G;
|
|
if (GetHasSpell(SPELL_MORDENKAINENS_DISJUNCTION) == TRUE)
|
|
return X2_SPELL_AOEBEHAVIOR_DISPEL_M;
|
|
}
|
|
}
|
|
|
|
return X2_SPELL_AOEBEHAVIOR_FLEE;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GZ: 2003-Oct-15
|
|
// Removes all effects from nID without paying attention to the caster as
|
|
// the spell can from only one caster anyway
|
|
// By default, it will only cancel magical effects
|
|
//--------------------------------------------------------------------------
|
|
void GZRemoveSpellEffects(int nID,object oTarget, int bMagicalEffectsOnly = TRUE)
|
|
{
|
|
effect eEff = GetFirstEffect(oTarget);
|
|
while (GetIsEffectValid(eEff))
|
|
{
|
|
if (GetEffectSpellId(eEff) == nID)
|
|
{
|
|
if (GetEffectSubType(eEff) != SUBTYPE_MAGICAL && bMagicalEffectsOnly)
|
|
{
|
|
// ignore
|
|
}
|
|
else
|
|
{
|
|
RemoveEffect(oTarget,eEff);
|
|
}
|
|
}
|
|
eEff = GetNextEffect(oTarget);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// GZ: 2003-Oct-15
|
|
// A different approach for timing these spells that has the positive side
|
|
// effects of making the spell dispellable as well.
|
|
// I am using the VFX applied by the spell to track the remaining duration
|
|
// instead of adding the remaining runtime on the stack
|
|
//
|
|
// This function returns FALSE if a delayed Spell effect from nSpell_ID has
|
|
// expired. See x2_s0_bigby4.nss for details
|
|
//------------------------------------------------------------------------------
|
|
int GZGetDelayedSpellEffectsExpired(int nSpell_ID, object oTarget, object oCaster)
|
|
{
|
|
|
|
if (!GetHasSpellEffect(nSpell_ID,oTarget) )
|
|
{
|
|
DeleteLocalInt(oTarget,"XP2_L_SPELL_SAVE_DC_" + IntToString (nSpell_ID));
|
|
return TRUE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GZ: 2003-Oct-15
|
|
// If the caster is dead or no longer there, cancel the spell, as it is
|
|
// directed
|
|
//--------------------------------------------------------------------------
|
|
if( !GetIsObjectValid(oCaster))
|
|
{
|
|
GZRemoveSpellEffects(nSpell_ID, oTarget);
|
|
DeleteLocalInt(oTarget,"XP2_L_SPELL_SAVE_DC_" + IntToString (nSpell_ID));
|
|
return TRUE;
|
|
}
|
|
|
|
if (GetIsDead(oCaster))
|
|
{
|
|
DeleteLocalInt(oTarget,"XP2_L_SPELL_SAVE_DC_" + IntToString (nSpell_ID));
|
|
GZRemoveSpellEffects(nSpell_ID, oTarget);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|