PRC8/nwn/nwnprc/trunk/newspellbook/shd_myst_darkair.nss
Jaysyn904 6ec137a24e Updated AMS marker feats
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.
2024-02-11 14:01:05 -05:00

115 lines
4.7 KiB
Plaintext

/*
15/02/19 by Stratovarius
Dark Air
Initiate, Elemental Shadows
Level/School: 5th/Transmutation [Air]
Reaching out with your mind to the darkness attached to your soul, you infuse nature with shadow and compel it to do your will.
This mystery acts like the spell control wind, tossing creatures about and knocking them to the ground if they fail a reflex save.
*/
#include "shd_inc_shdfunc"
#include "shd_mysthook"
void DoRandomMove(object oTarget)
{
// Calculate the new location
object oArea = GetArea(oTarget);
float fDistance = FeetToMeters(10.0f * d4());
float fAngle = IntToFloat(Random(3600)) / 10.0;
float fFacing = IntToFloat(Random(3600)) / 10.0;
vector vOrigin = GetPosition(oTarget);
vector vAngle = AngleToVector(fAngle);
vector vTarget = vOrigin + (vAngle * fDistance);
// If there is blocking geometry on the way, determine where
if(!LineOfSightVector(vOrigin, vTarget))
{
float fEpsilon = 1.0f; // Search precision
float fLowerBound = 0.0f; // The lower search bound, initialise to 0
float fUpperBound = fDistance; // The upper search bound, initialise to the initial distance
fDistance = fDistance / 2; // The search position, set to middle of the range
do{
// Create test vector for this iteration
vTarget = vOrigin + (vAngle * fDistance);
// Determine which bound to move.
if(LineOfSightVector(vOrigin, vTarget))
fLowerBound = fDistance;
else
fUpperBound = fDistance;
// Get the new middle point
fDistance = (fUpperBound + fLowerBound) / 2;
}while(fabs(fUpperBound - fLowerBound) > fEpsilon);
}// end if - The location was blocked by geometry
// Create the final target vector
vTarget = vOrigin + (vAngle * fDistance);
// Move the target
int bCommandable = GetCommandable(oTarget);
location lTargetDestination = Location(oArea, vTarget, fFacing);
float fDelay = PRCGetRandomDelay();
// Set commandable if it isn't already
/* if(!bCommandable)
SetCommandable(TRUE, oTarget);*/
// Assign jump commands
AssignCommand(oTarget, ClearAllActions(TRUE));
AssignCommand(oTarget, JumpToLocation(lTargetDestination));
// Set commandability off it it was off in the beginning
/* if(!bCommandable)
AssignCommand(oTarget, ActionDoCommand(SetCommandable(FALSE, oTarget)));*/
/*DoDebug("DoRandomMove(): Jumping creature " + DebugObject2Str(oTarget) + "\n"
+ "Old location = " + DebugLocation2Str(GetLocation(oTarget)) + "\n"
+ "New location = " + DebugLocation2Str(lTargetDestination) + "\n"
+ "Commandability = " + DebugBool2String(bCommandable) + "\n"
);*/
// Do some VFX during the jump delay
DrawLineFromVectorToVector(DURATION_TYPE_INSTANT, VFX_IMP_WIND, oArea, vOrigin, vTarget, 0.0f,
FloatToInt(GetDistanceBetweenLocations(GetLocation(oTarget), lTargetDestination)), // One VFX every meter
fDelay
);
}
void main()
{
if(!ShadPreMystCastCode()) return;
object oShadow = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
location lTarget = PRCGetSpellTargetLocation();
struct mystery myst = EvaluateMystery(oShadow, oTarget, METASHADOW_NONE);
if(myst.bCanMyst)
{
//ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_STORM), lTarget);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_TORNADO), lTarget);
oTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0f), lTarget, TRUE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oTarget))
{
if(spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, oShadow))
{
// Let the AI know
PRCSignalSpellEvent(oTarget, TRUE, myst.nMystId, oShadow);
if (!PRCMySavingThrow(SAVING_THROW_REFLEX, oTarget, GetShadowcasterDC(oShadow), SAVING_THROW_TYPE_SPELL))
{
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectKnockdown(), oTarget, 6.0, TRUE, myst.nMystId, myst.nShadowcasterLevel);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_PULSE_WIND), oTarget);
}// end if - Reflex save
DoRandomMove(oTarget);
}// end if - Difficulty check
// Get next target
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0f), lTarget, TRUE, OBJECT_TYPE_CREATURE);
}// end while - Explosion target loop
}
}