OnPainScript: function getlocalvar("attacktype") result as #0 instead of 0

Bruce

Active member
Hello everyone,
Can someone take a look at this?
I am trying to setup the counters using onpainscript for the boss entities to prevent players from spamming.

OnPainScript:
Code:
void AttackType = getlocalvar("attacktype"); // Get attack type
void self = getlocalvar("self");   // Caller
int random = rand()%50;   // RANDOM -49 to 49,
if(random < 0)
{ random = random * -1;  }
    
if(AttackType == openborconstant("ATK_NORMAL"))
{
    if(getentityvar(self, "Spawn_Pain_Counter") > random)
    {
        performattack(self, openborconstant("ANI_block"));
    }
}

performattack never triggers because getlocalvar("attacktype") gives the result of #0 instead of 0.
Since openborconstant("ATK_NORMAL") is 0. Therefore, the if condition is never met.

I am using this attack x x x x x x x x x x in the animations of the boss's entity.
samething happens to attack2 x x x x x x x x x x and so on


I've tried it with OnFallScript which it is working fine.
getlocalvar("attacktype" functions seems to give the wrong result in the onpainscript, not in the OnFallScript.


I am using Kartus's version because of the bug I reported here:
What causes the stage not to end after the certain boss is defeated?

Thank you so much
 
I guess I can just use the lasthitt function to replace this native function getlocalvar("attacktype") for now.
Hopefully someone can figure it out and update it accordingly.
 
I'll try to take a closer look at this when I have more time at my desk if someone else doesn't beat me to it.

DC
@DCurrent I looked at the engine source and compared it with the takedamage script, which works fine. It seems that the onpain event has a different structure, maybe some rework applied on the takedamage but not applied in the onpain?

Code:
void    execute_takedamage_script               (entity *ent, entity *other, s_attack *attack);
void    execute_on_bind_update_other_to_self    (entity *ent, entity *other, s_bind *bind);
void    execute_on_bind_update_self_to_other    (entity *ent, entity *other, s_bind *bind);
void    execute_ondeath_script                  (entity *ent, entity *other, s_attack *attack);
void    execute_onkill_script                   (entity *ent, e_kill_entity_trigger trigger);
void    execute_onpain_script                   (entity *ent, int iType, int iReset);

Code:
void execute_takedamage_script(entity *ent, entity *other, s_attack *attack)
{
    ScriptVariant tempvar;
    Script *cs = ent->scripts->takedamage_script;
    if(Script_IsInitialized(cs))
    {
        ScriptVariant_Init(&tempvar);
        ScriptVariant_ChangeType(&tempvar, VT_PTR);

        tempvar.ptrVal = (VOID *)ent;
        Script_Set_Local_Variant(cs, "self",        &tempvar);

        tempvar.ptrVal = (VOID *)other;
        Script_Set_Local_Variant(cs, "attacker",    &tempvar);

        ScriptVariant_ChangeType(&tempvar, VT_INTEGER);

        tempvar.lVal = (LONG)attack->attack_force;
        Script_Set_Local_Variant(cs, "damage",      &tempvar);

        tempvar.lVal = (LONG)attack->attack_drop;
        Script_Set_Local_Variant(cs, "drop",        &tempvar);

        tempvar.lVal = (LONG)attack->attack_type;
        Script_Set_Local_Variant(cs, "attacktype",  &tempvar);

        tempvar.lVal = (LONG)attack->no_block;
        Script_Set_Local_Variant(cs, "noblock",     &tempvar);

        tempvar.lVal = (LONG)attack->guardcost;
        Script_Set_Local_Variant(cs, "guardcost",   &tempvar);

        tempvar.lVal = (LONG)attack->jugglecost;
        Script_Set_Local_Variant(cs, "jugglecost",  &tempvar);

        tempvar.lVal = (LONG)attack->pause_add;
        Script_Set_Local_Variant(cs, "pauseadd",    &tempvar);

        tempvar.lVal = (LONG)attack->meta_tag;
        Script_Set_Local_Variant(cs, "tag",    &tempvar);


        Script_Execute(cs);

        //clear to save variant space
        ScriptVariant_Clear(&tempvar);
        Script_Set_Local_Variant(cs, "self",        &tempvar);
        Script_Set_Local_Variant(cs, "attacker",    &tempvar);
        Script_Set_Local_Variant(cs, "damage",      &tempvar);
        Script_Set_Local_Variant(cs, "drop",        &tempvar);
        Script_Set_Local_Variant(cs, "attacktype",  &tempvar);
        Script_Set_Local_Variant(cs, "noblock",     &tempvar);
        Script_Set_Local_Variant(cs, "guardcost",   &tempvar);
        Script_Set_Local_Variant(cs, "jugglecost",  &tempvar);
        Script_Set_Local_Variant(cs, "pauseadd",    &tempvar);
        Script_Set_Local_Variant(cs, "tag",    &tempvar);
    }
}

Code:
void execute_onpain_script(entity *ent, int iType, int iReset)
{
    ScriptVariant tempvar;
    Script *cs = ent->scripts->onpain_script;
    if(Script_IsInitialized(cs))
    {
        ScriptVariant_Init(&tempvar);
        ScriptVariant_ChangeType(&tempvar, VT_PTR);
        tempvar.ptrVal = (VOID *)ent;
        Script_Set_Local_Variant(cs, "self",        &tempvar);
        tempvar.lVal = (LONG)iType;
        Script_Set_Local_Variant(cs, "attacktype",   &tempvar);
        tempvar.lVal = (LONG)iReset;
        Script_Set_Local_Variant(cs, "reset",       &tempvar);
        Script_Execute(cs);
        //clear to save variant space
        ScriptVariant_Clear(&tempvar);
        Script_Set_Local_Variant(cs, "self",        &tempvar);
        Script_Set_Local_Variant(cs, "type",        &tempvar);
        Script_Set_Local_Variant(cs, "reset",       &tempvar);
    }
}

I guess I can just use the lasthitt function to replace this native function getlocalvar("attacktype") for now.
Hopefully someone can figure it out and update it accordingly.
@Bruce For now, I suggest using the takedamage instead, which is more complete and can be used to detect pain animations too.
 
@DCurrent I looked at the engine source and compared it with the takedamage script, which works fine. It seems that the onpain event has a different structure, maybe some rework applied on the takedamage but not applied in the onpain?

Code:
void    execute_takedamage_script               (entity *ent, entity *other, s_attack *attack);
void    execute_on_bind_update_other_to_self    (entity *ent, entity *other, s_bind *bind);
void    execute_on_bind_update_self_to_other    (entity *ent, entity *other, s_bind *bind);
void    execute_ondeath_script                  (entity *ent, entity *other, s_attack *attack);
void    execute_onkill_script                   (entity *ent, e_kill_entity_trigger trigger);
void    execute_onpain_script                   (entity *ent, int iType, int iReset);

Code:
void execute_takedamage_script(entity *ent, entity *other, s_attack *attack)
{
    ScriptVariant tempvar;
    Script *cs = ent->scripts->takedamage_script;
    if(Script_IsInitialized(cs))
    {
        ScriptVariant_Init(&tempvar);
        ScriptVariant_ChangeType(&tempvar, VT_PTR);

        tempvar.ptrVal = (VOID *)ent;
        Script_Set_Local_Variant(cs, "self",        &tempvar);

        tempvar.ptrVal = (VOID *)other;
        Script_Set_Local_Variant(cs, "attacker",    &tempvar);

        ScriptVariant_ChangeType(&tempvar, VT_INTEGER);

        tempvar.lVal = (LONG)attack->attack_force;
        Script_Set_Local_Variant(cs, "damage",      &tempvar);

        tempvar.lVal = (LONG)attack->attack_drop;
        Script_Set_Local_Variant(cs, "drop",        &tempvar);

        tempvar.lVal = (LONG)attack->attack_type;
        Script_Set_Local_Variant(cs, "attacktype",  &tempvar);

        tempvar.lVal = (LONG)attack->no_block;
        Script_Set_Local_Variant(cs, "noblock",     &tempvar);

        tempvar.lVal = (LONG)attack->guardcost;
        Script_Set_Local_Variant(cs, "guardcost",   &tempvar);

        tempvar.lVal = (LONG)attack->jugglecost;
        Script_Set_Local_Variant(cs, "jugglecost",  &tempvar);

        tempvar.lVal = (LONG)attack->pause_add;
        Script_Set_Local_Variant(cs, "pauseadd",    &tempvar);

        tempvar.lVal = (LONG)attack->meta_tag;
        Script_Set_Local_Variant(cs, "tag",    &tempvar);


        Script_Execute(cs);

        //clear to save variant space
        ScriptVariant_Clear(&tempvar);
        Script_Set_Local_Variant(cs, "self",        &tempvar);
        Script_Set_Local_Variant(cs, "attacker",    &tempvar);
        Script_Set_Local_Variant(cs, "damage",      &tempvar);
        Script_Set_Local_Variant(cs, "drop",        &tempvar);
        Script_Set_Local_Variant(cs, "attacktype",  &tempvar);
        Script_Set_Local_Variant(cs, "noblock",     &tempvar);
        Script_Set_Local_Variant(cs, "guardcost",   &tempvar);
        Script_Set_Local_Variant(cs, "jugglecost",  &tempvar);
        Script_Set_Local_Variant(cs, "pauseadd",    &tempvar);
        Script_Set_Local_Variant(cs, "tag",    &tempvar);
    }
}

Code:
void execute_onpain_script(entity *ent, int iType, int iReset)
{
    ScriptVariant tempvar;
    Script *cs = ent->scripts->onpain_script;
    if(Script_IsInitialized(cs))
    {
        ScriptVariant_Init(&tempvar);
        ScriptVariant_ChangeType(&tempvar, VT_PTR);
        tempvar.ptrVal = (VOID *)ent;
        Script_Set_Local_Variant(cs, "self",        &tempvar);
        tempvar.lVal = (LONG)iType;
        Script_Set_Local_Variant(cs, "attacktype",   &tempvar);
        tempvar.lVal = (LONG)iReset;
        Script_Set_Local_Variant(cs, "reset",       &tempvar);
        Script_Execute(cs);
        //clear to save variant space
        ScriptVariant_Clear(&tempvar);
        Script_Set_Local_Variant(cs, "self",        &tempvar);
        Script_Set_Local_Variant(cs, "type",        &tempvar);
        Script_Set_Local_Variant(cs, "reset",       &tempvar);
    }
}


@Bruce For now, I suggest using the takedamage instead, which is more complete and can be used to detect pain animations too.
This is great.
I just checked the logs for
void DropValue = getlocalvar("drop"); // Get damage juggle power value vale
void PauseValue = getlocalvar("pauseadd");
void AttackType = getlocalvar("attacktype");

takedamagescript actually give these results!
The manual doesn't list these functions for takedamagescript.
I only had takedamagescript for subject_to_screen for wall splatter based on your script.
Now I can add the counters to the takedamagescript to replace counters from onpainscipt then.
Thank you so much for your help.
 
detect pain animations
I was just thinking to use getlocalvar("drop") to check if it is 0.
If it is 0 then it is for pain animations.
I guess I can also check for this
openborconstant("ANI_PAIN")

Thanks a lot

Editted:

Oh no, takedamagescript won't work for my counter setup.
It can change to the animation I want (ANI_BLOCK), but then it gets stopped at the first frame.
I have even tried to make it change to other animations that have bbox 0000, same results.
This is so weird...it looks like the animation has changed, but then it just stopped at first frame for some reasons.
This does not make any sense.
 
Last edited:
Editted:

Oh no, takedamagescript won't work for my counter setup.
It can change to the animation I want (ANI_BLOCK), but then it gets stopped at the first frame.
I have even tried to make it change to other animations that have bbox 0000, same results.
This is so weird...it looks like the animation has changed, but then it just stopped at first frame for some reasons.
This does not make any sense.
@Bruce In this case, since you are using it for a counter attack, I suggest using the ondoattack event together with the lasthit.c variant.
Something like this (I disabled your entityvar only for test purpose, you can enable it again):

Code:
void main()
{
    //WORKS FOR DEFENDER ONLY
    if(getlocalvar("which")){
        void AttackType = getlocalvar("attacktype"); // Get attack type
        void self = getlocalvar("self");   // Caller
        int random = rand()%50;   // RANDOM -49 to 49,
        if(random < 0)
        { random = random * -1;  }
            
        if(AttackType == openborconstant("ATK_NORMAL"))
        {
            // if(getentityvar(self, "Spawn_Pain_Counter") > random)
            // {
            //     performattack(self, openborconstant("ANI_block"));
            // }
            //log("success"+"\n");

            changeopenborvariant("lasthitc", 0); //DISABLE THE LAST COLLISION
            changeentityproperty(self, "velocity", 0, 0, 0); //STOP THE ENTITY
            performattack(self, openborconstant("ANI_BLOCK")); //PERFORM THE BLOCK ANIMATION
        }
    }
}
 
@Bruce In this case, since you are using it for a counter attack, I suggest using the ondoattack event together with the lasthit.c variant.
Something like this (I disabled your entityvar only for test purpose, you can enable it again):

Code:
void main()
{
    //WORKS FOR DEFENDER ONLY
    if(getlocalvar("which")){
        void AttackType = getlocalvar("attacktype"); // Get attack type
        void self = getlocalvar("self");   // Caller
        int random = rand()%50;   // RANDOM -49 to 49,
        if(random < 0)
        { random = random * -1;  }
      
        if(AttackType == openborconstant("ATK_NORMAL"))
        {
            // if(getentityvar(self, "Spawn_Pain_Counter") > random)
            // {
            //     performattack(self, openborconstant("ANI_block"));
            // }
            //log("success"+"\n");

            changeopenborvariant("lasthitc", 0); //DISABLE THE LAST COLLISION
            changeentityproperty(self, "velocity", 0, 0, 0); //STOP THE ENTITY
            performattack(self, openborconstant("ANI_BLOCK")); //PERFORM THE BLOCK ANIMATION
        }
    }
}
I have tried this OnDoAttack script, but for some reasons I am not getting any log...
I even copied exact what you have, still no log.
Did you mean if(getlocalvar("which") == 0){ for defender? the manual says 0 for defender, 1 for attacker,
but regardless, I have checked the logs for both, but still no log.
I must be doing something wrong!


I put this in the boss entity header

ondoattack data/scripts/DoAttack/OnDoAttack_Enemy.c
this location data/scripts/DoAttack is where I put OnDoAttack_Enemy.c

I don't understand why I am not getting any logs! so weird
thank you


Update:

I found the error!
the manual says
ondoattack and I was wondering about this..., but it is actually ondoattackscript!
It is working now, I will test it more, and report back if I see anything,

thank you so much
 
Last edited:
Back
Top Bottom