• All, I am currently in the process of migrating domain registrations. During this time there may be some intermittent outages or slowdowns. Please contact staff if you have any questions.

Enemy "Doge" bullets (?)

Crimsondeath

Active member
Hi, I'm stuck x.x .
I need an enemy do an specifict animation just before getting shot by a bullet to dodge it.

I tried with animationscripts:
Spawnbinding an invisible entity that detect the bullets and forced him to do the animation:

Code:
name Koga
health    400
mp      90
type enemy

...

load    Kogacounter

animationscript  data/scripts/fscript.c

...

anim    follow4 #The boss Spawns with this animation
    loop    0
    delay    1
    offset    53 206
    @cmd     spawnbind "Kogacounter" 0 0 0  # The spawnbinded entity
    frame    data/chars/koga/spawn1.gif
    frame    data/chars/koga/spawn4.gif
    frame    data/chars/koga/spawn2.gif
    frame    data/chars/koga/spawn3.gif
    delay    3
    offset    53 150
    frame    data/chars/koga/attack1c.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/koga/attack1c.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/koga/attack1c.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/koga/attack1c.gif
    frame    data/chars/misc/empty.gif
    frame    data/chars/koga/attack1c.gif
    delay    109
    frame    data/chars/koga/attack1c.gif

The Spawnbinded entity code, Kogacounter.txt:
Code:
name    Kogacounter
type    npc
shadow    0
stealth 100 100
nomove    1 1

animationscript  data/chars/koga/Kogacounter.c


anim    follow1
        loop    0
        delay    1
        offset    0 0
@script
if(frame == 0){
    void self = getlocalvar("self");
    void vEntity;
    int  iEntity;
    char iName;
    int  iMax = openborvariant("count_entities");

    for(iEntity=0; iEntity<iMax; iEntity++){
        vEntity = getentity(iEntity);
        iName   = getentityproperty(vEntity, "name");

        if(iName == "Koga"){ // This force the boss to dodge the bullet
            executeanimation(openborconstant("ANI_FOLLOW2"), 1);
        }
    }
}
@end_script 
        frame    data/chars/misc/empty.gif
        delay    100
        frame    data/chars/misc/empty.gif

anim    idle
        loop    1
        delay    1
        offset    0 0
        @cmd    dodgebullet -100 100 -100 100 -10 10 "ANI_FOLLOW1"
        frame    data/chars/misc/empty.gif
        @cmd    dodgebullet -100 100 -100 100 -10 10 "ANI_FOLLOW1"
        frame    data/chars/misc/empty.gif

anim    spawn
        loop    0
        delay    1
        offset    0 0
        frame    data/chars/misc/empty.gif

The Spawnbinded entity animationscript, Kogacounter.c:
Code:
void dodgebullet(int RxMin, int RxMax, int RyMin, int RyMax, int RzMin, int RzMax, void Ani)
{

    void self = getlocalvar("self");
    void target;
    void vEntity;
    int  iEntity;
    char iName;
    int  iMax = openborvariant("count_entities");
    float x = getentityproperty(self, "x");
    float y = getentityproperty(self, "a");
    float z = getentityproperty(self, "z");
    int dir = getentityproperty(self, "direction");

    for(iEntity=0; iEntity<iMax; iEntity++){
        vEntity = getentity(iEntity);
        iName   = getentityproperty(vEntity, "name");

        if(iName == "Bala"){
                target = vEntity;
        }
    }

    if(target!=NULL()){
      float Tx = getentityproperty(target, "x");
      float Ty = getentityproperty(target, "a");
      float Tz = getentityproperty(target, "z");
      float Disx = Tx - x;
      float Disy = Ty - y;
      float Disz = Tz - z;

      if( 
      Disx >= RxMin && 
      Disx <= RxMax && 
      Disy >= RyMin && 
      Disy <= RyMax && 
      Disz >= RzMin && 
      Disz <= RzMax && dir == 1) // Target within range on right facing?
      {
        performattack(self, openborconstant(Ani)); //Change the animation
      } else if( 
          Disx >= -RxMax && 
          Disx <= -RxMin && 
          Disy >= RyMin && 
          Disy <= RyMax && 
          Disz >= RzMax && 
          Disz <= RzMin && dir == 0) // Target within range on left facing?
      {
        performattack(self, openborconstant(Ani)); //Change the animation
      }
    }
}

The problem: The script throws me "There's an exception while executing script 'Kogacounter' data/chars/koga/kogacounter.txt"
I attached the log.

I also tried with takedamagescript, but It didn't detect the attacktype I guess.

