Overworld combat attacks?

I did indeed get that working! Now all four actions I’ve asked about so far do function at a baseline.

My only other question on the topic of this particular set of events is-looping back to the A-dash command-I assume I can take the code that makes the shield command not spawn inside the player mid-dash, and apply it to the Z-attack? That also lags way behind the player while they’re running fast. The only difference is the Z-attack needs to have the ATTACK COLLISION visibly move forward from inside the player.

Yes, same idea, just without the one tile offset. Read the player’s position and direction in the block itself, place the collision on that tile with the matching direction, then let the existing Step Forward do the visible move:

◆Control Switches: #0181 ATTACKING = ON
◆Play SE: Blow1
◆Control Variables: AtkX = Player Map X
◆Control Variables: AtkY = Player Map Y
◆Control Variables: AtkDir = Player Direction
◆If: AtkDir = 2
  ◆Set Event Location: Attack collision, ({AtkX},{AtkY}), Down
◆End
◆If: AtkDir = 4
  ◆Set Event Location: Attack collision, ({AtkX},{AtkY}), Left
◆End
◆If: AtkDir = 6
  ◆Set Event Location: Attack collision, ({AtkX},{AtkY}), Right
◆End
◆If: AtkDir = 8
  ◆Set Event Location: Attack collision, ({AtkX},{AtkY}), Up
◆End
◆Set Movement Route: Attack collision (Skip, Wait)
  : Transparent OFF
  : Image: MH VitalAttacks1(2)
  : Speed: 6
  : 1 Step Forward

Two things change from what you have. The position comes from Player Map X and Y read right there instead of the BPlayer variables, and the facing comes from the Direction field on Set Event Location instead of waiting on the collision’s own turn logic, which is the part that was a frame behind. Mid run, Player Map X and Y are already the tile the player is stepping into, so at full speed the punch starts a touch ahead of the sprite rather than behind it, which is the side you want to err on.

It does still lag behind the player a little bit, but actually i think i don’t mind it. It gives it a shorter range and prioritizes being careful using the boost-if I decide I don’t like it later, I’ll come back and let you know if I can’t figure out how to fix it. As it stands, I’m satisfied with that.

I’m gonna see if I can retrofit the code here into making the shield ALSO slide out of the player, rather than instantly snap in front.

That was successful! Only thing is, I want the enemy to be continually bounced back by the shield when it’s up, but the enemy bounces off it once and then it’s like the shield loses its collision and the enemy can walk right through it. Do you know why that would be?

Another thing I’ve found is that when trying to make the S-ram interact with the enemy event, it just won’t do damage. I understand why; the Enemy event is coded so that it takes damage when in contact with Attack Collision, but I’m not sure how to make the Enemy event take damage when ATTACKING is on, ATTACK TYPE=2, and when the player comes into contact with it.

The shield only gets one bounce because of the self switch B guard. It turns ON after a hit and only clears in the Else when ATTACKING goes OFF, and the shield holds ATTACKING ON the whole time X is down, so after the first bounce that enemy skips the hit check until you let go. The walking through is part of the same thing. The Attack collision has Through on, so it never physically blocked anything, and the bounce was the only thing stopping them.

Since the shield should catch every touch, I’d only set B for the other attack types. Tick Create Else Branch on that ATTACK TYPE = 1 condition and move the B line into it:

◆If: ATTACK TYPE = 1
  (your bounce, unchanged)
: Else
  ◆Control Self Switch: B = ON
◆End

Dropping the guard for the shield should be safe since the bounce route has Wait on. The loop can’t check again until the step back is done, and by then the enemy is already off the shield tile.

For the ram, the collision stays parked where the ram started, since its follow logic only runs while ATTACKING is OFF. The player can’t walk onto an enemy’s tile either, so the enemy never lines up with anything. What if the enemy checked the tile in front of the player instead when ATTACK TYPE is 2? Put this right after your two Hit X and Hit Y lines:

