Solved To make chained attack works

Question that is answered or resolved.

haxpor

New member
Prior to this I have attack animation which does 3 attacks. I want to split it into 3 chained attack, if the previous one hits then continue next attack. Simply put, this is to solve not playing whole 3 attack animation unnecessary if prior one doesn't hit.

I did that by creating a new follow1, follow2, and follow3. First two follows are for 2nd attack and 3rd attack (if previous one hits) respectively. follow3 is for resting/final frames for attack animation.

In didhit script, I check the current frame number and if it hits, then I call performattack() for the next chained attack one. It seems to work, but the animation doesn't seem to update properly on screen although the logic hit box checking and sound playing are correct.

The following function taken from what I did currently (didhit script)

Code:
void docontinued_atk()
{
  void self = getlocalvar("self");
  void v_anim_id = getentityproperty(self, "animationID");
  void frame = getentityproperty(self, "animpos");

  // remember: it's already hit, so no need to query
  // from "animhits"

  if (v_anim_id == openborconstant("ANI_ATTACK1"))
  {
    log("in ANI_ATTACK1\n");
    log("frame " + frame + "\n");
    if (frame >= 12 && frame <= 14)
    {
      log("continue with ANI_FOLLOW1\n");
      // follow up with another attack
      performattack(self, openborconstant("ANI_FOLLOW1"));
    }
  }
  else if (v_anim_id == openborconstant("ANI_FOLLOW1"))
  {
    log("in ANI_FOLLOW1\n");
    if (frame >= 2 && frame <= 4)
    {
      log("continue with ANI_FOLLOW2\n");
      // follow up with another attack
      performattack(self, openborconstant("ANI_FOLLOW2"));
    }
  }
  else if (v_anim_id == openborconstant("ANI_FOLLOW2"))
  {
    log("in ANI_FOLLOW2\n");
    if (frame >= 2 && frame <= 4)
    {
      log("continue with ANI_FOLLOW3\n");
      executeanimation(self, openborconstant("ANI_FOLLOW3"));
    }
  }
}

PS. those frame range checking is frames that has attack action in it, at least one of those frame has attack box inside. If you need more information, please feel free to let me know. Thanks.

Any hint on what might be the problem?
 
Solution
I solved the problem by using "@cmd".

By using the following for attack1 adding such line after the final attack action frame.

Code:
@cmd chainedatk "ANI_ATTACK1" "ANI_FOLLOW1"

and using the following for follow1 adding such line simlarly

Code:
@cmd chainedatk "ANI_FOLLOW1" "ANI_FOLLOW2"

with the following chainedatk function (mostly added inside animation script and used by all script files)

Code:
/**
 * Play `next_anim` attack animation if `curr_anim` hits the target.
 */
