View a summary of what's new in 2.55.
Features
- Respawn Point Half-Gridlock
a1d895ce79New QR allows the new respawn points to lock the respawn check to the nearest half-grid (8px) position. This places you slightly further from some unsafe obstacles, and helps in certain edge-cases.
- New QR Rerolled Drops Always Roll 'Nothing'
4c4a24dd42This works alongside the other smart drops qrs to help rebalance dropsets. If set, any drops that would be 'rerolled' always roll 'Nothing' instead, keeping the odds of each drop the same under all circumstances. This allows simply removing drops from the pool when they are unneeded, instead of requiring them to be rerolled into other drops.
- Both invincibility-granting magic items can now prevent knockback
c1930dfd30If knockback is prevented, the player can ex. walk over spikes without being stopped / hit back.
Player
- Water/pitfall attributes for IFrames and Stun Frames
35da0e1ed7- Allows customizing InvFrames after falling / drowning
- Allows stunning the player (to prevent them from ex. walking directly back into the water/pitfall) after falling / drowning
- Cane of Byrna "Invincible Hero" flag
627087fdbaImplement the Cane of Byrna's "Invincible Hero" flag, which was present in the item editor but had never actually done anything. When set, an active Byrna beam now protects the Hero from damage, the same way Nayru's Love (Divine Protection) does.
Editor
- Improve some tile editor shortcuts
54183281b9- Ctrl+Arrows no longer prevent changing pages
- Holding Shift makes the Alt+Arrows shortcut move in increments of 8px instead of 1px
- Improve tile editor quarter-tile draw modes
0607bcd629"Diag Flip" was implemented wrong, acting exactly the same as 180 rotation- it has been replaced with "+Diag Flip" and "-Diag Flip" which properly flip across the positive and negative diagonal lines respectively.
"Translate" has also been added, drawing at the same position in each of the 4 quarters of the tile, useful for minitile-drawing ex. for life meters.
- Show combo label on favorite combo tooltip
4f0513ce28 - Item Wizard for Stomp Boots
feeb4a9c24 - Subscreen 'hint' draws
7d53a5989cSome things that would normally be invisible will have a 'hint' draw to indicate where and what it is in the editor (ex. Button Items, Text with empty string, etc).
Bug Fixes
- AltGr key combinations
6e83d3b488 - Ditherblit ignoring clipping rectangles
4518a325c8 - Add runtime SSE2/SSSE3 detection and fallbacks
f317a332992.55.12 added fast-path code for some tile draws, which required CPUs made in at least 2007 or later. Older CPUs would crash when executing these unknown instructions. Now, the tile drawing code checks if the CPU supports these instructions, and if not uses the slower drawing code.
- Preserve scroll position in new listers
e352f8e7b5Discord - Switchhook Block combo attributes overlapping
0b38f9e5d4The 'Item/Dropset' attribute was in the same spot as the 'Break SFX' attribute! The 'Item/Dropset' attribute has been moved to fix this. If you were using 'Item/Dropset' before, you'll want to update your Switchhook Block combos.
- Continue hearts being improperly bounded
e1c870c9eeThis led to high continue heart values wrapping around to lower values.
Regressed in 2.55-alpha-120 (acb7c84).
- Prevent out-of-bounds write when loading a quest with an invalid combo count
722bcf936cA crafted quest file could declare a combo count larger than the maximum number of combos, causing writes past the end of the combo buffer.
- Prevent out-of-bounds write when loading a quest with too many counters
e5018aa903A crafted quest file could declare a counter count larger than the maximum, causing writes past the end of the counter arrays in the init data.
- Prevent out-of-bounds read from invalid DMap subscreen script index
9285d6aa74A crafted quest file could set a DMap's active/passive subscreen script index beyond the script table, causing an out-of-bounds read and dereference of an invalid script pointer when the quest is loaded or run.
- Avoid out-of-bounds read on unterminated enemy name in quest file
3bfac596afA crafted quest file could supply a 64-byte enemy name with no terminator, causing a string length scan to read past the end of the buffer.
- Avoid out-of-bounds read from invalid FFC combo index during quest load
c61ec35b6fA crafted quest file could give a freeform combo a combo index past the end of the combo buffer, causing an out-of-bounds read while fixing up old quests.
- Avoid out-of-bounds read from legacy secret-combo template index
067feacc4bLoading a crafted old-format quest could use a secret-combo value as an index past the end of the template screen's combo arrays, reading out of bounds.
- Prevent out-of-bounds write from invalid combo pool/autocombo counts
dca3afdf21A crafted quest file could declare more combo pools or autocombos than the engine supports, causing writes past the end of those fixed arrays.
- Prevent out-of-bounds write from invalid favorite combo data
f115f177cbA crafted quest file could declare too many favorite combos or an invalid per-row value, causing writes past the favorite-combo arrays (or a divide by zero from a zero per-row value).
- QR for chests/signs/lockblocks working above layer 2
d4d23e1264 - [mac] size default window using the screen's usable area
4fa90869b0The default window size on macOS subtracted a hardcoded guess for the menu bar and ignored the dock, so the window could end up larger than the available space. It now uses the screen's actual usable area, which excludes both the menu bar and the dock, and reserves the window title bar at the correct size on high-DPI displays.
Player
- Sideview drowning softlocking the player forever sometimes
a47f527d64 Hero->Immortalnot clearing on quest loadbe322f1002- Per-quest controls resetting wrongly on Continue
e84449c199 - Pitfalls not resetting attack timer
015b811e09this allowed the player to be in the attacking animation instead of the falling animation in some situations.
- Ffc solid pushing of the player stopping too soon
d9cb3d03a9incorrect hitbox check was being used
- Lens hints showing during player death animation
edc8e90f65 - Softlock with
No Scrolling Screen While CarryingQR in NES dungeonsd23376f639This QR wasn't preventing the "suck" of bombed doors and walk-through walls from trying to scroll. This resulted in softlocking the player because they were being permanently sucked into the scroll, while the scroll was being prevented by the carried object.
- Standing state not checking properly for ffc platforms
1677d574a5this made it hard to jump when riding a downwards-moving ffc platform
- Wrong offset being used for solid object pushing
ac1e9ed137These offsets would commonly be the same value, so, unlikely this actually caused any issues yet.
- Fix ePatra firing too early when ENEMY_FLAG7 is set
86ad21162cWhen the "don't fire while looping" flag was set, ePatra could still fire in certain attack modes (dmisc20==4 and default) regardless of whether it was mid-loop. Now all modes correctly wait until the loop finishes before allowing fire.
- New/Newer Hero Movement inconsistencies
c4d457feaaSome spots were only checking for New movement which should've checked for either, causing inconsistencies between enabling both and just enabling newer movement.
- Allow "255"/"0xFF" as transparent for more subscreen colors
72b13e7a78Setting the
BS Darkcolor to 0xFF in misc colors makes its minimap look more similar to Dungeon/Interior minimaps.Some colors already handled this, but it was missing from places that could really use it.
- Sideview drowning sprites being broken
7c22a4bd51 - Sideview ground checks ignoring enemies' 'ignore solidity' flag
82b6eb3d3bThe code for "is the enemy standing on a solid" was using entirely different code that didn't check this flag. Now it checks it when "Use 'Scripted Movement' for engine movement" is enabled.
- Chests not checking all layers for Armos/
Chest->Item4f1a6d2a66this caused chests placed on layers > 2 to open without giving you anything
- Enemy bombs disappearing due to negative fuse timer
d996f1b9ae - Bombs not resetting Timeout when exploding
b831914950Timeout is meant to function as an alternate fuse for these, but if it explodes before the timeout runs out, the timeout was leaking over to the explosion and killing it mid-boom.
- Light beams not working properly during stepforward
1413c8f520 - Item sounds sometimes being wrongly killed
8bb98f0594The hookshot resetting code was killing the sound of the currently in-use item, without regard for if that item was a hookshot or not.
- Pushblocks not properly counting towards trigger groups
6677d9b6e8 - BS Overworld not respecting having the Map item or not
3cacbc2fd1 - Enemy bad hitboxes for standing on the ground in sideview
8513081f8aEnemies with weird hitboxes may still have other problems, such as walking sideways through walls, because enemy movement code is super jank- though the
Use 'Scripted Movement' for engine movementenemy movement flag seems to help with those issues. - New respawn points not counting damage combos or slidey ice
88e4644fe4 - Solid moving objects interacting poorly with water/pits
bf4281c74fthey now can push the player into pits, and no longer push the player while the player is already falling/drowning
- Prevent infinite loop in trig_trigger_groups
bc0054ef5b - Combo general loop sfx cutting out when looping
ec0e1a1268 - Knockback through sideview platforms
147c1b0413 - Buggy solid platform sideview ffc collision
c51805f07aWhen moving at angles the collision for riding the platform was getting confused with the collision for solid objects pushing the player, knocking the player off the platform weirdly.
- Shooter/crumble combos ticking when screen is 'frozen'
d6c4678934 - Prevent rng desync when manually ending replay
8f20d39267When playing a replay file, selecting Quit in the menu caused an rng desync dialog to appear. Now, the program actually closes.
- Deterministic high-precision math for gameplay and replays
c44d4ff325While recording a replay, trig (Sin/Cos/Tan) switched to a low-precision lookup table, so simply having a replay enabled could change gameplay. Separately, ArcSin/ArcCos/ArcTan and Ln/Log10/Pow always used the system math library, whose results vary across platforms and compilers - a source of cross-platform replay desyncs. All of this math is now both high-precision and bit-identical on every platform and compiler: recording a replay never changes behavior, and replays cannot desync across machines due to math differences.
As an example of how the old trig error presented: in Stellar Seas, a boss laser derives its collision geometry from trig, and the recording- mode error (up to ~0.001) was amplified by the script into "phantom hitboxes" - hits landing tens of pixels away from the visible attack, only while a replay was recording.
Other user-facing effects:
- Pow(2, n) and Pow(10, n) are exact, and Log10 of a power of ten returns an exact integer, so digit-counting scripts behave reliably.
- Replays recorded before this version still play back with the old math, bit for bit.
- Walking/standing combo effects not blocked by bridges
c374637443this includes the general tab sfx/sprites
- Stomp Boots block flags being backwards
68ef97426dRegressed in 2.55.0 (de1cb2b).
- Frozen scripts wrongly having draws stopped by running strings
98b0be2340 - SCC setting screen state of non-current screen using wrong map
94b4872336 - Bottom 8px bad collision using 4-way newer hero movement
d9faad3742 - Stop triforce pickup softlocking with low MP/HP counter settings
8d1181cdfcPicking up a triforce would freeze the game when MP per Block was set to 1-3 (or HP per Heart to 1). The refill animation never finished, so the pickup cutscene looped forever and quitting crashed.
- 1-wide gaps being hard to fall through in sideview
c542da8ebe - Handle replay load failures gracefully with a GUI error
90ddfd3d7fLoading an invalid replay could crash the program. Now, an error dialog is displayed when a replay fails to load.
- Prevent previous qst misc data leaking to next
527c9699cc - Hammer triggering combos outside its hitbox
67dc1df14cThe hammer could trigger combos and secret flags above and behind the player, outside the area its hitbox was drawn. It was most obvious with the "don't trigger while the hammer is in the air" item flag enabled: on the first frame the hammer became active on the ground, it triggered combos where it had been a frame earlier, while still raised.
- Armos combos with custom enemies not clearing the combo
564fa7fb21 - Large armos bad tile offset
9f8a9714b5 - Auto Sidewarp combos not using the assigned Warp SFX
70ab4774ae
Editor
- Remove unused wand attributes/flags from item editor
14ede02c46 - Tile editor rotations sometimes undone
a1d15cc88bDiscordCaused by a bug in tile caching code.
- Preview mode combo cycling using bad colors for Ignore CSet
13636edb06 - Water/shallow water combo wizard not setting levels properly
fec4002703If you didn't edit the
Req Item Level/Flippers Levelfields, they would stay at value 0, despite showing as value 1 in the GUI. For req item level, this could completely disable the passive hp mod. - Don't show confirmation on exit in new quest wizard
29f7dfedc0 - 'block' missing from 'Mirror (Custom)' attribute help
bf5cfa1d1c - Typo in ffc editor 'Swap' flags' info
4e705ed824 - Avoid potential crash when drawing doors
1c850ea5d7 - Clean up the string editor / add infobuttons
80aae94aaf - Respect "New Darkness Trans Layer Stacking" QR in editor
13f5c6b760 - Clean up 'Button Counter' subscreen widget '?' buttons
fe9053d1e4
ZScript Standard Library (std.zh)
- CenterY for an item returned an X-based coordinate
162013f324CenterY(item, false) used the item's X coordinate instead of its Y in the sprite-center branch, returning a wrong value. It now uses Y, matching the hitbox branch and every other CenterY overload.
ZScript
- Show correct code location for script drawing errors
6fdd14f83e - Prevent DMap and hero scripts running twice on init
8285221f7eDiscordThe first frame of these scripts were incorrectly running twice. The exact behavior depended on whether these QRs are enabled:
- "Scripts Draw During Warps"
- "Passive Subscreen Script runs during wipes/refills"
This bug only occurred if one of these QRs was enabled.
- Prevent crash from out-of-bounds sprite script IDs
9202045134 - Use proper gfx for script created sword beams
559bdddf2aThis regressed in 9ca67c7b0 (2.55-alpha-120).
Game->CurrentItemID()using a bad default value for bitflagsfca4d972d0- Strcmp-family functions now always return -1, 0, or 1
6d55503949strcmp(), stricmp(), strncmp(), and strnicmp() returned the raw C library comparison result, which is only guaranteed to be negative, zero, or positive - the exact value varies by platform and compiler. Scripts comparing the result against exactly -1 or 1 could behave differently across builds. These functions now always return -1, 0, or 1.
- Free script-owned objects when a script's state is cleared
201ebe3426Resetting or clearing a script's engine data did not reliably release the script objects that the script had taken ownership of. Several script types that run in less common ways (like active subscreen scripts) could therefore leak these until the engine eventually ran out of slots.
Releasing owned objects is now an inseparable part of resetting or clearing a script's engine data, so it can no longer be skipped.
- Prevent crash when taking the modulo of the minimum integer by -1
3f09fc4fa2Computing the remainder of the smallest representable integer modulo -1 crashed the game, in both the interpreter and the JIT. The result is now 0, the same as any value modulo -1.
- Remove unimplemented
Audio->PauseCurMIDI()andResumeCurMIDI()ff942cc537 - Free objects owned by DMap and subscreen scripts
97ac507bf8Objects and arrays that a DMap, OnMap, or active/passive subscreen script took ownership of were not released when the script's state was cleared, leaking them until the engine ran out of object slots.
ZConsole
- [win] prevent debug console from freezing
bd68efde70DiscordThe named-pipe connection was treated as a hard failure when it didn't complete instantly, popping a modal dialog that could hide behind the game window (appearing as a frozen black screen) and orphaning the helper console in an endless retry loop. Connect now waits with a bounded timeout so a slow-to-start console attaches normally, and any setup failure quietly disables the console instead of blocking the app.
Refactors
Player
- Copy cpos_update optimization from combos to ffcs
07f75a7887 - Greatly speed up refresh_rgb_tables using last key cache
809dd2019bDiscordThis greatly speeds up the program within fade effects. For terror_of_necromancy_demo6_32_of_54.zplay it reduced the total CPU time being spent in
refresh_rgb_tablesfrom 60% to 0.3%. - Optimize code for common dithering args
af60e181aaThis speeds up dithering by a lot - between 3x and 25x depending on the platform.
- [win] remove obsolete vsync workaround (use_dwm_flush)
8d33ad6b05Remove a Windows-only screen-tearing workaround from the Vista/Win7 era, along with its hidden use_dwm_flush config option, which is now ignored if set. It was off by default and is redundant now: the display backend owns frame presentation, and desktop composition is always on in modern Windows.
- Greatly speed up dithercircfill
d50e8a9da3Discord
Editor
- Improve FFC hover tooltips
78d9fc3d32
CI
- Upgrade actions due to node 20 deprecation
d64d2270dc
Misc.
- Update rulesets
f6b7cbcd56
Editor
- Remove darkness dithered corner by default
a8b25517b2Etc->Options->Toggles->Show Darkness Corner Dither toggles this Darkness now shows a line in Screen Info, to less obtrusively indicate dark screens.
- Improve infotext for string editor 'Layer'
bc2ef07408