◆If: ATTACK TYPE = 2
  ◆Control Variables: Hit X = Player Map X
  ◆Control Variables: Hit Y = Player Map Y
  ◆Control Variables: Hit Dir = Player Direction
  ◆If: Hit Dir = 2
    ◆Control Variables: Hit Y += 1
  ◆End
  ◆If: Hit Dir = 4
    ◆Control Variables: Hit X -= 1
  ◆End
  ◆If: Hit Dir = 6
    ◆Control Variables: Hit X += 1
  ◆End
  ◆If: Hit Dir = 8
    ◆Control Variables: Hit Y -= 1
  ◆End
◆End

Hit Dir is one more self variable. The comparison below it and the B guard stay as they are, so the ram hits each enemy once per ram. The ram’s damage and knockback go in an ATTACK TYPE = 2 branch next to your others.

This is what I have down but it doesn’t work. Whether the player touches the enemy or not, no damage or knockback happens. Sometimes the player doesn’t move at all, which makes me think that both events are checking for collision in front of their tiles and stopping themselves early.

Things are coming along great. I’ve been able to do several more attacks entirely myself since you’ve helped lay the groundwork and I’m incredibly grateful for that. I think it’ll be done pretty soon.

I tried to add an “ATTACK TYPE 3” where the enemy freezes in place to be hit by the player constantly ONLY until the player stops attacking, but instead, like the shield, the enemy gets hit once and then continues on its way. Any ideas?

Update: I learned that adding the “Else: Self Switch B On” command to this block actually breaks the ability for the shield to continually deflect, and I’m really confused.

Ran into another issue. One of the potential attacks the player can use is one that damages every enemy on the field once for some weak damage.

However, the attack kills every enemy instantaneously. I think this is because the code is running every frame and so the enemy is getting damaged every frame, but I can’t figure out how to stop that.

This is what I’ve got so far. Any ideas?

Enemy code. As you can see, it’s been placed outside the code that checks for the Attack Collision because it doesn’t need it in this attack.

Player attack code. The ATKdir stuff is redundant here and can be ignored i think.

(also the visual effect with the pictures doesn’t go offscreen)

  1. From the indent, I think the ATTACK TYPE = 2 block ended up inside the hit check next to your other attack types. That check compares against the Attack collision, which stays parked where the ram started, so it never passes and nothing inside it runs, including the new position lines. It needs to be split in two. The position part (the three Control Variables and the four Hit Dir branches) goes right after the two lines that read the Attack collision’s X and Y, before the If: SV: AtkCol X = SV: My X. The HP, snap and knockback route go in their own ATTACK TYPE = 2 branch inside the hit check like the others.

The player not moving is the enemy blocking the step. Events block the player, so if one is right in front when the ram starts, Skip burns through the steps and the player stays put.

  1. Every Else on an ATTACK TYPE branch catches all the other types. So the Else B ON on type 1 from my last post also fires on a type 3 hit, which is why it only gets hit once. The Else you added on type 3 fires on a shield hit, which is what broke the deflect. I’d take both Elses out and set B once, after all the type branches and still inside the hit check, only when the attack is neither of those:
◆If: ATTACK TYPE ≠ 1
  ◆If: ATTACK TYPE ≠ 3
    ◆Control Self Switch: B = ON
  ◆End
◆End
  1. The instant kill comes from the Set Movement Route: Player in the enemy’s Else. An event only holds one forced route at a time, so every enemy hit replaces the attack’s 1 frame Wait route with a new 30 frame one. The attack’s Wait for Completion never gets to finish, ATTACK TYPE stays at 4, and every enemy keeps taking 25 every other pass until it’s dead. The Ambient Attack variable just flips between 0 and 1 each pass, so it spaces the hits out but doesn’t stop them.

The B guard already handles the once part, so I’d drop the Ambient Attack variable and the Player route and set B like the other attacks:

◆If: ATTACK TYPE = 4
  ◆Control Variables: #0189 SV: This event HP -= 25
  ◆Play SE: Blow1 (90, 150, 0)
  ◆Set Movement Route: This Event
    : Blend Mode: Additive
    : Wait: 30 frames
    : Blend Mode: Normal
  ◆Control Self Switch: B = ON
◆End

That needs to stay inside the Self Switch B is OFF check, which is where it looks like it is from the indent.

