Enemy still grabbable after being knocked down??

MysticalMist

Well-known member
I have one particular enemy where whenever they're knocked down, the player is still able to grab them? It makes for an easily exploitable loop where the player can just endlessly throw them and for some reason, it only seems to happen with that particular npc. Here is their stats and the fall animation in question.


Code:
type enemy
health  1250
score 15000 5
gfxshadow    1
nodieblink 1
riseinv 1
speed   15
nolife 1
falldie 2
aggression 3000
nodieblink 3
aimove avoidx
dust dust dust dust
jugglepoints 30
subject_to_screen 1
subject_to_platform 1
defense normal3 1 100
animationscript data/scripts/escript.c
ondrawscript data/scripts/shadowon.c
script           data/scripts/superarmorVelvette.c
remap data/chars/altvelvette/idle/0.png data/chars/altvelvette/freeze.png
fmap 1
knockdowncount 30
lifebarstatus        200 10 0 1 0 0 0 0 0
lifeposition        145 250
nameposition        145 240
iconposition        110 235
antigravity 6
aggression 200
escapehits 5

The fall animation:
Code:
anim fall
landframe 1
@script
    void self = getlocalvar("self"); //Get calling entity.
    int Health = getentityproperty(self,"health");
    if(Health <= 0){
    changeentityproperty(self, "Subject_to_minz", 1);
    changeentityproperty(self,"subject_to_screen",1);
    }
@end_script
    offset 57 103
    delay 9999
    bbox 20 57 77 31
    attack 19 77 61 11 5 9999 0 0 5 0
    frame data/chars/altvelvette/dmg/2.png
    delay 80
    offset 57 103
    bbox none
    attack none
    frame data/chars/altvelvette/dmg/3.png

Is there anything I'm missing in particular? I find this kinda odd.
 
How is the enemy grabbable exactly? I mean, is it by grab scripts or by the normal "grab" animation?
And is this during the "fall" animation while in the air or after bouncing the ground?
When the enemy is on the ground, it is able to be normally grabbed.

The fall animation is the standard one. The second frame is when they bounce to the ground, without a bbox.
 
Now I understand. Are you using a scripted throw or the native one? If it's scripted, please can you post the code?
Another thing you can try is to replace "bbox none" with "bbox 0 0 0 0".
The player uses grabbackward/grabforward for a scripted throw.

Code:
    @cmd grabStart
    @cmd slamstart 9999
    @cmd position 1 20 12 1 0
    delay 12
    offset    59 123
    sound data/sounds/Millie1.wav
    frame    data/chars/Millie/grab/3.png
    delay 7
    offset    59 123
    @cmd position 4 10 0 1 0
    frame    data/chars/Millie/grab/4.png
    offset    59 123
    @cmd position 4 0 5 1 0
    sound data/sounds/swing.wav
    frame    data/chars/Millie/grab/5.png
    @cmd position 2 -25 15 1 1
    offset    59 123
    frame    data/chars/Millie/grab/6.png
    delay 24
    @cmd depost 0
    @cmd throw 20 2 -2 3 0 0
    @cmd    clearL
    offset    59 123
    delay 24
    frame    data/chars/Millie/grab/6.png

This issue does not persist with other enemies however.
 
This issue does not persist with other enemies however.
This is really strange, I have a lot of grab scripts in the SORX but never had this issue.
I don't know if it's the cause but usually the clearL is placed in another frame separated from the throw/depost functions. I would like to take a look in your "void throw" code too.

1778126903681.png

Like this.
Code:
delay 24
@cmd depost 0
@cmd throw 20 2 -2 3 0 0
offset    59 123
delay 12
frame    data/chars/Millie/grab/6.png
@cmd    clearL
frame    data/chars/Millie/grab/6.png
 
This is really strange, I have a lot of grab scripts in the SORX but never had this issue.
I don't know if it's the cause but usually the clearL is placed in another frame separated from the throw/depost functions. I would like to take a look in your "void throw" code too.


