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.
360 lines
12 KiB
Plaintext
360 lines
12 KiB
Plaintext
/*:://////////////////////////////////////////////
|
|
//:: Spell Name Status
|
|
//:: Spell FileName PHS_S_Status
|
|
//:://////////////////////////////////////////////
|
|
//:: In Game Spell desctiption
|
|
//:://////////////////////////////////////////////
|
|
Divination
|
|
Level: Clr 2
|
|
Components: V, S
|
|
Casting Time: 1 standard action
|
|
Range: Touch
|
|
Targets: One living party member per three levels within 10M (30ft)
|
|
Duration: 1 hour/level
|
|
Saving Throw: Will negates (harmless)
|
|
Spell Resistance: Yes (harmless)
|
|
|
|
When you need to keep track of comrades who may get separated, status allows
|
|
you to mentally monitor their relative positions and general condition. You
|
|
are aware of direction and distance to the creatures and any conditions
|
|
affecting them: unharmed, wounded, disabled, staggered, unconscious, dying,
|
|
nauseated, panicked, stunned, poisoned, diseased, confused, or the like.
|
|
Once the spell has been cast upon the subjects, the distance between them
|
|
and the caster does not affect the spell as long as they are on the same
|
|
plane of existence. If a subject leaves the plane, or if it dies, the spell
|
|
ceases to function for it. The spell reports the status of allies once
|
|
every 15 seconds.
|
|
//:://////////////////////////////////////////////
|
|
//:: Spell Effects Applied / Notes
|
|
//:://////////////////////////////////////////////
|
|
Puts the effects on each party member within 10M (up to 1 per 3 caster
|
|
levels) and then does a 15 second delayed check on party members for the
|
|
spells effect. If it is cast again, the originals are lost.
|
|
|
|
Anyone who dies (and thusly will lose the good visual effect on them) or
|
|
gets it dispelled, will be ignored and removed from the array.
|
|
|
|
Anyone in another plane (explicitly Maze and so on) will be removed from the
|
|
array and the spell effect removed.
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Jasperre
|
|
//::////////////////////////////////////////////*/
|
|
|
|
#include "PHS_INC_SPELLS"
|
|
|
|
const string ARRAY_NAME = "PHS_STATUS_ARRAY";
|
|
|
|
// You are aware of direction and distance to the creatures and any conditions
|
|
// affecting them: unharmed, wounded, disabled, staggered, unconscious, dying,
|
|
// nauseated, panicked, stunned, poisoned, diseased, confused, or the like.
|
|
struct StatusOfPerson
|
|
{
|
|
// Status'
|
|
int Poison;
|
|
int Panicked;
|
|
int Stunned;
|
|
int Diseased;
|
|
int Confused;
|
|
int Paralyzed;
|
|
int Stone;
|
|
int Cursed;
|
|
int Deaf;
|
|
int Blind;
|
|
// Wounds
|
|
int Unharmed;
|
|
int Wounded;
|
|
int Dying;
|
|
int Dead;
|
|
};
|
|
|
|
// Runs a check for the caster so they know what is going on for thier allies.
|
|
void StatusCheck(object oCaster, int nTimesCast);
|
|
|
|
// Do status check for the members of oCaster's party, using bPCOnly to check the
|
|
// correct stuff in GetFirstFactionMember(), thusly called twice.
|
|
void StatusOfParty(object oCaster, int bPCOnly);
|
|
|
|
// Gets the status of oPerson with integers returned.
|
|
struct StatusOfPerson GetStatusOfPerson(object oCreature);
|
|
|
|
void main()
|
|
{
|
|
// Spell hook check.
|
|
if(PHS_SpellHookCheck(PHS_SPELL_STATUS)) return;
|
|
|
|
// Define ourselves.
|
|
object oCaster = OBJECT_SELF;
|
|
object oTarget;
|
|
location lSelf = GetLocation(oCaster);
|
|
int nCasterLevel = PHS_GetCasterLevel();
|
|
int nMetaMagic = PHS_GetMetaMagicFeat();
|
|
float fDelay;
|
|
int nMaxTargets = PHS_LimitInteger(nCasterLevel/3);
|
|
int nCnt = 0;
|
|
|
|
// Duration - 1 hour/level
|
|
float fDuration = PHS_GetDuration(PHS_HOURS, nCasterLevel, nMetaMagic);
|
|
|
|
// Declare effects
|
|
effect eVis = EffectVisualEffect(VFX_IMP_HEAD_HOLY);
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
|
|
effect eCasterDur = EffectVisualEffect(VFX_DUR_MAGICAL_SIGHT);
|
|
|
|
// AOE visual applied.
|
|
effect eImpact = EffectVisualEffect(VFX_FNF_LOS_HOLY_30);
|
|
PHS_ApplyLocationVFX(lSelf, eImpact);
|
|
|
|
// Add one to times cast
|
|
int nTimesCast = PHS_IncreaseStoredInteger(oCaster, "PHS_STATUS_TIMES_CAST");
|
|
|
|
// Remove this spells effect from all party members
|
|
// * PC's then NPC's.
|
|
PHS_RemoveSpellEffectsFromFactionCaster(PHS_SPELL_STATUS, oCaster, oCaster, TRUE);
|
|
PHS_RemoveSpellEffectsFromFactionCaster(PHS_SPELL_STATUS, oCaster, oCaster, FALSE);
|
|
|
|
// Loop allies - and apply the effects. AOE is 30ft, 10M
|
|
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_FEET_30, lSelf);
|
|
while(GetIsObjectValid(oTarget) && nCnt < nMaxTargets)
|
|
{
|
|
// Only affects party members (and a special case for ourselves)
|
|
if((GetFactionEqual(oTarget, oCaster) || oTarget == oCaster) &&
|
|
// Make sure they are not immune to spells
|
|
!PHS_TotalSpellImmunity(oTarget))
|
|
{
|
|
// Fire cast spell at event for the specified target
|
|
PHS_SignalSpellCastAt(oTarget, PHS_SPELL_STATUS, FALSE);
|
|
|
|
// One more target done
|
|
nCnt++;
|
|
|
|
// Remove previous effects from this spell (of course, you cannot
|
|
// be in 2 parties at once! Sorts dispel problems mainly). Only
|
|
// remove spell effects from this caster!
|
|
PHS_RemoveSpellEffects(PHS_SPELL_STATUS, oCaster, oTarget);
|
|
|
|
// Check if us
|
|
if(oTarget == oCaster)
|
|
{
|
|
// Apply visual effect to us, a special one.
|
|
PHS_ApplyDuration(oTarget, eCasterDur, fDuration);
|
|
}
|
|
else
|
|
{
|
|
// Delay for visuals and effects.
|
|
fDelay = GetDistanceBetween(oCaster, oTarget)/20;
|
|
|
|
// Apply normal cessate to track oTarget.
|
|
DelayCommand(fDelay, PHS_ApplyVFX(oTarget, eVis));
|
|
PHS_ApplyDuration(oTarget, eDur, fDuration);
|
|
}
|
|
}
|
|
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_FEET_30, lSelf);
|
|
}
|
|
// Do first 15 second heartbeat
|
|
StatusCheck(oCaster, nTimesCast);
|
|
}
|
|
|
|
// Runs a check for the caster so they know what is going on for thier allies.
|
|
void StatusCheck(object oCaster, int nTimesCast)
|
|
{
|
|
// Make sure we don't stop
|
|
if(!GetIsObjectValid(oCaster) ||
|
|
!GetHasSpellEffect(PHS_SPELL_STATUS, oCaster) ||
|
|
GetLocalInt(oCaster, "PHS_STATUS_TIMES_CAST") != nTimesCast ||
|
|
GetIsDead(oCaster))
|
|
{
|
|
PHS_RemoveSpellEffects(PHS_SPELL_STATUS, oCaster, oCaster);
|
|
// Stop
|
|
return;
|
|
}
|
|
|
|
// We check for the spell effect on party members (NPC and PC!) in any area
|
|
// apart from different planes.
|
|
SendMessageToPC(oCaster, "Status Check:");
|
|
|
|
// PC's status'
|
|
StatusOfParty(oCaster, TRUE);
|
|
// NPC's status'
|
|
StatusOfParty(oCaster, FALSE);
|
|
|
|
// Delay another check
|
|
DelayCommand(15.0, StatusCheck(oCaster, nTimesCast));
|
|
}
|
|
|
|
// Do status check for the members of oCaster's party, using bPCOnly to check the
|
|
// correct stuff in GetFirstFactionMember(), thusly called twice.
|
|
void StatusOfParty(object oCaster, int bPCOnly)
|
|
{
|
|
// Declare stuff
|
|
string sAffictions = "";
|
|
struct StatusOfPerson Status;
|
|
int nSize;
|
|
|
|
// Get first party member
|
|
object oParty = GetFirstFactionMember(oCaster, bPCOnly);
|
|
while(GetIsObjectValid(oParty))
|
|
{
|
|
// Got the spells effects from oCaster?
|
|
if(PHS_GetHasSpellEffectFromCaster(PHS_SPELL_STATUS, oParty, oCaster) &&
|
|
!GetIsDead(oParty))
|
|
{
|
|
// If not in our plane, remove the status visuals
|
|
if(!PHS_CheckIfSamePlane(GetLocation(oCaster), GetLocation(oParty)))
|
|
{
|
|
// Remove the spells effects
|
|
PHS_RemoveSpellEffects(PHS_SPELL_STATUS, oCaster, oParty);
|
|
}
|
|
else
|
|
{
|
|
// Add on what stuff oParty has
|
|
Status = GetStatusOfPerson(oParty);
|
|
|
|
// Check if dead
|
|
|
|
// Sort out sAffictions total.
|
|
sAffictions = "Status of " + GetName(oParty) + " is that they are: ";
|
|
nSize = GetStringLength(sAffictions);
|
|
|
|
// Add them all as we see them
|
|
if(Status.Poison == TRUE)
|
|
{
|
|
sAffictions += "poisoned, ";
|
|
}
|
|
if(Status.Panicked == TRUE)
|
|
{
|
|
sAffictions += "panicked, ";
|
|
}
|
|
if(Status.Stunned == TRUE)
|
|
{
|
|
sAffictions += "stunned, ";
|
|
}
|
|
if(Status.Confused == TRUE)
|
|
{
|
|
sAffictions += "confused, ";
|
|
}
|
|
if(Status.Paralyzed == TRUE)
|
|
{
|
|
sAffictions += "paralyzed, ";
|
|
}
|
|
if(Status.Stone == TRUE)
|
|
{
|
|
sAffictions += "turned to stone, ";
|
|
}
|
|
if(Status.Cursed == TRUE)
|
|
{
|
|
sAffictions += "cursed, ";
|
|
}
|
|
if(Status.Deaf == TRUE)
|
|
{
|
|
sAffictions += "deaf, ";
|
|
}
|
|
if(Status.Blind == TRUE)
|
|
{
|
|
sAffictions += "blind, ";
|
|
}
|
|
// If we havn't added anything, we don't add "and ". However, if
|
|
// we have added anything to sAffictions, we add a "and " to make
|
|
// it look correct. EG:
|
|
// "Status of George is that they are: unharmed"
|
|
// "Status of George is that they are: blind, and wounded"
|
|
// "Status of George is that they are: turned to stone, cursed, and unharmed"
|
|
if(nSize != GetStringLength(sAffictions))
|
|
{
|
|
// Add "and"
|
|
sAffictions += "and ";
|
|
}
|
|
// Do wounded status
|
|
if(Status.Dying == TRUE)
|
|
{
|
|
sAffictions += "dying.";
|
|
}
|
|
else if(Status.Wounded == TRUE)
|
|
{
|
|
sAffictions += "wounded.";
|
|
}
|
|
// Must be unharmed!
|
|
else //if(Status.Unharmed == TRUE)
|
|
{
|
|
sAffictions += "unharmed.";
|
|
}
|
|
// Send message
|
|
SendMessageToPC(oCaster, sAffictions);
|
|
}
|
|
}
|
|
// Get next member
|
|
oParty = GetNextFactionMember(oCaster, bPCOnly);
|
|
}
|
|
}
|
|
|
|
// Gets the status of oPerson with integers returned.
|
|
struct StatusOfPerson GetStatusOfPerson(object oCreature)
|
|
{
|
|
// Return structure
|
|
struct StatusOfPerson Return;
|
|
|
|
// Loop effects
|
|
effect eCheck = GetFirstEffect(oCreature);
|
|
while(GetIsEffectValid(eCheck))
|
|
{
|
|
// Check type of effect
|
|
switch(GetEffectType(eCheck))
|
|
{
|
|
// Status'
|
|
case EFFECT_TYPE_POISON:
|
|
Return.Poison = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_FRIGHTENED:
|
|
case EFFECT_TYPE_TURNED:
|
|
Return.Panicked = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_STUNNED:
|
|
Return.Stunned = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_DISEASE:
|
|
Return.Diseased = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_CONFUSED:
|
|
Return.Confused = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_PARALYZE:
|
|
Return.Paralyzed = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_PETRIFY:
|
|
Return.Stone = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_CURSE:
|
|
Return.Cursed = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_DEAF:
|
|
Return.Deaf = TRUE;
|
|
break;
|
|
case EFFECT_TYPE_BLINDNESS:
|
|
Return.Blind = TRUE;
|
|
break;
|
|
}
|
|
eCheck = GetNextEffect(oCreature);
|
|
}
|
|
// Wounds
|
|
int nHP = GetCurrentHitPoints(oCreature);
|
|
int nMaxHP = GetMaxHitPoints(oCreature);
|
|
// Set variables
|
|
if(nHP >= nMaxHP)
|
|
{
|
|
Return.Unharmed = TRUE;
|
|
}
|
|
else if(nHP > 0)
|
|
{
|
|
Return.Wounded = TRUE;
|
|
}
|
|
else if(nHP > -10)
|
|
{
|
|
Return.Dying = TRUE;
|
|
}
|
|
else
|
|
{
|
|
Return.Dead = TRUE;
|
|
}
|
|
// Return Return ( ;-) )
|
|
return Return;
|
|
}
|