ehye_khandee wrote...
It is in, tested a bit (not every spell but it seems to work so far). Here it is, the 'impossible to make in nwscript' script to allow your PCs to remove spells on themselves which they cast themselves. 31 lines of lean, clean code. Enjoy.
Here's what we use on HG to do this. It's a lot slicker, but it takes a lot more code, and some plugins to boot. It's done via custom SIMTools (chat) command, and takes a lot more types of input (you can cancel AoEs, weapon props, etc). I'm also including our listing function, which solves the whole issue of pcs having to look up / write their favorites. Code is acaos'.
First, the listing command (players do this by speaking '!effects'):
} else if (sCText == "effects") {
DeleteLocalString(oCPC, "FKY_CHAT_LOCAL_CTEXT");
if (!GetIsObjectValid(oCTarget)) {
oCTarget = GetLocalObject(oCPC, "FKY_CHAT_TARGET");
if (!GetIsObjectValid(oCTarget)) {
FloatingTextStringOnCreature(COLOR_GOLD + REQUIRES_TARGET + COLOR_END, oCPC, FALSE);
SetLocalString(oCPC, "FKY_CHAT_COMMAND", OBJECT_TARGET + "!" + sCText);
if (!GetIsObjectValid(GetItemPossessedBy(oCPC, "fky_chat_target")))
CreateItemOnObject("fky_chat_target", oCPC);
return;
}
else
DeleteLocalObject(oCPC, "FKY_CHAT_TARGET");
}
int nSpellId, nDur;
string sSpellName, sSpellId, sSpellsListed = "";
string sMessage;
if (GetObjectType(oCTarget) == OBJECT_TYPE_CREATURE) {
if (oCTarget == oCPC)
sMessage = COLOR_LT_GREEN + "Effects on you:\\n";
else
sMessage = COLOR_LT_GREEN + "Effects you cast on " + GetName(oCTarget) + ":\\n";
effect eEff = GetFirstEffect(oCTarget);
while (GetIsEffectValid(eEff)) {
if ((nSpellId = GetListableEffectSpellId(oCPC, oCTarget, eEff)) >= 0 &&
FindSubString(sSpellsListed, (sSpellId = "#" + IntToString(nSpellId) + " ")) < 0) {
if ((sSpellName = SFGetSpellName(nSpellId)) != "") {
sMessage += COLOR_WHITE + " " + sSpellId + COLOR_LT_GREEN + sSpellName;
if (GetEffectDurationType(eEff) == DURATION_TYPE_TEMPORARY) {
nDur = FloatToInt(GetEffectDurationRemaining(eEff));
if (nDur > 60)
sMessage += " [" + IntToString(nDur / 60) + "m" + IntToString(nDur % 60) + "s left]";
else
sMessage += " [" + IntToString(nDur) + "s left]";
} else
sMessage += " [perm]";
object oCreator = GetListableEffectCreator(oCTarget, eEff);
if (oCreator != oCPC)
sMessage += " (" + GetName(oCreator) + ")\\n";
else
sMessage += "\\n";
}
sSpellsListed += sSpellId;
}
eEff = GetNextEffect(oCTarget);
}
} else if (GetObjectType(oCTarget) == OBJECT_TYPE_ITEM && GetItemPossessor(oCTarget) == oCPC) {
sMessage = COLOR_LT_GREEN + "Magical effects on " + GetName(oCTarget) + ":\\n";
itemproperty ip = GetFirstItemProperty(oCTarget);
while (GetIsItemPropertyValid(ip)) {
if (GetItemPropertyDurationType(ip) == DURATION_TYPE_TEMPORARY &&
(nSpellId = GetItemPropertySpellId(ip)) >= 0 &&
FindSubString(sSpellsListed, (sSpellId = "#" + IntToString(nSpellId) + " ")) < 0) {
if ((sSpellName = SFGetSpellName(nSpellId)) != "") {
sMessage += COLOR_WHITE + " " + sSpellId + COLOR_LT_GREEN + sSpellName;
nDur = FloatToInt(GetItemPropertyDurationRemaining(ip));
if (nDur > 60)
sMessage += " [" + IntToString(nDur / 60) + "m" + IntToString(nDur % 60) + "s left]\\n";
else
sMessage += " [" + IntToString(nDur) + "s left]\\n";
}
sSpellsListed += sSpellId;
}
ip = GetNextItemProperty(oCTarget);
}
} else {
FloatingTextStringOnCreature(COLOR_RED +
"This command may only be targeted at creatures or items you possess!" + COLOR_END, oCPC, FALSE);
return;
}
SendChatLogMessage(oCPC, sMessage + COLOR_END, oCPC, 5);
}
Then, the canceling command. Expected inputs are in the form of !cancel aoe, !cancel poly, and so on - the ! is pre-parsed out:
if (GetStringLeft(sCText, 7) == "cancel ") {
string sCancel = GetStringLowerCase(GetStringRight(sCText, GetStringLength(sCText) - 7));
DeleteLocalString(oCPC, "FKY_CHAT_LOCAL_CTEXT");
if (sCancel == "aoe") {
int nCount = 1;
object oPlace;
while (GetIsObjectValid(oCTarget = GetNearestObject(OBJECT_TYPE_AREA_OF_EFFECT, oCPC, nCount++))) {
if (GetAreaOfEffectCreator(oCTarget) == oCPC && !GetLocalInt(oCTarget, "NoAoEDispel")) {
oPlace = GetLocalObject(oCTarget, "AoEPlaceable");
ApplyVisualAtLocation(VFX_FNF_DISPEL, GetLocation(oCTarget));
DestroyObject(oCTarget);
DestroyObject(oPlace);
}
}
return;
} else if (sCancel == "maze") {
int nCount = 1;
while (GetIsObjectValid(oCTarget = GetNearestObjectByTag("MazeReturn", oCPC, nCount++))) {
if (GetLocalObject(oCTarget, "MazeCaster") == oCPC) {
object oVictim = GetLocalObject(oCTarget, "MazeTarget");
RemoveEffectsFromSpell(SPELL_DOMINATE_MONSTER, oVictim);
ApplyVisualAtLocation(VFX_IMP_DISPEL, GetLocation(oCTarget));
SetPlotFlag(oCTarget, FALSE);
DestroyObject(oCTarget, 0.1);
}
}
return;
} else if (sCancel == "poly") {
int nHP = 20 + (GetAbilityModifier(ABILITY_CONSTITUTION, oCPC) * GetHitDice(oCPC));
if (GetCurrentHitPoints(oCPC) < nHP)
FloatingTextStringOnCreature(COLOR_RED + "Unshifting now would kill you!" + COLOR_END, oCPC, FALSE);
else if (RemoveEffectsOfType(EFFECT_TYPE_POLYMORPH, oCPC, oCPC) > 0)
AssignCommand(oCPC, ClearAllActions());
return;
}
if (!GetIsObjectValid(oCTarget)) {
oCTarget = GetLocalObject(oCPC, "FKY_CHAT_TARGET");
if (!GetIsObjectValid(oCTarget)) {
FloatingTextStringOnCreature(COLOR_GOLD + REQUIRES_TARGET + COLOR_END, oCPC, FALSE);
SetLocalString(oCPC, "FKY_CHAT_COMMAND", OBJECT_TARGET + "!" + sCText);
if (!GetIsObjectValid(GetItemPossessedBy(oCPC, "fky_chat_target")))
CreateItemOnObject("fky_chat_target", oCPC);
return;
} else
DeleteLocalObject(oCPC, "FKY_CHAT_TARGET");
}
if (GetObjectType(oCTarget) != OBJECT_TYPE_CREATURE &&
!(GetObjectType(oCTarget) == OBJECT_TYPE_ITEM && GetItemPossessor(oCTarget) == oCPC)) {
FloatingTextStringOnCreature(COLOR_RED +
"This command may only be targeted at creatures or items you possess!" + COLOR_END, oCPC, FALSE);
return;
}
int nRemoved = 0;
if (sCancel != "all") {
struct SubString ss;
ss.rest = sCancel;
while (ss.rest != "") {
ss = GetFirstSubString(ss.rest, " ");
nRemoved += RemoveMagicalEffects(oCTarget, oCPC, StringToInt(ss.first));
}
} else
nRemoved = RemoveMagicalEffects(oCTarget, oCPC);
if (nRemoved > 0)
ApplyVisualToObject(VFX_IMP_DISPEL, oCTarget);
}
If you're interested in trying to adapt any of that, let me know what subfunctions you want to look at - I don't want to codebomb your thread.
Funky