PRC8/trunk/smp/smp_inc_dispel.nss
Jaysyn904 1662218bb4 Initial upload.
Adding base PRC 4.19a files to repository.
2022-10-07 13:51:24 -04:00

918 lines
34 KiB
Plaintext
Raw Blame History

/*:://////////////////////////////////////////////
//:: Name Dispel Include
//:: FileName SMP_INC_DISPEL
//:://////////////////////////////////////////////
All dispel magic things.
//:://////////////////////////////////////////////
//:: Created By: Jasperre
//::////////////////////////////////////////////*/
#include "SMP_INC_AOE"
#include "SMP_INC_REMOVE"
const string SMP_IMMUNNITY_TO_DISPEL = "SMP_IMMUNNITY_TO_DISPEL";
// SMP_INC_DISPEL. This will dispel magic (All, IE targeted) on oTarget.
// * Checks spell effects for special things when ended.
// * No special reaction checks.
// * Put in eDispel, all effect.
// * Removes all friendly-spell effects off oTarget, by oCaster if "good" spells.
// * Will check items equipped by oTarget, and dispel ALL possible ones.
void SMP_DispelMagicAll(object oTarget, effect eDispel, effect eVis, object oCaster = OBJECT_SELF);
// SMP_INC_DISPEL. This will dispel magic (All, IE targeted) on oTarget.
// * Checks spell effects for special things when ended.
// * No special reaction checks.
// * Put in eDispel, best effect.
// * Removes all friendly-spell effects off oTarget, by oCaster if "good" spells.
// * Will check items equipped by oTarget, and dispel ONE possible effect.
void SMP_DispelMagicBest(object oTarget, effect eDispel, effect eVis, object oCaster = OBJECT_SELF);
// SMP_INC_DISPEL. Dispels all magic on oItem.
// * TRUE if we dispel anything.
int SMP_DispelMagicAllOnItem(object oItem);
// SMP_INC_DISPEL. Dispels one spell on oItem.
// * TRUE if we dispel anything.
int SMP_DispelMagicBestOnItem(object oItem);
// SMP_INC_DISPEL. This will disjoin magical effects on oTarget (Mage's Disjuction).
// - Checks spell effects for special things when ended.
// - No special reaction checks.
// - It will remove all SUBTYPE_MAGICAL effects which have
// GetEffectSpellId() != SPELL_INVALID
// * Note it can remove some effects Dispel Magic cannot. And does so here.
void SMP_DisjoinMagic(object oTarget, int nVFX = VFX_IMP_DISPEL, object oCaster = OBJECT_SELF);
// SMP_INC_DISPEL.
// This will dispel magic - on an area of effect. Each one will need a seperate
// caster check to destroy and must be from a spell, of course.
void SMP_DispelMagicAreaOfEffect(object oAOE, int nCasterLevel);
// SMP_INC_DISPEL.
// By putting in nMPH, it will see if it can remove oAOE, if it is a fog-based AOE.
void SMP_DispelWindAreaOfEffect(object oAOE, int nMPH);
// SMP_INC_DISPEL.
// This will remove all "friendly" effects from oTarget which are from spells.
// - Only do this if oTarget is an enemy.
void SMP_DispelAllFriendlySpells(object oTarget, object oCaster = OBJECT_SELF);
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells which are of
// nEffectType, using nCasterLevel.
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllEffectsOfType(object oTarget, int nCasterLevel, int nEffectType);
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells which are
// nSpellId, using nCasterLevel. Once one is tested, all are removed.
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllSpellsOfId(object oTarget, int nCasterLevel, int nSpellId);
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells cast by
// Good/Evil Alignment nAlignment. Goes from Best to Worse, using nCasterLevel.
// * Also the list will try any GoodEvil spells of nAlignment
// * Returns TRUE if any are removed, and 2 if any are found. (for VFX's)
int SMP_DispelBestSpellFromGoodEvilAlignment(object oTarget, int nCasterLevel, int nAlignment);
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells cast by
// Good/Evil Alignment nAlignment.
// * Also the list will try any GoodEvil spells of nAlignment
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllSpellFromGoodEvilAlignment(object oTarget, int nCasterLevel, int nAlignment);
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells cast by
// Law/Chaos Alignment nAlignment. Goes from Best to Worse, using nCasterLevel.
// * Also the list will try any LawChaos spells of nAlignment
// * Returns TRUE if any are removed, and 2 if any are found. (for VFX's)
int SMP_DispelBestSpellFromLawChaosAlignment(object oTarget, int nCasterLevel, int nAlignment);
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells cast by
// Law/Chaos Alignment nAlignment.
// * Also the list will try any LawChaos spells of nAlignment
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllSpellFromLawChaosAlignment(object oTarget, int nCasterLevel, int nAlignment);
// SMP_INC_DISPEL.
// Get the caster level of nSpellId from oCaster. This will get the last caster level
// of the spell cast by oCaster of nSpellId.
// * Used in dispel functions.
// * If oCaster is invalid, it will use the Spell Level (Innate) + 1 / 2 to get the
// minimum caster level for at least a half-decent DC
int SMP_DispelGetCasterLevelOfSpell(int nSpellId, object oCaster);
// SMP_INC_DISPEL. Get the level of the spell, nSpellId, last cast by oCreator.
// * Use the innate level if the caster is invalid.
int SMP_DispelGetLevelOfSpell(int nSpellId, object oCaster);
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells which are of
// the spell school nSpellSchool.
// * If nLevelIfSpecial is over 0, and the effect is supernatural or extraodinary,
// it will dispel it still if the spell's level is <= nLevelIfSpecial
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllSpellsFromSpellSchool(object oTarget, int nCasterLevel, int nSpellSchool, int nLevelIfSpecial = 0);
// SMP_INC_DISPEL. Returns an integer value of all the valid effects on oTarget.
// Used in "Best" dispel function.
int SMP_DispelCountEffectsOnTarget(object oTarget);
// Start functions
// SMP_INC_DISPEL. This will dispel magic (All, IE targeted) on oTarget.
// * Checks spell effects for special things when ended.
// * No special reaction checks.
// * Put in eDispel, all effect.
// * Removes all friendly-spell effects off oTarget, by oCaster if "good" spells.
// * Will check items equipped by oTarget, and dispel ALL possible ones.
void SMP_DispelMagicAll(object oTarget, effect eDispel, effect eVis, object oCaster = OBJECT_SELF)
{
// If they are specifically immune to dispel, do not dispel!
if(GetLocalInt(oTarget, SMP_IMMUNNITY_TO_DISPEL)) return;
// We remove all friendly spell effects cast by oCaster if they are not
// a friend/faction equal
if(!GetIsFriend(oTarget, oCaster) && !GetFactionEqual(oTarget, oCaster))
{
// Remove them
SMP_DispelAllFriendlySpells(oTarget, oCaster);
}
// Apply dispel
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDispel, oTarget);
// We can also dispel all magical spells from thier items
int nCnt;
for(nCnt = 0; nCnt <= NUM_INVENTORY_SLOTS; nCnt++)
{
// Dispel the magic from that slot.
SMP_DispelMagicAllOnItem(GetItemInSlot(nCnt, oTarget));
}
}
// SMP_INC_DISPEL. This will dispel magic (All, IE targeted) on oTarget.
// * Checks spell effects for special things when ended.
// * No special reaction checks.
// * Put in eDispel, best effect.
// * Removes all friendly-spell effects off oTarget, by oCaster if "good" spells.
// * Will check items equipped by oTarget, and dispel ONE possible effect.
void SMP_DispelMagicBest(object oTarget, effect eDispel, effect eVis, object oCaster = OBJECT_SELF)
{
// If they are specifically immune to dispel, do not dispel!
if(GetLocalInt(oTarget, SMP_IMMUNNITY_TO_DISPEL)) return;
// We remove all friendly spell effects cast by oCaster if they are not
// a friend/faction equal
if(!GetIsFriend(oTarget, oCaster) && !GetFactionEqual(oTarget, oCaster))
{
// Remove them
SMP_DispelAllFriendlySpells(oTarget, oCaster);
}
// Count up the effects on oTarget before applying eDispel
int nBefore = SMP_DispelCountEffectsOnTarget(oTarget);
// Apply dispel
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDispel, oTarget);
// Count up the effects on oTarget after applying eDispel
int nAfter = SMP_DispelCountEffectsOnTarget(oTarget);
// If we have removed at least 1 effect from oTarget, we do not dispel
// item properties.
if(nBefore > nAfter)
{
// We can also dispel the best magical spells from thier items if we have
// not removed anything from eDispel.
int nCnt, bDone;
for(nCnt = 0; (bDone != TRUE && nCnt <= NUM_INVENTORY_SLOTS); nCnt++)
{
// Dispel the best magic from that slot.
bDone = SMP_DispelMagicBestOnItem(GetItemInSlot(nCnt, oTarget));
}
}
}
// SMP_INC_DISPEL. Dispels all magic on oItem.
// * TRUE if we dispel anything.
int SMP_DispelMagicAllOnItem(object oItem)
{
// Return value
int bReturn, bGotSpell;
// We need to check a local variable - is there any valid spells on the
// item, or cast on it?
if(GetLocalInt(oItem, "SMP_ITEM_SPELLCASTON") == TRUE)
{
// We loop the item properties on oItem.
itemproperty ipCheck = GetFirstItemProperty(oItem);
int nPropType;
while(GetIsItemPropertyValid(ipCheck))
{
// Check duration
if(GetItemPropertyDurationType(ipCheck) == DURATION_TYPE_TEMPORARY)
{
// We check nPropType
nPropType = GetItemPropertyType(ipCheck);
// Each spell will set, on the item, a valid integer for the caster
// level of the temp item property.
// TO DO
// Set bGotSpell to TRUE
bGotSpell = TRUE;
}
}
// Note: Here, if we didn't find any tempoary item properties from spells, we
// will set the local to FALSE again, by deleting it.
if(bGotSpell == FALSE)
{
DeleteLocalInt(oItem, "SMP_ITEM_SPELLCASTON");
}
}
return bReturn;
}
// SMP_INC_DISPEL. Dispels one spell on oItem.
// * TRUE if we dispel anything.
int SMP_DispelMagicBestOnItem(object oItem)
{
// Return value
int bReturn, bGotSpell;
// We need to check a local variable - is there any valid spells on the
// item, or cast on it?
if(GetLocalInt(oItem, "SMP_ITEM_SPELLCASTON") == TRUE)
{
// We loop the item properties on oItem.
itemproperty ipCheck = GetFirstItemProperty(oItem);
int nPropType;
while(GetIsItemPropertyValid(ipCheck))
{
// Check duration
if(GetItemPropertyDurationType(ipCheck) == DURATION_TYPE_TEMPORARY)
{
// We check nPropType
nPropType = GetItemPropertyType(ipCheck);
// Each spell will set, on the item, a valid integer for the caster
// level of the temp item property.
// TO DO
// Set bGotSpell to TRUE
bGotSpell = TRUE;
}
}
// Note: Here, if we didn't find any tempoary item properties from spells, we
// will set the local to FALSE again, by deleting it.
if(bGotSpell == FALSE)
{
DeleteLocalInt(oItem, "SMP_ITEM_SPELLCASTON");
}
}
return bReturn;
}
// SMP_INC_DISPEL.
// This will dispel magic - on an area of effect. Each one will need a seperate
// caster check to destroy and must be from a spell, of course.
void SMP_DispelMagicAreaOfEffect(object oAOE, int nCasterLevel)
{
// Can't be a plotted AOE - as it will not be destroyed anyway!
if(GetPlotFlag(oAOE)) return;
// Dispel the AOE
int nEnemyCasterLevel = SMP_GetAOECasterLevel(oAOE);
// Forbiddance:
// Dispel magic does not dispel a forbiddance effect unless the dispeller<65>s
// level is at least as high as your caster level.
if(GetTag(oAOE) == SMP_AOE_TAG_PER_FORBIDDANCE)
{
if(nEnemyCasterLevel >= nCasterLevel)
{
// Cannot dispel!
return;
}
}
// Get the level of the AOE
int nDC = 11 + nEnemyCasterLevel;
// Do the roll
int nCasterRoll = d20() + nCasterLevel;
// If sucessful, destroy the target.
if(nCasterRoll >= nDC)
{
DestroyObject(oAOE);
}
}
// SMP_INC_DISPEL.
// By putting in nMPH, it will see if it can remove oAOE, if it is a fog-based AOE.
void SMP_DispelWindAreaOfEffect(object oAOE, int nMPH)
{
// Can't be a plotted AOE - as it will not be destroyed anyway!
if(GetPlotFlag(oAOE)) return;
// Spells used in: Gust of Wind (50MPH)
// We check the tag of oAOE
string sTag = GetTag(oAOE);
// We get the DC of the MPH needed. It will be slightly randomised.
// - Note that it is the "is removed in 1 round" MPH needed. This is an instant
// gust of wind.
int nDC;
// Will finish later.
if(sTag == SMP_AOE_TAG_PER_ACID_FOG)
{
nDC = 40 + Random(11);
}
// If sucessful, destroy the target.
if(nMPH >= nDC)
{
DestroyObject(oAOE);
}
}
// SMP_INC_DISPEL. This will disjoin magical effects on oTarget (Mage's Disjuction).
// - Checks spell effects for special things when ended.
// - No special reaction checks.
// - It will remove all SUBTYPE_MAGICAL effects which have
// GetEffectSpellId() != SPELL_INVALID
// * Note it can remove some effects Dispel Magic cannot. And does so here.
void SMP_DisjoinMagic(object oTarget, int nVFX = VFX_IMP_DISPEL, object oCaster = OBJECT_SELF)
{
// If they are specifically immune to dispel, do not dispel!
if(GetLocalInt(oTarget, SMP_IMMUNNITY_TO_DISPEL)) return;
// We do not affect ourselves:
// All magical effects from spells and magic items within the radius of the
// spell, |||except for those that you carry or touch|||, are disjoined.
if(oTarget == oCaster) return;
// Declare effects
effect eVis = EffectVisualEffect(nVFX);
int nSpellId;
// Set if the target has any spell effects that have effects applied
// when ended.
// - Stuff
// Apply dispel
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck))
{
nSpellId = GetEffectSpellId(eCheck);
// Remove all magical spell applied effects
if(nSpellId != SPELL_INVALID &&
GetEffectSubType(eCheck) == SUBTYPE_MAGICAL)
{
RemoveEffect(oTarget, eCheck);
}
// * Seal magic is also disjoined
else if(nSpellId == SMP_SPELL_SEAL_MAGIC)
{
RemoveEffect(oTarget, eCheck);
}
eCheck = GetNextEffect(oTarget);
}
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
// And apply the effects of spells removed.
// - Stuff
}
// SMP_INC_DISPEL.
// This will remove all "friendly" effects from oTarget which are from spells.
// - Only do this if oTarget is an enemy.
void SMP_DispelAllFriendlySpells(object oTarget, object oCaster = OBJECT_SELF)
{
// Get first effect from oTarget
effect eCheck = GetFirstEffect(oTarget);
int nSpellId = -1;
// Remove all from oCaster, which have a valid spell ID and friendly status.
while(GetIsEffectValid(eCheck))
{
if(GetEffectCreator(eCheck) == oCaster)
{
//If the effect was created by the spell then remove it
nSpellId = GetEffectSpellId(eCheck);
if(nSpellId >= 0)
{
// Check if not-hostile.
if(SMP_ArrayGetIsHostile(nSpellId) == FALSE)
{
RemoveEffect(oTarget, eCheck);
}
}
}
//Get next effect on the target
eCheck = GetNextEffect(oTarget);
}
}
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells which are of
// nEffectType, using nCasterLevel.
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllEffectsOfType(object oTarget, int nCasterLevel, int nEffectType)
{
int bReturn = FALSE;
int nEffectCasterLevel, nSpellId, nDC;
// Loop effects and try and dispel each one!
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck))
{
// Magical subtype and must be from a spell, and nEffectType must match!
nSpellId = GetEffectSpellId(eCheck);
if(nSpellId >= 0 && GetEffectType(eCheck) == nEffectType &&
GetEffectSubType(eCheck) == SUBTYPE_MAGICAL)
{
// We try and dispel the spells effects
nEffectCasterLevel = SMP_DispelGetCasterLevelOfSpell(nSpellId, GetEffectCreator(eCheck));
// DC is always 11 + nEffectCasterLevel
nDC = 11 + nEffectCasterLevel;
// Dispel!
if(nCasterLevel + d20() >= nDC)
{
// Remove the effect!
RemoveEffect(oTarget, eCheck);
bReturn = TRUE;
}
}
eCheck = GetNextEffect(oTarget);
}
return bReturn;
}
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells which are
// nSpellId, using nCasterLevel. Once one is tested, all are removed.
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllSpellsOfId(object oTarget, int nCasterLevel, int nSpellId)
{
int bReturn = FALSE;
int nEffectCasterLevel, nSpellId, nDC;
// Loop effects and try and dispel each one!
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck))
{
// Magical subtype and must be from nSpellId.
nSpellId = GetEffectSpellId(eCheck);
if(nSpellId == nSpellId &&
GetEffectSubType(eCheck) == SUBTYPE_MAGICAL)
{
// We try and dispel the spells effects
nEffectCasterLevel = SMP_DispelGetCasterLevelOfSpell(nSpellId, GetEffectCreator(eCheck));
// DC is always 11 + nEffectCasterLevel
nDC = 11 + nEffectCasterLevel;
// Dispel!
if(nCasterLevel + d20() >= nDC)
{
// Remove the effect!
RemoveEffect(oTarget, eCheck);
bReturn = TRUE;
}
}
eCheck = GetNextEffect(oTarget);
}
return bReturn;
}
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells cast by
// Good/Evil Alignment nAlignment. Goes from Best to Worse, using nCasterLevel.
// * Also the list will try any GoodEvil spells of nAlignment
// * Returns TRUE if any are removed, and 2 if any are found. (for VFX's)
int SMP_DispelBestSpellFromGoodEvilAlignment(object oTarget, int nCasterLevel, int nAlignment)
{
// BEST VERSION. This will only dispel the best evil spell on the target.
// Decided:
// - Going to just dispel the FIST evil spell on the target...
int bReturn = FALSE;
int nEffectCasterLevel, nSpellId, nDC;
object oCreator;
// Loop effects to get the best to worst spells.
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck) && bReturn != TRUE)
{
// Magical subtype and must be from nSpellId.
nSpellId = GetEffectSpellId(eCheck);
oCreator = GetEffectCreator(eCheck);
if(nSpellId >= 0 &&
GetEffectSubType(eCheck) == SUBTYPE_MAGICAL)
{
// Check alignment GOOD/EVIL
if(SMP_ArrayGetSpellGoodEvilAlignment(nSpellId) == nAlignment ||
// Note: Returns -1 if invalid, so this is good to use easily.
GetAlignmentGoodEvil(oCreator) == nAlignment)
{
// Dispel found
bReturn = 2;
// We try and dispel the spells effects
nEffectCasterLevel = SMP_DispelGetCasterLevelOfSpell(nSpellId, oCreator);
// DC is always 11 + nEffectCasterLevel
nDC = 11 + nEffectCasterLevel;
// Dispel!
if(nCasterLevel + d20() >= nDC)
{
// Remove all effects from the spell by oCreator
SMP_PRCRemoveSpellEffects(nSpellId, oCreator, oTarget, 0.1);
bReturn = TRUE;
}
}
}
eCheck = GetNextEffect(oTarget);
}
return bReturn;
}
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells cast by
// Good/Evil Alignment nAlignment.
// * Also the list will try any GoodEvil spells of nAlignment
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllSpellFromGoodEvilAlignment(object oTarget, int nCasterLevel, int nAlignment)
{
int bReturn = FALSE;
int nEffectCasterLevel, nSpellId, nDC;
object oCreator;
string sId;
// Loop effects and try and dispel each one!
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck))
{
// Magical subtype and must be from nSpellId.
nSpellId = GetEffectSpellId(eCheck);
sId = "SMP_ALIGNMENTDISPEL" + IntToString(nSpellId);
oCreator = GetEffectCreator(eCheck);
// We check if we have dispelled this spells' effect already
// * Local will be either an alignment (>= 1), -1 for invalid alignment
// or -2 for "never dispel this effect". -2 will never match.
if(GetAlignmentGoodEvil(oCreator) == GetLocalInt(OBJECT_SELF, sId))
{
// Remove
// * Note to self: could make it more complexe and, say, check the
// effect creator. Would need more complexe integers, however.
// * We do, though, check the alignment of the spellcaster against
// the local, this is a partial check.
RemoveEffect(oTarget, eCheck);
}
else if(nSpellId >= 0 &&
GetEffectSubType(eCheck) == SUBTYPE_MAGICAL &&
GetLocalInt(OBJECT_SELF, sId) != -2)
{
// Check alignment GOOD/EVIL
if(SMP_ArrayGetSpellGoodEvilAlignment(nSpellId) == nAlignment ||
// Note: Returns -1 if invalid, so this is good to use easily.
GetAlignmentGoodEvil(oCreator) == nAlignment)
{
// We try and dispel the spells effects
nEffectCasterLevel = SMP_DispelGetCasterLevelOfSpell(nSpellId, oCreator);
// DC is always 11 + nEffectCasterLevel
nDC = 11 + nEffectCasterLevel;
// Dispel!
if(nCasterLevel + d20() >= nDC)
{
// Remove the effect!
RemoveEffect(oTarget, eCheck);
// NOTE:
// - Because we have dispelled this spell - other effects
// from this spell (like visuals) might still be present.
// This isn't the case when we check specific effects, but
// it is when we dispel all spells of nSpellId, from oTarget.
// This means I'll set a local variable to the caster (OBJECT_SELF)
// so it'll remove futher effects from nSpellId.
// GetAlignmentGoodEvil() is DISPEL ALL OTHERS
SetLocalInt(OBJECT_SELF, sId, GetAlignmentGoodEvil(oCreator));
DelayCommand(1.0, DeleteLocalInt(OBJECT_SELF, sId));
bReturn = TRUE;
}
else
{
// See above, but the dispel failed, so we set to NEVER
// remove futher effects from nSpellId.
// -2 is IGNORE ALL OTHERS
SetLocalInt(OBJECT_SELF, sId, -2);
DelayCommand(1.0, DeleteLocalInt(OBJECT_SELF, sId));
}
}
}
eCheck = GetNextEffect(oTarget);
}
return bReturn;
}
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells cast by
// Law/Chaos Alignment nAlignment. Goes from Best to Worse, using nCasterLevel.
// * Also the list will try any LawChaos spells of nAlignment
// * Returns TRUE if any are removed, and 2 if any are found. (for VFX's)
int SMP_DispelBestSpellFromLawChaosAlignment(object oTarget, int nCasterLevel, int nAlignment)
{
// BEST VERSION. This will only dispel the best evil spell on the target.
// Decided:
// - Going to just dispel the FIST evil spell on the target...
int bReturn = FALSE;
int nEffectCasterLevel, nSpellId, nDC;
object oCreator;
// Loop effects to get the best to worst spells.
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck) && bReturn != TRUE)
{
// Magical subtype and must be from nSpellId.
nSpellId = GetEffectSpellId(eCheck);
oCreator = GetEffectCreator(eCheck);
if(nSpellId >= 0 &&
GetEffectSubType(eCheck) == SUBTYPE_MAGICAL)
{
// Check alignment LAW/CHAOS
if(SMP_ArrayGetSpellLawChaosAlignment(nSpellId) == nAlignment ||
// Note: Returns -1 if invalid, so this is good to use easily.
GetAlignmentLawChaos(oCreator) == nAlignment)
{
// Dispel found
bReturn = 2;
// We try and dispel the spells effects
nEffectCasterLevel = SMP_DispelGetCasterLevelOfSpell(nSpellId, oCreator);
// DC is always 11 + nEffectCasterLevel
nDC = 11 + nEffectCasterLevel;
// Dispel!
if(nCasterLevel + d20() >= nDC)
{
// Remove all effects from the spell by oCreator
SMP_PRCRemoveSpellEffects(nSpellId, oCreator, oTarget, 0.1);
bReturn = TRUE;
}
}
}
eCheck = GetNextEffect(oTarget);
}
return bReturn;
}
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells cast by
// Law/Chaos Alignment nAlignment.
// * Also the list will try any LawChaos spells of nAlignment
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllSpellFromLawChaosAlignment(object oTarget, int nCasterLevel, int nAlignment)
{
int bReturn = FALSE;
int nEffectCasterLevel, nSpellId, nDC;
object oCreator;
string sId;
// Loop effects and try and dispel each one!
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck))
{
// Magical subtype and must be from nSpellId.
nSpellId = GetEffectSpellId(eCheck);
sId = "SMP_ALIGNMENTDISPEL" + IntToString(nSpellId);
oCreator = GetEffectCreator(eCheck);
// We check if we have dispelled this spells' effect already
// * Local will be either an alignment (>= 1), -1 for invalid alignment
// or -2 for "never dispel this effect". -2 will never match.
if(GetAlignmentLawChaos(oCreator) == GetLocalInt(OBJECT_SELF, sId))
{
// Remove
// * Note to self: could make it more complexe and, say, check the
// effect creator. Would need more complexe integers, however.
// * We do, though, check the alignment of the spellcaster against
// the local, this is a partial check.
RemoveEffect(oTarget, eCheck);
}
else if(nSpellId >= 0 &&
GetEffectSubType(eCheck) == SUBTYPE_MAGICAL &&
GetLocalInt(OBJECT_SELF, sId) != -2)
{
// Check alignment LAW/CHAOS
if(SMP_ArrayGetSpellLawChaosAlignment(nSpellId) == nAlignment ||
// Note: Returns -1 if invalid, so this is good to use easily.
GetAlignmentLawChaos(oCreator) == nAlignment)
{
// We try and dispel the spells effects
nEffectCasterLevel = SMP_DispelGetCasterLevelOfSpell(nSpellId, oCreator);
// DC is always 11 + nEffectCasterLevel
nDC = 11 + nEffectCasterLevel;
// Dispel!
if(nCasterLevel + d20() >= nDC)
{
// Remove the effect!
RemoveEffect(oTarget, eCheck);
// NOTE:
// - Because we have dispelled this spell - other effects
// from this spell (like visuals) might still be present.
// This isn't the case when we check specific effects, but
// it is when we dispel all spells of nSpellId, from oTarget.
// This means I'll set a local variable to the caster (OBJECT_SELF)
// so it'll remove futher effects from nSpellId.
// GetAlignmentGoodEvil() is DISPEL ALL OTHERS
SetLocalInt(OBJECT_SELF, sId, GetAlignmentLawChaos(oCreator));
DelayCommand(1.0, DeleteLocalInt(OBJECT_SELF, sId));
bReturn = TRUE;
}
else
{
// See above, but the dispel failed, so we set to NEVER
// remove futher effects from nSpellId.
// -2 is IGNORE ALL OTHERS
SetLocalInt(OBJECT_SELF, sId, -2);
DelayCommand(1.0, DeleteLocalInt(OBJECT_SELF, sId));
}
}
}
eCheck = GetNextEffect(oTarget);
}
return bReturn;
}
// SMP_INC_DISPEL.
// Get the caster level of nSpellId from oCaster. This will get the last caster level
// of the spell cast by oCaster of nSpellId.
// * Used in dispel functions.
// * If oCaster is invalid, it will use the Spell Level (Innate) + 1 / 2 to get the
// minimum caster level for at least a half-decent DC
int SMP_DispelGetCasterLevelOfSpell(int nSpellId, object oCaster)
{
int nReturn;
if(GetIsObjectValid(oCaster))
{
// Get value stored SMP_inc_spellhook
nReturn = GetLocalInt(oCaster, "SMP_SPELL_CAST_BY_LEVEL_" + IntToString(nSpellId));
}
else
{
// If oCaster is invalid, it will use the Spell Level (Innate) + 1 / 2 to
// get the minimum caster level for at least a half-decent DC
nReturn = (SMP_ArrayGetInteger(SMP_2DA_NAME_SPELLS, SMP_2DA_COLUMN_SPELLS_INNATE, nSpellId) + 1) / 2;
}
return nReturn;
}
// SMP_INC_DISPEL. Get the level of the spell, nSpellId, last cast by oCreator.
// * Use the innate level if the caster is invalid.
int SMP_DispelGetLevelOfSpell(int nSpellId, object oCaster)
{
int nReturn;
if(GetIsObjectValid(oCaster))
{
// Get value stored SMP_inc_spellhook
nReturn = GetLocalInt(oCaster, "SMP_SPELL_CAST_SPELL_LEVEL" + IntToString(nSpellId));
}
else
{
// If oCaster is invalid, it will use the Spell Level (Innate)
nReturn = SMP_ArrayGetInteger(SMP_2DA_NAME_SPELLS, SMP_2DA_COLUMN_SPELLS_INNATE, nSpellId);
}
return nReturn;
}
// SMP_INC_DISPEL.
// Does a dispel check against oTarget for all effects from spells which are of
// the spell school nSpellSchool.
// * If nLevelIfSpecial is over 0, and the effect is supernatural or extraodinary,
// it will dispel it still if the spell's level is <= nLevelIfSpecial
// * Returns TRUE if any are removed (for VFX's)
int SMP_DispelAllSpellsFromSpellSchool(object oTarget, int nCasterLevel, int nSpellSchool, int nLevelIfSpecial = 0)
{
int bReturn = FALSE;
int nEffectCasterLevel, nSpellLevel, nSpellId, nDC;
object oCreator;
string sId;
// Loop effects and try and dispel each one!
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck))
{
// Magical subtype and must be from nSpellId.
nSpellId = GetEffectSpellId(eCheck);
sId = "SMP_SPELLSCHOOLDISPEL" + IntToString(nSpellId);
oCreator = GetEffectCreator(eCheck);
// We check if we have dispelled this spells' effect already
// * Local will be either be 1, for dispel all spells of this spell ID,
// or -2 for "never dispel this effect". -2 will never match.
if(GetLocalInt(OBJECT_SELF, sId) == TRUE)
{
// Remove
// * Note to self: could make it more complexe and, say, check the
// effect creator. Would need more complexe integers, however.
// * In this case (against the alignment thing) we don't check
// alignment.
RemoveEffect(oTarget, eCheck);
}
else if(nSpellId >= 0 &&
// Check spell school
SMP_ArrayGetSpellSchool(nSpellId) == nSpellSchool &&
// Special: If it isn't a magical subtype, we may still dispel
// if the spells level is <= nLevelIfSpecial.
(GetEffectSubType(eCheck) == SUBTYPE_MAGICAL ||
// * NOTE: Using special function, will at least return innate column
// or the value, if present, set in the spell hook.
SMP_DispelGetLevelOfSpell(nSpellId, oCreator) <= nLevelIfSpecial) &&
GetLocalInt(OBJECT_SELF, sId) != -2)
{
// We try and dispel the spells effects
nEffectCasterLevel = SMP_DispelGetCasterLevelOfSpell(nSpellId, oCreator);
// DC is always 11 + nEffectCasterLevel
nDC = 11 + nEffectCasterLevel;
// Dispel!
if(nCasterLevel + d20() >= nDC)
{
// Remove the effect!
RemoveEffect(oTarget, eCheck);
// NOTE:
// - Because we have dispelled this spell - other effects
// from this spell (like visuals) might still be present.
// This isn't the case when we check specific effects, but
// it is when we dispel all spells of nSpellId, from oTarget.
// This means I'll set a local variable to the caster (OBJECT_SELF)
// so it'll remove futher effects from nSpellId.
// We use a mear TRUE value for this for now.
SetLocalInt(OBJECT_SELF, sId, TRUE);
DelayCommand(1.0, DeleteLocalInt(OBJECT_SELF, sId));
bReturn = TRUE;
}
else
{
// -2 is IGNORE ALL OTHERS
SetLocalInt(OBJECT_SELF, sId, -2);
DelayCommand(1.0, DeleteLocalInt(OBJECT_SELF, sId));
}
}
eCheck = GetNextEffect(oTarget);
}
return bReturn;
}
// SMP_INC_DISPEL. Returns an integer value of all the valid effects on oTarget.
// Used in "Best" dispel function.
int SMP_DispelCountEffectsOnTarget(object oTarget)
{
int nReturn = 0;
effect eCheck = GetFirstEffect(oTarget);
while(GetIsEffectValid(eCheck))
{
// Add one to effects found
nReturn++;
eCheck = GetNextEffect(oTarget);
}
// Return the amount
return nReturn;
}
// End of file Debug lines. Uncomment below "/*" with "//" and compile.
/*
void main()
{
return;
}
//*/