The Move Picture comes after that same stuck Wait, so the pictures were starting late too. Their destination is also (0,0), the same spot they were shown at, so they fade out in place rather than slide. If you want them to leave the screen, set the X or Y in Move Picture to somewhere past the edge.

Since these all touch the same part of the enemy loop, here’s how I’d expect the whole hit section to look with all three changes in. The parts in parentheses are your existing contents, unchanged:

◆Loop
  (your attack logic, unchanged)
  ◆If: ATTACKING is ON
    ◆If: Self Switch B is OFF
      ◆Control Variables: #0192 SV: AtkCol X = Map X of Attack collision
      ◆Control Variables: #0193 SV: AtkCol Y = Map Y of Attack collision
      ◆If: ATTACK TYPE = 2
        ◆Control Variables: #0192 SV: AtkCol X = Map X of Player
        ◆Control Variables: #0193 SV: AtkCol Y = Map Y of Player
        ◆Control Variables: #0221 Hit Dir = Direction of Player
        ◆If: Hit Dir = 2
          ◆Control Variables: #0193 SV: AtkCol Y += 1
        ◆End
        ◆If: Hit Dir = 4
          ◆Control Variables: #0192 SV: AtkCol X -= 1
        ◆End
        ◆If: Hit Dir = 6
          ◆Control Variables: #0192 SV: AtkCol X += 1
        ◆End
        ◆If: Hit Dir = 8
          ◆Control Variables: #0193 SV: AtkCol Y -= 1
        ◆End
      ◆End
      ◆Control Variables: #0194 SV: My X = Map X of This Event
      ◆Control Variables: #0195 SV: My Y = Map Y of This Event
      ◆If: ATTACK TYPE = 4
        ◆Control Variables: #0189 SV: This event HP -= 25
        ◆Play SE: Blow1 (90, 150, 0)
        ◆Set Movement Route: This Event
          : Blend Mode: Additive
          : Wait: 30 frames
          : Blend Mode: Normal
        ◆Control Self Switch: B = ON
      ◆End
      ◆If: SV: AtkCol X = SV: My X
        ◆If: SV: AtkCol Y = SV: My Y
          ◆If: ATTACK TYPE = 0
            (your punch hit, unchanged)
          ◆End
          ◆If: ATTACK TYPE = 1
            (your shield bounce, no Else)
          ◆End
          ◆If: ATTACK TYPE = 2
            ◆Control Variables: #0189 SV: This event HP -= 25
            ◆Control Variables: #0194 SV: My X = Math.round(this.character(0)._realX)
            ◆Control Variables: #0195 SV: My Y = Math.round(this.character(0)._realY)
            ◆Set Event Location: This Event, ({SV: My X},{SV: My Y})
            ◆Set Movement Route: This Event (Skip, Wait)
              (your knockback route, unchanged)
          ◆End
          ◆If: ATTACK TYPE = 3
            (your freeze hit, no Else)
          ◆End
          ◆If: ATTACK TYPE ≠ 1
            ◆If: ATTACK TYPE ≠ 3
              ◆Control Self Switch: B = ON
            ◆End
          ◆End
        ◆End
      ◆End
    ◆End
  : Else
    ◆Control Self Switch: B = OFF
  ◆End
  (your HP 0 check and Break Loop, unchanged)
◆Repeat Above

Wow, this is INCREDIBLY helpful, I was worried I’d miss stuff with all the details, thank you so much. I implemented it all and here’s the current state of affairs;

1: The ram still does no damage to the enemy-I think maybe the player is getting stopped before touching them by the events checking what is ahead of them, and I tested it rather thoroughly and it never did damage.

2: Attack Type 3 has definitely gotten closer to what I want, and the enemy will pause once they take damage, but when that pausing command ends then they have a chance to move away again. Can I stop this somehow? I’d like the enemy to be stuck in front of the player for the duration of while the player is using a certain move.

3: The “every enemy attack” is almost there too, but if the player accidentally presses Z more than once to trigger the move, then the visual effect will stay onscreen and the player won’t be able to act again until they press an arrow key, where it will then clear.

This system is getting very close to being done, I can’t thank you enough

  1. Before I guess at the movement, which ATTACK TYPE value does the ram set now? When you wired it through the MOVING ATTACK HANDLER you had it on 3, and the enemy block is comparing against 2, so if that’s still the case then the position lines never run and the enemy keeps checking the parked Attack collision instead.

