1761 lines
64 KiB
Plaintext
1761 lines
64 KiB
Plaintext
//::///////////////////////////////////////////////
|
|
//:: x0_i0_spells
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Expansion 1 and above include file for spells
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Brent
|
|
//:: Created On: July 2002
|
|
//:: Updated On: August 2003, Georg Zoeller:
|
|
//:: Arcane Archer special ability fix,
|
|
//:: New creatures added to Flying/Petrification check
|
|
//:: Several Fixes toMDispelagic
|
|
//:: Added spellsGetHighestSpellcastingClassLevel
|
|
//:: Added code to spellsIsTarget to make NPCs hurt their allies with AoE spells if ModuleSwitch MODULE_SWITCH_ENABLE_NPC_AOE_HURT_ALLIES is set
|
|
//:: Creatures with Plot or DM Flag set will no longer be affected by petrify. DMs used to get a GUI panel, even if unaffected.
|
|
//:: Updated On: September 2003, Georg Zoeller:
|
|
//:: spellsIsTarget was not using oSource in source checks.
|
|
//:: Creatures with Plot or DM Flag set will no longer be affected by petrify. DMs used to get a GUI panel, even if unaffected.
|
|
//:: Updated On: October 2003, Georg Zoeller:
|
|
//:: Missile storm's no longer do a SR check for each missile, but only one per target
|
|
//:: ... and there was much rejoicing
|
|
//:: Added code to handleldispeling of AoE spells better
|
|
//:: Henchmen are booted from the party when petrified
|
|
//:: Dispel Magic delay until VFX hit has been set down to 0.3
|
|
//:://////////////////////////////////////////////
|
|
|
|
//:: modifications by mr_bumpkin on Dec 4, 2003
|
|
//:: changed all instances of GetSpellSaveDC to GetSpellSaveDC + GetChangesToSaveDC
|
|
//:: changed all instances of myResistSpell to myPRCResistSpell
|
|
|
|
//Added code into spellsInflictTouchAttack to maximize for Faith Healing and Blast Infidel
|
|
//Aaon Graywolf - Jan 6, 2003
|
|
|
|
//#include "NW_I0_SPELLS"
|
|
//#include "x0_i0_match"
|
|
#include "x2_inc_switches"
|
|
#include "x2_inc_itemprop"
|
|
#include "x0_i0_henchman"
|
|
|
|
//* get the hightest spellcasting class level of oCreature)
|
|
int GZGetHighestSpellcastingClassLevel(object oCreature);
|
|
|
|
// * dispel magic on one or multiple targets.
|
|
// * if bAll is set to TRUE, all effects are dispelled from a creature
|
|
// * else it will only dispel the best effect from each creature (used for AoE)
|
|
// * Specify bBreachSpells to add Mord's Disjunction to the dispel
|
|
void spellsDispelMagic(object oTarget, int nCasterLevel, effect eVis, effect eImpac, int bAll = TRUE, int bBreachSpells = FALSE);
|
|
|
|
// * returns true if oCreature does not have a mind
|
|
int spellsIsMindless(object oCreature);
|
|
|
|
// * Returns true or false depending on whether the creature is flying
|
|
// * or not
|
|
int spellsIsFlying(object oCreature);
|
|
|
|
// * returns true if the creature has flesh
|
|
int spellsIsImmuneToPetrification(object oCreature);
|
|
|
|
// * Generic apply area of effect Wrapper
|
|
// * lTargetLoc = where spell was targeted
|
|
// * fRadius = RADIUS_SIZE_ constant
|
|
// * nSpellID
|
|
// * eImpact = ring impact
|
|
// * eLink = Linked effects to apply to targets in area
|
|
// * eVis
|
|
void spellsGenericAreaOfEffect(
|
|
object oCaster, location lTargetLoc,
|
|
int nShape, float fRadiusSize, int nSpellID,
|
|
effect eImpact, effect eLink, effect eVis,
|
|
int nDurationType=DURATION_TYPE_INSTANT, float fDuration = 0.0,
|
|
int nTargetType=SPELL_TARGET_ALLALLIES, int bHarmful = FALSE,
|
|
int nRemoveEffectSpell=FALSE, int nRemoveEffect1=0, int nRemoveEffect2=0, int nRemoveEffect3=0,
|
|
int bLineOfSight=FALSE, int nObjectFilter=OBJECT_TYPE_CREATURE,
|
|
int bPersistentObject=FALSE, int bResistCheck=FALSE, int nSavingThrowType=SAVING_THROW_NONE,
|
|
int nSavingThrowSubType=SAVING_THROW_TYPE_ALL
|
|
);
|
|
|
|
// * how much should special archer arrows do for damage
|
|
int ArcaneArcherDamageDoneByBow(int bCrit = FALSE, object oUser = OBJECT_SELF);
|
|
|
|
// * simulating enchant arrow
|
|
int ArcaneArcherCalculateBonus();
|
|
|
|
// * returns the size modifier for bullrush in spells
|
|
int GetSizeModifier(object oCreature);
|
|
|
|
// * Returns the modifier from the ability score that matters for this caster
|
|
int GetCasterAbilityModifier(object oCaster);
|
|
|
|
// * Checks the appropriate metamagic to see
|
|
// * how the damage should be scaled.
|
|
int MaximizeOrEmpower(int nDice, int nNumberOfDice, int nMeta, int nBonus = 0);
|
|
|
|
// * can the creature be destroyed without breaking a plot
|
|
int CanCreatureBeDestroyed(object oTarget);
|
|
|
|
// * Does a stinking cloud. If oTarget is Invalid, then does area effect, otherwise
|
|
// * just attempts on otarget
|
|
void spellsStinkingCloud(object oTarget = OBJECT_INVALID);
|
|
|
|
// * caltrops do 25 points of damage (1 pnt per target per round) and then are gone
|
|
void DoCaltropEffect(object oTarget);
|
|
|
|
// * apply effects of spike trap on entering object
|
|
void DoTrapSpike(int nDamage);
|
|
|
|
//* fires a storm of nCap missiles at targets in area
|
|
void DoMissileStorm(int nD6Dice, int nCap, int nSpell, int nMIRV = VFX_IMP_MIRV, int nVIS = VFX_IMP_MAGBLUE, int nDAMAGETYPE = DAMAGE_TYPE_MAGICAL, int nONEHIT = FALSE, int nReflexSave = FALSE);
|
|
|
|
// * Applies ability score damage
|
|
void DoDirgeEffect(object oTarget,int nPenetr);
|
|
|
|
void spellsInflictTouchAttack(int nDamage, int nMaxExtraDamage, int nMaximized, int vfx_impactHurt, int vfx_impactHeal, int nSpellID,int ModCasterlevel = 0, int nDC = 0);
|
|
|
|
// * improves an animal companion or summoned creature's attack and damage and the ability to hit
|
|
// * magically protected creatures
|
|
void DoMagicFang(int nPower, int nDamagePower,int nCasterLevel);
|
|
|
|
// * for spike growth area of effect object
|
|
// * applies damage and slow effect
|
|
void DoSpikeGrowthEffect(object oTarget, int nPenetr);
|
|
|
|
// * Applies the 'camoflage' magical effect to the target
|
|
void DoCamoflage(object oTarget);
|
|
|
|
// * Does a damage type grenade (direct or splash on miss)
|
|
void DoGrenade(int nDirectDamage, int nSplashDamage, int vSmallHit, int vRingHit, int nDamageType, float fExplosionRadius , int nObjectFilter, int nRacialType=RACIAL_TYPE_ALL);
|
|
|
|
// * This is a wrapper for how Petrify will work in Expansion Pack 1
|
|
// * Scripts affected: flesh to stone, breath petrification, gaze petrification, touch petrification
|
|
// * nPower : This is the Hit Dice of a Monster using Gaze, Breath or Touch OR it is the Caster Spell of
|
|
// * a spellcaster
|
|
// * nFortSaveDC: pass in this number from the spell script
|
|
void DoPetrification(int nPower, object oSource, object oTarget, int nSpellID, int nFortSaveDC);
|
|
|
|
// * removed mind effects and provide mind protection
|
|
void spellApplyMindBlank(object oTarget, int nSpellId, float fDelay=0.0);
|
|
|
|
// * Handle dispel magic of AoEs
|
|
void spellsDispelAoE(object oTargetAoE, object oCaster, int nCasterLevel);
|
|
|
|
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: DoTrapSpike
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Does a spike trap. Reflex save allowed.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
// apply effects of spike trap on entering object
|
|
void DoTrapSpike(int nDamage)
|
|
{
|
|
//Declare major variables
|
|
object oTarget = GetEnteringObject();
|
|
|
|
int nRealDamage = PRCGetReflexAdjustedDamage(nDamage, oTarget, 15, SAVING_THROW_TYPE_TRAP, OBJECT_SELF);
|
|
if (nDamage > 0)
|
|
{
|
|
effect eDam = EffectDamage(nRealDamage, DAMAGE_TYPE_PIERCING);
|
|
effect eVis = EffectVisualEffect(253);
|
|
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, GetLocation(oTarget));
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
|
|
}
|
|
}
|
|
//::///////////////////////////////////////////////
|
|
//:: MaximizeOrEmpower
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Checks the appropriate metamagic to see
|
|
how the damage should be scaled.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Brent
|
|
//:: Created On: September 2002
|
|
//:://////////////////////////////////////////////
|
|
|
|
int MaximizeOrEmpower(int nDice, int nNumberOfDice, int nMeta, int nBonus = 0)
|
|
{
|
|
int i = 0;
|
|
int nDamage = 0;
|
|
for (i=1; i<=nNumberOfDice; i++)
|
|
{
|
|
nDamage = nDamage + Random(nDice) + 1;
|
|
}
|
|
//Resolve metamagic
|
|
if (nMeta == METAMAGIC_MAXIMIZE)
|
|
{
|
|
nDamage = nDice * nNumberOfDice;
|
|
}
|
|
else if (nMeta == METAMAGIC_EMPOWER)
|
|
{
|
|
nDamage = nDamage + nDamage / 2;
|
|
}
|
|
return nDamage + nBonus;
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: DoGrenade
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Does a damage type grenade (direct or splash on miss)
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
void DoGrenade(int nDirectDamage, int nSplashDamage, int vSmallHit, int vRingHit, int nDamageType, float fExplosionRadius , int nObjectFilter, int nRacialType=RACIAL_TYPE_ALL)
|
|
{
|
|
//Declare major variables ( fDist / (3.0f * log( fDist ) + 2.0f) )
|
|
object oTarget = GetSpellTargetObject();
|
|
int nCasterLvl = PRCGetCasterLevel(OBJECT_SELF);
|
|
int nDamage = 0;
|
|
int nMetaMagic = GetMetaMagicFeat();
|
|
int nCnt;
|
|
effect eMissile;
|
|
effect eVis = EffectVisualEffect(vSmallHit);
|
|
location lTarget = GetSpellTargetLocation();
|
|
|
|
|
|
float fDist = GetDistanceBetween(OBJECT_SELF, oTarget);
|
|
int nTouch;
|
|
|
|
|
|
if (GetIsObjectValid(oTarget) == TRUE)
|
|
{
|
|
/* // * BK September 27 2002
|
|
// * if the object is 'far' from the original impact it
|
|
// * will be an automatic miss too
|
|
location lObject = GetLocation(oTarget);
|
|
float fDistance = GetDistanceBetweenLocations(lTarget, lObject);
|
|
// SpawnScriptDebugger();
|
|
if (fDistance > 1.0)
|
|
{
|
|
nTouch = -1;
|
|
}
|
|
else
|
|
This did not work. The location and object location are the same.
|
|
For now we'll have to live with the possiblity of the 'explosion'
|
|
happening away from where the grenade hits.
|
|
We could convert everything to splash...
|
|
*/
|
|
nTouch = TouchAttackRanged(oTarget);
|
|
|
|
}
|
|
else
|
|
{
|
|
nTouch = -1; // * this means that target was the ground, so the user
|
|
// * intended to splash
|
|
}
|
|
if (nTouch >= 1)
|
|
{
|
|
//Roll damage
|
|
int nDam = nDirectDamage;
|
|
|
|
if(nTouch == 2)
|
|
{
|
|
nDam *= 2;
|
|
}
|
|
|
|
//Set damage effect
|
|
effect eDam = EffectDamage(nDam, nDamageType);
|
|
//Apply the MIRV and damage effect
|
|
|
|
// * only damage enemies
|
|
if(spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE,OBJECT_SELF) )
|
|
{
|
|
// * must be the correct racial type (only used with Holy Water)
|
|
if ((nRacialType != RACIAL_TYPE_ALL) && (nRacialType == MyPRCGetRacialType(oTarget)))
|
|
{
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
|
//ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget); VISUALS outrace the grenade, looks bad
|
|
}
|
|
else
|
|
if ((nRacialType == RACIAL_TYPE_ALL) )
|
|
{
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
|
//ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget); VISUALS outrace the grenade, looks bad
|
|
}
|
|
|
|
}
|
|
|
|
// ApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget);
|
|
}
|
|
|
|
// *
|
|
// * Splash damage always happens as well now
|
|
// *
|
|
{
|
|
effect eExplode = EffectVisualEffect(vRingHit);
|
|
//Apply the fireball explosion at the location captured above.
|
|
|
|
/* float fFace = GetFacingFromLocation(lTarget);
|
|
vector vPos = GetPositionFromLocation(lTarget);
|
|
object oArea = GetAreaFromLocation(lTarget);
|
|
vPos.x = vPos.x - 1.0;
|
|
vPos.y = vPos.y - 1.0;
|
|
lTarget = Location(oArea, vPos, fFace);
|
|
missing code looks bad because it does not jive with visual
|
|
*/
|
|
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eExplode, lTarget);
|
|
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fExplosionRadius, lTarget, TRUE, nObjectFilter);
|
|
//Cycle through the targets within the spell shape until an invalid object is captured.
|
|
while (GetIsObjectValid(oTarget))
|
|
{
|
|
if(spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE,OBJECT_SELF) )
|
|
{
|
|
float fDelay = GetDistanceBetweenLocations(lTarget, GetLocation(oTarget))/20;
|
|
//Roll damage for each target
|
|
nDamage = nSplashDamage;
|
|
|
|
//Set the damage effect
|
|
effect eDam = EffectDamage(nDamage, nDamageType);
|
|
if(nDamage > 0)
|
|
{
|
|
// * must be the correct racial type (only used with Holy Water)
|
|
if ((nRacialType != RACIAL_TYPE_ALL) && (nRacialType == MyPRCGetRacialType(oTarget)))
|
|
{
|
|
// Apply effects to the currently selected target.
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
|
//This visual effect is applied to the target object not the location as above. This visual effect
|
|
//represents the flame that erupts on the target not on the ground.
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
|
|
}
|
|
else
|
|
if ((nRacialType == RACIAL_TYPE_ALL) )
|
|
{
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
|
|
}
|
|
|
|
}
|
|
}
|
|
//Select the next target within the spell shape.
|
|
oTarget = GetNextObjectInShape(SHAPE_SPHERE, fExplosionRadius, lTarget, TRUE, nObjectFilter);
|
|
}
|
|
}
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: GetCasterAbilityModifier
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Returns the modifier from the ability
|
|
score that matters for this caster
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
int GetCasterAbilityModifier(object oCaster)
|
|
{
|
|
int nClass = GetLevelByClass(CLASS_TYPE_WIZARD, oCaster);
|
|
int nAbility;
|
|
if (nClass > 0)
|
|
{
|
|
nAbility = ABILITY_INTELLIGENCE;
|
|
}
|
|
else
|
|
nAbility = ABILITY_CHARISMA;
|
|
|
|
return GetAbilityModifier(nAbility, oCaster);
|
|
}
|
|
//::///////////////////////////////////////////////
|
|
//:: GetSizeModifier
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Gets the creature's applicable size modifier.
|
|
Used in Bigby's Forceful hand for the 'bullrush'
|
|
attack.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
int GetSizeModifier(object oCreature)
|
|
{
|
|
int nSize = GetCreatureSize(oCreature);
|
|
int nModifier = 0;
|
|
switch (nSize)
|
|
{
|
|
case CREATURE_SIZE_TINY: nModifier = -8; break;
|
|
case CREATURE_SIZE_SMALL: nModifier = -4; break;
|
|
case CREATURE_SIZE_MEDIUM: nModifier = 0; break;
|
|
case CREATURE_SIZE_LARGE: nModifier = 4; break;
|
|
case CREATURE_SIZE_HUGE: nModifier = 8; break;
|
|
}
|
|
return nModifier;
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//::
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Applies the ability score damage of the dirge effect.
|
|
|
|
March 2003
|
|
Because ability score penalties do not stack, I need
|
|
to store the ability score damage done
|
|
and increment each round.
|
|
To that effect I am going to update the description and
|
|
remove the dirge effects if the player leaves the area of effect.
|
|
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
void DoDirgeEffect(object oTarget,int nPenetr)
|
|
{ //Declare major variables
|
|
// int nMetaMagic = GetMetaMagicFeat();
|
|
|
|
// SpawnScriptDebugger();
|
|
|
|
if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, GetAreaOfEffectCreator()))
|
|
{
|
|
//Fire cast spell at event for the target
|
|
SignalEvent(oTarget, EventSpellCastAt(GetAreaOfEffectCreator(), GetSpellId()));
|
|
//Spell resistance check
|
|
if(!MyPRCResistSpell(GetAreaOfEffectCreator(), oTarget,nPenetr))
|
|
{
|
|
|
|
//Make a Fortitude Save to avoid the effects of the movement hit.
|
|
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, (GetSpellSaveDC() + GetChangesToSaveDC(oTarget,GetAreaOfEffectCreator())), SAVING_THROW_ALL, GetAreaOfEffectCreator()))
|
|
{
|
|
int nGetLastPenalty = GetLocalInt(oTarget, "X0_L_LASTPENALTY");
|
|
// * increase penalty by 2
|
|
nGetLastPenalty = nGetLastPenalty + 2;
|
|
|
|
effect eStr = EffectAbilityDecrease(ABILITY_STRENGTH, nGetLastPenalty);
|
|
effect eDex = EffectAbilityDecrease(ABILITY_DEXTERITY, nGetLastPenalty);
|
|
//change from sonic effect to bard song...
|
|
effect eVis = EffectVisualEffect(VFX_FNF_SOUND_BURST);
|
|
effect eLink = EffectLinkEffects(eDex, eStr);
|
|
|
|
//Apply damage and visuals
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oTarget);
|
|
SetLocalInt(oTarget, "X0_L_LASTPENALTY", nGetLastPenalty);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
//::///////////////////////////////////////////////
|
|
//:: DoCamoflage
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Applies the 'camoflage' magical effect
|
|
to the target
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
void DoCamoflage(object oTarget)
|
|
{
|
|
//Declare major variables
|
|
effect eVis = EffectVisualEffect(VFX_IMP_IMPROVE_ABILITY_SCORE);
|
|
int nMetaMagic = GetMetaMagicFeat();
|
|
|
|
effect eHide = EffectSkillIncrease(SKILL_HIDE, 10);
|
|
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
|
|
effect eLink = EffectLinkEffects(eHide, eDur);
|
|
|
|
int nDuration = PRCGetCasterLevel(OBJECT_SELF); // * Duration 1 turn/level
|
|
if (nMetaMagic == METAMAGIC_EXTEND) //Duration is +100%
|
|
{
|
|
nDuration = nDuration * 2;
|
|
}
|
|
|
|
//Fire spell cast at event for target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, 421, FALSE));
|
|
//Apply VFX impact and bonus effects
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, TurnsToSeconds(nDuration));
|
|
}
|
|
//::///////////////////////////////////////////////
|
|
//:: DoSpikeGrowthEffect
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
1d4 damage, plus a 24 hr slow if take damage.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
void DoSpikeGrowthEffect(object oTarget,int nPenetr)
|
|
{
|
|
float fDelay = GetRandomDelay(1.0, 2.2);
|
|
if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, GetAreaOfEffectCreator()))
|
|
{
|
|
//Fire cast spell at event for the target
|
|
SignalEvent(oTarget, EventSpellCastAt(GetAreaOfEffectCreator(), 453));
|
|
//Spell resistance check
|
|
if(!MyPRCResistSpell(GetAreaOfEffectCreator(), oTarget,nPenetr, fDelay))
|
|
{
|
|
int nMetaMagic = GetMetaMagicFeat();
|
|
int nDam = MaximizeOrEmpower(4, 1, nMetaMagic);
|
|
|
|
effect eDam = EffectDamage(nDam, DAMAGE_TYPE_PIERCING);
|
|
effect eVis = EffectVisualEffect(VFX_IMP_ACID_S);
|
|
//effect eLink = eDam;
|
|
//Apply damage and visuals
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam/*eLink*/, oTarget));
|
|
|
|
// * only apply a slow effect from this spell once
|
|
if (GetHasSpellEffect(453, oTarget) == FALSE)
|
|
{
|
|
//Make a Reflex Save to avoid the effects of the movement hit.
|
|
if(!PRCMySavingThrow(SAVING_THROW_REFLEX, oTarget, (GetSpellSaveDC() + GetChangesToSaveDC(oTarget,GetAreaOfEffectCreator())), SAVING_THROW_ALL, GetAreaOfEffectCreator(), fDelay))
|
|
{
|
|
effect eSpeed = EffectMovementSpeedDecrease(30);
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eSpeed, oTarget, HoursToSeconds(24));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//::///////////////////////////////////////////////
|
|
//:: spellsInflictTouchAttack
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
nDamage: Amount of damage to do
|
|
nMaxExtraDamage: Max amount of +1 per level damage
|
|
nMaximized: Amount of damage to do if maximized
|
|
vfx_impactHurt: Impact to play if hurt by spell
|
|
vfx_impactHeal: Impact to play if healed by spell
|
|
nSpellID: SpellID to broactcast in the signal event
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
void spellsInflictTouchAttack(int nDamage, int nMaxExtraDamage, int nMaximized, int vfx_impactHurt, int vfx_impactHeal, int nSpellID,int ModCasterlevel = 0 , int nDC = 0)
|
|
{
|
|
//Declare major variables
|
|
object oTarget = GetSpellTargetObject();
|
|
int nMetaMagic = GetMetaMagicFeat();
|
|
int nTouch = TouchAttackMelee(oTarget);
|
|
|
|
int CasterLvl;
|
|
if ( ModCasterlevel == 0)
|
|
CasterLvl = PRCGetCasterLevel(OBJECT_SELF);
|
|
else
|
|
CasterLvl = ModCasterlevel;
|
|
|
|
int nExtraDamage = CasterLvl; // * figure out the bonus damage
|
|
if (nExtraDamage > nMaxExtraDamage)
|
|
{
|
|
nExtraDamage = nMaxExtraDamage;
|
|
}
|
|
|
|
CasterLvl +=SPGetPenetr();
|
|
|
|
|
|
//Check for metamagic
|
|
int iBlastFaith = BlastInfidelOrFaithHeal(OBJECT_SELF, oTarget, DAMAGE_TYPE_NEGATIVE, TRUE);
|
|
if (nMetaMagic == METAMAGIC_MAXIMIZE || iBlastFaith)
|
|
{
|
|
nDamage = nMaximized;
|
|
}
|
|
else
|
|
if (nMetaMagic == METAMAGIC_EMPOWER)
|
|
{
|
|
nDamage = nDamage + (nDamage / 2);
|
|
}
|
|
|
|
|
|
//Check that the target is undead
|
|
if (MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
|
|
{
|
|
effect eVis2 = EffectVisualEffect(vfx_impactHeal);
|
|
//Figure out the amount of damage to heal
|
|
//nHeal = nDamage;
|
|
//Set the heal effect
|
|
effect eHeal = EffectHeal(nDamage + nExtraDamage);
|
|
//Apply heal effect and VFX impact
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis2, oTarget);
|
|
//Fire cast spell at event for the specified target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpellID, FALSE));
|
|
}
|
|
else if (nTouch >0 )
|
|
{
|
|
if(!GetIsReactionTypeFriendly(oTarget))
|
|
{
|
|
//Fire cast spell at event for the specified target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpellID));
|
|
if (!MyPRCResistSpell(OBJECT_SELF, oTarget,CasterLvl))
|
|
{
|
|
int nDamageTotal = nDamage + nExtraDamage;
|
|
// A succesful will save halves the damage
|
|
if (nDC == 0) nDC = GetSpellSaveDC() ;
|
|
if(PRCMySavingThrow(SAVING_THROW_WILL, oTarget, (nDC + GetChangesToSaveDC(oTarget,OBJECT_SELF)), SAVING_THROW_ALL,OBJECT_SELF))
|
|
{
|
|
nDamageTotal = nDamageTotal / 2;
|
|
}
|
|
effect eVis = EffectVisualEffect(vfx_impactHurt);
|
|
effect eDam = EffectDamage(nDamageTotal,DAMAGE_TYPE_NEGATIVE);
|
|
//Apply the VFX impact and effects
|
|
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: DoMissileStorm
|
|
//:: Copyright (c) 2002 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Fires a volley of missiles around the area
|
|
of the object selected.
|
|
|
|
Each missiles (nD6Dice)d6 damage.
|
|
There are casterlevel missiles (to a cap as specified)
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Brent
|
|
//:: Created On: July 31, 2002
|
|
//:://////////////////////////////////////////////
|
|
//:: Modified March 14 2003: Removed the option to hurt chests/doors
|
|
//:: was potentially causing bugs when no creature targets available.
|
|
void DoMissileStorm(int nD6Dice, int nCap, int nSpell, int nMIRV = VFX_IMP_MIRV, int nVIS = VFX_IMP_MAGBLUE, int nDAMAGETYPE = DAMAGE_TYPE_MAGICAL, int nONEHIT = FALSE, int nReflexSave = FALSE)
|
|
{
|
|
object oTarget = OBJECT_INVALID;
|
|
int nCasterLvl = PRCGetCasterLevel(OBJECT_SELF);
|
|
// int nDamage = 0;
|
|
int nMetaMagic = GetMetaMagicFeat();
|
|
int nCnt = 1;
|
|
effect eMissile = EffectVisualEffect(nMIRV);
|
|
effect eVis = EffectVisualEffect(nVIS);
|
|
float fDist = 0.0;
|
|
float fDelay = 0.0;
|
|
float fDelay2, fTime;
|
|
location lTarget = GetSpellTargetLocation(); // missile spread centered around caster
|
|
int nMissiles = nCasterLvl;
|
|
|
|
nCasterLvl +=SPGetPenetr();
|
|
|
|
if (nMissiles > nCap)
|
|
{
|
|
nMissiles = nCap;
|
|
}
|
|
|
|
/* New Algorithm
|
|
1. Count # of targets
|
|
2. Determine number of missiles
|
|
3. First target gets a missile and all Excess missiles
|
|
4. Rest of targets (max nMissiles) get one missile
|
|
*/
|
|
int nEnemies = 0;
|
|
|
|
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
//Cycle through the targets within the spell shape until an invalid object is captured.
|
|
while (GetIsObjectValid(oTarget) )
|
|
{
|
|
// * caster cannot be harmed by this spell
|
|
if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, OBJECT_SELF) && (oTarget != OBJECT_SELF))
|
|
{
|
|
// GZ: You can only fire missiles on visible targets
|
|
if (GetObjectSeen(oTarget,OBJECT_SELF))
|
|
{
|
|
nEnemies++;
|
|
}
|
|
}
|
|
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
}
|
|
|
|
if (nEnemies == 0) return; // * Exit if no enemies to hit
|
|
int nExtraMissiles = nMissiles / nEnemies;
|
|
|
|
// April 2003
|
|
// * if more enemies than missiles, need to make sure that at least
|
|
// * one missile will hit each of the enemies
|
|
if (nExtraMissiles <= 0)
|
|
{
|
|
nExtraMissiles = 1;
|
|
}
|
|
|
|
// by default the Remainder will be 0 (if more than enough enemies for all the missiles)
|
|
int nRemainder = 0;
|
|
|
|
if (nExtraMissiles >0)
|
|
nRemainder = nMissiles % nEnemies;
|
|
|
|
if (nEnemies > nMissiles)
|
|
nEnemies = nMissiles;
|
|
|
|
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
//Cycle through the targets within the spell shape until an invalid object is captured.
|
|
while (GetIsObjectValid(oTarget) && nCnt <= nEnemies)
|
|
{
|
|
// * caster cannot be harmed by this spell
|
|
if (spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, OBJECT_SELF) && (oTarget != OBJECT_SELF) && (GetObjectSeen(oTarget,OBJECT_SELF)))
|
|
{
|
|
//Fire cast spell at event for the specified target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpell));
|
|
|
|
// * recalculate appropriate distances
|
|
fDist = GetDistanceBetween(OBJECT_SELF, oTarget);
|
|
fDelay = fDist/(3.0 * log(fDist) + 2.0);
|
|
|
|
// Firebrand.
|
|
// It means that once the target has taken damage this round from the
|
|
// spell it won't take subsequent damage
|
|
if (nONEHIT == TRUE)
|
|
{
|
|
nExtraMissiles = 1;
|
|
nRemainder = 0;
|
|
}
|
|
|
|
int i = 0;
|
|
//--------------------------------------------------------------
|
|
// GZ: Moved SR check out of loop to have 1 check per target
|
|
// not one check per missile, which would rip spell mantels
|
|
// apart
|
|
//--------------------------------------------------------------
|
|
if (!MyPRCResistSpell(OBJECT_SELF, oTarget,nCasterLvl, fDelay))
|
|
{
|
|
for (i=1; i <= nExtraMissiles + nRemainder; i++)
|
|
{
|
|
//Roll damage
|
|
int nDam = d6(nD6Dice);
|
|
//Enter Metamagic conditions
|
|
if (nMetaMagic == METAMAGIC_MAXIMIZE)
|
|
{
|
|
nDam = nD6Dice*6;//Damage is at max
|
|
}
|
|
if (nMetaMagic == METAMAGIC_EMPOWER)
|
|
{
|
|
nDam = nDam + nDam/2; //Damage/Healing is +50%
|
|
}
|
|
// Jan. 29, 2004 - Jonathan Epp
|
|
// Reflex save was not being calculated for Firebrand
|
|
if(nReflexSave)
|
|
{
|
|
nDam = GetReflexAdjustedDamage(nDam, oTarget, GetSpellSaveDC(), SAVING_THROW_TYPE_FIRE);
|
|
}
|
|
|
|
fTime = fDelay;
|
|
fDelay2 += 0.1;
|
|
fTime += fDelay2;
|
|
|
|
//Set damage effect
|
|
effect eDam = EffectDamage(nDam, nDAMAGETYPE);
|
|
//Apply the MIRV and damage effect
|
|
DelayCommand(fTime, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget));
|
|
DelayCommand(fDelay2, ApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget));
|
|
DelayCommand(fTime, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
|
}
|
|
} // for
|
|
else
|
|
{ // * apply a dummy visual effect
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget);
|
|
}
|
|
nCnt++;// * increment count of missiles fired
|
|
nRemainder = 0;
|
|
}
|
|
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|
}
|
|
|
|
}
|
|
//::///////////////////////////////////////////////
|
|
//:: DoMagicFang
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
+1 enhancement bonus to attack and damage rolls.
|
|
Also applys damage reduction +1; this allows the creature
|
|
to strike creatures with +1 damage reduction.
|
|
|
|
Checks to see if a valid summoned monster or animal companion
|
|
exists to apply the effects to. If none exists, then
|
|
the spell is wasted.
|
|
|
|
FEB 19: Made it so only Animal Companions get these bonuses
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
void DoMagicFang(int nPower, int nDamagePower,int nCasterLevel)
|
|
{
|
|
|
|
|
|
//Declare major variables
|
|
object oTarget = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION);
|
|
|
|
if (GetIsObjectValid(oTarget) == FALSE)
|
|
{
|
|
FloatingTextStrRefOnCreature(8962, OBJECT_SELF, FALSE);
|
|
return; // has neither an animal companion
|
|
}
|
|
|
|
//Remove effects of anyother fang spells
|
|
RemoveSpellEffects(452, GetMaster(oTarget), oTarget);
|
|
RemoveSpellEffects(453, GetMaster(oTarget), oTarget);
|
|
|
|
effect eVis = EffectVisualEffect(VFX_IMP_HOLY_AID);
|
|
int nMetaMagic = GetMetaMagicFeat();
|
|
|
|
effect eAttack = EffectAttackIncrease(nPower);
|
|
effect eDamage = EffectDamageIncrease(nPower);
|
|
effect eReduction = EffectDamageReduction(nPower, nDamagePower); // * doing this because
|
|
// * it creates a true
|
|
// * enhancement bonus
|
|
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
|
|
effect eLink = EffectLinkEffects(eAttack, eDur);
|
|
eLink = EffectLinkEffects(eLink, eDamage);
|
|
eLink = EffectLinkEffects(eLink, eReduction);
|
|
|
|
int nDuration = nCasterLevel; // * Duration 1 turn/level
|
|
if (nMetaMagic == METAMAGIC_EXTEND) //Duration is +100%
|
|
{
|
|
nDuration = nDuration * 2;
|
|
}
|
|
|
|
//Fire spell cast at event for target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId(), FALSE));
|
|
//Apply VFX impact and bonus effects
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, TurnsToSeconds(nDuration));
|
|
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: DoCaltropEffect
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
The area effect will only do a total of
|
|
25 points of damage and then destroy itself.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
void DoCaltropEffect(object oTarget)
|
|
{
|
|
|
|
//int nDam = 1;
|
|
|
|
// effect eVis = EffectVisualEffect(VFX_IMP_SPIKE_TRAP);
|
|
//effect eLink = eDam;
|
|
|
|
if(spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE, GetAreaOfEffectCreator())
|
|
&& spellsIsFlying(oTarget) == FALSE)
|
|
{
|
|
//Fire cast spell at event for the target
|
|
SignalEvent(oTarget, EventSpellCastAt(GetAreaOfEffectCreator(), 471));
|
|
{
|
|
effect eDam = EffectDamage(1, DAMAGE_TYPE_PIERCING);
|
|
float fDelay = GetRandomDelay(1.0, 2.2);
|
|
//Apply damage and visuals
|
|
//DelayCommand(fDelay, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, GetLocation(oTarget)));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
|
int nDamageDone = GetLocalInt(OBJECT_SELF, "NW_L_TOTAL_DAMAGE");
|
|
nDamageDone++;
|
|
|
|
// * storing variable on area of effect object
|
|
SetLocalInt(OBJECT_SELF, "NW_L_TOTAL_DAMAGE", nDamageDone);
|
|
if (nDamageDone == 25)
|
|
{
|
|
DestroyObject(OBJECT_SELF);
|
|
object oImpactNode = GetLocalObject(OBJECT_SELF, "X0_L_IMPACT");
|
|
if (GetIsObjectValid(oImpactNode) == TRUE)
|
|
{
|
|
DestroyObject(oImpactNode);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: CanCreatureBeDestroyed
|
|
//:: Copyright (c) 2003 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Returns true if the creature is allowed
|
|
to die (i.e., not plot)
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
int CanCreatureBeDestroyed(object oTarget)
|
|
{
|
|
if (GetPlotFlag(oTarget) == FALSE && GetImmortal(oTarget) == FALSE)
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//*GZ: 2003-07-23. honor critical and weapon spec
|
|
// nCrit -
|
|
|
|
int ArcaneArcherDamageDoneByBow(int bCrit = FALSE, object oUser = OBJECT_SELF)
|
|
{
|
|
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND);
|
|
int nDamage;
|
|
int bSpec = FALSE;
|
|
|
|
if (GetIsObjectValid(oItem) == TRUE)
|
|
{
|
|
if (GetBaseItemType(oItem) == BASE_ITEM_LONGBOW )
|
|
{
|
|
nDamage = d8();
|
|
if (GetHasFeat(FEAT_WEAPON_SPECIALIZATION_LONGBOW,oUser))
|
|
{
|
|
bSpec = TRUE;
|
|
}
|
|
}
|
|
else
|
|
if (GetBaseItemType(oItem) == BASE_ITEM_SHORTBOW)
|
|
{
|
|
nDamage = d6();
|
|
if (GetHasFeat(FEAT_WEAPON_SPECIALIZATION_SHORTBOW,oUser))
|
|
{
|
|
bSpec = TRUE;
|
|
}
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// add strength bonus
|
|
int nStrength = GetAbilityModifier(ABILITY_STRENGTH,oUser);
|
|
nDamage += nStrength;
|
|
|
|
if (bSpec == TRUE)
|
|
{
|
|
nDamage +=2;
|
|
}
|
|
if (bCrit == TRUE)
|
|
{
|
|
nDamage *=3;
|
|
}
|
|
|
|
return nDamage;
|
|
}
|
|
|
|
//*GZ: 2003-07-23. Properly calculated enhancement bonus
|
|
int ArcaneArcherCalculateBonus()
|
|
{
|
|
int nLevel = GetLevelByClass(CLASS_TYPE_ARCANE_ARCHER, OBJECT_SELF);
|
|
|
|
if (nLevel == 0) //not an arcane archer?
|
|
{
|
|
return 0;
|
|
}
|
|
int nBonus = ((nLevel+1)/2); // every odd level after 1 get +1
|
|
return nBonus;
|
|
}
|
|
|
|
|
|
// * This is a wrapper for how Petrify will work in Expansion Pack 1
|
|
// * Scripts affected: flesh to stone, breath petrification, gaze petrification, touch petrification
|
|
// * nPower : This is the Hit Dice of a Monster using Gaze, Breath or Touch OR it is the Caster Spell of
|
|
// * a spellcaster
|
|
// * nFortSaveDC: pass in this number from the spell script
|
|
void DoPetrification(int nPower, object oSource, object oTarget, int nSpellID, int nFortSaveDC)
|
|
{
|
|
|
|
if(!GetIsReactionTypeFriendly(oTarget))
|
|
{
|
|
// * exit if creature is immune to petrification
|
|
if (spellsIsImmuneToPetrification(oTarget) == TRUE)
|
|
{
|
|
return;
|
|
}
|
|
float fDifficulty = 0.0;
|
|
int bIsPC = GetIsPC(oTarget);
|
|
int bShowPopup = FALSE;
|
|
|
|
// * calculate Duration based on difficulty settings
|
|
int nGameDiff = GetGameDifficulty();
|
|
switch (nGameDiff)
|
|
{
|
|
case GAME_DIFFICULTY_VERY_EASY:
|
|
case GAME_DIFFICULTY_EASY:
|
|
case GAME_DIFFICULTY_NORMAL:
|
|
fDifficulty = RoundsToSeconds(nPower); // One Round per hit-die or caster level
|
|
break;
|
|
case GAME_DIFFICULTY_CORE_RULES:
|
|
case GAME_DIFFICULTY_DIFFICULT:
|
|
bShowPopup = TRUE;
|
|
break;
|
|
}
|
|
|
|
int nSaveDC = nFortSaveDC;
|
|
effect ePetrify = EffectPetrify();
|
|
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
|
|
|
|
effect eLink = EffectLinkEffects(eDur, ePetrify);
|
|
|
|
// Let target know the negative spell has been cast
|
|
SignalEvent(oTarget,
|
|
EventSpellCastAt(OBJECT_SELF, nSpellID));
|
|
//SpeakString(IntToString(nSpellID));
|
|
|
|
// Do a fortitude save check
|
|
if (!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nSaveDC))
|
|
{
|
|
// Save failed; apply paralyze effect and VFX impact
|
|
|
|
/// * The duration is permanent against NPCs but only temporary against PCs
|
|
if (bIsPC == TRUE)
|
|
{
|
|
if (bShowPopup == TRUE)
|
|
{
|
|
// * under hardcore rules or higher, this is an instant death
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oTarget);
|
|
DelayCommand(2.75, PopUpDeathGUIPanel(oTarget, FALSE , TRUE, 40579));
|
|
// if in hardcore, treat the player as an NPC
|
|
bIsPC = FALSE;
|
|
//fDifficulty = TurnsToSeconds(nPower); // One turn per hit-die
|
|
}
|
|
else
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDifficulty);
|
|
}
|
|
else
|
|
{
|
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oTarget);
|
|
|
|
//----------------------------------------------------------
|
|
// GZ: Fix for henchmen statues haunting you when changing
|
|
// areas. Henchmen are now kicked from the party if
|
|
// petrified.
|
|
//----------------------------------------------------------
|
|
if (GetAssociateType(oTarget) == ASSOCIATE_TYPE_HENCHMAN)
|
|
{
|
|
FireHenchman(GetMaster(oTarget),oTarget);
|
|
}
|
|
|
|
}
|
|
// April 2003: Clearing actions to kick them out of conversation when petrified
|
|
AssignCommand(oTarget, ClearAllActions(TRUE));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// * generic area of effect constructor
|
|
void spellsGenericAreaOfEffect(
|
|
object oCaster, location lTargetLoc,
|
|
int nShape, float fRadiusSize, int nSpellID,
|
|
effect eImpact, effect eLink, effect eVis,
|
|
int nDurationType=DURATION_TYPE_INSTANT, float fDuration = 0.0,
|
|
int nTargetType=SPELL_TARGET_ALLALLIES, int bHarmful = FALSE,
|
|
int nRemoveEffectSpell=FALSE, int nRemoveEffect1=0, int nRemoveEffect2=0, int nRemoveEffect3=0,
|
|
int bLineOfSight=FALSE, int nObjectFilter=OBJECT_TYPE_CREATURE,
|
|
int bPersistentObject=FALSE, int bResistCheck=FALSE, int nSavingThrowType=SAVING_THROW_NONE,
|
|
int nSavingThrowSubType=SAVING_THROW_TYPE_ALL
|
|
)
|
|
{
|
|
//Apply Impact
|
|
if (GetEffectType(eImpact) != 0)
|
|
{
|
|
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpact, lTargetLoc);
|
|
}
|
|
|
|
object oTarget = OBJECT_INVALID;
|
|
float fDelay = 0.0;
|
|
|
|
int nPenetr = PRCGetCasterLevel(oCaster);
|
|
|
|
|
|
//Get the first target in the radius around the caster
|
|
if (bPersistentObject == TRUE)
|
|
oTarget = GetFirstInPersistentObject();
|
|
else
|
|
oTarget = GetFirstObjectInShape(nShape, fRadiusSize, lTargetLoc, bLineOfSight, nObjectFilter);
|
|
|
|
while(GetIsObjectValid(oTarget))
|
|
{
|
|
if (spellsIsTarget(oTarget, nTargetType, oCaster) == TRUE)
|
|
{
|
|
//Fire spell cast at event for target
|
|
SignalEvent(oTarget, EventSpellCastAt(oCaster, nSpellID, bHarmful));
|
|
int nResistSpellSuccess = FALSE;
|
|
// * actually perform the resist check
|
|
if (bResistCheck == TRUE)
|
|
{
|
|
nResistSpellSuccess = MyPRCResistSpell(oCaster, oTarget,nPenetr);
|
|
}
|
|
if(!nResistSpellSuccess)
|
|
{
|
|
int nDC = GetChangesToSaveDC(oTarget,oCaster);
|
|
int nSavingThrowSuccess = FALSE;
|
|
// * actually roll saving throw if told to
|
|
if (nSavingThrowType != SAVING_THROW_NONE)
|
|
{
|
|
nSavingThrowSuccess = PRCMySavingThrow(nSavingThrowType, oTarget, (GetSpellSaveDC() + nDC), nSavingThrowSubType);
|
|
}
|
|
if (!nSavingThrowSuccess)
|
|
{
|
|
fDelay = GetRandomDelay(0.4, 1.1);
|
|
|
|
|
|
|
|
//Apply VFX impact
|
|
if (GetEffectType(eVis) != 0)
|
|
{
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
|
|
}
|
|
|
|
// * Apply effects
|
|
// if (GetEffectType(eLink) != 0)
|
|
// * Had to remove this test because LINKED effects have no valid type.
|
|
{
|
|
|
|
DelayCommand(fDelay, ApplyEffectToObject(nDurationType, eLink, oTarget, fDuration));
|
|
}
|
|
|
|
// * If this is a removal spell then perform the appropriate removals
|
|
if (nRemoveEffectSpell == TRUE)
|
|
{
|
|
//Remove effects
|
|
RemoveSpecificEffect(nRemoveEffect1, oTarget);
|
|
if(nRemoveEffect2 != 0)
|
|
{
|
|
RemoveSpecificEffect(nRemoveEffect2, oTarget);
|
|
}
|
|
if(nRemoveEffect3 != 0)
|
|
{
|
|
RemoveSpecificEffect(nRemoveEffect3, oTarget);
|
|
}
|
|
|
|
}
|
|
}// saving throw
|
|
} // resist spell check
|
|
}
|
|
//Get the next target in the specified area around the caster
|
|
if (bPersistentObject == TRUE)
|
|
oTarget = GetNextInPersistentObject();
|
|
else
|
|
oTarget = GetNextObjectInShape(nShape, fRadiusSize, lTargetLoc, bLineOfSight, nObjectFilter);
|
|
|
|
}
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: ApplyMindBlank
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Applies Mind blank to the target
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
void spellApplyMindBlank(object oTarget, int nSpellId, float fDelay=0.0)
|
|
{
|
|
effect eImm1 = EffectImmunity(IMMUNITY_TYPE_MIND_SPELLS);
|
|
effect eVis = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_POSITIVE);
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
|
|
|
|
effect eLink = EffectLinkEffects(eImm1, eVis);
|
|
eLink = EffectLinkEffects(eLink, eDur);
|
|
effect eSearch = GetFirstEffect(oTarget);
|
|
int bValid;
|
|
int nDuration = PRCGetCasterLevel(OBJECT_SELF);
|
|
int nMetaMagic = GetMetaMagicFeat();
|
|
//Enter Metamagic conditions
|
|
if (nMetaMagic == METAMAGIC_EXTEND)
|
|
{
|
|
nDuration = nDuration *2; //Duration is +100%
|
|
}
|
|
|
|
//Fire cast spell at event for the specified target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpellId, FALSE));
|
|
//Search through effects
|
|
while(GetIsEffectValid(eSearch))
|
|
{
|
|
|
|
|
|
|
|
|
|
bValid = FALSE;
|
|
//Check to see if the effect matches a particular type defined below
|
|
if (GetEffectType(eSearch) == EFFECT_TYPE_DAZED)
|
|
{
|
|
bValid = TRUE;
|
|
}
|
|
else if(GetEffectType(eSearch) == EFFECT_TYPE_CHARMED)
|
|
{
|
|
bValid = TRUE;
|
|
}
|
|
else if(GetEffectType(eSearch) == EFFECT_TYPE_SLEEP)
|
|
{
|
|
bValid = TRUE;
|
|
}
|
|
else if(GetEffectType(eSearch) == EFFECT_TYPE_CONFUSED)
|
|
{
|
|
bValid = TRUE;
|
|
}
|
|
else if(GetEffectType(eSearch) == EFFECT_TYPE_STUNNED)
|
|
{
|
|
bValid = TRUE;
|
|
}
|
|
else if(GetEffectType(eSearch) == EFFECT_TYPE_DOMINATED)
|
|
{
|
|
bValid = TRUE;
|
|
}
|
|
// * Additional March 2003
|
|
// * Remove any feeblemind originating effects
|
|
else if (GetEffectSpellId(eSearch) == SPELL_FEEBLEMIND)
|
|
{
|
|
bValid = TRUE;
|
|
}
|
|
else if (GetEffectSpellId(eSearch) == SPELL_BANE)
|
|
{
|
|
bValid = TRUE;
|
|
}
|
|
|
|
//Apply damage and remove effect if the effect is a match
|
|
if (bValid == TRUE)
|
|
{
|
|
RemoveEffect(oTarget, eSearch);
|
|
}
|
|
eSearch = GetNextEffect(oTarget);
|
|
}
|
|
|
|
//After effects are removed we apply the immunity to mind spells to the target
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, TurnsToSeconds(nDuration)));
|
|
|
|
}
|
|
//::///////////////////////////////////////////////
|
|
//:: doAura
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Used in the Alignment aura - unholy and holy
|
|
aura scripts fromthe original campaign
|
|
spells. Cleaned them up to be consistent.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
|
|
void doAura(int nAlign, int nVis1, int nVis2, int nDamageType)
|
|
{
|
|
//Declare major variables
|
|
object oTarget = GetSpellTargetObject();
|
|
int nDuration = PRCGetCasterLevel(OBJECT_SELF);
|
|
|
|
effect eVis = EffectVisualEffect(nVis1);
|
|
effect eAC = EffectACIncrease(4, AC_DEFLECTION_BONUS);
|
|
effect eSave = EffectSavingThrowIncrease(SAVING_THROW_ALL, 4);
|
|
//Change the effects so that it only applies when the target is evil
|
|
effect eImmune = EffectImmunity(IMMUNITY_TYPE_MIND_SPELLS);
|
|
effect eSR = EffectSpellResistanceIncrease(25); //Check if this is a bonus or a setting.
|
|
effect eDur = EffectVisualEffect(nVis2);
|
|
effect eDur2 = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
|
|
effect eEvil = EffectDamageShield(6, DAMAGE_BONUS_1d8, nDamageType);
|
|
|
|
|
|
// * make them versus the alignment
|
|
|
|
eImmune = VersusAlignmentEffect(eImmune, ALIGNMENT_ALL, nAlign);
|
|
eSR = VersusAlignmentEffect(eSR,ALIGNMENT_ALL, nAlign);
|
|
eAC = VersusAlignmentEffect(eAC,ALIGNMENT_ALL, nAlign);
|
|
eSave = VersusAlignmentEffect(eSave,ALIGNMENT_ALL, nAlign);
|
|
eEvil = VersusAlignmentEffect(eEvil,ALIGNMENT_ALL, nAlign);
|
|
|
|
|
|
//Link effects
|
|
effect eLink = EffectLinkEffects(eImmune, eSave);
|
|
eLink = EffectLinkEffects(eLink, eAC);
|
|
eLink = EffectLinkEffects(eLink, eSR);
|
|
eLink = EffectLinkEffects(eLink, eDur);
|
|
eLink = EffectLinkEffects(eLink, eDur2);
|
|
eLink = EffectLinkEffects(eLink, eEvil);
|
|
|
|
//Fire cast spell at event for the specified target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId(), FALSE));
|
|
|
|
//Apply the VFX impact and effects
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
|
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nDuration));
|
|
}
|
|
|
|
// * Does a stinking cloud. If oTarget is Invalid, then does area effect, otherwise
|
|
// * just attempts on otarget
|
|
void spellsStinkingCloud(object oTarget = OBJECT_INVALID)
|
|
{
|
|
effect eStink = EffectDazed();
|
|
effect eMind = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DISABLED);
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
|
|
effect eLink = EffectLinkEffects(eMind, eStink);
|
|
eLink = EffectLinkEffects(eLink, eDur);
|
|
|
|
effect eVis = EffectVisualEffect(VFX_IMP_DAZED_S);
|
|
|
|
effect eImpact; // * null
|
|
|
|
|
|
if (GetIsObjectValid(oTarget) == TRUE)
|
|
{
|
|
if(spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, GetAreaOfEffectCreator()))
|
|
{
|
|
|
|
//Fire cast spell at event for the specified target
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
|
//Make a Fort Save
|
|
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, (GetSpellSaveDC() + GetChangesToSaveDC(oTarget,GetAreaOfEffectCreator())), SAVING_THROW_TYPE_POISON))
|
|
{
|
|
float fDelay = GetRandomDelay(0.75, 1.75);
|
|
//Apply the VFX impact and linked effects
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(2)));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
spellsGenericAreaOfEffect(GetAreaOfEffectCreator(),
|
|
GetLocation(OBJECT_SELF), // * not relevent for persistent area of effect
|
|
SHAPE_CONE, 0.0, // * not relevent for persistent area of effect
|
|
GetSpellId(), eImpact, eLink, eVis,
|
|
DURATION_TYPE_TEMPORARY, RoundsToSeconds(2), SPELL_TARGET_STANDARDHOSTILE,
|
|
TRUE, FALSE, 0, 0, 0, FALSE, OBJECT_TYPE_CREATURE,
|
|
TRUE, FALSE, SAVING_THROW_FORT, SAVING_THROW_TYPE_POISON);
|
|
}
|
|
}
|
|
|
|
//::///////////////////////////////////////////////
|
|
//:: RemoveSpellEffects2
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Advanced version of RemoveSpellEffects to
|
|
handle multiple spells (allows code reuse
|
|
for shadow conjuration darkness)
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By:
|
|
//:: Created On:
|
|
//:://////////////////////////////////////////////
|
|
void RemoveSpellEffects2(int nSpell_ID, object oCaster, object oTarget, int nSpell_ID2, int nSpell_ID3)
|
|
{
|
|
|
|
//Declare major variables
|
|
int bValid = FALSE;
|
|
effect eAOE;
|
|
if(GetHasSpellEffect(nSpell_ID, oTarget) || GetHasSpellEffect(nSpell_ID2, oTarget) || GetHasSpellEffect(nSpell_ID3, oTarget))
|
|
{
|
|
//Search through the valid effects on the target.
|
|
eAOE = GetFirstEffect(oTarget);
|
|
while (GetIsEffectValid(eAOE) && bValid == FALSE)
|
|
{
|
|
if (GetEffectCreator(eAOE) == oCaster)
|
|
{
|
|
//If the effect was created by the spell then remove it
|
|
if(GetEffectSpellId(eAOE) == nSpell_ID || GetEffectSpellId(eAOE) == nSpell_ID2
|
|
|| GetEffectSpellId(eAOE) == nSpell_ID3)
|
|
{
|
|
RemoveEffect(oTarget, eAOE);
|
|
bValid = TRUE;
|
|
}
|
|
}
|
|
//Get next effect on the target
|
|
eAOE = GetNextEffect(oTarget);
|
|
}
|
|
}
|
|
}
|
|
|
|
// * returns true if the creature has flesh
|
|
int spellsIsImmuneToPetrification(object oCreature)
|
|
{
|
|
int nAppearance = GetAppearanceType(oCreature);
|
|
int bImmune = FALSE;
|
|
switch (nAppearance)
|
|
{
|
|
case APPEARANCE_TYPE_BASILISK:
|
|
case APPEARANCE_TYPE_COCKATRICE:
|
|
case APPEARANCE_TYPE_MEDUSA:
|
|
case APPEARANCE_TYPE_ALLIP:
|
|
case APPEARANCE_TYPE_ELEMENTAL_AIR:
|
|
case APPEARANCE_TYPE_ELEMENTAL_AIR_ELDER:
|
|
case APPEARANCE_TYPE_ELEMENTAL_EARTH:
|
|
case APPEARANCE_TYPE_ELEMENTAL_EARTH_ELDER:
|
|
case APPEARANCE_TYPE_ELEMENTAL_FIRE:
|
|
case APPEARANCE_TYPE_ELEMENTAL_FIRE_ELDER:
|
|
case APPEARANCE_TYPE_ELEMENTAL_WATER:
|
|
case APPEARANCE_TYPE_ELEMENTAL_WATER_ELDER:
|
|
case APPEARANCE_TYPE_GOLEM_STONE:
|
|
case APPEARANCE_TYPE_GOLEM_IRON:
|
|
case APPEARANCE_TYPE_GOLEM_CLAY:
|
|
case APPEARANCE_TYPE_GOLEM_BONE:
|
|
case APPEARANCE_TYPE_GORGON:
|
|
case APPEARANCE_TYPE_HEURODIS_LICH:
|
|
case APPEARANCE_TYPE_LANTERN_ARCHON:
|
|
case APPEARANCE_TYPE_SHADOW:
|
|
case APPEARANCE_TYPE_SHADOW_FIEND:
|
|
case APPEARANCE_TYPE_SHIELD_GUARDIAN:
|
|
case APPEARANCE_TYPE_SKELETAL_DEVOURER:
|
|
case APPEARANCE_TYPE_SKELETON_CHIEFTAIN:
|
|
case APPEARANCE_TYPE_SKELETON_COMMON:
|
|
case APPEARANCE_TYPE_SKELETON_MAGE:
|
|
case APPEARANCE_TYPE_SKELETON_PRIEST:
|
|
case APPEARANCE_TYPE_SKELETON_WARRIOR:
|
|
case APPEARANCE_TYPE_SKELETON_WARRIOR_1:
|
|
case APPEARANCE_TYPE_SPECTRE:
|
|
case APPEARANCE_TYPE_WILL_O_WISP:
|
|
case APPEARANCE_TYPE_WRAITH:
|
|
case APPEARANCE_TYPE_BAT_HORROR:
|
|
case 405: // Dracolich:
|
|
case 415: // Alhoon
|
|
case 418: // shadow dragon
|
|
case 420: // mithral golem
|
|
case 421: // admantium golem
|
|
case 430: // Demi Lich
|
|
case 469: // animated chest
|
|
case 474: // golems
|
|
case 475: // golems
|
|
bImmune = TRUE;
|
|
}
|
|
|
|
// * GZ: Sept 2003 - Prevent people from petrifying DM, resulting in GUI even when
|
|
// effect is not successful.
|
|
if (!GetPlotFlag(oCreature) && GetIsDM(oCreature))
|
|
{
|
|
bImmune = FALSE;
|
|
}
|
|
return bImmune;
|
|
}
|
|
|
|
// * Returns true or false depending on whether the creature is flying
|
|
// * or not
|
|
int spellsIsFlying(object oCreature)
|
|
{
|
|
int nAppearance = GetAppearanceType(oCreature);
|
|
int bFlying = FALSE;
|
|
switch(nAppearance)
|
|
{
|
|
case APPEARANCE_TYPE_ALLIP:
|
|
case APPEARANCE_TYPE_BAT:
|
|
case APPEARANCE_TYPE_BAT_HORROR:
|
|
case APPEARANCE_TYPE_ELEMENTAL_AIR:
|
|
case APPEARANCE_TYPE_ELEMENTAL_AIR_ELDER:
|
|
case APPEARANCE_TYPE_FAERIE_DRAGON:
|
|
case APPEARANCE_TYPE_FALCON:
|
|
case APPEARANCE_TYPE_FAIRY:
|
|
case APPEARANCE_TYPE_HELMED_HORROR:
|
|
case APPEARANCE_TYPE_IMP:
|
|
case APPEARANCE_TYPE_LANTERN_ARCHON:
|
|
case APPEARANCE_TYPE_MEPHIT_AIR:
|
|
case APPEARANCE_TYPE_MEPHIT_DUST:
|
|
case APPEARANCE_TYPE_MEPHIT_EARTH:
|
|
case APPEARANCE_TYPE_MEPHIT_FIRE:
|
|
case APPEARANCE_TYPE_MEPHIT_ICE:
|
|
case APPEARANCE_TYPE_MEPHIT_MAGMA:
|
|
case APPEARANCE_TYPE_MEPHIT_OOZE:
|
|
case APPEARANCE_TYPE_MEPHIT_SALT:
|
|
case APPEARANCE_TYPE_MEPHIT_STEAM:
|
|
case APPEARANCE_TYPE_MEPHIT_WATER:
|
|
case APPEARANCE_TYPE_QUASIT:
|
|
case APPEARANCE_TYPE_RAVEN:
|
|
case APPEARANCE_TYPE_SHADOW:
|
|
case APPEARANCE_TYPE_SHADOW_FIEND:
|
|
case APPEARANCE_TYPE_SPECTRE:
|
|
case APPEARANCE_TYPE_WILL_O_WISP:
|
|
case APPEARANCE_TYPE_WRAITH:
|
|
case APPEARANCE_TYPE_WYRMLING_BLACK:
|
|
case APPEARANCE_TYPE_WYRMLING_BLUE:
|
|
case APPEARANCE_TYPE_WYRMLING_BRASS:
|
|
case APPEARANCE_TYPE_WYRMLING_BRONZE:
|
|
case APPEARANCE_TYPE_WYRMLING_COPPER:
|
|
case APPEARANCE_TYPE_WYRMLING_GOLD:
|
|
case APPEARANCE_TYPE_WYRMLING_GREEN:
|
|
case APPEARANCE_TYPE_WYRMLING_RED:
|
|
case APPEARANCE_TYPE_WYRMLING_SILVER:
|
|
case APPEARANCE_TYPE_WYRMLING_WHITE:
|
|
case APPEARANCE_TYPE_ELEMENTAL_WATER:
|
|
case APPEARANCE_TYPE_ELEMENTAL_WATER_ELDER:
|
|
case 401: //beholder
|
|
case 402: //beholder
|
|
case 403: //beholder
|
|
case 419: // harpy
|
|
case 430: // Demi Lich
|
|
case 472: // Hive mother
|
|
bFlying = TRUE;
|
|
}
|
|
return bFlying;
|
|
}
|
|
|
|
// * returns true if oCreature does not have a mind
|
|
int spellsIsMindless(object oCreature)
|
|
{
|
|
int nRacialType = MyPRCGetRacialType(oCreature);
|
|
switch(nRacialType)
|
|
{
|
|
case RACIAL_TYPE_ELEMENTAL:
|
|
case RACIAL_TYPE_UNDEAD:
|
|
case RACIAL_TYPE_VERMIN:
|
|
case RACIAL_TYPE_CONSTRUCT:
|
|
case RACIAL_TYPE_OOZE:
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Doesn't care who the caster was removes the effects of the spell nSpell_ID.
|
|
// will ignore the subtype as well...
|
|
// GZ: Removed the check that made it remove only one effect.
|
|
//------------------------------------------------------------------------------
|
|
void RemoveAnySpellEffects(int nSpell_ID, object oTarget)
|
|
{
|
|
//Declare major variables
|
|
|
|
effect eAOE;
|
|
if(GetHasSpellEffect(nSpell_ID, oTarget))
|
|
{
|
|
//Search through the valid effects on the target.
|
|
eAOE = GetFirstEffect(oTarget);
|
|
while (GetIsEffectValid(eAOE))
|
|
{
|
|
//If the effect was created by the spell then remove it
|
|
if(GetEffectSpellId(eAOE) == nSpell_ID)
|
|
{
|
|
RemoveEffect(oTarget, eAOE);
|
|
}
|
|
//Get next effect on the target
|
|
eAOE = GetNextEffect(oTarget);
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Attempts a dispel on one target, with all safety checks put in.
|
|
//------------------------------------------------------------------------------
|
|
void spellsDispelMagic(object oTarget, int nCasterLevel, effect eVis, effect eImpac, int bAll = TRUE, int bBreachSpells = FALSE)
|
|
{
|
|
//--------------------------------------------------------------------------
|
|
// Don't dispel magic on petrified targets
|
|
// this change is in to prevent weird things from happening with 'statue'
|
|
// creatures. Also creature can be scripted to be immune to dispel
|
|
// magic as well.
|
|
//--------------------------------------------------------------------------
|
|
if (GetHasEffect(EFFECT_TYPE_PETRIFY, oTarget) == TRUE || GetLocalInt(oTarget, "X1_L_IMMUNE_TO_DISPEL") == 10)
|
|
{
|
|
return;
|
|
}
|
|
|
|
effect eDispel;
|
|
float fDelay = GetRandomDelay(0.1, 0.3);
|
|
int nId = GetSpellId();
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Fire hostile event only if the target is hostile...
|
|
//--------------------------------------------------------------------------
|
|
if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF))
|
|
{
|
|
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nId));
|
|
}
|
|
else
|
|
{
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nId, FALSE));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GZ: Bugfix. Was always dispelling all effects, even if used for AoE
|
|
//--------------------------------------------------------------------------
|
|
if (bAll == TRUE )
|
|
{
|
|
eDispel = EffectDispelMagicAll(nCasterLevel);
|
|
//----------------------------------------------------------------------
|
|
// GZ: Support for Mord's disjunction
|
|
//----------------------------------------------------------------------
|
|
if (bBreachSpells)
|
|
{
|
|
DoSpellBreach(oTarget, 6, 10, nId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
eDispel = EffectDispelMagicBest(nCasterLevel);
|
|
if (bBreachSpells)
|
|
{
|
|
DoSpellBreach(oTarget, 2, 10, nId);
|
|
}
|
|
}
|
|
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDispel, oTarget));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// GZ: Aug 27 2003
|
|
// Return the hightest spellcasting class of oCreature, used for dispel magic
|
|
// workaround
|
|
//------------------------------------------------------------------------------
|
|
int GZGetHighestSpellcastingClassLevel(object oCreature)
|
|
{
|
|
int nMax;
|
|
if (GetIsPC(oCreature))
|
|
{
|
|
int i;
|
|
int nClass;
|
|
int nLevel;
|
|
for (i =1; i<= 3; i++)
|
|
{
|
|
// This is kind of hacky as high level pally's and ranger's will
|
|
// dispell at their full class level...
|
|
nClass= GetClassByPosition(i,oCreature);
|
|
if (nClass != CLASS_TYPE_INVALID)
|
|
{
|
|
if (nClass == CLASS_TYPE_SORCERER || nClass == CLASS_TYPE_WIZARD ||
|
|
nClass == CLASS_TYPE_PALEMASTER || nClass == CLASS_TYPE_CLERIC ||
|
|
nClass == CLASS_TYPE_DRUID || nClass == CLASS_TYPE_BARD ||
|
|
nClass == CLASS_TYPE_RANGER || nClass == CLASS_TYPE_PALADIN)
|
|
{
|
|
nLevel = GetLevelByClass(nClass,oCreature);
|
|
|
|
if (nLevel> nMax)
|
|
{
|
|
nMax = nLevel;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
//* not a creature ... be unfair and count full HD :)
|
|
nMax = GetHitDice(oCreature);
|
|
}
|
|
|
|
return nMax;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// returns TRUE if a creature is not in the condition to use gaze attacks
|
|
// i.e. blindness
|
|
//------------------------------------------------------------------------------
|
|
int GZCanNotUseGazeAttackCheck(object oCreature)
|
|
{
|
|
if (GetHasEffect( EFFECT_TYPE_BLINDNESS,oCreature))
|
|
{
|
|
FloatingTextStrRefOnCreature(84530, oCreature ,FALSE); // * blinded
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Handle Dispelling Area of Effects
|
|
// Before adding this AoE's got automatically destroyed. Since NWN does not give
|
|
// the required information to do proper dispelling on AoEs, we do some simulated
|
|
// stuff here:
|
|
// - Base chance to dispel is 25, 50, 75 or 100% depending on the spell
|
|
// - Chance is modified positive by the caster level of the spellcaster as well
|
|
// - as the relevant ability score
|
|
// - Chance is modified negative by the highest spellcasting class level of the
|
|
// AoE creator and the releavant ability score.
|
|
// Its bad, but its not worse than just dispelling the AoE as the game did until
|
|
// now
|
|
//------------------------------------------------------------------------------
|
|
void spellsDispelAoE(object oTargetAoE, object oCaster, int nCasterLevel)
|
|
{
|
|
object oCreator = GetAreaOfEffectCreator(oTargetAoE);
|
|
int nChance;
|
|
int nId = GetSpellId();
|
|
if ( nId == SPELL_LESSER_DISPEL )
|
|
{
|
|
nChance = 25;
|
|
}
|
|
else if ( nId == SPELL_DISPEL_MAGIC)
|
|
{
|
|
nChance = 50;
|
|
}
|
|
else if ( nId == SPELL_GREATER_DISPELLING )
|
|
{
|
|
nChance = 75;
|
|
}
|
|
else if ( nId == SPELL_MORDENKAINENS_DISJUNCTION )
|
|
{
|
|
nChance = 100;
|
|
}
|
|
|
|
|
|
nChance += ((nCasterLevel + GetCasterAbilityModifier(oCaster)) - (10 + GetCasterAbilityModifier(oCreator))*2) ;
|
|
|
|
//--------------------------------------------------------------------------
|
|
// the AI does cheat here, because it can not react as well as a player to
|
|
// AoE effects. Also DMs are always successful
|
|
//--------------------------------------------------------------------------
|
|
if (!GetIsPC(oCaster))
|
|
{
|
|
nChance +=30;
|
|
}
|
|
|
|
if (oCaster == oCreator)
|
|
{
|
|
nChance = 100;
|
|
}
|
|
|
|
int nRand = Random(100);
|
|
|
|
if ((nRand < nChance )|| GetIsDM(oCaster) || GetIsDMPossessed(oCaster))
|
|
{
|
|
FloatingTextStrRefOnCreature(100929,oCaster); // "AoE dispelled"
|
|
DestroyObject (oTargetAoE);
|
|
}
|
|
else
|
|
{
|
|
FloatingTextStrRefOnCreature(100930,oCaster); // "AoE not dispelled"
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|