Does the EffectKnockdown() effect is bugged?

I have created an effect that should knockdown the target for 1 round on a failed fort save, the target must do that save each round, i’m applying the effect from an AoE.

Now the bug, very often, the target will do the stand up animation right away without moving or even will move normally and rarely will stay down.

Here is my code that i’m using in the heartbeat:

	object oCreator = GetAreaOfEffectCreator();
    object oTarget = GetFirstInPersistentObject();
	int nSpellID = GetAreaOfEffectSpellId();
	
	while(GetIsObjectValid(oTarget))
	{
		if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, oCreator))
		{
	        SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpellID));
			if(!ResistSpell(oCreator, oTarget))
			{
				if(!MySavingThrow(SAVING_THROW_FORT,oTarget,GetSpellSaveDC(),SAVING_THROW_TYPE_SPELL))
				{
					ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectKnockdown(), oTarget, 6.0);
				}
			}
		}
		oTarget = GetNextInPersistentObject();
	}

Don’t use GetSpellSaveDC() inside the AOE scripts, there’s a bug causing this function to return 0 (or so) in that case. Instead set the DC as a local integer variable on the AOE object itself in the spell impact script and retrieve it with GetLocalInt() in the AOE script.

effect eAOE = EffectAreaOfEffect(SOME_SPELL_ID, "aoe_onenter_script", "aoe_heartbeat_script", "aoe_onexit_script", "aoe_unique_tag");

ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eAOE, lTarget, RoundsToSeconds(nDuration));
object oAOE = GetNearestObjectByTag("aoe_unique_tag", OBJECT_SELF);
SetLocalInt(oAOE, "DC", GetSpellSaveDC());

Mmm, i didn’t knew about that bug. I’m actually using a local var for the DC. I put that code to make it simpler to understand. This is the actual code. The local vars are getting the right parameters.

	object oCreator = GetAreaOfEffectCreator();
	int nSpellID = GetAreaOfEffectSpellId();
	int nCasterLvl = GetLocalInt(OBJECT_SELF,"CASTER_LEVEL");
	int nDC = GetLocalInt(OBJECT_SELF,"SAVE_DC");
	float fDuration = GetLocalFloat(OBJECT_SELF,"DURATION");		

	effect eWindstorm = EffectDeaf();
	eWindstorm = EffectLinkEffects(eWindstorm,EffectConcealment(100,MISS_CHANCE_TYPE_VS_RANGED));
	
	
    object oTarget = GetEnteringObject();
	int nCreatureSize = GetCreatureSize(oTarget);
	float fKnockdownDuration = 6.0;
	int nSlow = 65;
	
	if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, oCreator))
	{
        SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, nSpellID));

			if(nCreatureSize == CREATURE_SIZE_LARGE || nCreatureSize == CREATURE_SIZE_HUGE)
			{
				nSlow-=	GetAbilityScore(oTarget,ABILITY_STRENGTH);
				
				if(nSlow<=0) nSlow = 1;
				eWindstorm = EffectLinkEffects(eWindstorm,EffectMovementSpeedDecrease(nSlow));
			}
			else
			{
				if(nCreatureSize == CREATURE_SIZE_TINY || nCreatureSize == CREATURE_SIZE_SMALL)
					fKnockdownDuration = fDuration;
				else if(nCreatureSize == CREATURE_SIZE_MEDIUM)
					fKnockdownDuration = 6.0;
			
				if(!MySavingThrow(SAVING_THROW_FORT,oTarget,nDC,SAVING_THROW_TYPE_SPELL))
				{
					ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectKnockdown(), oTarget, fKnockdownDuration);
				}
			}
			
			eWindstorm = ExtraordinaryEffect(eWindstorm);
			ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eWindstorm, oTarget, fDuration);
		
	}

And this is the description of the custom spell(Mystery):

Initiate Mystery, Elemental Shadows Path
Caster Level(s): Shadowcaster
Innate Level: 5
School: Transmutation
Descriptor(s):
Component(s): Somatic
Range: Long
Area of Effect / Target: Huge
Duration: 1 round / level
Save: Fortitude negates
Spell Resistance: No

You alter wind force in the area surrounding you. You can make the wind blow in a certain direction or manner, increase its strength, or decrease its strength.

This mystery creates a powerful windstorm in the area. Each round, any smaller and medium creature must do a fortitude saving throw or be knocked down. Smalls creatures that fail are knocked down for the duration of this mystery and can’t roll again the save, medium creatures will be knocked down for 1 round. Large and Huge creatures will move at a reduced rate.

In addition, ranged attacks have a 100% chance to miss and the creatures inside gets deafened due to the howling of the wind.

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.

Thanks, i’m going to experiment with this, this bug is very strange since i have another custom spell that is like the Knockdown feat but is ranged and that one applies it normally without problems.

It seems that the EffectKnockdown function is actually bugged,i tested it with Gust of Wind, if you are knocked down and you click on anywhere to try to move or you were moving when you got knocked down, your character will stand up but you still will be under the effect of knockdown. It seems that this behavior also affects to creatures controlled by the AI.

It seems that is a buggy interaction between the SetCommandable function that many of this type of effects use and the mouse clicks.

1 Like

here’s what i did for Tasha’s Laughter (long ago…)

case SAVING_THROW_CHECK_FAILED:
{
    // kL. ToDo this so IMMUNITY to KnockDown doesn't spoil the fun ...
    int bCommandable = GetCommandable(oTarget);
    if (!bCommandable) SetCommandable(TRUE, oTarget);

    int iDur = GetCasterLevel(OBJECT_SELF);
    float fDur = RoundsToSeconds(iDur);
    fDur = ApplyMetamagicDurationMods(fDur);

    AssignCommand(oTarget, ClearAllActions(TRUE));
    AssignCommand(oTarget, PlayVoiceChat(VOICE_CHAT_LAUGH));
    AssignCommand(oTarget, ActionSpeakString("I never heard THAT one !! hahahahah", TALKVOLUME_TALK));
    AssignCommand(oTarget, ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING));

    effect eHit = EffectVisualEffect(VFX_HIT_SPELL_ENCHANTMENT);
    ApplyEffectToObject(DURATION_TYPE_INSTANT, eHit, oTarget);

    if (iDur > 1)
    {
        effect eDur = EffectVisualEffect(VFX_DUR_SPELL_TASHA_LAUGHTER);
        effect eLaugh = EffectKnockdown();
        eLaugh = EffectLinkEffects(eLaugh, eDur);

        DelayCommand(6.f, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLaugh, oTarget, fDur - 6.f));
    }


    DelayCommand(0.1f, SetCommandable(FALSE, oTarget));
    if (bCommandable) DelayCommand(fDur, SetCommandable(TRUE, oTarget));
    break;
}
1 Like