I threw your ideas through the grinder and these came out …
i believe the code is tight, but that doesn’t mean they’d work as expected
bounce them around however you like; they’re just to give another perspective,
// 'windstorm_en'
#include "nw_i0_spells"
void main()
{
object oCreator = GetAreaOfEffectCreator();
object oTarget = GetEnteringObject();
if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, oCreator))
{
int iSpellId = GetAreaOfEffectSpellId();
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, iSpellId));
effect eDeaf = EffectDeaf();
effect eConceal = EffectConcealment(100, MISS_CHANCE_TYPE_VS_RANGED);
effect eLink = EffectLinkEffects(eDeaf, eConceal);
float fDur = GetLocalFloat(OBJECT_SELF, "DURATION");
float fKd = 0.f;
int iSpeedDecr;
switch (GetCreatureSize(oTarget))
{
case CREATURE_SIZE_HUGE:
case CREATURE_SIZE_LARGE:
iSpeedDecr = 55;
break;
case CREATURE_SIZE_MEDIUM:
iSpeedDecr = 75;
fKd = 6.f;
break;
case CREATURE_SIZE_SMALL:
case CREATURE_SIZE_TINY:
iSpeedDecr = 95;
fKd = fDur;
break;
}
if (fKd != 0.f)
{
int iDC = GetLocalInt(OBJECT_SELF, "SAVE_DC");
if (!MySavingThrow(SAVING_THROW_FORT, oTarget, iDC, SAVING_THROW_TYPE_SPELL))
{
effect eKd = EffectKnockdown();
eKd = SetEffectSpellId(eKd, iSpellId);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eKd, oTarget, fKd);
}
}
iSpeedDecr -= GetAbilityScore(oTarget, ABILITY_STRENGTH);
if (iSpeedDecr > 0)
{
effect eSpeedDecr = EffectMovementSpeedDecrease(iSpeedDecr);
eLink = EffectLinkEffects(eLink, eSpeedDecr);
}
eLink = ExtraordinaryEffect(eLink);
eLink = SetEffectSpellId(eLink, iSpellId);
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDur);
}
}
// 'windstorm_hb'
#include "nw_i0_spells"
void main()
{
object oCreator = GetAreaOfEffectCreator();
int iSpellId = GetAreaOfEffectSpellId();
int iDC = GetLocalInt(OBJECT_SELF, "SAVE_DC");
effect eKd = EffectKnockdown();
eKd = SetEffectSpellId(eKd, iSpellId);
object oTarget = GetFirstInPersistentObject();
while (GetIsObjectValid(oTarget))
{
if (GetCreatureSize(oTarget) == CREATURE_SIZE_MEDIUM
&& spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, oCreator))
{
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, iSpellId));
if (!MySavingThrow(SAVING_THROW_FORT, oTarget, iDC, SAVING_THROW_TYPE_SPELL))
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eKd, oTarget, 6.f);
}
}
oTarget = GetNextInPersistentObject();
}
}
// 'windstorm_ex'
void main()
{
int iSpellId = GetAreaOfEffectSpellId();
object oTarget = GetExitingObject();
effect eScan = GetFirstEffect(oTarget);
while (GetIsEffectValid(eScan))
{
if (GetEffectSpellId(eScan) == iSpellId)
{
RemoveEffect(oTarget, eScan);
eScan = GetFirstEffect(oTarget);
}
else
eScan = GetNextEffect(oTarget);
}
}
/untested
I don’t know why the knockdown isn’t doing a knockdown animation (unless target saves). A workaround would be to /not/ use (effect)knockdown and do PlayCustomAnimation along with a judicious use of SetCommandable.