forked from Jaysyn/PRC8
Updated AMS marker feats. Removed arcane & divine marker feats. Updated Dread Necromancer for epic progression. Updated weapon baseitem models. Updated new weapons for crafting & npc equip. Updated prefix. Updated release archive.
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;
|
||
}
|
||
//*/
|