Rune_PRC8/_removed/x0_i0_spells.nss
Jaysyn904 d1c309ae63 Initial commit
Initial commit
2024-09-13 09:10:39 -04:00

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"
}
}