Code:
void main()
{
    void self = getlocalvar("self");
    void attacker = getlocalvar("attacker");
    int iTyp7 = openborconstant("ATK_NORMAL7");
    int iTyp8 = openborconstant("ATK_NORMAL8");
    int attacktype = getentityproperty(attacker, "attackid");

    if(attacktype == iTyp7 || attacktype == iTyp8) {
        executeanimation(self, openborconstant("ANI_FOLLOW5"), 1);
    }
}

Is there an effective way to do it? :(
 

Attachments

  • OpenBorLog.txt
    119.6 KB · Views: 0
This type of thing is better done using ondoattack script, as you can act BEFORE the damage (and nullify it totally) and the hit routine, while takedamage takes action AFTER it.
You can give the bullets a special attack type (like attack6) and make the code to check it the entity receives an attack with that type. If so, nullify the attack and make the entity to execute the dodge.
 
This type of thing is better done using ondoattack script, as you can act BEFORE the damage (and nullify it totally) and the hit routine, while takedamage takes action AFTER it.
You can give the bullets a special attack type (like attack6) and make the code to check it the entity receives an attack with that type. If so, nullify the attack and make the entity to execute the dodge.
Hi, thanks.
I tried something similar but do you know if there is a way to get the damage taken with an "animation script" or a frame?

I apply this to pain7 & 8 which is the bullet damage:
Code:
anim    pain7
    loop    0
    offset    59 127
    bbox    35 15 50 90
    delay    7
@script
    void self = getlocalvar("self");
    int Health = getentityproperty(self,"health");
    int damage = getlocalvar("damage");
    int r = rand()%2+2;

    if( frame == 0){
      if( r > 0){
            changeentityproperty(self, "health", Health + damage); // "health" the received damage
            changeentityproperty(self, "animation", openborconstant("ANI_FOLLOW6")); // execute counter attack
      }
    }
    @end_script
    @cmd    spawnbind "blood" 0 90 1
    frame    data/chars/koga/pain2a.gif
    frame    data/chars/koga/pain2b.gif
    frame    data/chars/koga/pain2a.gif

Is working great, but I can't nullify the damage taken:
- If the condition fail the boss take damage.
- but if the condicion is succeed it take damage too (but executing his counter attack of course xd).


EDIT: Ok I put the code on "takedamagescript" with a little tweaks. I think that conditions work like frames (?) .
Code:
void main()
{
  void self = getlocalvar("self");
  int Health = getentityproperty(self,"health");
  int damage = getlocalvar("damage");
  int attacktype = getlocalvar("attacktype");
  int r = rand()%10+10;
  int iTyp7 = openborconstant("ATK_NORMAL7"); 
  int iTyp8 = openborconstant("ATK_NORMAL8"); 

  if(attacktype == iTyp7 || attacktype == iTyp8){ // Counter attack only this damage type
    if( r > 1){ // with a 75% of posibility xd
      changeentityproperty(self, "nopain", 1); // This helps to stop pain animation
      changeentityproperty(self, "nodrop", 1); // This helps to stop fall animation
      executeanimation(self, openborconstant("ANI_SPECIAL")); // I change the animation to Special xd
      changeentityproperty(self, "health", Health + damage);
    }
  }
}

EDIT 2:
There is a new problem the entity shows its pain7/8 animation, so he don't do the dodge or counterattack :( Is there a way to force it to do it or it's imposible?

EDIT 3:
Ok, edited the code again xD.

I changed ANI_FOLLOW6 to ANI_SPECIAL, so from ANI_SPECIAL frame 0, move it to the ANI_FOLLOW I desire. It's working great! But sometimes the entity moves to the right or left while falling, missing its target (he needs to fall straight to the ground). It's there a way to change the property "nomove" ? I didn´t found it in the manual.
 
Last edited:
changeentityproperty(self, "nopain", 1); // This helps to stop pain animation
changeentityproperty(self, "nodrop", 1); // This helps to stop fall animation
I see a problem here: once you change this by script, it will remain that way until you revert it back - works like that in most of things you change by script, if I am not mistaken.

But sometimes the entity moves to the right or left while falling, missing its target (he needs to fall straight to the ground). It's there a way to change the property "nomove" ?
Probably because you are using a takedamagescrip, which happens AFTER the hit routine was triggered.
If you change your script from "takedamangescript" to "ondoatttackscript" (yeah, it has the word 'script' on it), you won't need to change NOPAIN, NODROP, neither will have any change on the velocity. See more about ondoattack here.

Once you move it to ondoattack, you would be able to use this:
Code:
changeopenborvariant("lasthitc",0); // not confirm the last hit, ignoring all the hit routine

Oh, by the way, I forgot I made a autododge code exactly like you want!

This is what I am using on Quicksilver:

ondoattackscript data/scripts/didhit/autododge.c

autododge.c:
C-like:
void main()
{
    //WORKS FOR DEFENDER ONLY
    if(getlocalvar("which")){
        void self    = getlocalvar("self");
        void type    = getentityproperty(self,"type");
        int iR       = rand()%50+50; //AVOID NEGATIVE NUMBERS, COUNT FROM 0 TO 50
        void alt     = getentityproperty(self, "a"); //Get Y location and add adjustment.
        void other = getlocalvar("other");     // gets the attacker
        char iType = getentityproperty(other, "type"); // gets the attacker type


        if(type == openborconstant("TYPE_PLAYER")){ //WORKS ONLY FOR PLAYERS
            if(iR > 20 && alt == 0 && iType != openborconstant("TYPE_ITEM")){ //CHECK THE CHANCE, ALTITUDE and not ITEM
                changeopenborvariant("lasthitc", 0); //DISABLE LAST HIT
                performattack(self, openborconstant("ANI_FOLLOW16"), 1); //CHANGE TO DODGE
            }
        }
    }
}

As you can see, I am not checking the attack type, just the attacker type. But you can modify it to your need :)

