Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
612 lines
24 KiB
Plaintext
612 lines
24 KiB
Plaintext
/*:://////////////////////////////////////////////
|
||
//:: Name Wish functions
|
||
//:: FileName SMP_INC_WISH
|
||
//:://////////////////////////////////////////////
|
||
Functions for the Wish, Miracle and so on spells.
|
||
|
||
These can be used, therefore, in those scripts, and replaces the SMP_INC_SPELLS
|
||
line, as it will include it here.
|
||
|
||
Not just wish effects, but also wish checks :-)
|
||
|
||
Call these functions from a script from a wish creature or DM.
|
||
//:://////////////////////////////////////////////
|
||
//:: Created By: Jasperre
|
||
//::////////////////////////////////////////////*/
|
||
|
||
#include "SMP_INC_SPELLS"
|
||
|
||
// Note: You must set on the person calling these functions a name - under
|
||
// SMP_WISH_NAME, so it can be used to send a correct message:
|
||
// "You cannot cast Magic Missile using Wish", might be "using Miracle" instead.
|
||
// Remember:
|
||
const string SMP_WISH_NAME_LOCAL = "SMP_WISH_NAME_LOCAL";
|
||
|
||
// SPECIAL
|
||
|
||
// SMP_INC_WISH. Gets the wish's name - IE: Miracle, Limited Wish, Wish, for things like
|
||
// "You cannot cast Magic Missile using Miracle"
|
||
string SMP_WishGetName();
|
||
|
||
// SMP_INC_WISH. Checks if oObject is within oWisher's LOS
|
||
// * Placables, doors, items. Creatures use GetObjectSeen()/Heard().
|
||
int SMP_WishGetObjectInLOS(object oTarget, object oWisher);
|
||
// SMP_INC_WISH. Applies the loop onto oWisher of what they can see in thier LOS (40M)
|
||
// * Only call this directly from the object doing the wish, so oWisher should
|
||
// always be OBJECT_SELF
|
||
void SMP_WishSetLOS(object oWisher = OBJECT_SELF);
|
||
// SMP_INC_WISH. Deletes all locals set in SMP_WishSetLOS().
|
||
void SMP_WishDeleteLOS(location lWisher, string sLocal);
|
||
|
||
|
||
// CHECKS
|
||
|
||
// Note 2: Given the above local setting, whenever it says "Wish" inside debug
|
||
// strings, it'll be subsituted as approprate.
|
||
|
||
// SMP_INC_WISH. This will make sure cirtain spells can *never* be cast from wish.
|
||
// * TRUE if they cannot cast it ever, period.
|
||
// Debugs using: "You cannot cast 'GetName(nSpellId)' using Wish" (or other..)
|
||
int SMP_WishGetIsUncastableSpell(object oWisher, int nSpellId);
|
||
// SMP_INC_WISH. This makes sure that oTarget is a valid target for nSpellId, using range,
|
||
// types of target affected,
|
||
// * TRUE if they ARE a valid target
|
||
// If FALSE Debug: "You cannot cast nSpellId at oTarget"... + Reason
|
||
int SMP_WishGetIsSpellTargetValid(object oWisher, object oTarget, int nSpellId);
|
||
|
||
// SMP_INC_WISH. Deciphers sName into a spell id's number. This, sadly, will
|
||
// do a large loop. Use wisely! It uses FindSubString(), and so must match
|
||
// pretty well. Does capitalise both.
|
||
// * loops the spell values on SMP_ArrayGetObject(SMP_2DA_NAME_SPELLS, SMP_2DA_COLUMN_SPELLS_NAME);
|
||
// * Returns SPELL_INVALID as default, if no spell is found to be a match.
|
||
int SMP_WishGetSpellId(string sName, object oWisher);
|
||
// SMP_INC_WISH. This is from this (this is from Wish, it is similar for others)
|
||
// <20> Duplicate any wizard or sorcerer spell of 8th level or lower, provided the
|
||
// spell is not of a school prohibited to you. (nClassBan = any spell from nClass's normal list)
|
||
// <20> Duplicate any other spell of 6th level or lower, provided the spell is not
|
||
// of a school prohibited to you. (nAnyBan = Any spell from any list, not banned via. school)
|
||
// <20> Duplicate any wizard or sorcerer spell of 7th level or lower even if it<69>s
|
||
// of a prohibited school. (nClassNoBan = Any spell from this class's list, up to this level)
|
||
// <20> Duplicate any other spell of 5th level or lower even if it<69>s of a
|
||
// prohibited school. (nAny = Any other spell, even opposing schools)
|
||
// In this example: nClassBan = 7, nClassNoBan = 8, nAnyBan = 6, nAny = 5.
|
||
// * Put in CLASS_TYPE_WIZARD or CLASS_TYPE_CLERIC for nClass, always.
|
||
int SMP_WishGetIsSpellValid(object oWisher, int nClass, int nSpellId, int nClassBan, int nClassNoBan, int nAnyBan, int nAny);
|
||
|
||
// SMP_INC_WISH. Get a valid target for wish, using sName. We will loop all
|
||
// objects which we allow (In order: Creatuers, then any Placables, Doors,
|
||
// Items on the Ground).
|
||
// * Can use bCreatureOnly to only check creatures in range.
|
||
// * Only will use seen creatures, that oWisher can see, or objects that are within
|
||
// oWisher's LOS too (we do a loop in the SMP_S_WISH script, or similar, to
|
||
// set it up using functions here).
|
||
// * Returns OBJECT_INVALID in case of no valid target to return
|
||
// * Can use bSeenOnly to force the object to be seen (ala, spell targeting)
|
||
// Gets the nearest target, of course, a placable with name sNAme could be nearer
|
||
// then a creature with sName, but we return the creature first. Also, hardly happens.
|
||
object SMP_WishGetTargetByName(object oWisher, string sName, int bCreatureOnly = FALSE, int bSeenOnly = FALSE);
|
||
|
||
|
||
// EFFECTS
|
||
|
||
// SMP_INC_WISH. Cures oWisher's party of all damage, to thier maximum hit points, if they
|
||
// are at -10 or higher hit points
|
||
void SMP_WishDoCurePartyDamage(object oWisher);
|
||
// SMP_INC_WISH. Cures oWisher's party of nAffiction
|
||
void SMP_WishDoCurePartyAffiction(object oWisher, int nAffiction);
|
||
// SMP_INC_WISH. Makes oWisher cast nSpellId at oTarget
|
||
void SMP_WishCastSpellAtObject(object oWisher, int nSpellId, object oTarget);
|
||
// SMP_INC_WISH. Makes oWisher undo the harmful effects of all Insanity spells on oTarget
|
||
void SMP_WishRemoveInsanity(object oWisher, object oTarget);
|
||
// SMP_INC_WISH. Makes oWisher attempt to teleport oTarget to lLocation.
|
||
// Must be used seperatly on each person. Willing people go for free, else, it
|
||
// uses nSpellSaveDC, and nCasterLevel to do the checks for resistance and will save
|
||
// * Reports saves normally, etc.
|
||
// * No other feedback.
|
||
// * Returns TRUE if sucessful, so a complete feedback can be made up.
|
||
int SMP_WishTeleportPerson(object oWisher, object oTarget, location lTarget, int nSpellSaveDC, int nCasterLevel);
|
||
|
||
// Creates a particular item for oWisher, named by them, it will search a database
|
||
// of items to get which one to create.
|
||
// void SMP_WishCreateMundateItem()
|
||
// Creates magical of above
|
||
// FINISH!!!!
|
||
|
||
// START SPECIAL
|
||
|
||
// Gets the wish's name
|
||
string SMP_WishGetName()
|
||
{
|
||
return GetLocalString(OBJECT_SELF, SMP_WISH_NAME_LOCAL);
|
||
}
|
||
|
||
// Checks if oObject is within oWisher's LOS
|
||
// * Placables, doors, items. Creatures use GetObjectSeen()/Heard().
|
||
int SMP_WishGetObjectInLOS(object oTarget, object oWisher)
|
||
{
|
||
// Check local on the target
|
||
string sLocal = "SMP_WISH_LOS" + ObjectToString(oWisher);
|
||
// Local gets set on the target if they are in the wishers LOS. Gets
|
||
// removed too after wish is cast.
|
||
if(GetLocalInt(oTarget, sLocal))
|
||
{
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
// Applies the loop onto oWisher of what they can see in thier LOS (40M)
|
||
// * Only call this directly from the object doing the wish, so oWisher should
|
||
// always be OBJECT_SELF
|
||
void SMP_WishSetLOS(object oWisher = OBJECT_SELF)
|
||
{
|
||
// Check LOS of those objects:
|
||
// * Placables, doors, items
|
||
string sLocal = "SMP_WISH_LOS" + ObjectToString(oWisher);
|
||
location lWisher = GetLocation(oWisher);
|
||
object oLOS = GetFirstObjectInShape(SHAPE_SPHERE, 40.0, lWisher, TRUE, OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM);
|
||
while(GetIsObjectValid(oLOS))
|
||
{
|
||
// Set local on them
|
||
SetLocalInt(oLOS, sLocal, TRUE);
|
||
|
||
// Get next object
|
||
oLOS = GetNextObjectInShape(SHAPE_SPHERE, 40.0, lWisher, TRUE, OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM);
|
||
}
|
||
|
||
// Delay the deletion
|
||
DelayCommand(6.0, SMP_WishDeleteLOS(lWisher, sLocal));
|
||
}
|
||
|
||
// Deletes all locals set in SMP_WishSetLOS().
|
||
void SMP_WishDeleteLOS(location lWisher, string sLocal)
|
||
{
|
||
// Delete all previous (if any) locals.
|
||
// This is delayed after they have been set. Should clear up them all
|
||
int nCnt = 1;
|
||
object oLOS = GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM, lWisher, nCnt);
|
||
while(GetIsObjectValid(oLOS) && GetDistanceBetweenLocations(lWisher, GetLocation(oLOS)) <= 41.0)
|
||
{
|
||
// Delete the local.
|
||
DeleteLocalInt(oLOS, sLocal);
|
||
|
||
nCnt++;
|
||
oLOS = GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM, lWisher, nCnt);
|
||
}
|
||
}
|
||
|
||
// START CHECKS
|
||
|
||
// This will make sure cirtain spells can *never* be cast from wish.
|
||
// * TRUE if they cannot cast it ever, period.
|
||
// Debugs using: "You cannot cast 'GetName(nSpellId)' using Wish"
|
||
int SMP_WishGetIsUncastableSpell(object oWisher, int nSpellId)
|
||
{
|
||
switch(nSpellId)
|
||
{
|
||
// Spells which have more then 1 round casting time
|
||
//case SMP_SPELL_RAISE_DEAD:
|
||
//{
|
||
// SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " using " + SMP_WishGetName() + " because it takes longer then a round to cast");
|
||
// return TRUE;
|
||
//}
|
||
break;
|
||
// Spells which are duplicated by the resurrection part of all these spells
|
||
case SMP_SPELL_RAISE_DEAD:
|
||
//case SMP_SPELL_RESURRECTION:
|
||
//case SMP_SPELL_TRUE_RESURRECTION:
|
||
{
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " because you can duplicate its effects using " + SMP_WishGetName() + " anyway.");
|
||
return TRUE;
|
||
}
|
||
break;
|
||
}
|
||
// Default return - no debug
|
||
return FALSE;
|
||
}
|
||
|
||
// This makes sure that oTarget is a valid target for nSpellId, using range,
|
||
// types of target affected,
|
||
// * TRUE if they ARE a valid target
|
||
// If FALSE Debug: "You cannot cast nSpellId at oTarget
|
||
int SMP_WishGetIsSpellTargetValid(object oWisher, object oTarget, int nSpellId)
|
||
{
|
||
// Check the target type (IE: Self, creature, trigger ETC)
|
||
int nTargetsType = GetObjectType(oTarget);
|
||
int nSpellTargetType = SMP_ArrayGetSpellTargetType(nSpellId);
|
||
|
||
// If the spell can be cast at any location, it can be cast at any object
|
||
// too (because otherwise some locations under people cannot be hit right)
|
||
if(!SMP_GetIsTargetTypeLocation(nSpellTargetType))
|
||
{
|
||
// Check for any object, regardless (cannot target the ground with
|
||
// wish, it targets a specific being)
|
||
if(!SMP_GetIsTargetTypeObject(nSpellTargetType))
|
||
{
|
||
// This spell cannot target any object
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " at " + GetName(oTarget) + " because the spell doesn't allow it");
|
||
return FALSE;
|
||
}
|
||
// Check each type.
|
||
switch(nTargetsType)
|
||
{
|
||
case OBJECT_TYPE_CREATURE:
|
||
{
|
||
// Special case for self
|
||
if(oTarget == oWisher)
|
||
{
|
||
if(!SMP_GetIsTargetTypeSelf(nSpellTargetType))
|
||
{
|
||
// Cannot cast at yourself.
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " at yourself.");
|
||
return FALSE;
|
||
}
|
||
}
|
||
// Check default
|
||
if(!SMP_GetIsTargetTypeCreature(nSpellTargetType))
|
||
{
|
||
// Cannot cast at a creature.
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " at a creature.");
|
||
return FALSE;
|
||
}
|
||
}
|
||
case OBJECT_TYPE_DOOR:
|
||
{
|
||
// Check door
|
||
if(!SMP_GetIsTargetTypeDoor(nSpellTargetType))
|
||
{
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " at a door.");
|
||
return FALSE;
|
||
}
|
||
}
|
||
case OBJECT_TYPE_ITEM:
|
||
{
|
||
// Check item
|
||
if(!SMP_GetIsTargetTypeItem(nSpellTargetType))
|
||
{
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " at an item.");
|
||
return FALSE;
|
||
}
|
||
}
|
||
case OBJECT_TYPE_PLACEABLE:
|
||
{
|
||
// Check placeable
|
||
if(!SMP_GetIsTargetTypePlaceable(nSpellTargetType))
|
||
{
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " at a placeable.");
|
||
return FALSE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// Check the range of this spell
|
||
float fRange = SMP_ArrayGetSpellRange(nSpellId);
|
||
// Note: We make the "personal" range 1.0 here, in case some spell uses it.
|
||
// ABOVE is a nicer check for target type, and is more by the book.
|
||
if(fRange == 0.0) fRange = 1.0;
|
||
if(SMP_ArrayGetSpellRange(nSpellId) > GetDistanceBetween(oWisher, oTarget))
|
||
{
|
||
// Cannot cast - to far away
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + ", the target is too far away");
|
||
return FALSE;
|
||
}
|
||
// Return TRUE by default, allowing the target as valid
|
||
return TRUE;
|
||
}
|
||
|
||
// Deciphers sName into a spell id's number. This, sadly, will do a large loop.
|
||
// Use wisely! It uses FindSubString(), and so must match pretty well. Does capitalise both.
|
||
// * loops the spell values on SMP_ArrayGetObject(SMP_2DA_NAME_SPELLS, SMP_2DA_COLUMN_SPELLS_NAME);
|
||
// * Returns SPELL_INVALID as default, if no spell is found to be a match.
|
||
int SMP_WishGetSpellId(string sName, object oWisher)
|
||
{
|
||
string sCheck, sSpell;
|
||
int nCnt;
|
||
// Uppercase of sName.
|
||
sCheck = GetStringUpperCase(sName);
|
||
|
||
// We set the last spell name got by this onto OBJECT_SELF, and oWisher's
|
||
// Id. This is retrieved first, and checked (they might have asked to cast
|
||
// the same spell, but wrong syntax etc. before).
|
||
nCnt = GetLocalInt(OBJECT_SELF, "SMP_WISH_LASTSPELLNAME" + ObjectToString(oWisher));
|
||
// We won't ever recheck spell entry 0, because it returns 0 on default
|
||
if(nCnt > 0)
|
||
{
|
||
// Get the spell name at nCnt
|
||
sSpell = GetStringUpperCase(SMP_ArrayGetSpellName(nCnt));
|
||
|
||
// Check the two strings together
|
||
if(FindSubString(sCheck, sSpell) >= 0)
|
||
{
|
||
// Return nCnt - the names match
|
||
return nCnt;
|
||
}
|
||
}
|
||
|
||
// Loop all the spell names until we find a match.
|
||
// * Check only real spells.
|
||
for(nCnt = SMP_SPELLS_2DA_MIN_SPELL_ENTRY;
|
||
nCnt <= SMP_SPELLS_2DA_MAX_ENTRY; nCnt++)
|
||
{
|
||
// Get the spell name at nCnt
|
||
sSpell = GetStringUpperCase(SMP_ArrayGetSpellName(nCnt));
|
||
|
||
// Check the two strings together
|
||
if(FindSubString(sCheck, sSpell) >= 0)
|
||
{
|
||
// Return nCnt - the names match
|
||
return nCnt;
|
||
}
|
||
}
|
||
return SPELL_INVALID;
|
||
}
|
||
// This is from this (this is from Wish, it is similar for others)
|
||
// <20> Duplicate any wizard or sorcerer spell of 8th level or lower, provided the
|
||
// spell is not of a school prohibited to you. (nClassBan = any spell from nClass's normal list)
|
||
// <20> Duplicate any other spell of 6th level or lower, provided the spell is not
|
||
// of a school prohibited to you. (nAnyBan = Any spell from any list, not banned via. school)
|
||
// <20> Duplicate any wizard or sorcerer spell of 7th level or lower even if it<69>s
|
||
// of a prohibited school. (nClassNoBan = Any spell from this class's list, up to this level)
|
||
// <20> Duplicate any other spell of 5th level or lower even if it<69>s of a
|
||
// prohibited school. (nAny = Any other spell, even opposing schools)
|
||
// In this example: nClassBan = 7, nClassNoBan = 8, nAnyBan = 6, nAny = 5.
|
||
// * Put in CLASS_TYPE_WIZARD or CLASS_TYPE_CLERIC for nClass, always.
|
||
int SMP_WishGetIsSpellValid(object oWisher, int nClass, int nSpellId, int nClassBan, int nClassNoBan, int nAnyBan, int nAny)
|
||
{
|
||
// MUST BE CASTABLE NORMALLY
|
||
if(!SMP_ArrayGetSpellIsPCCastable(nSpellId))
|
||
{
|
||
// Cannot cast it
|
||
SpeakString("You cannot cast " + SMP_ArrayGetSpellName(nSpellId) + " because it is on no class' spell list");
|
||
return FALSE;
|
||
}
|
||
|
||
// Get nSpellId's level, from nClass and nInnate
|
||
int nClassLevel = SMP_ArrayGetSpellLevel(nSpellId, nClass);
|
||
int nInnateLevel = SMP_ArrayGetSpellLevelGeneral(nSpellId, oWisher);
|
||
|
||
// Check if they can cast it regardless of class, or school
|
||
if(nInnateLevel <= nAny)
|
||
{
|
||
// Can cast it!
|
||
return TRUE;
|
||
}
|
||
// Have they got nSpellId on thier list of spells?
|
||
if(nClassLevel != -1)
|
||
{
|
||
// Check if they can cast it due to it being on thier class list, and it is
|
||
// of a low enough level, and so we can cast it (never mind spell schools)
|
||
// we check here
|
||
if(nClassLevel <= nClassNoBan)
|
||
{
|
||
// Can cast it!
|
||
return TRUE;
|
||
}
|
||
// Checks for the spell school one
|
||
//if(SMP_ArrayGetSpellSchool(nSpellId) != WHAT_THIER_BANNED_SPELL_SCHOOL_IS)
|
||
//{
|
||
// if(nClassLevel <= nClassBan)
|
||
// {
|
||
// // Can cast it!
|
||
// return TRUE;
|
||
// }
|
||
//}
|
||
}
|
||
// Check for the spell school for all class lists.
|
||
//if(SMP_ArrayGetSpellSchool(nSpellId) != WHAT_THIER_BANNED_SPELL_SCHOOL_IS)
|
||
//{
|
||
// if(nInnateLevel <= nAnyBan)
|
||
// {
|
||
// // Can cast it!
|
||
// return TRUE;
|
||
// }
|
||
//}
|
||
// Cannot cast it (default return)
|
||
return FALSE;
|
||
}
|
||
|
||
// Get a valid target for wish, using sName. We will loop all objects which we
|
||
// allow (In order: Creatuers, then any Placables, Doors, Items on the Ground).
|
||
// * Can use bCreatureOnly to only check creatures in range.
|
||
// * Only will use seen creatures, that oWisher can see, or objects that are within
|
||
// oWisher's LOS too (we do a loop in the SMP_S_WISH script, or similar, to
|
||
// set it up using functions here).
|
||
// * Returns OBJECT_INVALID in case of no valid target to return
|
||
// * Can use bSeenOnly to force the object to be seen (ala, spell targeting)
|
||
// Gets the nearest target, of course, a placable with name sNAme could be nearer
|
||
// then a creature with sName, but we return the creature first. Also, hardly happens.
|
||
object SMP_WishGetTargetByName(object oWisher, string sName, int bCreatureOnly = FALSE, int bSeenOnly = FALSE)
|
||
{
|
||
// Loop all creatures first
|
||
int nCnt = 1;
|
||
object oCheck = GetNearestObject(OBJECT_TYPE_CREATURE, oWisher, nCnt);
|
||
while(GetIsObjectValid(oCheck))
|
||
{
|
||
if(FindSubString(sName, GetName(oCheck)) >= 0)
|
||
{
|
||
// Check if seen, or can sometimes be heard
|
||
if(GetObjectSeen(oCheck, oWisher) ||
|
||
(bSeenOnly == FALSE && GetObjectHeard(oCheck, oWisher)))
|
||
{
|
||
// Return them
|
||
return oCheck;
|
||
}
|
||
}
|
||
nCnt++;
|
||
oCheck = GetNearestObject(OBJECT_TYPE_CREATURE, oWisher, nCnt);
|
||
}
|
||
// Check placables, doors and items last
|
||
nCnt = 1;
|
||
oCheck = GetNearestObject(OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM | OBJECT_TYPE_PLACEABLE, oWisher, nCnt);
|
||
while(GetIsObjectValid(oCheck))
|
||
{
|
||
if(FindSubString(sName, GetName(oCheck)) >= 0)
|
||
{
|
||
// Check if in LOS
|
||
if(SMP_WishGetObjectInLOS(oCheck, oWisher))
|
||
{
|
||
// Return them
|
||
return oCheck;
|
||
}
|
||
}
|
||
nCnt++;
|
||
oCheck = GetNearestObject(OBJECT_TYPE_DOOR | OBJECT_TYPE_ITEM | OBJECT_TYPE_PLACEABLE, oWisher, nCnt);
|
||
}
|
||
// Default return value
|
||
return OBJECT_INVALID;
|
||
}
|
||
|
||
// START FUNCTIONS
|
||
|
||
|
||
// Cures oWisher's party of all damage, to thier maximum hit points, if they
|
||
// are at -10 or higher hit points
|
||
void SMP_WishDoCurePartyDamage(object oWisher)
|
||
{
|
||
// Get PC party members, and our area
|
||
effect eHeal;
|
||
effect eVis = EffectVisualEffect(VFX_IMP_HEALING_L);
|
||
object oArea = GetArea(oWisher);
|
||
object oMember = GetFirstFactionMember(oWisher, TRUE);
|
||
while(GetIsObjectValid(oMember))
|
||
{
|
||
// Must be in same area
|
||
if(GetArea(oMember) == oArea)
|
||
{
|
||
// Heal them
|
||
eHeal = EffectHeal(GetMaxHitPoints(oMember));
|
||
SMP_ApplyInstantAndVFX(oMember, eVis, eHeal);
|
||
}
|
||
// Get next member
|
||
oMember = GetNextFactionMember(oWisher, TRUE);
|
||
}
|
||
// Loop NPC's
|
||
oMember = GetFirstFactionMember(oWisher, FALSE);
|
||
while(GetIsObjectValid(oMember))
|
||
{
|
||
// Must be in same area
|
||
if(GetArea(oMember) == oArea)
|
||
{
|
||
// Heal them
|
||
eHeal = EffectHeal(GetMaxHitPoints(oMember));
|
||
SMP_ApplyInstantAndVFX(oMember, eVis, eHeal);
|
||
}
|
||
// Get next member
|
||
oMember = GetNextFactionMember(oWisher, FALSE);
|
||
}
|
||
}
|
||
// Cures oWisher's party of nAffiction
|
||
void SMP_WishDoCurePartyAffiction(object oWisher, int nAffiction)
|
||
{
|
||
// Get PC party members, and our area
|
||
effect eVis = EffectVisualEffect(VFX_IMP_HEALING_L);
|
||
object oArea = GetArea(oWisher);
|
||
object oMember = GetFirstFactionMember(oWisher, TRUE);
|
||
while(GetIsObjectValid(oMember))
|
||
{
|
||
// Must be in same area
|
||
if(GetArea(oMember) == oArea)
|
||
{
|
||
// Heal them
|
||
SMP_RemoveSpecificEffect(nAffiction, oMember, SUBTYPE_IGNORE);
|
||
SMP_ApplyVFX(oMember, eVis);
|
||
}
|
||
// Get next member
|
||
oMember = GetNextFactionMember(oWisher, TRUE);
|
||
}
|
||
// Loop NPC's
|
||
oMember = GetFirstFactionMember(oWisher, FALSE);
|
||
while(GetIsObjectValid(oMember))
|
||
{
|
||
// Must be in same area
|
||
if(GetArea(oMember) == oArea)
|
||
{
|
||
// Heal them
|
||
SMP_RemoveSpecificEffect(nAffiction, oMember, SUBTYPE_IGNORE);
|
||
SMP_ApplyVFX(oMember, eVis);
|
||
}
|
||
// Get next member
|
||
oMember = GetNextFactionMember(oWisher, FALSE);
|
||
}
|
||
}
|
||
|
||
// Makes oWisher cast nSpellId at oTarget
|
||
void SMP_WishCastSpellAtObject(object oWisher, int nSpellId, object oTarget)
|
||
{
|
||
// Say we have done the wish
|
||
SpeakString("Your " + SMP_WishGetName() + " is granted, you cast " + SMP_ArrayGetSpellName(nSpellId));
|
||
|
||
// Assign the wisher to cast the spell
|
||
AssignCommand(oWisher, ActionCastSpellAtObject(nSpellId, oTarget, METAMAGIC_NONE, TRUE, FALSE, PROJECTILE_PATH_TYPE_DEFAULT, TRUE));
|
||
}
|
||
|
||
// Makes oWisher undo the harmful effects of all Insanity spells on oTarget
|
||
void SMP_WishRemoveInsanity(object oWisher, object oTarget)
|
||
{
|
||
// Say we have done the wish
|
||
SpeakString("Your " + SMP_WishGetName() + " is granted, Insanity will be removed from " + GetName(oTarget));
|
||
|
||
// Send messages
|
||
// * Not in yet, might not add
|
||
|
||
// Loop effects, remove isanity
|
||
effect eCheck = GetFirstEffect(oTarget);
|
||
while(GetIsEffectValid(eCheck))
|
||
{
|
||
switch(GetEffectSpellId(eCheck))
|
||
{
|
||
// - All insanity
|
||
case SMP_SPELL_INSANITY:
|
||
case SMP_SPELL_SYMBOL_OF_INSANITY:
|
||
{
|
||
// Remove it
|
||
RemoveEffect(oTarget, eCheck);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Makes oWisher attempt to teleport oTarget to lLocation.
|
||
// Must be used seperatly on each person. Willing people go for free, else, it
|
||
// uses nSpellSaveDC, and nCasterLevel to do the checks for resistance and will save
|
||
// * Reports saves normally, etc.
|
||
// * No other feedback.
|
||
// * Returns TRUE if sucessful, so a complete feedback can be made up.
|
||
int SMP_WishTeleportPerson(object oWisher, object oTarget, location lTarget, int nSpellSaveDC, int nCasterLevel)
|
||
{
|
||
// If the target is in the party of oWisher, it is automatic.
|
||
if(GetFactionEqual(oWisher, oTarget))
|
||
{
|
||
// Move them (with some feedback to them)
|
||
SendMessageToPC(oTarget, "*You are teleported by Wish to a new location*");
|
||
AssignCommand(oTarget, SMP_ForceMovementToLocation(lTarget, VFX_FNF_TELEPORT_OUT, VFX_FNF_TELEPORT_IN));
|
||
return TRUE;
|
||
}
|
||
// Else, check saves and spell resistance.
|
||
// Spell resistance (Only)
|
||
if(!SMP_SpellResistanceManualCheck(oWisher, oTarget, nCasterLevel, 9))
|
||
{
|
||
// * Will save negates (And note: It is save type spell, because this isn't a
|
||
// spell script).
|
||
if(!SMP_SavingThrow(SAVING_THROW_WILL, oTarget, nSpellSaveDC, SAVING_THROW_TYPE_SPELL, oWisher))
|
||
{
|
||
// Move them! (Forcefully)
|
||
SendMessageToPC(oTarget, "*You are teleported by Wish to a new location*");
|
||
AssignCommand(oTarget, SMP_ForceMovementToLocation(lTarget, VFX_FNF_TELEPORT_OUT, VFX_FNF_TELEPORT_IN));
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
// Failed to teleport them
|
||
return FALSE;
|
||
}
|
||
|
||
// End of file Debug lines. Uncomment below "/*" with "//" and compile.
|
||
/*
|
||
void main()
|
||
{
|
||
return;
|
||
}
|
||
//*/
|