If it is on 2 already, can you post the enemy block again? What I’d want to see is whether the three Control Variables and the four Hit Dir branches ended up above the If: SV: AtkCol X = SV: My X, or still inside it.

A quick way to tell which half is failing is to drop a Play SE inside the If: ATTACK TYPE = 2 position block for a moment. If you hear it during a ram, the enemy is reading the right tile and it’s the comparison below that’s off. If you don’t, the enemy never gets that far and it’s the type value or where the block sits.

  1. Same trick as the player freeze from the shield. A repeating forced route holds a character still and blocks its autonomous movement for as long as it repeats. Set it in the type 3 hit along with a second self switch to mark that enemy as held, then release it once when the attack ends. Pick any letter you aren’t using, I’ve written it as C.
  2. Gate the trigger on ATTACKING being OFF, so a second press while the first one is still running gets ignored. This one goes in the attack common event, not the enemy:
◆If: ATTACKING is OFF
  ◆If: Script: Input.isTriggered("ok")
    (your type 4 attack, unchanged)
  ◆End
◆End

The arrow key part makes me think the second press is forcing a route on the Player while the first route is still going, which is the one route at a time thing again, and TurnInPlace only interferes with player routes coming from a parallel. If the guard doesn’t clear it, move that attack into an Autorun the way you did with the ram and it’ll behave like the ram does.

Here’s the whole enemy hit section again with everything in it. Parts in parentheses are your existing contents, unchanged:

◆Loop
  (your attack logic, unchanged)
  ◆If: ATTACKING is ON
    ◆If: Self Switch B is OFF
      ◆Control Variables: #0192 SV: AtkCol X = Map X of Attack collision
      ◆Control Variables: #0193 SV: AtkCol Y = Map Y of Attack collision
      ◆If: ATTACK TYPE = 2
        ◆Control Variables: #0192 SV: AtkCol X = Map X of Player
        ◆Control Variables: #0193 SV: AtkCol Y = Map Y of Player
        ◆Control Variables: #0221 Hit Dir = Direction of Player
        ◆If: Hit Dir = 2
          ◆Control Variables: #0193 SV: AtkCol Y += 1
        ◆End
        ◆If: Hit Dir = 4
          ◆Control Variables: #0192 SV: AtkCol X -= 1
        ◆End
        ◆If: Hit Dir = 6
          ◆Control Variables: #0192 SV: AtkCol X += 1
        ◆End
        ◆If: Hit Dir = 8
          ◆Control Variables: #0193 SV: AtkCol Y -= 1
        ◆End
      ◆End
      ◆Control Variables: #0194 SV: My X = Map X of This Event
      ◆Control Variables: #0195 SV: My Y = Map Y of This Event
      ◆If: ATTACK TYPE = 4
        ◆Control Variables: #0189 SV: This event HP -= 25
        ◆Play SE: Blow1 (90, 150, 0)
        ◆Set Movement Route: This Event
          : Blend Mode: Additive
          : Wait: 30 frames
          : Blend Mode: Normal
        ◆Control Self Switch: B = ON
      ◆End
      ◆If: SV: AtkCol X = SV: My X
        ◆If: SV: AtkCol Y = SV: My Y
          ◆If: ATTACK TYPE = 0
            (your punch hit, unchanged)
          ◆End
          ◆If: ATTACK TYPE = 1
            (your shield bounce, no Else)
          ◆End
          ◆If: ATTACK TYPE = 2
            ◆Control Variables: #0189 SV: This event HP -= 25
            ◆Control Variables: #0194 SV: My X = Math.round(this.character(0)._realX)
            ◆Control Variables: #0195 SV: My Y = Math.round(this.character(0)._realY)
            ◆Set Event Location: This Event, ({SV: My X},{SV: My Y})
            ◆Set Movement Route: This Event (Skip, Wait)
              (your knockback route, unchanged)
          ◆End
          ◆If: ATTACK TYPE = 3
            (your freeze hit damage, unchanged)
            ◆Set Movement Route: This Event (Repeat)
              : Wait: 1 frame
            ◆Control Self Switch: C = ON
          ◆End
          ◆If: ATTACK TYPE ≠ 1
            ◆If: ATTACK TYPE ≠ 3
              ◆Control Self Switch: B = ON
            ◆End
          ◆End
        ◆End
      ◆End
    ◆End
  : Else
    ◆Control Self Switch: B = OFF
    ◆If: Self Switch C is ON
      ◆Set Movement Route: This Event
        : Wait: 1 frame
      ◆Control Self Switch: C = OFF
    ◆End
  ◆End
  (your HP 0 check and Break Loop, unchanged)
