Here's our dispel code, courtesy of acaos. The first script fires for all dispel spells (modified all dispell spell scripts to it in the 2da). The second is an include. Most of the functions you need are there, though the GetSpellInfo function, and the resulting si. struct is not - it simply collects normal information like casterlevel, dc, metamagic, and the like prior to the rest of the spellscript:
#include "hg_inc"
#include "ac_spell_inc"
#include "ac_dispel_inc"
void main() {
struct SpellInfo si = GetSpellInfo();
if (si.id < 0)
return;
int nBreach = 0, nSR = 0, nBonus = 0, nVis = -1, bAoE = !GetIsObjectValid(si.target);
int nAoEMask = OBJECT_TYPE_CREATURE|OBJECT_TYPE_PLACEABLE|OBJECT_TYPE_AREA_OF_EFFECT;
int nAoESpellId = SPELL_HOLY_SWORD;
float fRadius = RADIUS_SIZE_COLOSSAL;
int nOrigClvl = si.clevel;
switch (si.id) {
case SPELL_LESSER_DISPEL:
si.clevel = 1 + (si.clevel / 4);
nBonus = 4;
nVis = VFX_FNF_DISPEL;
break;
case SPELL_DISPEL_MAGIC:
si.clevel = 1 + (si.clevel / 3);
nBonus = 6;
nVis = VFX_FNF_DISPEL;
break;
case SPELL_GREATER_DISPELLING:
si.clevel = 1 + (si.clevel / 2);
nBonus = 8;
nVis = VFX_FNF_DISPEL_GREATER;
break;
case SPELL_LESSER_SPELL_BREACH:
si.clevel = 0;
nBreach = 2;
nSR = 3;
break;
case SPELL_GREATER_SPELL_BREACH:
if (si.class == class_TYPE_SHIFTER) {
si.clevel = 0;
nBreach = 1 + GetLocalInt(si.caster, "PolyFoci");
nSR = nBreach + 1;
bAoE = TRUE;
nVis = VFX_IMP_DISPEL;
nAoEMask = OBJECT_TYPE_CREATURE;
nAoESpellId = si.id;
fRadius = RADIUS_SIZE_SMALL;
} else {
si.clevel = 0;
nBreach = 4;
nSR = 5;
}
break;
case HGSPELL_GREATER_SPELL_BREACH:
si.clevel = 0;
nBreach = 6;
nSR = 7;
break;
case SPELL_MORDENKAINENS_DISJUNCTION:
if ((si.clevel = GetHitDiceIncludingLLs(si.caster)) > 60)
si.clevel = 60;
nBreach = (bAoE ? 2 : 6);
nSR = 10;
nBonus = 2;
nVis = VFX_FNF_DISPEL_DISJUNCTION;
break;
default:
FloatingTextStringOnCreature("An invalid dispel spell #" + IntToString(si.id) + " was cast. Please inform a DM.", si.caster);
break;
}
if (nBonus > 0 && !GetIsObjectValid(si.item)) {
int nFocus = GetCasterSpellFocus(SPELL_SCHOOL_ABJURATION, si.caster, nOrigClvl, si.class);
si.clevel += nFocus * nBonus;
if (GetIsObjectValid(si.target))
SetLocalInt(si.target, "AuraSuppressed", 1 + nFocus);
}
if (bAoE) {
float fDelay;
if (nVis < 0)
return;
ApplyVisualAtLocation(nVis, si.loc);
for (si.target = GetFirstObjectInShape(SHAPE_SPHERE, fRadius, si.loc, TRUE, nAoEMask);
GetIsObjectValid(si.target);
si.target = GetNextObjectInShape(SHAPE_SPHERE, fRadius, si.loc, TRUE, nAoEMask)) {
fDelay = GetSpellEffectDelay(si.loc, si.target);
SignalEvent(si.target, EventSpellCastAt(si.caster, si.id, FALSE));
if (GetObjectType(si.target) == OBJECT_TYPE_AREA_OF_EFFECT)
DoIndividualAoEDispel(si.target, si.clevel);
else
DelayCommand(fDelay, DoBreachAndDispel(si.target, si.clevel, (si.clevel > 0 ? 1 : 0), nBreach, nSR, nAoESpellId));
}
} else
DoBreachAndDispel(si.target, si.clevel, (si.clevel > 0 ? 100 : 0), nBreach, nSR, si.id);
}
Here's the ac_dispel_inc include:
// Replacements for spellsDispelMagic, spellsDispelAoE, and DoSpellBreach,
// which integrate most of the common code from those and from the dispel
// and breach spells into a single source base.
#include "spell_func_inc"
#include "fky_chat_const"
const string COLOR_LT_ORANGE = "<cþÀP>";
void DoIndividualAoEDispel (object oTarget, int nDispelLevel) {
object oArea = GetArea(oTarget);
object oCreator = GetAreaOfEffectCreator(oTarget);
/* The old code used 25% for Lesser Dispel, 50% for Dispel, 75% for Greater
Dispel, and 100% for Mordenkainen's Disjunction. Here, just use twice the
caster level as the dispel chance. */
/* Area-created and Hells AoEs are not dispellable */
if (oCreator == oArea ||
GetResRef(oCreator) == "h_quimath" ||
GetLocalInt(oTarget, "NoAoEDispel"))
nDispelLevel = 0;
if (Random(100) < nDispelLevel * 2) {
object oPlaceable = GetLocalObject(oTarget, "AoEPlaceable");
if (GetIsObjectValid(oPlaceable)) {
SetPlotFlag(oPlaceable, FALSE);
DestroyObject(oPlaceable);
}
DestroyObject(oTarget);
FloatingTextStrRefOnCreature(100929, OBJECT_SELF); // "AoE dispelled"
} else {
FloatingTextStrRefOnCreature(100930, OBJECT_SELF); // "AoE not dispelled "
}
}
void DoBreachAndDispel (object oTarget, int nDispelLevel, int nDispels, int nBreaches, int nSR, int nSpellId=-1, object oCaster=OBJECT_SELF) {
if (nSpellId < 0) {
switch (nBreaches) {
case 4: nSpellId = SPELL_GREATER_SPELL_BREACH; break;
case 2: nSpellId = SPELL_LESSER_SPELL_BREACH; break;
case 6: nSpellId = HGSPELL_GREATER_SPELL_BREACH; break;
case 3: nSpellId = SPELL_HOLY_SWORD; break;
case 0: nSpellId = SPELL_DISPEL_MAGIC; break;
default: nSpellId = SPELL_GREATER_SPELL_BREACH; break;
}
}
if (nSpellId >= 0) {
if (GetIsReactionTypeFriendly(oTarget))
SignalEvent(oTarget, EventSpellCastAt(oCaster, nSpellId, FALSE));
else
SignalEvent(oTarget, EventSpellCastAt(oCaster, nSpellId));
if (GetHasSpellImmunity(nSpellId, oTarget) || GetHasSpellEffect(20127, oTarget)) //Checks for Spellguard now
return;
}
int nTargetType = GetObjectType(oTarget);
if (!(nTargetType == OBJECT_TYPE_PLACEABLE && !GetUseableFlag(oTarget)))
ApplyVisualToObject(VFX_IMP_BREACH, oTarget);
if (GetIsReactionTypeFriendly(oTarget, oCaster)) {
nSR = 0;
nBreaches = 0;
} else if (nSR > 0 && nTargetType == OBJECT_TYPE_CREATURE && (nSpellId < 0 || !GetHasSpellEffect(nSpellId, oTarget))) {
effect eSR = EffectSpellResistanceDecrease(nSR);
if (!GetIsObjectValid(oTarget) || !GetIsPC(oTarget)) {
if (nSR >= 10)
eSR = EffectLinkEffects(eSR, EffectVisualEffect(HGVFX_DUR_BREACH_SEPTAGON));
else if (nSR >= 7)
eSR = EffectLinkEffects(eSR, EffectVisualEffect(HGVFX_DUR_BREACH_PENTAGON));
else if (nSR >= 4)
eSR = EffectLinkEffects(eSR, EffectVisualEffect(HGVFX_DUR_BREACH_SQUARE));
else
eSR = EffectLinkEffects(eSR, EffectVisualEffect(HGVFX_DUR_BREACH_TRIANGLE));
}
eSR = EffectLinkEffects(eSR, EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE));
eSR = ExtraordinaryEffect(eSR);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eSR, oTarget, RoundsToSeconds(10));
}
/* Petrified creatures cannot be dispelled without causing bugs */
if (GetHasEffectOfType(EFFECT_TYPE_PETRIFY, oTarget))
return;
float fDelay = 0.1 + (IntToFloat(Random(3)) / 10.0);
int nEffectSpellId, nEffectSubType, nDC, nBreached = 0, nDispelled = 0;
int nCasterFilter = GetPCFilter(oCaster, PCFILTER_DISPEL);
int nTargetFilter = GetPCFilter(oTarget, PCFILTER_DISPEL);
string sCasterName = COLOR_LT_ORANGE + GetName(oCaster) + " : ";
string sTargetName = COLOR_LT_GREEN + GetName(oTarget) + " : ";
string sSpellName, sCasterMessage = "", sTargetMessage = "", sSpellsDispelled = "";
/* cap DC at 71 */
if ((nDC = GetHitDiceIncludingLLs(oTarget) + 11) > 71)
nDC = 71;
effect eEff = GetFirstEffect(oTarget);
while (GetIsEffectValid(eEff)) {
int bSkip = 0;
nEffectSpellId = GetEffectSpellId(eEff);
nEffectSubType = GetEffectSubType(eEff);
/* Don't check against the same spell multiple times. Use a string as a horribly
* hacky version of a list. */
if (nEffectSpellId != -1) {
string sSpellId = " " + IntToString(nEffectSpellId) + " ";
if (FindSubString(sSpellsDispelled, sSpellId) != -1)
bSkip = 1;
else
sSpellsDispelled += sSpellId;
}
/* Extraordinary and supernatural effects cannot be dispelled */
if (nEffectSubType == SUBTYPE_EXTRAORDINARY || nEffectSubType == SUBTYPE_SUPERNATURAL)
bSkip = 1;
/* If there are breaches remaining, check to see if the current effect is breachable */
if (!bSkip && nBreached < nBreaches) {
if (nEffectSpellId != -1 && SFGetIsSpellBreachable(nEffectSpellId)) {
DelayCommand(fDelay, RemoveEffect(oTarget, eEff));
sSpellName = SFGetSpellName(nEffectSpellId);
if (sSpellName != "") {
if (oTarget != oCaster) {
if (nTargetFilter < 2)
sTargetMessage += sCasterName + "Breach " + sSpellName + "\\n";
else if (nTargetFilter == 2)
FloatingTextStringOnCreature(sCasterName + "Breach " + sSpellName + COLOR_END, oTarget, FALSE);
}
if (nCasterFilter < 2)
sCasterMessage += sTargetName + "Breach " + sSpellName + "\\n";
else if (nCasterFilter == 2)
FloatingTextStringOnCreature(sTargetName + "Breach " + sSpellName + COLOR_END, oCaster, FALSE);
}
nBreached += 1;
bSkip = 1;
}
}
/* If there are dispels remaining, try to dispel the current effect */
if (!bSkip && nDispelled < nDispels) {
object oCreator = GetEffectCreator(eEff);
if (nTargetType == OBJECT_TYPE_PLACEABLE && GetEffectType(eEff) == EFFECT_TYPE_VISUALEFFECT) {
bSkip = 1;
} else if (nSpellId != HGSPELL_BREAK_ENCHANTMENT || !GetIsReactionTypeFriendly(oCreator, oCaster)) {
int nRoll = d20(1);
string sSpellName = SFGetSpellName(nEffectSpellId);
string sDispelRoll;
if (sSpellName == "") {
string sCreatorName = GetName(oCreator);
sSpellName = "unknown spell (" + (sCreatorName != "" ? sCreatorName + " / " : "") +
GetEffectTypeName(GetEffectType(eEff)) + ")";
}
sDispelRoll = "(" + IntToString(nRoll) + " + " + IntToString(nDispelLevel) +
" = " + IntToString(nRoll + nDispelLevel) + " vs. DC: " +
IntToString(nDC) + ")";
if (nDispelLevel + nRoll >= nDC) {
DelayCommand(fDelay, RemoveEffect(oTarget, eEff));
if (sSpellName != "") {
if (oTarget != oCaster) {
if (nTargetFilter < 2)
sTargetMessage += sCasterName + "Dispel " + sSpellName + " : *dispelled* : " + sDispelRoll + "\\n";
else if (nTargetFilter == 2)
FloatingTextStringOnCreature(sCasterName + "Dispel " + sSpellName + " : *dispelled* : " + sDispelRoll + COLOR_END, oTarget, FALSE);
}
if (nCasterFilter < 2)
sCasterMessage += sTargetName + "Dispel " + sSpellName + " : *dispelled* : " + sDispelRoll + "\\n";
else if (nCasterFilter == 2)
FloatingTextStringOnCreature(sTargetName + "Dispel " + sSpellName + " : *dispelled* : " + sDispelRoll + COLOR_END, oCaster, FALSE);
}
nDispelled += 1;
bSkip = 1;
} else if (sSpellName != "") {
if (oTarget != oCaster) {
if (nTargetFilter < 2)
sTargetMessage += sCasterName + "Dispel " + sSpellName + " : *failure* : " + sDispelRoll + "\\n";
else if (nTargetFilter == 2)
FloatingTextStringOnCreature(sCasterName + "Dispel " + sSpellName + " : *failure* : " + sDispelRoll + COLOR_END, oTarget, FALSE);
}
if (nCasterFilter < 2)
sCasterMessage += sTargetName + "Dispel " + sSpellName + " : *failure* : " + sDispelRoll + "\\n";
else if (nCasterFilter == 2)
FloatingTextStringOnCreature(sTargetName + "Dispel " + sSpellName + " : *failure* : " + sDispelRoll + COLOR_END, oCaster, FALSE);
}
}
}
/* Stop processing this target if there are no breaches or dispels remaining */
if (nBreached >= nBreaches && nDispelled >= nDispels)
break;
eEff = GetNextEffect(oTarget);
}
if (sCasterMessage != "") {
sCasterMessage = GetStringLeft(sCasterMessage, GetStringLength(sCasterMessage) - 1) + COLOR_END;
if (nCasterFilter == 1)
SendSystemMessage(oCaster, "\\n" + sCasterMessage);
else
SendMessageToPC(oCaster, sCasterMessage);
}
if (sTargetMessage != "") {
sTargetMessage = GetStringLeft(sTargetMessage, GetStringLength(sTargetMessage) - 1) + COLOR_END;
if (nTargetFilter == 1)
SendSystemMessage(oTarget, "\\n" + sTargetMessage);
else
SendMessageToPC(oTarget, sTargetMessage);
}
}
Funky