If you will use it on more than one entity, remember to use a fowarder ok?

ps: dunno why, but I don't receive any notification about your replies.
 
Thank you @O Ilusionista ,
The Script is way better that the mine :D the bullet didn't even touch the enemy making the dodge more "realistic" xd. But the enemy keep moving to the right or left while falling. If its not posible to fix that maybe I'll find a way to give an use to that bug xd.

Here you have the code to look What I did :D :

Code:
void main()
{
    //WORKS FOR DEFENDER ONLY
    if(getlocalvar("which")){
        void self    = getlocalvar("self");
        void type    = getentityproperty(self,"type");
        int iR       = rand()%10+10; //AVOID NEGATIVE NUMBERS, COUNT FROM 0 TO 10
        void alt     = getentityproperty(self, "a"); //Get Y location and add adjustment.
        void other = getlocalvar("other");     // gets the attacker
        char iType = getentityproperty(other, "type"); // gets the attacker type

        void aType   = getlocalvar("attacktype"); // Added the Attack Type :D 

        if(aType == openborconstant("ATK_NORMAL7") || aType == openborconstant("ATK_NORMAL8")){ // Added the Attack Type Condition :D
            if(type == openborconstant("TYPE_ENEMY")){ //WORKS ONLY FOR ENEMIES
                if(iR > 1 && alt == 0 && iType != openborconstant("TYPE_ITEM")){ //CHECK THE CHANCE, ALTITUDE and not ITEM
                    changeopenborvariant("lasthitc", 0); //DISABLE LAST HIT
                    performattack(self, openborconstant("ANI_FOLLOW6"), 1); //CHANGE TO DODGE
                }
            }
        }
    }
}

Thanks a lot! I hope to finish Neon Lightning Force before 25 June I'm all of it with this game, soon I'll post news answering the comments of the demo too xd.
 
the bullet didn't even touch the enemy making the dodge more "realistic" xd
Because ondoattack happens even before the engine process all the hit routines. And when you change "lasthitc" (last hit confirmation or something like that) to 0, you tell to the engine that the attack haven't hit anything.

But the enemy keep moving to the right or left while falling.
But that code isn't supposed to trigger when you are falling, hence the "a" check. Let's try to change the "a" check for the "y" check

C-like:
void main()
{
    //WORKS FOR DEFENDER ONLY
    if(getlocalvar("which")){
        void self    = getlocalvar("self");
        void type    = getentityproperty(self,"type");
        int iR       = rand()%10+10; //AVOID NEGATIVE NUMBERS, COUNT FROM 0 TO 10
        int alt = getentityproperty(self,"y"); // GET Y POSITION
        void other = getlocalvar("other");     // gets the attacker
        char iType = getentityproperty(other, "type"); // gets the attacker type


        void aType   = getlocalvar("attacktype"); // Added the Attack Type :D


        if(aType == openborconstant("ATK_NORMAL7") || aType == openborconstant("ATK_NORMAL8")){ // Added the Attack Type Condition :D
            if(type == openborconstant("TYPE_ENEMY")){ //WORKS ONLY FOR ENEMIES
                if(iR > 1 && alt == 0 && iType != openborconstant("TYPE_ITEM")){ //CHECK THE CHANCE, ALTITUDE and not ITEM
                    changeopenborvariant("lasthitc", 0); //DISABLE LAST HIT
                    performattack(self, openborconstant("ANI_FOLLOW6"), 1); //CHANGE TO DODGE
                }
            }
        }
    }
}

The code should trigger only if you are not in the air. At least, on my game, it never triggers on air.
 
Back
Top Bottom