◆Repeat Above

On the type 3 route, Repeat Movement is ticked and Wait for Completion is off. The release one below has both off, so it runs its single frame, ends, and the enemy goes back to normal. One caveat, any other route forced on that enemy replaces the freeze, so a knockback landing on a held enemy would free it early.

1-You know how i mentioned that it’s the small things that always get me? Cause it is-ATTACK TYPE was not being set by the ram at all. I set it to 2, and now the ram works perfectly. Thank you and oops.

3-The “all-enemy-hit” now works precisely the way I wanted it to!

2, the “enemy must stay still while being hit multiple times” event, is still having issues, though. When the player lands a Type 3 hit on an enemy now, the enemy will take damage and flash one time, and then become completely inert and unable to move or take damage ever again, even if the attack collision remains on top of them or they are attacked by something else.

(Self Switch D was the only switch I had left, so it’s been changed to that.)

Glad 1 and 3 are sorted!

For 2, if it stops reacting to everything and not just the Attack collision, I think the loop itself has stopped running rather than something in the type 3 branch misfiring. The all enemy attack doesn’t check the Attack collision at all, so if that’s one of the things you tried, it should still land as long as the loop is going. My guess is it’s sitting on a wait somewhere that never finishes.

The part I haven’t seen is the attack logic at the top of the loop. Is there a Set Movement Route: This Event in there with Wait ticked, especially one with a step and Skip If Cannot Move off? A type 3 hit always pins the enemy right in front of the player, so I’m wondering if its own attack fires while it’s stuck there, tries to step onto the player’s tile, and retries that step forever. That could explain why only type 3 does this, since it’s the one hit that holds the enemy next to the player.

If nothing like that shows up, here’s a way to find where it stops. With just one enemy on the map, drop a few of these through the loop, numbered in order, one near the top, one after the attack logic, one after the hit section, one before Repeat Above:

◆Control Variables: #0XXX Loop Test = 1

Playtest, land a type 3, wait for it to go inert, then press F9 and check Loop Test. The number you see is the last checkpoint it got past, so the command it’s stuck on is somewhere between that one and the next.

Here’s the whole loop with the checkpoints and your D switch in. Parts in parentheses are your existing contents, unchanged:

◆Loop
  ◆Control Variables: #0XXX Loop Test = 1
  (your attack logic, unchanged)
  ◆Control Variables: #0XXX Loop Test = 2
  ◆If: ATTACKING is ON
    ◆If: Self Switch B is OFF
      ◆Control Variables: #0192 SV: AtkCol X = Map X of Attack collision
      ◆Control Variables: #0193 SV: AtkCol Y = Map Y of Attack collision
      ◆If: ATTACK TYPE = 2
        ◆Control Variables: #0192 SV: AtkCol X = Map X of Player
        ◆Control Variables: #0193 SV: AtkCol Y = Map Y of Player
        ◆Control Variables: #0221 Hit Dir = Direction of Player
        ◆If: Hit Dir = 2
          ◆Control Variables: #0193 SV: AtkCol Y += 1
        ◆End
        ◆If: Hit Dir = 4
          ◆Control Variables: #0192 SV: AtkCol X -= 1
        ◆End
        ◆If: Hit Dir = 6
          ◆Control Variables: #0192 SV: AtkCol X += 1
        ◆End
        ◆If: Hit Dir = 8
          ◆Control Variables: #0193 SV: AtkCol Y -= 1
        ◆End
      ◆End
      ◆Control Variables: #0194 SV: My X = Map X of This Event
      ◆Control Variables: #0195 SV: My Y = Map Y of This Event
      ◆If: ATTACK TYPE = 4
        ◆Control Variables: #0189 SV: This event HP -= 25
        ◆Play SE: Blow1 (90, 150, 0)
        ◆Set Movement Route: This Event
          : Blend Mode: Additive
          : Wait: 30 frames
          : Blend Mode: Normal
        ◆Control Self Switch: B = ON
      ◆End
      ◆If: SV: AtkCol X = SV: My X
        ◆If: SV: AtkCol Y = SV: My Y
          ◆If: ATTACK TYPE = 0
            (your punch hit, unchanged)
          ◆End
          ◆If: ATTACK TYPE = 1
            (your shield bounce, no Else)
          ◆End
          ◆If: ATTACK TYPE = 2
            ◆Control Variables: #0189 SV: This event HP -= 25
            ◆Control Variables: #0194 SV: My X = Math.round(this.character(0)._realX)
            ◆Control Variables: #0195 SV: My Y = Math.round(this.character(0)._realY)
            ◆Set Event Location: This Event, ({SV: My X},{SV: My Y})
            ◆Set Movement Route: This Event (Skip, Wait)
              (your knockback route, unchanged)
          ◆End
          ◆If: ATTACK TYPE = 3
            ◆Common Event: DAMAGE SFX
            ◆Control Variables: #0189 SV: This event HP -= 25
            ◆Set Movement Route: This Event (Wait)
              : Blend Mode: Additive
              : Wait: 30 frames
              : Blend Mode: Normal
            ◆Set Movement Route: This Event (Repeat)
              : Wait: 1 frame
            ◆Control Self Switch: D = ON
          ◆End
          ◆If: ATTACK TYPE ≠ 1
            ◆If: ATTACK TYPE ≠ 3
              ◆Control Self Switch: B = ON
            ◆End
          ◆End
        ◆End
      ◆End
    ◆End
  : Else
    ◆Control Self Switch: B = OFF
    ◆If: Self Switch D is ON
      ◆Set Movement Route: This Event
        : Wait: 1 frame
      ◆Control Self Switch: D = OFF
    ◆End
  ◆End
  ◆Control Variables: #0XXX Loop Test = 3
  (your HP 0 check and Break Loop, unchanged)
  ◆Control Variables: #0XXX Loop Test = 4
◆Repeat Above

Once you’ve found it, the four Loop Test lines can come back out.

It stops at 6, which is the very last variable set in the entire enemy event. It’s literally the last line in the entire page.

(If it helps, these lines aren’t running inside a Loop COMMAND, it’s just that the code that tells it what to become is inside a Self Switch conditional branch, and that switch turns itself on after it’s done so the enemy won’t reference it for a second time.)

Good, that narrows it a lot. If the page reaches the last line every pass then nothing is hanging, and since the ON side of the ATTACKING check is what deals damage and the Else is what releases the freeze, I’m wondering if that whole block isn’t being reached on either side after a type 3 hit.

Two questions. Is the If: ATTACKING is ON at the top level of the page, or does it sit inside another branch, like the self switch one from your setup or something in the attack logic? A screenshot from the top of the page down to that line would show it. And what’s inside DAMAGE SFX? It’s the one piece of the type 3 branch I haven’t seen.

To see how deep a pass actually gets, here’s the same checkpoint idea one level down, on a second variable so your Loop Test lines can stay where they are. Set Hit Test to 0 as the very first line of the page, then 1 as the first line inside If: ATTACKING is ON, 2 as the first line inside If: Self Switch B is OFF, 3 as the first line inside the SV: AtkCol Y = SV: My Y match, and 9 as the first line of the Else. Get an enemy inert, walk up and hold the shield on it since that keeps ATTACKING ON for as long as X is down, and press F9 while still holding X.

Hit Test at 0 with Loop Test at 6 means the pass finished without touching the ATTACKING check on either side, so something above it is stepping around it. 1 means B is stuck ON. 2 means B is fine but the position compare isn’t matching. 3 means it gets all the way in and the type 3 branch itself is what’s off. 9 means it read ATTACKING as OFF and ran the release, which would point at the release route instead.