void chainedatk(void curr_anim, void next_anim)
{
  // get self from entity calling this function
  void self = getlocalvar("self");
  void v_anim_id = getentityproperty(self, "animationID");
  int hits		= getentityproperty(self,"animhits");

  if...
I solved the problem by using "@cmd".

By using the following for attack1 adding such line after the final attack action frame.

Code:
@cmd chainedatk "ANI_ATTACK1" "ANI_FOLLOW1"

and using the following for follow1 adding such line simlarly

Code:
@cmd chainedatk "ANI_FOLLOW1" "ANI_FOLLOW2"

with the following chainedatk function (mostly added inside animation script and used by all script files)

Code:
/**
 * Play `next_anim` attack animation if `curr_anim` hits the target.
 */
void chainedatk(void curr_anim, void next_anim)
{
  // get self from entity calling this function
  void self = getlocalvar("self");
  void v_anim_id = getentityproperty(self, "animationID");
  int hits		= getentityproperty(self,"animhits");

  if (v_anim_id == openborconstant(curr_anim))
  {
    log("inside the check\n");
    if (hits >= 1)
    {
      log("hits it\n");
      performattack(self, openborconstant(next_anim), 1);
    }
  }
}

Now the character will try to attack at most 3 times if previous 2 attacks hit, or at least 1 attack if it doesn't hit, or else try 2 attacks if the first time hits.

Thanks again, I now learned more about scripting in openbor.
 
Solution
haxpor nice code but the engine can already handle this using the cancel command.

cancel {start frame} {end frame} {hits} {sequence of inputs} {freespecial#}

~This command allows animation change by inputting sequence of inputs to certain freespecial. In other word, cancel. Obviously it's only for players.
~This command can be declared in any attack animations, jump animations and grab animations. Also it can be declared more than once in same animation for various cancels.
~{start frame} and {end frame} defines frames where sequence of inputs is accepted. Inputs entered before {start frame} and after {end frame} will be ignored.
~{hits} defines how many hits attackboxes in this animation must hit before cancelling is allowed. It doesn't matter whether the attacks are blocked or not. If you don't want to have this limit, just set it to 0.
~{sequence of inputs} defines input sequence required to activate the freespecial. The accepted values here is exactly same with 'com' command in Entity Files: Header Date above.
~{freespecial#} defines the freespecial to be played after input sequence is valid. Don't forget to set 'maxfreespecials' (see models.txt above) if you need more freespecials to access.
~Technically, the animation cancelling is like this: when valid sequence is accepted, this animation will stop immediately and defined freespecial will be played.
~If 'cancel' is declared in jump animation, the freespecial will subject to gravity and will end immediately when player landed like any jump animations.
~If 'cancel' is declared in grab animation, grabbed enemy will be freed IOW player is not in grabbing state anymore.
~If you declare 'cancel' in GRAB for player who also has GRABWALK, declare it in latter animation too so the input is received even if player is grabwalking. Same goes with GRABBACKWALK.
~Be careful in using single button input cause engine can easily accept the input when this animation is played. For example, cancel with just attack button as input in GRABATTACK will make cancel activated immediately as soon as it's played. To avoid this, set {start frame} late enough for engine to remove the input which activated GRABATTACK.

~{sequence of inputs} now accepts "+" to add mutiple commands. Examples:
a + a2
u + f a
u + f -> a
"->" symbol useful just for better reading
 
msmalik681 said:
haxpor nice code but the engine can already handle this using the cancel command.

cancel {start frame} {end frame} {hits} {sequence of inputs} {freespecial#}

~This command allows animation change by inputting sequence of inputs to certain freespecial. In other word, cancel. Obviously it's only for players.
~This command can be declared in any attack animations, jump animations and grab animations. Also it can be declared more than once in same animation for various cancels.
~{start frame} and {end frame} defines frames where sequence of inputs is accepted. Inputs entered before {start frame} and after {end frame} will be ignored.
~{hits} defines how many hits attackboxes in this animation must hit before cancelling is allowed. It doesn't matter whether the attacks are blocked or not. If you don't want to have this limit, just set it to 0.
~{sequence of inputs} defines input sequence required to activate the freespecial. The accepted values here is exactly same with 'com' command in Entity Files: Header Date above.
~{freespecial#} defines the freespecial to be played after input sequence is valid. Don't forget to set 'maxfreespecials' (see models.txt above) if you need more freespecials to access.
~Technically, the animation cancelling is like this: when valid sequence is accepted, this animation will stop immediately and defined freespecial will be played.
~If 'cancel' is declared in jump animation, the freespecial will subject to gravity and will end immediately when player landed like any jump animations.
~If 'cancel' is declared in grab animation, grabbed enemy will be freed IOW player is not in grabbing state anymore.
~If you declare 'cancel' in GRAB for player who also has GRABWALK, declare it in latter animation too so the input is received even if player is grabwalking. Same goes with GRABBACKWALK.
~Be careful in using single button input cause engine can easily accept the input when this animation is played. For example, cancel with just attack button as input in GRABATTACK will make cancel activated immediately as soon as it's played. To avoid this, set {start frame} late enough for engine to remove the input which activated GRABATTACK.

~{sequence of inputs} now accepts "+" to add mutiple commands. Examples:
a + a2
u + f a
u + f -> a
"->" symbol useful just for better reading

Thank you for pointing out malik. I  saw it but that's only for player, in my case it's enemy character. Thanks anyway, I noted it as I might be using that in the future.
 
Bloodbane said:
haxpor, that's a nice code :)

However have you tried using simple followup mechanic?

I've tried with followcond and followanim, for some reasons it didn't work for me then I switched to above solution instead. The same problem I faced from the start.
 
Back
Top Bottom