Amon_PRC8/_removed/x2_i0_spells.nss
Jaysyn904 c5cffc37af Initial Commit
Initial Commit [v1.01]
2025-04-03 19:00:46 -04:00

635 lines
24 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);
// * Checks the character for the thundering rage feat and will apply temporary massive critical
// * to the worn weapons
// * Checks and runs Rerrifying Rage feat
void CheckAndApplyEpicRageFeats(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,DAMAGE_TYPE_SLASHING);
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
// 1.70: made the function custom content weapons compatible
//------------------------------------------------------------------------------
int GetSlashingWeapon(object oItem)
{
int nBaseItem = GetBaseItemType(oItem);
if(nBaseItem == BASE_ITEM_INVALID)
return FALSE;
switch(StringToInt(Get2DAString("baseitems","WeaponType",nBaseItem)))
{
case 3://slashing
case 4://slashing+piercing
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
// 1.70: made the function custom content weapons compatible
//------------------------------------------------------------------------------
int GetMeleeWeapon(object oItem)
{
int nBaseItem = GetBaseItemType(oItem);
if(nBaseItem == BASE_ITEM_INVALID || GetWeaponRanged(oItem))
return FALSE;
return StringToInt(Get2DAString("baseitems","WeaponType",nBaseItem)) > 0;
}
//------------------------------------------------------------------------------
// AN, 2003
// Returns TRUE if oItem has any item property that classifies it as magical item
// 1.70: negative item properties, thieves tool and trap are not considered
// anymore and added arcane spell failure and bonus spell slots into consideration
//------------------------------------------------------------------------------
int GetIsMagicalItem(object oItem)
{
itemproperty ip = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ip))
{
switch(GetItemPropertyType(ip))
{
case ITEM_PROPERTY_ABILITY_BONUS:
case ITEM_PROPERTY_AC_BONUS:
case ITEM_PROPERTY_AC_BONUS_VS_ALIGNMENT_GROUP:
case ITEM_PROPERTY_AC_BONUS_VS_DAMAGE_TYPE:
case ITEM_PROPERTY_AC_BONUS_VS_RACIAL_GROUP:
case ITEM_PROPERTY_AC_BONUS_VS_SPECIFIC_ALIGNMENT:
case ITEM_PROPERTY_ATTACK_BONUS:
case ITEM_PROPERTY_ATTACK_BONUS_VS_ALIGNMENT_GROUP:
case ITEM_PROPERTY_ATTACK_BONUS_VS_RACIAL_GROUP:
case ITEM_PROPERTY_ATTACK_BONUS_VS_SPECIFIC_ALIGNMENT:
case ITEM_PROPERTY_BASE_ITEM_WEIGHT_REDUCTION:
case ITEM_PROPERTY_BONUS_FEAT:
case ITEM_PROPERTY_CAST_SPELL:
case ITEM_PROPERTY_DAMAGE_BONUS:
case ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP:
case ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP:
case ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT:
case ITEM_PROPERTY_DAMAGE_REDUCTION:
case ITEM_PROPERTY_DAMAGE_RESISTANCE:
case ITEM_PROPERTY_DAMAGE_VULNERABILITY:
case ITEM_PROPERTY_DARKVISION:
// case ITEM_PROPERTY_DECREASED_ABILITY_SCORE:
// case ITEM_PROPERTY_DECREASED_AC:
// case ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER:
// case ITEM_PROPERTY_DECREASED_DAMAGE:
// case ITEM_PROPERTY_DECREASED_ENHANCEMENT_MODIFIER:
// case ITEM_PROPERTY_DECREASED_SAVING_THROWS:
// case ITEM_PROPERTY_DECREASED_SAVING_THROWS_SPECIFIC:
// case ITEM_PROPERTY_DECREASED_SKILL_MODIFIER:
case ITEM_PROPERTY_ENHANCED_CONTAINER_REDUCED_WEIGHT:
case ITEM_PROPERTY_ENHANCEMENT_BONUS:
case ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_ALIGNMENT_GROUP:
case ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_RACIAL_GROUP:
case ITEM_PROPERTY_ENHANCEMENT_BONUS_VS_SPECIFIC_ALIGNEMENT:
case ITEM_PROPERTY_EXTRA_MELEE_DAMAGE_TYPE:
case ITEM_PROPERTY_EXTRA_RANGED_DAMAGE_TYPE:
case ITEM_PROPERTY_FREEDOM_OF_MOVEMENT:
case ITEM_PROPERTY_HASTE:
case ITEM_PROPERTY_HOLY_AVENGER:
case ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE:
case ITEM_PROPERTY_IMMUNITY_MISCELLANEOUS:
case ITEM_PROPERTY_IMMUNITY_SPECIFIC_SPELL:
case ITEM_PROPERTY_IMMUNITY_SPELL_SCHOOL:
case ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL:
case ITEM_PROPERTY_IMPROVED_EVASION:
case ITEM_PROPERTY_KEEN:
case ITEM_PROPERTY_LIGHT:
case ITEM_PROPERTY_MASSIVE_CRITICALS:
case ITEM_PROPERTY_MIGHTY:
case ITEM_PROPERTY_MIND_BLANK://never implemented itemproperty, but nvm
case ITEM_PROPERTY_MONSTER_DAMAGE:
// case ITEM_PROPERTY_NO_DAMAGE:
case ITEM_PROPERTY_ON_HIT_PROPERTIES:
case ITEM_PROPERTY_ON_MONSTER_HIT:
case ITEM_PROPERTY_POISON://never implemented itemproperty, but nvm
case ITEM_PROPERTY_REGENERATION:
case ITEM_PROPERTY_REGENERATION_VAMPIRIC:
case ITEM_PROPERTY_SAVING_THROW_BONUS:
case ITEM_PROPERTY_SAVING_THROW_BONUS_SPECIFIC:
case ITEM_PROPERTY_SKILL_BONUS:
case ITEM_PROPERTY_SPELL_RESISTANCE:
// case ITEM_PROPERTY_THIEVES_TOOLS:
// case ITEM_PROPERTY_TRAP:
case ITEM_PROPERTY_TRUE_SEEING:
case ITEM_PROPERTY_TURN_RESISTANCE:
case ITEM_PROPERTY_UNLIMITED_AMMUNITION:
case ITEM_PROPERTY_ONHITCASTSPELL:
case ITEM_PROPERTY_ARCANE_SPELL_FAILURE:
case ITEM_PROPERTY_BONUS_SPELL_SLOT_OF_LEVEL_N:
return TRUE;
}
ip = GetNextItemProperty(oItem);
}
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);
}
//------------------------------------------------------------------------------
// Patch 1.70:
// -both additional functions were deleted and put into this one
// -thundering rage try to apply bonuses to creature weapons, if barbarian doesn't have weapons
// and if he haven't got even creature one, then this feat add deafness onhit to gloves (if exists)
//------------------------------------------------------------------------------
void CheckAndApplyEpicRageFeats(int nRounds)
{
object oBarbarian = OBJECT_SELF;
float fDuration = RoundsToSeconds(nRounds);
if(GetHasFeat(FEAT_EPIC_TERRIFYING_RAGE,oBarbarian))//if barbarian has terrifying rage
{
effect eAOE = EffectAreaOfEffect(AOE_MOB_FEAR,"x2_s2_terrage_A","","");
ApplyEffectToObject(DURATION_TYPE_TEMPORARY,ExtraordinaryEffect(eAOE),oBarbarian,fDuration);//apply fear aura
}//end of terrifying rage
if(!GetHasFeat(FEAT_EPIC_THUNDERING_RAGE,oBarbarian))//if player don't have thundering rage,
{ //this function ends
return;
}
//declare variables, because they will be used multiple times
itemproperty critical = ItemPropertyMassiveCritical(IP_CONST_DAMAGEBONUS_2d6);
itemproperty vfx = ItemPropertyVisualEffect(ITEM_VISUAL_SONIC);
itemproperty onhit = ItemPropertyOnHitProps(IP_CONST_ONHIT_DEAFNESS,IP_CONST_ONHIT_SAVEDC_20,IP_CONST_ONHIT_DURATION_25_PERCENT_3_ROUNDS);
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oBarbarian);
if(GetIsObjectValid(oWeapon))//barbarian has weapon
{
IPSafeAddItemProperty(oWeapon,critical,fDuration,X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE,TRUE);
IPSafeAddItemProperty(oWeapon,vfx,fDuration,X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
IPSafeAddItemProperty(oWeapon,onhit,fDuration,X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oBarbarian);
if(GetIsObjectValid(oWeapon))//barbarian has two weapons
{
IPSafeAddItemProperty(oWeapon,critical,fDuration,X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE,TRUE);
IPSafeAddItemProperty(oWeapon,vfx,fDuration,X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
//no onhit for left weapon - bioware decision, perhaps balanced issue?
}
}
else //no weapon!
{
int bCreature;
int nSlot=14;
for(nSlot;nSlot<17;nSlot++)
{
oWeapon = GetItemInSlot(nSlot,oBarbarian);//creature weapon
if(GetIsObjectValid(oWeapon))
{
bCreature = TRUE;
IPSafeAddItemProperty(oWeapon,critical,fDuration,X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE,TRUE);
IPSafeAddItemProperty(oWeapon,onhit,fDuration,X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
//no visual as it work only for non-creature weapons
}
}
if(!bCreature)//no creature's weapons! monk or brawler
{
oWeapon = GetItemInSlot(INVENTORY_SLOT_ARMS,oBarbarian);//gloves
if(GetIsObjectValid(oWeapon))
{
IPSafeAddItemProperty(oWeapon,onhit,fDuration,X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
}
}
}
}
//------------------------------------------------------------------------------
//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(!bImmune && oTarget != OBJECT_SELF && spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE,OBJECT_SELF))
{
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 (!MySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_MIND_SPELLS, OBJECT_SELF, fDelay))
{ //saving throw VFX added
//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 = 16)
{
if (!MySavingThrow(SAVING_THROW_FORT, oTarget, nSaveDC, SAVING_THROW_TYPE_PARALYSE, oSource))
{
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;
}
return FALSE;
}
// --------------------------------------------------------------------------------
// GZ: Gel. Cube special abilities
// --------------------------------------------------------------------------------
void EngulfAndDamage(object oTarget, object oSource)
{
int nDC = 13 + GetHitDice(oSource) - 4;
if (!MySavingThrow(SAVING_THROW_REFLEX, oTarget, nDC, SAVING_THROW_TYPE_NONE, oSource))
{
FloatingTextStrRefOnCreature(84610,oTarget); // * Engulfed
int nDamage = d6(1);
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, oSource))
{
if (DoCubeParalyze(oTarget,oSource,16))
{
FloatingTextStrRefOnCreature(84609,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
// 1.70: made the function more elaborated with more cases of ignore behavior
// --------------------------------------------------------------------------------
int GetBestAOEBehavior(int nSpellID)
{
switch(nSpellID)
{
case SPELL_EVARDS_BLACK_TENTACLES:
if(GetCreatureSize(OBJECT_SELF) < CREATURE_SIZE_MEDIUM)
return X2_SPELL_AOEBEHAVIOR_IGNORE;
break;
case SPELL_GREASE:
if(GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_KNOCKDOWN) || GetHasFeat(FEAT_WOODLAND_STRIDE))
return X2_SPELL_AOEBEHAVIOR_IGNORE;
case SPELL_SPIKE_GROWTH:
if(spellsIsFlying(OBJECT_SELF) || GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL))
return X2_SPELL_AOEBEHAVIOR_IGNORE;
break;
case SPELL_ENTANGLE:
case SPELL_VINE_MINE_ENTANGLE:
case SPELL_WEB:
if(GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_ENTANGLE) || GetHasFeat(FEAT_WOODLAND_STRIDE) || GetCreatureFlag(OBJECT_SELF, CREATURE_VAR_IS_INCORPOREAL))
return X2_SPELL_AOEBEHAVIOR_IGNORE;
break;
case SPELL_STINKING_CLOUD:
if(GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_DAZED))
return X2_SPELL_AOEBEHAVIOR_IGNORE;
case SPELL_STONEHOLD:
if(nSpellID == SPELL_STONEHOLD && GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_PARALYSIS))
return X2_SPELL_AOEBEHAVIOR_IGNORE;
case SPELL_MIND_FOG:
if(GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_MIND_SPELLS))
return X2_SPELL_AOEBEHAVIOR_IGNORE;
case SPELL_CLOUD_OF_BEWILDERMENT:
if(nSpellID == SPELL_CLOUD_OF_BEWILDERMENT && (GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_POISON) || (GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_BLINDNESS) && (GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_MIND_SPELLS) || GetIsImmune(OBJECT_SELF,IMMUNITY_TYPE_STUN)))))
return X2_SPELL_AOEBEHAVIOR_IGNORE;
case SPELL_CLOUDKILL:
case SPELL_CREEPING_DOOM:
case SPELL_INCENDIARY_CLOUD:
case SPELL_ACID_FOG:
if(GetHasSpell(SPELL_GUST_OF_WIND))
return X2_SPELL_AOEBEHAVIOR_GUST;
break;
}
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))
return X2_SPELL_AOEBEHAVIOR_DISPEL_L;
if(GetHasSpell(SPELL_DISPEL_MAGIC))
return X2_SPELL_AOEBEHAVIOR_DISPEL_N;
if(GetHasSpell(SPELL_GREATER_DISPELLING))
return X2_SPELL_AOEBEHAVIOR_DISPEL_G;
if(GetHasSpell(SPELL_MORDENKAINENS_DISJUNCTION))
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;
}