News:

Don't forget to visit the main site! There's lots of helpful docs, patches, and more!

Main Menu

[SM] Screw attack vs. frozen enemies

Started by adamf, March 13, 2015, 10:34:38 PM

Previous topic - Next topic

adamf

I'm working on this problem, of making Screw Attack hit frozen enemies...

The pseudo-code of Samus/enemy collisions, at least the early part where they get added to the "enemies that may interact w/ Samus or projectiles" list, goes like this:

if (enemy is frozen) {
   JMP platform_code;
}
if (enemy is not a platform) {
   JMP no_interaction;
}
platform_code:
if (Samus intersects enemy) {
   add to "may interact" list;
}
no_interaction:
RTS


Later, collisions are checked, and if the enemy is frozen, the collision is ignored entirely.

So I patched both points to claim the enemy wasn't frozen, and to do normal collision detection on frozen enemies.  It almost worked.

  • Metroids assume Samus cannot collide with them unless they should latch onto her.  Either they bounce off because Screw Attack, or being a platform when frozen prevents the collision.  Jumping through them makes them start draining energy instantly, and once they thaw, they teleport onto Samus' head.
  • Possesor enemies - Destroying a Kihunter, for example, "works"--but then their frozen wings float in the air until they thaw, then puff away.  I actually have no idea yet how possessors work (who has the pointer to whom.)
  • I think the collision stuff I did means that if Samus can glitch/clip into a frozen enemy somewhere, such as by jump-through-ceiling where the ceiling is the frozen enemy, it will hurt her.  I just thought of this, so I haven't checked.
  • Multiple/special hitbox enemies - do not use the normal damage calculation that I patched, so Samus just jumps harmlessly through them.  Example: green Space Pirates, enemy $F693.
I figured the first two were problems I could handle, but I don't think there's a simple one-shot way to handle the last one.  It looks like I'd have to patch them on an enemy-by-enemy basis... especially since, if I read the trace right, $F693 uses the same pointer $876C for touch and collision, and I don't want touching a frozen pirate to damage Samus.  That would be a nasty surprise.

person701 mentioned in Mumble (like, the one time I've been there so far) that people have worked on this problem in the past... am I missing some way to do this more easily?  Does anyone have any wisdom to share?

(Dunno if this is the right place, move/lock as desired.)

begrimed

Not sure if you've seen it, but Scyzer did something similar with making frozen enemies destructible to shinesparking and boosting. From what RealRed told me, and bit of my own testing, it doesn't work properly (enemies with extended tilemaps, probably posessors), so, something to consider. :P Maybe you can kill two birds with one stone here?

http://sadiztyk.metroidconstruction.com/tank/patches/enemies/enemyfreezeboost.zip
"Adds a short routine into the enemy frozen checks that allows you to destroy frozen enemies by speedboosting or shinesparking into them. This will fix that annoying problem of shooting enemies with ice while running, only to have them freeze right in front of you and stop you running. Screw attack will NOT destroy them, as it could make spinjumping onto frozen enemies later in a game annoying."

adamf

Aha, I hadn't seen that.  Thanks!

Yes, this sounds like it's exactly along the same lines--just as the platform code isn't checking for screw-attack, it isn't checking anything else.

adamf

Update/rant.  I've been working on this all week.  Run down a few dead ends.

Regular collisions are hiding out in the enemy AI code.  For 'normal' enemies, a collision eventually hits $A0:A102.  Stuff like wavers.  Space Pirates don't, though.  I'm assuming all the multi-tile enemies have their own collision-detection routines.  I tried logging them, but there are a few dozen of them... per space pirate type.

For frozen enemies, the collision detect happens a ways past $A0:A9D8, except it's weird.  I hijacked the JMP ($AA2F,X) code so that I could just set the enemy un-frozen if Samus is screw attacking, which works better, but somehow Samus velocity gets reset down in that pathway.  So screw attack is more like a wickedly powerful pseudo screw attack to the frozen enemies.  (But I have enough info at that point to make her land, if she falls down onto an enemy.)

So yeah.  This particular goal is proving to be ridiculous.  I hate this game code today.

Black Falcon

Quote from: adamf on March 20, 2015, 09:32:30 PM
Update/rant.  I've been working on this all week.  Run down a few dead ends.

Regular collisions are hiding out in the enemy AI code.  For 'normal' enemies, a collision eventually hits $A0:A102.  Stuff like wavers.  Space Pirates don't, though.  I'm assuming all the multi-tile enemies have their own collision-detection routines.  I tried logging them, but there are a few dozen of them... per space pirate type.
Space pirates make use of special tilemaps, where each tilemap can have its own hitbox assigned to it. I didn't mess with pirates so I don't know much about their hitbox reactions, but it'd explain why you stumbled across multiple collision detections.
Every hitbox can have unique shot/touch AI reaction pointers, that's why it's such a pain to find a proper way to deal with them.
Even if the actual shot/touch AI pointer is null, it still checks the proximities if being shot/touched.
That's also partly the reason why you can't simply copy the ninja pirates' setup to another enemy and expect shots to be reflected.
The hitbox settings in the enemy settings are mostly just used for the game to know when to draw the sprites onscreen, and I'm not sure if the actual shot/touch AI pointers in the setup are checked at all.

adamf

Quote from: Black Falcon on March 21, 2015, 11:25:26 AM
The hitbox settings in the enemy settings are mostly just used for the game to know when to draw the sprites onscreen, and I'm not sure if the actual shot/touch AI pointers in the setup are checked at all.

My current understanding of Space Pirates is that the "graphics/hitbox pointer" at $0F8E,X (with the enemy index in X) has the current graphics to draw, and each tile making up those graphics has any number of collision detect data (hitboxes and reaction pointers for Samus and projectiles).  And that is what actually gets used for collision-detection with the enemy, if it's special-tilemap property is set.

Since the gfx/hitbox pointer draws the graphics, the AI code updates it a lot to do the animation, and the collision detect data doesn't recycle pointers/routines very efficiently.  (Part of this, too, is that the pointers all lead into the enemy data bank.)  This also means that 'fixing the space pirates hitbox' so it's not sticking way out of their head would be a major project.  You'd have to trace all their AI and fix each animation frame's hitboxes.

As for the rest of what I wrote earlier, it looks like I'm just derping.  If I hijack all the way down inside "collided with a platform" and then continue the platform collision after my checks, of course Samus will be stopped.  She hit a platform, as far as the game knows.