//:://///////////////////////////////////////////// //:: 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 //::////////////////////////////////////////////// #include "NW_I0_SPELLS" #include "x0_i0_match" #include "x2_inc_switches" #include "x2_inc_itemprop" #include "x0_i0_henchman" // * Constants // * see spellsIsTarget for a definition of these constants const int SPELL_TARGET_ALLALLIES = 1; const int SPELL_TARGET_STANDARDHOSTILE = 2; const int SPELL_TARGET_SELECTIVEHOSTILE = 3; const int SAVING_THROW_NONE = 4; //* 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 ); // * Generic reputation wrapper // * definition of constants: // * SPELL_TARGET_ALLALLIES = Will affect all allies, even those in my faction who don't like me // * SPELL_TARGET_STANDARDHOSTILE: 90% of offensive area spells will work // this way. They will never hurt NEUTRAL or FRIENDLY NPCs. // They will never hurt FRIENDLY PCs // They WILL hurt NEUTRAL PCs // * SPELL_TARGET_SELECTIVEHOSTILE: Will only ever hurt enemies int spellsIsTarget(object oTarget, int nTargetType, object oSource); // * 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); void spellsInflictTouchAttack(int nDamage, int nMaxExtraDamage, int nMaximized, int vfx_impactHurt, int vfx_impactHeal, int nSpellID); // * 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); // * for spike growth area of effect object // * applies damage and slow effect void DoSpikeGrowthEffect(object oTarget); // * 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 = GetReflexAdjustedDamage(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 = GetCasterLevel(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 == GetRacialType(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 == GetRacialType(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) { //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(!MyResistSpell(GetAreaOfEffectCreator(), oTarget)) { //Make a Fortitude Save to avoid the effects of the movement hit. if(!MySavingThrow(SAVING_THROW_FORT, oTarget, GetSpellSaveDC(), 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 = GetCasterLevel(OBJECT_SELF); nDuration = 10 * nDuration; // * Duration 10 turn/level if (nMetaMagic == METAMAGIC_EXTEND) //Duration is +100% { nDuration = nDuration * 2; } //Fire spell cast at event for target SignalEvent(oTarget, EventSpellCastAt(oTarget, GetSpellId(), 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) { 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(), SPELL_SPIKE_GROWTH)); //Spell resistance check if(!MyResistSpell(GetAreaOfEffectCreator(), oTarget, 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(SPELL_SPIKE_GROWTH, oTarget) == FALSE) { //Make a Reflex Save to avoid the effects of the movement hit. if(!MySavingThrow(SAVING_THROW_REFLEX, oTarget, GetSpellSaveDC(), 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) { //Declare major variables object oTarget = GetSpellTargetObject(); int nMetaMagic = GetMetaMagicFeat(); int nTouch = TouchAttackMelee(oTarget); int nExtraDamage = GetCasterLevel(OBJECT_SELF); // * figure out the bonus damage if (nExtraDamage > nMaxExtraDamage) { nExtraDamage = nMaxExtraDamage; } //Check for metamagic if (nMetaMagic == METAMAGIC_MAXIMIZE) { nDamage = nMaximized; } else if (nMetaMagic == METAMAGIC_EMPOWER) { nDamage = nDamage + (nDamage / 2); } //Check that the target is undead if (GetRacialType(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 (!MyResistSpell(OBJECT_SELF, oTarget)) { int nDamageTotal = nDamage + nExtraDamage; // A succesful will save halves the damage if(MySavingThrow(SAVING_THROW_WILL, oTarget, GetSpellSaveDC(), 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 = GetCasterLevel(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; 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 the firing object is a placeable (such as a projectile trap), // we skip the line of sight check as placeables can't "see" things. if ( ( GetObjectType(OBJECT_SELF) == OBJECT_TYPE_PLACEABLE ) || 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) && (( GetObjectType(OBJECT_SELF) == OBJECT_TYPE_PLACEABLE ) || (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 (!MyResistSpell(OBJECT_SELF, oTarget, 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) { if ( nDAMAGETYPE == DAMAGE_TYPE_ELECTRICAL ) { nDam = GetReflexAdjustedDamage(nDam, oTarget, GetSpellSaveDC(), SAVING_THROW_TYPE_ELECTRICITY); } else if ( nDAMAGETYPE == DAMAGE_TYPE_FIRE ) { 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) { //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 = GetCasterLevel(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, 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 // Updated: 02/14/2008 CraigW - Added support for Epic Weapon Specialization. // nCrit - int ArcaneArcherDamageDoneByBow(int bCrit = FALSE, object oUser = OBJECT_SELF) { object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND); int nDamage; int bSpec = FALSE; int bEpicSpecialization = FALSE; if (GetIsObjectValid(oItem) == TRUE) { if (GetBaseItemType(oItem) == BASE_ITEM_LONGBOW ) { nDamage = d8(); if (GetHasFeat(FEAT_WEAPON_SPECIALIZATION_LONGBOW,oUser)) { bSpec = TRUE; } if (GetHasFeat(FEAT_EPIC_WEAPON_SPECIALIZATION_LONGBOW,oUser)) { bEpicSpecialization = TRUE; } } else if (GetBaseItemType(oItem) == BASE_ITEM_SHORTBOW) { nDamage = d6(); if (GetHasFeat(FEAT_WEAPON_SPECIALIZATION_SHORTBOW,oUser)) { bSpec = TRUE; } if (GetHasFeat(FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTBOW,oUser)) { bEpicSpecialization = TRUE; } } else return 0; } else { return 0; } // add strength bonus int nStrength = GetAbilityModifier(ABILITY_STRENGTH,oUser); nDamage += nStrength; if (bSpec == TRUE) { nDamage +=2; } if ( bEpicSpecialization == TRUE ) { nDamage +=4; } 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 (!MySavingThrow(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)); } } } //:://///////////////////////////////////////////// //:: spellsIsTarget //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* This is the reputation wrapper. It performs the check to see if, based on the constant provided it is okay to target this target with the spell effect. MODIFIED APRIL 2003 - Other player's associates will now be harmed in Standard Hostile mode - Will ignore dead people in all target attempts MODIFIED AUG 2003 - GZ - Multiple henchmen support: made sure that AoE spells cast by one henchmen do not affect other henchmen in the party */ //::////////////////////////////////////////////// //:: Created By: Brent //:: Created On: March 6 2003 //::////////////////////////////////////////////// int spellsIsTarget(object oTarget, int nTargetType, object oSource) { // * if dead, not a valid target if (GetIsDead(oTarget) == TRUE) { return FALSE; } int nReturnValue = FALSE; switch (nTargetType) { // * this kind of spell will affect all friendlies and anyone in my // * party, even if we are upset with each other currently. case SPELL_TARGET_ALLALLIES: { if(GetIsReactionTypeFriendly(oTarget,oSource) || GetFactionEqual(oTarget,oSource)) { nReturnValue = TRUE; } break; } case SPELL_TARGET_STANDARDHOSTILE: { //SpawnScriptDebugger(); int bPC = GetIsPC(oTarget); int bNotAFriend = FALSE; int bReactionType = GetIsReactionTypeFriendly(oTarget, oSource); if (bReactionType == FALSE) { bNotAFriend = TRUE; } // * Local Override is just an out for end users who want // * the area effect spells to hurt 'neutrals' if (GetLocalInt(GetModule(), "X0_G_ALLOWSPELLSTOHURT") == 10) { bPC = TRUE; } int bSelfTarget = FALSE; object oMaster = GetMaster(oTarget); // March 25 2003. The player itself can be harmed // by their own area of effect spells if in Hardcore mode... if (GetGameDifficulty() > GAME_DIFFICULTY_NORMAL) { // Have I hit myself with my spell? if (oTarget == oSource) { bSelfTarget = TRUE; } else // * Is the target an associate of the spellcaster if (oMaster == oSource) { bSelfTarget = TRUE; } } // April 9 2003 // Hurt the associates of a hostile player if (bSelfTarget == FALSE && GetIsObjectValid(oMaster) == TRUE) { // * I am an associate // * of someone if ( (GetIsReactionTypeFriendly(oMaster,oSource) == FALSE && GetIsPC(oMaster) == TRUE) || GetIsReactionTypeHostile(oMaster,oSource) == TRUE) { bSelfTarget = TRUE; } } // Assumption: In Full PvP players, even if in same party, are Neutral // * GZ: 2003-08-30: Patch to make creatures hurt each other in hardcore mode... if (GetIsReactionTypeHostile(oTarget,oSource)) { nReturnValue = TRUE; // Hostile creatures are always a target } else if (bSelfTarget == TRUE) { nReturnValue = TRUE; // Targetting Self (set above)? } else if (bPC && bNotAFriend) { nReturnValue = TRUE; // Enemy PC } else if (bNotAFriend && (GetGameDifficulty() > GAME_DIFFICULTY_NORMAL)) { if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_NPC_AOE_HURT_ALLIES) == TRUE) { nReturnValue = TRUE; // Hostile Creature and Difficulty > Normal } // note that in hardcore mode any creature is hostile } break; } // * only harms enemies, ever // * current list:call lightning, isaac missiles, firebrand, chain lightning, dirge, Nature's balance, // * Word of Faith case SPELL_TARGET_SELECTIVEHOSTILE: { if(GetIsEnemy(oTarget,oSource)) { nReturnValue = TRUE; } break; } } // GZ: Creatures with the same master will never damage each other if (GetMaster(oTarget) != OBJECT_INVALID && GetMaster(oSource) != OBJECT_INVALID ) { if (GetMaster(oTarget) == GetMaster(oSource)) { if (GetModuleSwitchValue(MODULE_SWITCH_ENABLE_MULTI_HENCH_AOE_DAMAGE) == 0 ) { nReturnValue = FALSE; } } } return nReturnValue; } // * 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; //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 = MyResistSpell(oCaster, oTarget); } if(!nResistSpellSuccess) { int nSavingThrowSuccess = FALSE; // * actually roll saving throw if told to if (nSavingThrowType != SAVING_THROW_NONE) { nSavingThrowSuccess = MySavingThrow(nSavingThrowType, oTarget, GetSpellSaveDC(), 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 = GetCasterLevel(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 = GetCasterLevel(OBJECT_SELF); int nMetaMagic = GetMetaMagicFeat(); if (nMetaMagic == METAMAGIC_EXTEND) { nDuration = nDuration * 2; //Duration is +100% } 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(!MySavingThrow(SAVING_THROW_FORT, oTarget, GetSpellSaveDC(), SAVING_THROW_TYPE_POISON)) { if (GetIsImmune(oTarget, IMMUNITY_TYPE_POISON) == FALSE) { 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) { // * GZ: Sept 2003 - Prevent people from petrifying DM, resulting in GUI even when // effect is not successful. // I think this is now prevention. -- TK. if ( GetIsDM(oCreature) || GetPlotFlag(oCreature) ) return TRUE; // We are identifying appearances that have no flesh. // (Plus the petrifiers -- medusa, gorgon, cockatrice.) // This operation is optimized into a two-tiered decision tree. int nAppearance = GetAppearanceType(oCreature); switch ( nAppearance / 100 ) { case 0: // BioWare appearances 0 - 99. switch ( nAppearance ) { case 11: // APPEARANCE_TYPE_BAT_HORROR case 24: // APPEARANCE_TYPE_GOLEM_BONE case 36: // APPEARANCE_TYPE_SKELETAL_DEVOURER case 39: // APPEARANCE_TYPE_LICH case 52: // APPEARANCE_TYPE_ELEMENTAL_AIR case 53: // APPEARANCE_TYPE_ELEMENTAL_AIR_ELDER case 56: // APPEARANCE_TYPE_ELEMENTAL_EARTH case 57: // APPEARANCE_TYPE_ELEMENTAL_EARTH_ELDER return TRUE; } if ( 60 <= nAppearance && nAppearance <= 64 ) // APPEARANCE_TYPE_ELEMENTAL_FIRE, APPEARANCE_TYPE_ELEMENTAL_FIRE_ELDER, return TRUE; // APPEARANCE_TYPE_SKELETON_PRIEST, APPEARANCE_TYPE_SKELETON_COMMON, // APPEARANCE_TYPE_INVISIBLE_STALKER if ( 68 <= nAppearance && nAppearance <= 71 ) // APPEARANCE_TYPE_ELEMENTAL_WATER_ELDER, APPEARANCE_TYPE_ELEMENTAL_WATER, return TRUE; // APPEARANCE_TYPE_SKELETON_WARRIOR_1, APPEARANCE_TYPE_SKELETON_WARRIOR_2 if ( 89 <= nAppearance && nAppearance <= 92 ) // APPEARANCE_TYPE_GOLEM_IRON, APPEARANCE_TYPE_SHIELD_GUARDIAN, return TRUE; // APPEARANCE_TYPE_GOLEM_CLAY, APPEARANCE_TYPE_GOLEM_STONE break; case 1: // BioWare appearances 100 - 199. switch ( nAppearance ) { case 100: // APPEARANCE_TYPE_HELMED_HORROR case 103: // APPEARANCE_TYPE_LANTERN_ARCHON case 116: // APPEARANCE_TYPE_WILL_O_WISP case 119: // APPEARANCE_TYPE_MINOGON case 156: // APPEARANCE_TYPE_SPECTRE case 169: // Golem, Emerald case 173: // Golem, Ruby case 182: // APPEARANCE_TYPE_SKELETON_CHIEFTAIN case 186: // APPEARANCE_TYPE_ALLIP case 187: // APPEARANCE_TYPE_WRAITH return TRUE; } if ( 146 <= nAppearance && nAppearance <= 150 ) // APPEARANCE_TYPE_SHADOW, APPEARANCE_TYPE_SHADOW_FIEND return TRUE; // APPEARANCE_TYPE_SKELETON_MAGE, Golem Diamond, // APPEARANCE_TYPE_SKELETON_WARRIOR break; case 2: // BioWare appearances 200-299. switch ( nAppearance ) { case 200: // APPEARANCE_TYPE_ARCH_TARGET case 201: // APPEARANCE_TYPE_COMBAT_DUMMY return TRUE; } break; case 3: // BioWare appearances 300-399. if ( 352 == nAppearance ) // APPEARANCE_TYPE_MEDUSA return TRUE; if ( 367 <= nAppearance && nAppearance <= 370 ) // APPEARANCE_TYPE_GORGON, APPEARANCE_TYPE_COCKATRICE, return TRUE; // APPEARANCE_TYPE_BASILISK, APPEARANCE_TYPE_HEURODIS_LICH break; case 4: // BioWare appearances 400-499. switch ( nAppearance ) { case 405: // APPEARANCE_TYPE_DRACOLICH case 415: // APPEARANCE_TYPE_MINDFLAYER_ALHOON case 418: // APPEARANCE_TYPE_DRAGON_SHADOW case 420: // APPEARANCE_TYPE_GOLEM_MITHRAL case 421: // APPEARANCE_TYPE_GOLEM_ADAMANTIUM return TRUE; } if ( 430 <= nAppearance && nAppearance <= 445 ) // APPEARANCE_TYPE_DEMI_LICH, APPEARANCE_TYPE_OBJECT_CHAIR return TRUE; // APPEARANCE_TYPE_OBJECT_TABLE, APPEARANCE_TYPE_OBJECT_CANDLE, // APPEARANCE_TYPE_OBJECT_CHEST, APPEARANCE_TYPE_OBJECT_WHITE, // APPEARANCE_TYPE_OBJECT_BLUE, APPEARANCE_TYPE_OBJECT_CYAN, // APPEARANCE_TYPE_OBJECT_GREEN, APPEARANCE_TYPE_OBJECT_YELLOW, // APPEARANCE_TYPE_OBJECT_ORANGE, APPEARANCE_TYPE_OBJECT_RED, // APPEARANCE_TYPE_OBJECT_PURPLE, APPEARANCE_TYPE_OBJECT_FLAME_SMALL, // APPEARANCE_TYPE_OBJECT_FLAME_MEDIUM, APPEARANCE_TYPE_OBJECT_FLAME_LARGE if ( 469 == nAppearance ) // APPEARANCE_TYPE_ANIMATED_CHEST return TRUE; if ( 473 <= nAppearance && nAppearance <= 475 ) // APPEARANCE_TYPE_OBJECT_BOAT, APPEARANCE_TYPE_DWARF_GOLEM, return TRUE; // APPEARANCE_TYPE_DWARF_HALFORC break; // Skipping cases 5-9. There are BioWare appearances, but all have flesh. case 10: // CEP appearances 1000-1099. switch ( nAppearance ) { case 1030: // Armor Stand* case 1031: // Dracolich B* case 1047: // Scarecrow* case 1049: // Skeleton: Small* case 1066: // Ghost Human: F-Red 3** case 1095: // Wraith: Hooded 1* case 1096: // Wraith: Hooded 2* case 1099: // Visage* return TRUE; } break; case 11: // CEP appearances 1100-1199. switch ( nAppearance ) { case 1100: // Visage, Greater* case 1101: // Demon: Vorlan* case 1104: // Belker* return TRUE; } break; case 12: // CEP appearances 1200-1299. switch ( nAppearance ) { case 1216: // Mechanon, Spiker* case 1217: // Mechanon, Spider* case 1218: // Mechanon, Cutter* case 1257: // Minogon B* case 1259: // Vampiric Mist 2* case 1277: // Skeleton: Dwarf* case 1281: // Bat, Battle* case 1282: // Bat, Bone* return TRUE; } if ( 1285 <= nAppearance && nAppearance <= 1289 ) // Skeleton: Red Eyes*; Skeleton: Flaming*; Skeleton: Green* return TRUE; // Skeleton: Purple*; Skeleton: Yellow* break; case 13: // CEP appearances 1300-1399. if ( 1307 == nAppearance || 1325 == nAppearance ) // Demilich B*; Vecna* return TRUE; if ( 1342 <= nAppearance && nAppearance <= 1389 ) // Elemental, Air L*; Elemental, Air M*; Elemental, Air S*; return TRUE; // Elemental, Smoke L*; Elemental, Smoke M*; Elemental, Smoke S*; // Elemental, Magma L*; Elemental, Magma M*; Elemental, Magma S*; // Elemental, Ooze L*; Elemental, Ooze M*; Elemental, Ooze S*; // Elemental, Water L*; Elemental, Water M*; Elemental, Water S*; // Elemental, Fire L*; Elemental, Fire M*; Elemental, Fire S*; // Elemental, Earth L*; Elemental, Earth M*; Elemental, Earth S*; // Elemental, Ice L*; Elemental, Ice M*; Elemental, Ice S*; // Elemental, Radiance L*; Elemental, Radiance M*; Elemental, Radiance S*; // Elemental, Mineral L*; Elemental, Mineral M*; Elemental, Mineral S*; // Elemental, Steam L*; Elemental, Steam M*; Elemental, Steam S*; // Elemental, Lightning L*; Elemental, Lightning M*; Elemental, Lightning S*; // Elemental, Salt L*; Elemental, Salt M*; Elemental, Salt S*; // Elemental, Dust L*; Elemental, Dust M*; Elemental, Dust S*; // Elemental, Ash L*; Elemental, Ash M*; Elemental, Ash S*; break; // Elemental, Vacuum L*; Elemental, Vacuum M*; Elemental, Vacuum S* case 14: // CEP appearances 1400-1499. if ( 1421 <= nAppearance && nAppearance <= 1426 ) // Animated Wheel*; Animated Table*; [1423 skipped]; Animated Chest*; // Exclude Jagre** // Animated Tome*; Animated Chest, Flying* return nAppearance != 1423; if ( 1435 <= nAppearance && nAppearance <= 1437 ) // Flying Book A*; Flying Book B*; Flying Book C* return TRUE; if ( 1440 <= nAppearance && nAppearance <= 1447 ) // Skeleton, Pirate 1*; Skeleton, Pirate 2*; Skeleton, Pirate 3*; [1443 and 1444 skipped]; // Exclude Zombie, Pirate 2*; Zombie, Pirate 3*.// Skeleton, Pirate 4*; Skeleton, Pirate 5*; Skeleton, Pirate 6* return nAppearance != 1443 && nAppearance != 1444; if ( 1449 == nAppearance || 1451 == nAppearance ) // Ghost Pirate*; Skeleton, Ogre* return TRUE; if ( 1486 <= nAppearance && nAppearance <= 1491 ) // Golem: Ruby*; Golem: Emerald*; Golem: Citrine*; Golem: Sapphire*; return TRUE; // Golem: Amethyst*; Golem: Obsidian* if ( 1498 <= nAppearance ) // Maug*; Maug, Lieutenant* return TRUE; break; case 15: // CEP appearances 1500-1599. if ( 1500 == nAppearance || 1504 == nAppearance ) // Maug, Commander*; Maug, Captain* return TRUE; if ( 1509 <= nAppearance && nAppearance <= 1514 ) // Golem: Hematite**; Golem: Topaz**; Golem: Diamond**; [1512 skipped]; // Exclude Dragon: Saphire** // Golem: Blackrock**; Golem: Maztica** return nAppearance != 1512; if ( 1532 <= nAppearance && nAppearance <= 1536 ) // Golem: Weathered**; Golem: Damaged 1**; Golem: Damaged 2**; // Exclude Ogre, 3.5e DLA** // [1535 skipped]; Basilisk - Large** return nAppearance != 1535; if ( 1579 <= nAppearance && nAppearance <= 1581 ) // Lizard: Lich**; Lizard: Lich, Chief**; Lizard: Lich, Risen** return TRUE; break; // Skipping case 16. All appearances have flesh. case 17: // CEP appearances 1700-1799. if ( 1755 <= nAppearance && nAppearance <= 1769 ) // Shield Guard Blue**; Shield Guard Vuong**; Shield Guard Wood**; // Exclude CEP reserved line. // Elemental: Ice 2**; [1759 skipped]; Shield Guard: Gold**; return nAppearance != 1759; // Shield Guard: Fatal**; Shield Guard: Black**; Shield Guard: Clan**; // Shield Guard: Mage**; Shield Guard: Knight**; Shield Guard: Mortar**; break; // Shield Guard: Bizarro**; Shield Guard: Rust**; Skeleton, Dynamic** case 18: // CEP appearances 1800-1899. if ( 1869 <= nAppearance && nAppearance <= 1875 ) // Shadow Lord**; Elemental: Ice**; Elemental: Lava**; Elemental: Death**; // Exclude Elemental: Floral** // [1873 skipped]; Flying Book: Death**; Flying Book: Myst** return nAppearance != 1873; break; case 19: // CEP appearances 1900-1999. if ( 1942 == nAppearance ) // Golem: Atlantis** return TRUE; if ( 1994 <= nAppearance && nAppearance <= 1998 ) // Will-O-Wisp: Pink**; Will-O-Wisp: Yellow**; Will-O-Wisp: Purple**; return TRUE; // Will-O-Wisp: Orange**; Will-O-Wisp: Green** break; // Skipping cases 20 to 24. All appearances have flesh. case 25: // CEP appearances 2500-2599. if ( nAppearance == 2507 ) // Skully return TRUE; break; // Skipping cases 26 to 30. All appearances have flesh. case 31: // CEP appearances 3100-3199. if ( nAppearance <= 3116 ) // Ghost Human: F-Red 1**; Ghost Human: F-Red 2**; Ghost Human: F-Blue 1**; return TRUE; // Ghost Human: F-Blue 2**; Ghost Human: F-Blue 3**; Ghost Human: F-Green 1**; // Ghost Human: F-Green 2**; Ghost Human: F-Green 3**; Ghost Human: M-Red 1**; // Ghost Human: M-Red 2**; Ghost Human: M-Red 3**; Ghost Human: M-Blue 1**; // Ghost Human: M-Blue 2**; Ghost Human: M-Blue 3**; Ghost Human: M-Green 1**; // Ghost Human: M-Green 2**; Ghost Human: M-Green 3** if ( 3126 <= nAppearance && nAppearance <= 3130 ) // Ice Fiend 1**; Ice Fiend 2**; Ice Fiend 3**; return TRUE; // Elemental: Fire, Grue; Elemental: Air, Grue break; }//switch (nAppearance/100) // 03/07/2005 CraigW - Petrification immunity can also be granted as an item property. // Default: not immune, unless protected by an item property. return ResistSpell(OBJECT_SELF, oCreature) == 2; } // * Returns TRUE or FALSE depending on whether the creature is flying or not. int spellsIsFlying(object oCreature) { // First check for a flying phenotype. int nPheno = GetPhenoType(oCreature); if ( nPheno == 16 || nPheno == 25 ) // Part-based creature set to appear to be flying. return TRUE; // We are identifying appearances that are "flying". // This operation is optimized into a two-tiered decision tree. int nAppearance = GetAppearanceType(oCreature); switch ( nAppearance / 100 ) { case 0: // BioWare appearances 0 - 99. switch ( nAppearance ) { case 10: // APPEARANCE_TYPE_BAT case 11: // APPEARANCE_TYPE_BAT_HORROR case 52: // APPEARANCE_TYPE_ELEMENTAL_AIR case 53: // APPEARANCE_TYPE_ELEMENTAL_AIR_ELDER case 55: // APPEARANCE_TYPE_FAIRY case 68: // APPEARANCE_TYPE_ELEMENTAL_WATER_ELDER case 69: // APPEARANCE_TYPE_ELEMENTAL_WATER return TRUE; } break; case 1: // BioWare appearances 100 - 199. // Take care of a largish range. if ( 103 <= nAppearance && nAppearance <= 116 ) // LANTERN_ARCHON, QUASIT, IMP, MEPHIT_AIR, MEPHIT_DUST, MEPHIT_EARTH, return TRUE; // MEPHIT_FIRE, MEPHIT_ICE, MEPHIT_SALT, MEPHIT_OOZE, MEPHIT_STEAM, // MEPHIT_MAGMA, MEPHIT_WATER, and WILL_O_WISP. // The rest can be done via a switch. switch ( nAppearance ) { case 100: // APPEARANCE_TYPE_HELMED_HORROR case 144: // APPEARANCE_TYPE_FALCON case 145: // APPEARANCE_TYPE_RAVEN case 146: // APPEARANCE_TYPE_SHADOW case 147: // APPEARANCE_TYPE_SHADOW_FIEND case 156: // APPEARANCE_TYPE_SPECTRE case 186: // APPEARANCE_TYPE_ALLIP case 187: // APPEARANCE_TYPE_WRAITH return TRUE; } break; case 2: // BioWare appearances 200-299. switch ( nAppearance ) { case 291: // APPEARANCE_TYPE_SEAGULL_FLYING case 299: // Beholder, G'Zhorb return TRUE; } break; case 3: // BioWare appearances 300-399. if ( 374 <= nAppearance && nAppearance <= 385 ) // FAERIE_DRAGON, PSEUDODRAGON, WYRMLING_RED, WYRMLING_BLUE, return TRUE; // WYRMLING_BLACK, WYRMLING_GREEN, WYRMLING_WHITE, WYRMLING_BRASS, break; // WYRMLING_COPPER, WYRMLING_BRONZE, WYRMLING_SILVER, WYRMLING_GOLD case 4: // BioWare appearances 400-499. switch ( nAppearance ) { case 401: // APPEARANCE_TYPE_BEHOLDER case 402: // APPEARANCE_TYPE_BEHOLDER_MAGE case 403: // APPEARANCE_TYPE_BEHOLDER_EYEBALL case 419: // APPEARANCE_TYPE_HARPY case 430: // APPEARANCE_TYPE_DEMI_LICH case 447: // APPEARANCE_TYPE_SHARK_MAKO case 448: // APPEARANCE_TYPE_SHARK_HAMMERHEAD case 449: // APPEARANCE_TYPE_SHARK_GOBLIN case 472: // APPEARANCE_TYPE_BEHOLDER_MOTHER return TRUE; } break; // Skipping cases 5-9. There are BioWare appearances, but none fly. case 10: // CEP appearances 1000-1099. switch ( nAppearance ) { case 1046: // Beholder: B* case 1050: // Stirge: Cave* case 1072: // Terradon case 1073: // Flying Eye* case 1087: // Terradon: Large case 1099: // Visage* return TRUE; } break; case 11: // CEP appearances 1100-1199. switch ( nAppearance ) { case 1100: // Visage, Greater* case 1104: // Belker* case 1171: // Bugs* case 1172: // Bugs, Large* return TRUE; } break; case 12: // CEP appearances 1200-1299. switch ( nAppearance ) { case 1218: // Mechanon, Cutter* case 1259: // Vampiric Mist 2* case 1275: // Eagle* case 1281: // Bat, Battle* case 1282: // Bat, Bone* case 1290: // Wendigo* return TRUE; } break; case 13: // CEP appearances 1300-1399. if ( nAppearance == 1307 ) // Demilich B* return TRUE; if ( 1342 <= nAppearance && nAppearance <= 1347 ) // Elemental, Air L*; Elemental, Air M*; Elemental, Air S*; return TRUE; // Elemental, Smoke L*; Elemental, Smoke M*; Elemental, Smoke S* if ( 1354 <= nAppearance && nAppearance <= 1359 ) // Elemental, Water L*; Elemental, Water M*; Elemental, Water S*; return TRUE; // Elemental, Fire L*; Elemental, Fire M*; Elemental, Fire S* if ( 1366 <= nAppearance && nAppearance <= 1368 ) // Elemental, Radiance L*; Elemental, Radiance M*; Elemental, Radiance S* return TRUE; if ( 1372 <= nAppearance && nAppearance <= 1377 ) // Elemental, Steam L*; Elemental, Steam M*; Elemental, Steam S*; return TRUE; // Elemental, Lightning L*; Elemental, Lightning M*; Elemental, Lightning S* if ( 1384 <= nAppearance && nAppearance <= 1389 ) // Elemental, Ash L*; Elemental, Ash M*; Elemental, Ash S*; return TRUE; // Elemental, Vacuum L*; Elemental, Vacuum M*; Elemental, Vacuum S* break; case 14: // CEP appearances 1400-1499. switch ( nAppearance ) { case 1419: // Feather Snake** case 1421: // Animated Wheel* case 1425: // Animated Tome* case 1426: // Animated Chest, Flying* case 1431: // Stirge A* case 1432: // Stirge B* case 1435: // Flying Book A* case 1436: // Flying Book B* case 1437: // Flying Book C* case 1494: // Wasp, Giant* return TRUE; } break; case 15: // CEP appearances 1500-1599. if ( nAppearance == 1508 ) // Beholder:Death Tyrant** return TRUE; if ( 1556 <= nAppearance && nAppearance <= 1565 ) // Dragon: Flying - Red**; Dragon: Flying - Black**; Dragon: Flying - Blue**; return TRUE; // Dragon: Flying - Gold**; Dragon: Flying - White**; Dragon: Flying - Silver**; // Dragon: Flying - Copper**; Dragon: Flying - Green**; // Dragon: Flying - Brass**; Dragon: Flying - Bronze** break; // Skipping cases 16 and 17. No flying appearances. case 18: // CEP appearances 1800-1899. if ( 1807 <= nAppearance && nAppearance <= 1817 ) // Flying Vampire Female**; Flying Vampire Male**; Flying Kobold**; // exclude Werecat Artic [SB]** // Flying Succubus**; [1811 skipped]; Flying Erinyes**; Flying Kobold B**; return nAppearance != 1811; // Flying Kobold Chief A**; Flying Kobold Chief B**; Flying Kobold ShamanA**; // Flying Kobold ShamanB** if ( 1871 <= nAppearance && nAppearance <= 1882 ) // Elemental: Lava**; Elemental: Death**; Elemental: Floral**; Flying Book: Death**; // exclude Barghest v2** // Flying Book: Myst**; Shark: Mako - low**; Shark: Goblin - low**; [1878 skipped]; return nAppearance != 1878; // Shark: Great White**; Shark: Great White - low**; Shark: Tiger**; // Shark: Tiger - low** if ( 1891 <= nAppearance && nAppearance <= 1893 ) // Eagle, Legend**; Bat: Fruit**; Bat: LeafNosed** return TRUE; break; case 19: // CEP appearances 1900-1999. if ( 1947 <= nAppearance && nAppearance <= 1952 ) // Bird: Owl, Brown**; Bird: Owl, Snowy**; Bird: Owl, Barn**; Bird: Owl, Great**; return TRUE; // Bird: Owl, Gray**; Bird: Owl, Black** if ( 1956 <= nAppearance && nAppearance <= 1965 ) // Bird: Macaw**; Bird: Macaw, Red**; Bird: Macaw, Blue**; Bird: Parrot, Grey**; return TRUE; // Bird: Cockatoo, White**; Bird: Cockatoo, Black**; Bird: Parrot, Green**; // Bird: Toucan**; Bird: Albatross**; Bird: Puffin** if ( 1975 <= nAppearance && nAppearance <= 1979 ) // Bird: Blue Jay**; Bird: Cardinal**; Bird: Mockingbird**; Bird: Blackbird**; return TRUE; // Bird: Oriole** if ( nAppearance == 1988 ) // Dragonfly** return TRUE; if ( 1990 <= nAppearance && nAppearance <= 1998 ) // Fairy: Blue**; Fairy: Purple**; Fairy: Orange**; Fairy: Pink**; return TRUE; // Will-O-Wisp: Pink**; Will-O-Wisp: Yellow**; Will-O-Wisp: Purple**; // Will-O-Wisp: Orange**; Will-O-Wisp: Green** break; // Skipping cases 20 to 24. No flying appearances. case 25: // CEP appearances 2500-2599. if ( nAppearance == 2507 ) // Skully return TRUE; break; // Skipping cases 26 to 30. No flying appearances. case 31: // CEP appearances 3100-3199. switch ( nAppearance ) { case 3121: // Efreeti: Noble** case 3122: // Dao** case 3123: // Marid** case 3124: // Djinni** case 3127: // Ice Fiend 2** case 3129: // Elemental: Fire, Grue case 3130: // Elemental: Air, Grue return TRUE; } break; // Skipping cases 32 to 38. No flying appearances. case 39: // CEP appearances 3900-3999. if ( nAppearance == 3999 ) // Bat: Fruit, Small** return TRUE; break; }//switch (nAppearance/100) // Default: not flying. return FALSE; }//spellsIsFlying() // * returns true if oCreature does not have a mind int spellsIsMindless(object oCreature) { switch ( GetRacialType(oCreature) ) { case RACIAL_TYPE_ELEMENTAL: case RACIAL_TYPE_UNDEAD: case RACIAL_TYPE_VERMIN: case RACIAL_TYPE_CONSTRUCT: case RACIAL_TYPE_OOZE: case 52: // CEP: Plant return TRUE; } // Default: has a mind. 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" } }