This is a custom Volcano Lotus sprite that has a number of pre-set configurations.
The projectiles have been converted to Cluster Sprites, which allow up to 20 to be on screen at any given time, rather than the 8 the default Volcano Lotus allows.
This sprite can be used as an outright replacement to the original sprite, or as a supplement to it.
The Extra Byte can be set to force it to be upside-down. Due to the way the projectile works, it feels more natural than the existing one.
Different behaviors can be achieved with settings to the Extension field, including allowing them to be sideways!
NOTE: The projectiles utilize a 20-byte RAM table in $7E0F5E, along with all other cluster sprite tables. If you use custom resources which occupy this RAM table, you must change the sprite or those resources accordingly.
-- v1.1 (1/8/2022) - Fixed some minor collision issues. Updated "ClusGetDrawInfo" routine to work slightly better.
Unfortunately, I have to reject this submission for a number of issues that popped up during testing. It's otherwise a very very nice sprite, and I'd really love to see it get resubmitted.
- There are several shared routines that use lookup tables. These must be accessed either by long addressing (LDA.l TableName,x) or by absolute addressing, but setting/restoring the DBR in the routine -- a PHB : PHK : PLB / PLB pair surrounding at least the area which accesses the table (with a normal LDA TableName,x). Otherwise, values will be (and there have been a couple reports of this already) read from the wrong bank if the routine gets placed in a different bank than the code where it's called from.
- You've included a LoseYoshi.asm shared routine which conflicts with the preexisting one in Pixi. Since you aren't using it, it can just be removed. (This wouldn't have been cause for rejecting on its own since it's a trivial fix). Why not just use Pixi's built-in version, anyway?
- On lorom, 3 regular lotuses (with 12 pollen on screen at once) with one extra sprite on screen was enough for slowdown. Even with just 2 lotuses/8 pollen, I could experience a little slowdown, especially so with a couple extra sprites running around. And just 1 fast, stream, or alternating lotus with nothing else on screen could cause slowdown. While I understand that there are fundamental limits to how much can be processed per frame, there's a lot of room for optimization here (more concrete thoughts on that below) that would make this a lot more usable with lorom.
- The alternating pattern doesn't work on lorom (but oddly, it does on SA-1). All the projectiles just shoot in the same direction instead of varying directions.
- There are OAM conflicts between the lotus projectiles and the sparkles from Mario having a star (ditto the glitter effect from collecting a coin) causing some of the projectiles to disappear while the star is active. This one may be a bit infeasible to fully resolve due to OAM table usage, but it's probably worth looking into at least.
- The "Act Like" should probably be $99, the sprite number of the regular Volcano Lotus.
- The pollen should probably erase itself (or just skip its interaction check) on level end; it won't hurt Mario directly, but it will knock him off Yoshi if it makes contact.
Here are just a couple general suggestions that aren't issues, but could help end users a bit.
- It's great that you've got the .json file filled out, but including an entry for every possible combination might be a bit overkill (I think there were 36 in total). Having a list that long can clutter someone's list of custom sprites and make it a bit hard to find what they're looking for perhaps. Maybe just one for each direction and leave it up to the user to set the extra byte themselves. Again, just an idea. And either way, it's helpful to modify the mouseover tooltip to at least match what shows up in "add sprite" window -- currently it just gives "volcano lotus".
- Since it seems that people are meant to add to (and modify) the existing list of behaviors, it might be good to document things a little more thoroughly. Like how using DefaultPattern only works for 4 projectiles; how the different timing values are used; what's passed and returned if someone wants to make their own pattern; etc.
Ideas for optimization:
This isn't exhaustive, and some of the things listed here will have much more or less of an impact than others, but it's just a quick rundown of some of the things I happened to notice while glancing at the code:
1) The way you read values from the BehaviorPointer table could be made more efficient. It's certainly a bit more tedious to specify, but having separate tables with the value for each pattern sequentially removes the need for having to switch the index registers between 8 and 16 bit all the time. Alternatively, there's a small enough amount of data that you can probably just stash everything into unused sprite tables at init time, in which case, changing table types wouldn't really even matter. This would also remove a lot of the restoring of X to the sprite index that you have to do in a lot of places (and I noticed some saves/restores that weren't even necessary).
2) You're using a lot of shared routines, which is good practice to save space when they're being called from multiple places, but they do introduce some extra overhead, especially when they're written generically, with arguments and results placed in specific spots. But you don't seem to be calling these from multiple places, and you're often wasting cycles by placing arguments and fetching return values that could be streamlined. Some of them are less important (like %LoseYoshi(), which gets called rarely), but some have the potential to be called many times per frame, and that little extra overhead can really add up.
3) There are plenty of little optimizations that can be made. For example, I noticed LDA $02 : ASL : STA $02. This can simply be replaced by ASL $02 (as long as you don't need the result in the accumulator, which seemed to be the case here).