Here’s the whole hit section with the Hit Test lines in. Since there’s no Loop command I’ve dropped the Loop and Repeat Above from the listing, the parallel restarting on its own does that job. Parts in parentheses are your existing contents, unchanged:

◆Control Variables: #0XXX Hit Test = 0
(your setup branch and attack logic, unchanged)
◆If: ATTACKING is ON
  ◆Control Variables: #0XXX Hit Test = 1
  ◆If: Self Switch B is OFF
    ◆Control Variables: #0XXX Hit Test = 2
    ◆Control Variables: #0192 SV: AtkCol X = Map X of Attack collision
    ◆Control Variables: #0193 SV: AtkCol Y = Map Y of Attack collision
    ◆If: ATTACK TYPE = 2
      ◆Control Variables: #0192 SV: AtkCol X = Map X of Player
      ◆Control Variables: #0193 SV: AtkCol Y = Map Y of Player
      ◆Control Variables: #0221 Hit Dir = Direction of Player
      ◆If: Hit Dir = 2
        ◆Control Variables: #0193 SV: AtkCol Y += 1
      ◆End
      ◆If: Hit Dir = 4
        ◆Control Variables: #0192 SV: AtkCol X -= 1
      ◆End
      ◆If: Hit Dir = 6
        ◆Control Variables: #0192 SV: AtkCol X += 1
      ◆End
      ◆If: Hit Dir = 8
        ◆Control Variables: #0193 SV: AtkCol Y -= 1
      ◆End
    ◆End
    ◆Control Variables: #0194 SV: My X = Map X of This Event
    ◆Control Variables: #0195 SV: My Y = Map Y of This Event
    ◆If: ATTACK TYPE = 4
      ◆Control Variables: #0189 SV: This event HP -= 25
      ◆Play SE: Blow1 (90, 150, 0)
      ◆Set Movement Route: This Event
        : Blend Mode: Additive
        : Wait: 30 frames
        : Blend Mode: Normal
      ◆Control Self Switch: B = ON
    ◆End
    ◆If: SV: AtkCol X = SV: My X
      ◆If: SV: AtkCol Y = SV: My Y
        ◆Control Variables: #0XXX Hit Test = 3
        ◆If: ATTACK TYPE = 0
          (your punch hit, unchanged)
        ◆End
        ◆If: ATTACK TYPE = 1
          (your shield bounce, no Else)
        ◆End
        ◆If: ATTACK TYPE = 2
          ◆Control Variables: #0189 SV: This event HP -= 25
          ◆Control Variables: #0194 SV: My X = Math.round(this.character(0)._realX)
          ◆Control Variables: #0195 SV: My Y = Math.round(this.character(0)._realY)
          ◆Set Event Location: This Event, ({SV: My X},{SV: My Y})
          ◆Set Movement Route: This Event (Skip, Wait)
            (your knockback route, unchanged)
        ◆End
        ◆If: ATTACK TYPE = 3
          ◆Common Event: DAMAGE SFX
          ◆Control Variables: #0189 SV: This event HP -= 25
          ◆Set Movement Route: This Event (Wait)
            : Blend Mode: Additive
            : Wait: 30 frames
            : Blend Mode: Normal
          ◆Set Movement Route: This Event (Repeat)
            : Wait: 1 frame
          ◆Control Self Switch: D = ON
        ◆End
        ◆If: ATTACK TYPE ≠ 1
          ◆If: ATTACK TYPE ≠ 3
            ◆Control Self Switch: B = ON
          ◆End
        ◆End
      ◆End
    ◆End
  ◆End
: Else
  ◆Control Variables: #0XXX Hit Test = 9
  ◆Control Self Switch: B = OFF
  ◆If: Self Switch D is ON
    ◆Set Movement Route: This Event
      : Wait: 1 frame
    ◆Control Self Switch: D = OFF
  ◆End
◆End
(your HP 0 check, unchanged)

This is all very clever as usual, but I’d like to put a pin in this specific method for now because it is taking up a lot of development time. I can get a similar result by just making the enemy take damage quicker, and I have quite a few other attacks to implement as well as the damage formula, stats and more. Maybe when the rest of the system is done I’ll come back to this but I think the best use of time would be to change the damage to happen quicker, call it good enough and move on-I’ll let you know