Code:
void throw(int damage, int type, int Vx, int Vy, int Vz, int face)
{//Damage as throw finisher
    void self    = getlocalvar("self");
    void target    = getentityvar(self,"grabbed");
    int z        = getentityproperty(self,"z");
    int tDir    = getentityproperty(target,"direction");
    int vDir;
    
    if(face == 0){ //SAME FACING?
        vDir = tDir;
    }

    if(face == 1){ //OPPOSITE FACING?
        if(tDir == 0){ //FACING LEFT?
            vDir = 1;
        }
        else
        {
            vDir = 0;
        }
    }

    if(target != NULL()){
        void atkType;
        void eType        = getentityproperty(target,"type");
        int dir            = getentityproperty(target,"direction");
        int dropType    = 1;
        
        if(dir == 0){Vx = -Vx;}
        if(type == 1){atkType = openborconstant("ATK_NORMAL8");}
        if(type == 2){atkType = openborconstant("ATK_NORMAL9");}
        
        if(eType == openborconstant("TYPE_PLAYER") || eType == openborconstant("TYPE_NPC")){
            changeentityproperty(target, "projectilehit", "type_player", "type_npc", "type_obstacle");
        }
        else
        if(eType == openborconstant("TYPE_ENEMY")){
            changeentityproperty(target, "projectilehit", "type_enemy", "type_obstacle");
        }
        
        damageentity(target, self, 0, dropType, atkType);
        changeentityproperty(target, "direction", vDir);
        changeentityproperty(target, "damage_on_landing", damage); //RESET PROJECTILE STATUS TO 0 WHEN FALL ON THE GROUND, TOTAL DAMAGE
        changeentityproperty(target, "aiflag", "projectile", 1);
        finishGrab(Vx, Vy, Vz); //EXECUTE ALL NECESSARY TASKS TO END THE GRAB MOVE (ANTIWALL, UNBIND AND TOSSENTITY)
        setentityvar(self, "grabbed", NULL()); //CLEAR ENTITYVAR
    }
}
 
Code:
void throw(int damage, int type, int Vx, int Vy, int Vz, int face)
{//Damage as throw finisher
    void self    = getlocalvar("self");
    void target    = getentityvar(self,"grabbed");
    int z        = getentityproperty(self,"z");
    int tDir    = getentityproperty(target,"direction");
    int vDir;
   
    if(face == 0){ //SAME FACING?
        vDir = tDir;
    }

    if(face == 1){ //OPPOSITE FACING?
        if(tDir == 0){ //FACING LEFT?
            vDir = 1;
        }
        else
        {
            vDir = 0;
        }
    }

    if(target != NULL()){
        void atkType;
        void eType        = getentityproperty(target,"type");
        int dir            = getentityproperty(target,"direction");
        int dropType    = 1;
       
        if(dir == 0){Vx = -Vx;}
        if(type == 1){atkType = openborconstant("ATK_NORMAL8");}
        if(type == 2){atkType = openborconstant("ATK_NORMAL9");}
       
        if(eType == openborconstant("TYPE_PLAYER") || eType == openborconstant("TYPE_NPC")){
            changeentityproperty(target, "projectilehit", "type_player", "type_npc", "type_obstacle");
        }
        else
        if(eType == openborconstant("TYPE_ENEMY")){
            changeentityproperty(target, "projectilehit", "type_enemy", "type_obstacle");
        }
       
        damageentity(target, self, 0, dropType, atkType);
        changeentityproperty(target, "direction", vDir);
        changeentityproperty(target, "damage_on_landing", damage); //RESET PROJECTILE STATUS TO 0 WHEN FALL ON THE GROUND, TOTAL DAMAGE
        changeentityproperty(target, "aiflag", "projectile", 1);
        finishGrab(Vx, Vy, Vz); //EXECUTE ALL NECESSARY TASKS TO END THE GRAB MOVE (ANTIWALL, UNBIND AND TOSSENTITY)
        setentityvar(self, "grabbed", NULL()); //CLEAR ENTITYVAR
    }
}
The code looks normal. Is the falling character in the video using some kind of custom animation instead of the rise/riseattack?
 
The code looks normal. Is the falling character in the video using some kind of custom animation instead of the rise/riseattack?
Not really. In the RISE animation, there's a check for if the health's a certain amount to go into a desperation move, but there's not even a bbox in that animation either, I think.
 
Not really. In the RISE animation, there's a check for if the health's a certain amount to go into a desperation move, but there's not even a bbox in that animation either, I think.
The only function I know that can force a grab using the native way is the dograb. Are you using it somewhere in the game?
It's really very strange, I would need to see the game file to understand better.
 
Back
Top Bottom