1-This move is meant to blast the Attack Collision directly forward until it can no longer move, then despawn it and return it to invisibility. However, when pressing S, it goes like this;
The player flashes and nothing happens. Then, when the player presses an arrow, regardless of the direction they’re pressing, they step back from the direction they originally pressed S in. Then, the attack collision visibly follows the PLAYER instead of going forward. It only disappears upon using Generic attack or Shield. I have a feeling this is a familiar issue but I don’t remember how to solve it I’m afraid

2-This attack is NEARLY working the way I want it to. It makes the Attack Collision spawn in and move around the arena at random before despawning and returning to being invisible. Is there a way to make the player be able to move during this sequence?

3-Regarding the earlier “move cooldown” discussion, how would I go about making a sound effect play when the cooldown itself has ended and the player is now audibly free to use the move again rather than guessing when the time is? I tried to implement it, but instead the sound effect only plays when the player first loads, and when the player presses the button for the first time.

Have any thoughts on these?

Makes sense on the freeze, it’ll still be there when you want to come back to it.

  1. I think this is two older issues stacking up. The Player route is being forced from the parallel, which is the TurnInPlace thing from the ram, so the step back waits until an arrow is held. The Attack collision route also has no Wait, so ATTACKING goes OFF on the same frame the blast starts. With ATTACKING OFF, the collision’s follow logic takes over and forces its own route every frame, which replaces the blast before it gets anywhere. That could also be why it stays visible, since the Transparent ON at the end of the blast never gets reached.

What I’d try is the ram’s shape, but only for the recoil. Make an Autorun common event with a switch, call it RecoilGo, that holds just the Player route and then turns itself off:

◆Set Movement Route: Player (Skip, Wait)
  (your recoil route, unchanged)
◆Control Switches: RecoilGo = OFF

The S block in the parallel then reads the player’s position and facing the same way the punch does, and puts Wait on the blast:

◆Control Switches: #0181 ATTACKING = ON
◆Control Variables: #0197 ATTACK TYPE = 5
◆Control Variables: AtkX = Map X of Player
◆Control Variables: AtkY = Map Y of Player
◆Control Variables: AtkDir = Direction of Player
(your four AtkDir branches from the punch)
◆Control Switches: RecoilGo = ON
◆Common Event: SCREENSHAKE MEDIUM
◆Set Movement Route: Attack collision (Skip, Wait)
  (your blast route, unchanged)
◆Control Switches: #0181 ATTACKING = OFF
◆Control Switches: #0182 MOVEMENT ATTACK = OFF

The type 5 is on purpose. Type 2 makes every enemy check the tile in front of the player instead of where the Attack collision is, so the blast would only hit right in front of you. A new number goes through the normal position compare, so it just needs an If: ATTACK TYPE = 5 in the enemy’s match block next to the punch one, holding whatever the blast should do. Also, the parallel sits on that Wait until the blast finishes, so your other actions won’t fire during it.

  1. I’m wondering if it’s the Player route again. If this block is in an Autorun, the player stays locked until its last line, and with Wait on the collision route that means the whole random walk. If it’s in the parallel, it’s the same TurnInPlace thing as 1. Either way I think the same split covers it. Have this block turn RecoilGo ON in place of its own Player route and keep everything else in the parallel. The Wait there only parks that one event, so the player keeps control while the collision wanders. The SHRILL can move out of the route into a Play SE right before RecoilGo turns ON. If you want the two recoils to feel different, a second Autorun works the same way.

  2. ActionCooldown is 0 while the move is ready and also for the whole time the boost is running, so checking for = 0 can’t tell either of those apart from the moment the cooldown actually runs out. Same fix as the DashTimer: put the sound inside the decrement so it only fires on the frame the value lands on 0. Then the Self Switch C block can come out:

◆If: ActionCooldown > 0
  ◆Control Variables: #0206 ActionCooldown -= 1
  ◆If: ActionCooldown = 0
    ◆Play SE: Maris Haven SFX/Fighting/BSFX STUTTER (100, 100, 0)
  ◆End
◆End