Skip to content

Instantly share code, notes, and snippets.

@connorjclark
Last active April 28, 2026 03:56
Show Gist options
  • Select an option

  • Save connorjclark/4a29fbaaca79d0044694ee65dfd4f78e to your computer and use it in GitHub Desktop.

Select an option

Save connorjclark/4a29fbaaca79d0044694ee65dfd4f78e to your computer and use it in GitHub Desktop.
3.0-so-far.md

Note: this is a draft!

Updated: apr 27, 2026

Features

  • New icons fbfcc87da8
  • Custom logo for quest package export 13030cb8a1
  • Custom title music for quest package export 705d14b31d
  • Add burn-based light radii for items, to change the glow radius when lit on fire 6cc9ab347a
  • SCC for 'Trigger Combo Copycat', allows triggering a triggers-tab copycat index bcf7b98cee
  • LW_REFARROW, LW_REFFIRE, LW_REFFIRE2 (reflected arrows, fire, fire2) e3b23aa7da
  • Slidy Ice for the Player a923d5c425
  • 'Toggle Darkness' trigger flag (toggles current room being a dark room) ff6c8151e9
  • 'Req. Darkness' / 'Req. No Darkness' trigger flags; act as conditionals on a room being dark or not dae41c8c72
  • Trigger flags relating to LItems (map,compass,etc) 42b835781f
  • Trigger options relating to tinting the palette 4917cea2d2
  • Trigger options relating to changing palette and wavy/quake vfx 9220affe4a
  • Trigger options relating to status effects and 'Push->' timing 3ee3da8573
  • Add Cure Shield Jinx to bottles 1846747289
  • Add shield effect for jinxes, update Whisp Ring 97688da502  

    Jinx enemies (aka Bubbles) can now impact shields, and whisp rings now correctly apply to temporary jinxes.

    See docs/enemies.txt for how to configure Jinx enemies.

  • Add shield jinx removal as refill effect 977e72321f
  • Add Shield Jinx trigger 985904538f
  • Expand palette from 6-bit to 8-bit color 4fccd75658  

    The RGB channels for colors have been increased to full RGB color range of 0-255, rather than 0-63. This increases the number of possible colors that palettes can use by 64x.

    This also impacts how colors are declared in ZScript, such as for Graphics->Tint, Graphics->MonochromeHue and combodata::TrigTintR/G/B. A script compat QR is added for existing quests that use 6-bit colors.

    A minor side effect of this change that applies for all quests is that palette effects, such as the fade in/out screen transitions and the death animation, are now smoother as there are more possible colors to animate through.

  • Add configurable weapon sfx to enemies e71f8dc99e  

    This can also be configured in ZScript with npc->WeaponSFX and npcdata->WeaponSFX.

  • Fully configurable enemy weapons 36f92c7bfc  

    The enemy editor now allows you to configure additional things for the weapon that the enemy fires. These used to be hardcoded based on the weapon type, but now all these are configurable per-enemy:

    • damage
    • speed
    • block flags (ignores player defense / shields / reflectable)
    • movement flags (gravity / pitfalls / drownable)
    • tile size and hit / draw offsets
    • burning sprites and light radius
  • Make the special sfx of enemy weapons configurable too 9fd9f4a3df  

    Some weapon types, like boomerangs and bombs, have a secondary sfx that was hardcoded. You can now configure them in the enemy editor.

  • Add enemy types to zinfo d2ed2627e0
  • Lift glove flag to drop objects when hit 73ceca28c5
  • 'Cycle to Screen Undercombo' combo animation flag 577e115bdd
  • Add Misc SFX when the Hero lands on the ground 57c43d98d6
  • Attribute 10 now used for hop height for vires/polsvoice 6ffb117532
  • Per-combo player landing sfx 29e5a0e08c  

    The MiscSFX landing SFX plays if none is set.

  • Pushblocks can drown (on a QR) f3ffe8e741
  • Combo-specific falling/drowning sprites/sfx for pushblocks b8a2c17e91
  • Trigger flag 'Apply Discount', allows wealth medal discount to apply to trigger counter costs 7ffb361135
  • 'Light Wave' effect for dark room lights b46b96c183  

    Makes the lights increase and decrease radius in a sine wave pattern, with a specified rate and size. Lantern items have a checkbox to ignore this effect.

  • Z3 scrolling regions 6b5e98dd70  

    Regions are a collection of screens that are stitched together to become one playing area that the player can move around in, with the viewport moving to track the player. All mechanics of ZC have been updated to support that there can now be multiple active screens. Additionally, there is a new DMap option to reclaim 160 more pixels in height for the visible playing field (making the passive subscreen draw over it). There is also scripting support for configuring regions and the viewport.

    Here is a guide covering what quest makers need to know about regions.

  • Pushblocks can "fall" in sideview gravity 89adebef37
  • Add 'Layer' property to FFCs (ignored for 'Overhead' ffcs) 5e270db775
  • Add "screen load" combo trigger 4e750bc071
  • Lifted combos specify glow shape / radius e74cc26d8a
  • Special subscreen counters for button item costs 3b90a03303
  • New subscreen widget, 'Counter Percentage Bar' 64bc639c72  

    Draws a rectangle of two colors, based on the percentage of a specified counter. Useful for a life/magic meter that doesn't change size as the max changes, but instead gets denser.

  • Subscreen minimap compass can point to any LItem instead of just McGuffin 963e0a4ba7
  • Subscreen widget conditionals 474322fb17
  • Add 3 custom LItems 5b8bc576ad
  • Allow any item to grant LItems on pickup (for any level) 2ee9dac5c7
  • 'Level Keys' can be for a specific level db256905e5
  • Multiple triggers per combo 56e9081285  
    • Each combo can have anywhere between 0-255 combo triggers. Only the used triggers take up space (in memory or qst).
    • The triggers are checked in order, so if the same combo has multiple triggers with the same cause, they will run in the specified order.
    • If in such a case, the combo is changed while there are still triggers remaining, the extra triggers will NOT be executed- the execution halts when the combo is altered.
    • Editable string Label for each trigger, used in the display name in the combo editor list
    • Script access. The old access should all still work, accessing the combo's first trigger. Access for new triggers uses the new combotrigger datatype.
    • Screen->TriggerCombo() can specify trigger index
    • the 'Only Gen Triggers' flag is now part of combos instead of triggers, so has separate access (combodata->OnlyGenTriggers)
    • combodata->GetTrigger() to get a specific trigger by it's label (where invalid names safely return a null value)
  • Swords use second item editor sound for beam sound 4c63cff50d
  • Editable MoveFlags for items/lweapons in Item Editor 7cefc064b9
  • A bunch of new combo trigger stuff 2f114cb239  
    • longer timer triggers
    • triggers can be conditional on LevelStates and GlobalStates in either direction
    • triggers can un-set an ExState or ExDoor
    • triggers can use "special counters" (like the subscreen, most importantly the "Any Keys")
    • Triggers can play strings. Also they can do a different string (and different button prompt) if their "conditions" currently fail.
    • The "screen load" trigger is now recursive- so if a "screen load" trigger changes the combo to another combo with a "screen load" trigger that will trigger too.
    • The ability to make the player jump. (Or well, to set the player's Jump value, so it could work for like, a fan slowly blowing you into the air, or to shove you down towards the ground with negatives)
    • The conditional to only trigger if the player is "standing", or "not standing" (works for sideview as well)
    • The conditional to only trigger if the player's Z value is >= or < a set value.
    • GUI re-organization and cleanup for the trigger GUI
  • Allow an 'active shield' to have a specified button that activates it 726205f97f
  • Set bottle contents in Init Data / Cheat Menu 7bf318ba0f
  • Conveyor flag to affect airborne entities 11f8b8704a  

    Works exactly like the screen flag "Combos affect Midair Hero", but specified on the conveyor itself.

  • "Only Visible In Editor" combo flag 629ba74509
  • Even more combo trigger features 89c5876ef2  
    • hero facing direction conditional
    • counter "percentage" / "gradual" flags
    • copycat "no cause" flag
    • "Land Here->"/"Land Anywhere->" causes
    • Move (teleport) Player effects
    • Player position / jump speed conditionals
    • combo type specific causes (currently only pitfalls/liquid)
    • "Load Level Palette" effect can now use "-2" to load the current screen's "Editor F4 Palette"
  • Standardized 'weapon data' settings for items/enemies/lifting b43e006d74
  • "No Collision When Still" weapon flag edb610c735  

    Useful for weapons that lay on the ground and can be lifted/thrown

  • QR to allow autorotated weapons to use right-facing sprite params d3859e27b9
  • Weapon pierce count 9fbc37a01c
  • QR for "Weapons Cannot Stunlock Enemies (ignore)" 3a70ecb2af  

    Like the existing no stunlock rule, stops stunned enemies from being hit. Unlike the existing rule, enemies IGNORE instead of BLOCK the weapon. The existing QR was renamed adding "(block)" to the end to differentiate.

  • Allow 'walk on top' for all combos, not just Switch Block combos e92a4899f8
  • Combo Trigger force ice physics / set player facing dir effects eb4dd3928d
  • 'Enemies->Stay Dead' screen flag 3b12dcca93
  • Expand 'noreset'/'nocarryover' to all screen states aa38836b1f
  • Exstate carryover/reset options e95b860ec6
  • Expand mirror capabilities with reflect flags 0ce825dc2e  

    Mirrors can now reflect many more weapon types. Player shields can also now reflect LW and EW wind.

  • 'Cutscene Effects' combo 0b4b32dd4d  

    A combo designed to interface with triggers to allow a variety of special effects useful for cutscenes. Ex. 'Player Walk' mode forces the player to walk directly to the specified point (ignoring collision).

  • Gravity Boots 960e00c524  

    Coming in 3 varieties, these boots alter the Player's gravity and terminal velocity! 'Gravity Boots' just change them passively (can optionally be sideview-only) 'Gravity Up Boots' change it when holding 'Up' in sideview 'Gravity Down Boots' change it when holding 'Down' in sideview

  • Roc's feather can subtract from player's jump after released 1b758c9f76
  • Improved player jump/fall animation QR ccc7c0e60e
  • Per-item cooldowns 00c21339e9
  • Subscreen Widget - 'Gauge Piece: Item Cooldown' for visual display of cooldowns f6e1e5a29c
  • 'Cooldown Ring' item type to modify all item cooldowns 67dbdacc3b
  • Subscreen Widget - 'Item Cooldown Text' for a simple text of the cooldown time 31d4772950
  • Per-screen and per-DMap custom gravity e2f856083a
  • Combo trigger to change screen's gravity fbf9b65af8
  • QR for armos/grave combos working on layers > 0 ffb8b92752
  • Expand litems from 8 to 16, add zinfo for litems 3bc63dabcf
  • Set LevelStates in Init Data 4e356be6f5
  • Combo flag "Step 'in front' in sideview" 198768b290  

    Allows 'walking'/'standing'/'landing on' effects to occur when behind the player instead of under the player in sideview. Useful for, ex., a stream of running water (as background combos behind you) having walking/landing sfx for splashes.

  • Add some customizable values related to timeout items 234085a7da  

    can customize the timeout duration, flicker duration on spawning, and the speed. can also customize a new feature, the duration it flickers before disappearing.

  • Allow "dive under" solids, QR for player to draw under layer 1 while diving d80084a4de
  • Add many new SCCs c4ff8de1a0  
    • CollectItem
    • Delay
    • ForceDelay
    • KillHero
    • Counter
    • MaxCounter
    • GoIfAnyScreenState
    • GoIfGlobalState
    • GoIfLevelItem
    • GoIfLevelState
    • GoIfScreenState
    • GoIfSecrets
    • GoIfScreenExState
    • GoIfAnyScreenExState
    • SetGlobalState
    • SetLevelItem
    • SetLevelState
    • SetScreenExState
    • SetAnyScreenExState

     

    See https://docs.zquestclassic.com/tutorials/message_strings for details.

  • Add SCCs for bottles and changing the portrait 7225481551  
    • ChangeBottle
    • GoIfBottle
    • Portrait
  • 'Map Subscreens' 753a530fff  

    If a Map Subscreen is assigned to a DMap, it will replace the map button map for that DMap.

  • QR for map button closing the active subscreen 2eb04c2ad8
  • Per-subscreen-page configurable buttons to change pages 2cee82f22b  

    Gives better control over how pages are cycled through.

  • DMap 'Floor' value, floor conditional for subscreen widgets 0c95310f71  

    DMaps now have a 'Floor' value (0-255). Subscreen widgets can have a list of floors set as a conditional, only appearing if the current floor is on the list.

  • Counter/ButtonCounter subscreen widgets can show max value / fraction of max 67f34833f9
  • More subscreen widget conditionals 530b991d5d
  • 'Visited' screen state no longer cares about DMap view map flag f4472416e1  

    Compat rule for old behavior

  • Subscreen page transition mode for "current screen" ac05d4e285  

    Used on it's own, can create visual effects of transitioning to a copy of the current page. Used with 'Swap Map Subscreen', can go to whatever page the other subscreen type was previously on.

  • Customizable save menus 92641e6231
  • Trigger requirements for screen state/exstate (including other screens) ae5ef3317c
  • Allow mirrors/prisms to work on FFCs 4076d99239  

    NOTE: Does NOT work for light beams!

  • New music system 25814a1e7f  

    Combine enhanced music and MIDI into a single object, such that the enhanced music will be played if possible, falling back to the MIDI if the enhanced is blank or fails to load. Replaces enhanced music on DMaps, and MIDIs on DMaps, Screens, and SaveMenus. Adds Combo Trigger and SCC access to play music from these new objects, and similar access to change the MusicRefresh value (modifying when the engine will change the music back on you).

    Overall, this should allow much better control of music, and much easier use of enhanced music. Common scripts like "Boss Music" can now be accomplished with a couple combos with the right triggers set up.

  • Remove combo 'attribytes' and 'attrishorts', expand 'attributes' 88ca703ab0  

    attribytes 0-7 are now attributes 8-15 attrishorts 0-7 are now attributes 16-23 attributes 0-3 are still 0-3, 4-7 are new. This will allow larger / negative / including-decimal-part values in some cases that would not allow them before.

  • Increase max MIDIs to 512 b48e524bfd  

    Also increased MIDI title max length

  • Upgrade to Allegro5 audio for sfx, bump max sfx to 1024 58486c3f4a  

    This changes the entire system for sfx playing on the backend; most importantly, this allows loading OGG sound effects.

  • Increase Max Items (256 -> 1024) 1f397dc208  

    Items can be added / deleted / re-ordered via the item editor list. Currently nothing will be updated for you when re-ordering (including deleting from the middle of the list), so take care when doing so.

  • Enable native file dialog by default ea0d20f1b3
  • Minimap can draw visited rooms 6a8767682d
  • Expand max Sprite Data (256 -> 8192) 786f85b17c
  • Add new SCC: SetCurrentScreenD 5e8f9ad07f
  • Customizable player hitbox for item collection a4f619394d  

    Also includes fix for item hitboxes being weird in general, so now modifying the size of item hitboxes should work MUCH cleaner.

  • Dropdown lists open when clicked anywhere, instead of just the arrow 3809fd3504
  • Dropdowns show more options at once ce12c14ffe
  • Clicking the thin border of rclick menus no longer closes them c3e81bc842  

    This means opening an RClick menu and then instantly lclicking will no longer 'click off' of the menu, nor will it select an option.

  • Spinning Tiles support '->ComboType Effects' and 'Only Gen Triggers' b42be7c9e2

Player

  • New logo and song to file select screen ee916ab45b
  • Add option to disable title music 9256d13d97
  • Optimize ZASM scripts 16da940b1f  

    First thing when loading a quest the ZASM scripts will undergo optimizations. Most optimization passes apply improvements similar to that which have been implemented in the ZScript compiler, but are not present in older quest scripts. Others are novel and improve even modern ZScript compiler output.

    Savings for a few quests:

    • Stellar Seas - 163762 ops (5%)
    • Yuurad - 604668 ops (4%)
    • Umbral Cloud - 105994 ops (8%)

     

    The optimizations done currently are:

    • Removing unreachable blocks of code
    • Replace many PUSH/POP with equivalent single PUSHARGSR/POPARGS
    • Reduce ops used for conditionals (COMPARER)

     

    This is on by default, but can be disabled with [ZScript] optimize_zasm = 0 in zc.cfg.

  • Add ZASM optimize_setv_pushr f2dd0314e7
  • Optimize comparison commands in ZASM 419aac8040
  • Optimize scripts just before use, instead of all upfront bf32e9105e
  • In optimizer, consider the null D5 register when combining commands like POP 0c5bc072b3
  • Optimize old scripts LOADI to LOADD 1d7fa6a48d  

    This removes ~8% of commands from Yuurand, ~12% from Nargad, and ~14% from Stellar Seas.

  • Optimize useless stack push/pops in old scripts a273d27c3a  

    This saves 15% of instructions for Yuurand.

  • Add simple titlescreen, and remove music from save select screen a593e75715  

    This also reintroduces the skip_title option in the launcher.

  • Continue ZASM comparison reduction even on LOAD D2 e20f62d4d4  

    At some point this was necessary, but not anymore.

  • Improve inference in optimizer simulator, and handle POP better 0a7117ba26
  • Improve ZASM comparison when subsequent block reuses D2 cac709f3d0
  • Optimize SETR PUSHR to just PUSHR 4429211711
  • Optimize ZASM pass converting to new function calls d40c0d6344  

    Replaces older GOTO/GOTOR and GOTO/RETURN with more succinct CALLFUNC/RETURNFUNC.

    This saved ~2.5% of instructions in Yuurand, ~4% in Nargads Trail.

  • Optimize ZASM by inlining functions 86edb55fbf
  • Optimize old scripts STOREI to STORED da7113489f
  • Option to show game time in the corner, for all those speedrunners out there 9d50c56879
  • Optimize LOADD/STORED to new LOAD/STORE to remove divisions d8a7872c8b
  • Optimize ZASM by removing intermediate registers dddd96cf11  
    • For example, SETR D3 LINKX ; TRACER D3 becomes TRACER LINKX
    • Also attempts to avoid pushing value to stack just to pop later, but only if the value of the register is unmodified in the original code between pushing and popping from the stack
    • Only occurs if the register is read once. If read twice, the overhead of calling get_register is too great so it would be worse to call multiple times. Data registers are much faster to access.
  • 'Toggle Lights' cheat works on new dark rooms 1f74bdc0a2
  • Show bottom 8 pixels by default for most quests made prior to 2.55.9 86b88dff9c
  • Enable ZASM optimizer 119445961b  

    Script heavy quests are known to run 2x more efficiently with this enabled.

  • Add -frame-timings CLI switch to log expensive frames 543415d80c
  • Revamp drawing code 3ee61b001c  
    • ffcs and script draws can be negative-layered
    • sprite Z-sort and optional Y-sort
    • z-thresholds for each layer, allowing sprites to "jump through" layers as their Z increases
    • weapon animation code is no longer done during weapon drawing (also fixes weapon shadow draw timing)
    • generally cleaner code
    • some minor graphical fixes
  • Update volume dialog 45c0e73328
  • "Temp Ignore Solids" weapon flag cd73a16070  

    Causes a weapon to ignore solids for the 'Break on Solid' / 'Stop on Solid' flags. Un-sets itself as soon as the weapon is NOT touching a solid. Using this flag on a solid shooter combo will prevent the shooter itself from killing it's shots.

  • Press B to backspace in name entry grid mode 925b393b07
  • Improved grid name entry mode dcdbf7231a  
    • Show on-screen controls for insert, backspace, confirm
    • Press 'Tab' to use keyboard to type name
  • Gzip compress uploaded replays f62d6f9231
  • Update replay versions on save load 8dba8da5b1  

    Previously, save files associated with replay file were permanently pinned to their initial replay version. This prevented older saves from benefiting from subsequent engine bug fixes. The replay version now dynamically updates when a save file is continued, seamlessly bringing new fixes to ongoing playthroughs without breaking existing replays.

Editor

  • New song to ambient music menu 47c8bf62ae
  • Merge 'Favorite Command' and 'Hotkey' systems 47617f7ad4  

    Any 'Hotkey' can now be set to a favorite command, and all old favorite commands now have 'Hotkey's. Favorite command buttons will clear upon this update, as the configs have changed.

  • Save backup when qst was last saved in a different version of ZC d9a81183a4
  • 'Adv. Paste' string editor rclick option bd40c292c6
  • Advanced Paste for Item Editor 138b58626e
  • 'Warp Back' rclick option to reverse after following a warp 8dd981f272
  • Item Wizard (Shields) f30dd70954
  • Assign 'notes' per-screen (just for editor use)

      Relevant changes:

    • feat(zq): 'Set Default' button to set default editbox colors e9e8b112de
    • feat(zq): 'Goto' button in 'Browse Notes' to go to a notes' screen 9bd560f937
  • Export/import strings to .tsv text file 13e56e789f  

    Allows for exporting strings to a spreadsheet, text editor, or other program for modification, then importing them back to ZC.

    The first row of the .tsv (tab separated values) file are the column names, followed by an example row to designate where the first three lines begin and end for each string (but you can add more lines than that).

    For best results in a spreadsheet, "Freeze" the first two rows and use a monospace font for the "message" column.

    Example: https://docs.google.com/spreadsheets/d/197-NSvNQJ174Ri9GVlxYDX4oFp8w1SZbmOXuDohKZZk/edit?usp=sharing

  • Add help text to the FFC editor a4030cac36
  • Zoom out to edit many screens at the same time 6fd217ecb0  

    It is now possible to zoom out when editing map screens, up to the size of the entire map (although 4x4 screens is roughly the last usable zoom level).

    Ctrl/Cmd + -/+ is the shortcut to zoom out and in. Note that this replaces an existing shortcut for modifying the screen palette by 16 - that is now Shift + Ctrl/Cmd + -/+.

    Arrow keys change the current screen as usual (and so updates all the screen-specific UI, like enemies/warps/the Screen menu). If you move beyond the current viewport, the viewport moves along with you.

    Clicking on any visible screen will also set the current screen.

    Should be able to perform any action as expected on screens when zoomed out: copying, pasting, ffcs, moving items, warp squares, all drawing modes, flood fill, editing layers, etc.

    The undo/redo system works as well.

    There are a few new options related to this feature, under the View menu.

  • Check/Uncheck/Toggle All buttons for checklist dialogs (ex. adv paste) 6d35395d3b
  • Add 'Alphabetized' checkbox to basic listers (item,enemy,sfx,midi,subscrwidget) 0a10202e22
  • Add '(000)' after '(None)' in some lists, allowing typing '0' to skip to it 94fa4ce00f
  • Add descriptive labels and dropdowns to walker type attributes in enemy editor e5cf4d4dab
  • 'Drag Squares From Center' option, for FFCs/warp squares/etc 4028184ffd
  • Tools->Fix Tools->Green Arrival Square Fix e07947d77c  

    Allows you to clear out all the green arrival squares in your quest (and optionally turn them into blue squares)

  • Add quests/examples/trigger_example.qst 2e886e3e14
  • 'default level palette' for each map / 'Quest->Map Settings' 2aaeb01862
  • Combo trigger 'Summarize' button 1c1e78608b  

    Describes the details of a combo trigger in a short summary, so you don't need to look through every tab just to figure out what it does.

  • Support updating existing SCCs in string editor ca3cd72fa1
  • Show warnings in string editor 023f961c75
  • Subscreen wizard for 'Tile Map Grid' 379598106e  

    Places a set of Tile Block widgets, designed to help make custom Maps. The different Tile Blocks can have different conditionals, so that some appear when you have the dungeon map, and others appear only when you've visited the appropriate screens.

  • Render screen editor in multiple palettes, higher resolution d7438d4f3b  

    The screen editor can now render multiple screens in different palettes at the same time. It also renders at a much higher resolution. This makes the zoom out feature much better.

    In case there are any regressions, this can be disabled via in the View menu: just uncheck "High Quality Screen Rendering".

  • Add history navigation for viewed screens 7b0e5333d2  

    You can now navigate recently viewed screens by using the side buttons on the mouse, or configuring the "Go back/forward" hotkeys.

  • Ffc placement / rclick improvements 21c410715f
  • Upgrade 'Layers' dialog c0ab222c73
  • Upgrade "Freeform Combos" dialog 7132bc16de
  • QR 'Weapons Better Screen Edge Hitbox' f7aad5f501  

    causes weapons to not die from reaching the edge of the screen until the weapon is actually off-screen.

  • Subscreen editor grid can now draw lines instead of dots 646aa2b7d6  

    also upgraded the dialog for editing the subscreen grid

  • 'Open Tile Page' directly from combos/ffcs onscreen f386d05ead
  • 'Copy Info' button 1debd3b39e  

    Copy Info from any info popup directly to your clipboard

  • 'Compare QR String' button 6d820c1757  

    Using a QR string copied from a quest, easily see what QRs your quest has set differently.

  • Update 'Help' dialog ece0ae1c6a
  • improve quest auto-backup and timed auto-saves a1002f4173  
    • Enable auto-backup by default.
    • Save all backups and auto-saves to a backups folder - on Windows, it is backups.YourQuest.qst/, otherwise it is YourQuest.qst.backups/.
    • Include timestamps and ZC version numbers in backup filenames for easier identification and recovery.
    • Implement read-only protection to prevent accidentally saving over files loaded from a backup folder.
  • Add 'Open Tile Page' to RClick menu of Combo Pages 9c87349db4
  • Add 'Select' to combo page RClick menu 3d76567f96  

    On using "Select": - Your current Combo + CSet you are drawing with are changed to the rclicked combo - Your current Drawing Mode is changed to Normal - The active Combo Column will scroll to the selected combo - The combo page dialog closes itself (so you can go use the selected combo quickly) Useful to quickly start using a combo / section of combos via the pages interface.

  • "DMap Levels" quest report, lists which dmaps are tied to each level e1431cdf8b
  • Show screen state carryovers in 'What Links Here' tool f3ddd68ade
  • Typable searchbar in some old lister dialogs (ex. level palettes) 6faeae348f

ZScript

  • Allow mathematical range expressions [A,B) etc 61c5ccc923
  • Range loops (loop(int q : 0=..10))

      Relevant changes:

    • feat(zscript): range loops can contain variables in ranges/increment, and negative increments cb583e1c41
    • feat(zscript): range loops have '@NoOverflow()' annoation, docs ded10db593
  • Allow multiple comma-delimited increment statements in for loops ab8232c783
  • Allow enums of non-int pre-existing types (ex. long) 9ca034ea19
  • Add networking via websockets 41c3622a43  

    WebSockets allow for scripts to communicate with an external WebSocket server. This introduces an official way to use the network in ZScript.

    The following example script communicates to a freely hosted WebSocket server, which simply responds back with the messages it receives.

    To make your own WebSocket server, Python is a good option. Some example libraries:

     

    #include "std.zh"
    
    generic script WebSocketScript
    {
       void run()
       {
           printf("Connecting to websocket.\n");
           websocket ws = Game->LoadWebSocket("ws://ws.ifelse.io");
           ws->Own();
           bool hasSentMessage = false;
    
           while (true)
           {
               if (ws->State == WEBSOCKET_STATE_CONNECTING)
               {
                   Waitframe();
                   continue;
               }
               else if (ws->State == WEBSOCKET_STATE_CLOSED)
               {
                   char32 error[0];
                   ws->GetError(error);
                   printf("Failed to connect: %s\n", error);
                   break;
               }
    
               if (ws->State != WEBSOCKET_STATE_OPEN)
               {
                   printf("Failed to connect: %l\n", ws->State);
                   break;
               }
    
               if (!hasSentMessage)
               {
                   printf("Connected!\n");
                   ws->Send("hello world!");
                   ws->Send("domo arigato!", WEBSOCKET_MESSAGE_TYPE_BINARY);
                   hasSentMessage = true;
               }
    
               while (ws->HasMessage)
               {
                   int message_ptr = ws->Receive();
                   int type = ws->MessageType;
                   if (type == WEBSOCKET_MESSAGE_TYPE_TEXT)
                       printf("got text message: %s\n", message_ptr);
                   else if (type == WEBSOCKET_MESSAGE_TYPE_BINARY)
                   {
                       int len = SizeOfArray(message_ptr);
                       printf("got binary message of length: %d\n", len);
                       for (int i = 0; i < len; ++i)
                           printf("%d: %l\n", i, message_ptr[i]);
                   }
                   else
                       printf("got message, but with unknown type: %l\n", type);
               }
    
               Waitframe();
           }
       }
    }
  • 'atol' (string to long) 475cac6ce3
  • Add template types to some internal functions 633d754718  

    The following internal functions have switched from using untyped to template types:

    void ArrayPushBack(T[] arr, T val)
    void ArrayPushFront(T[] arr, T val)
    void ArrayPushAt(T[] arr, T val, int index)
    T ArrayPopBack(T[] arr)
    T ArrayPopFront(T[] arr)
    T ArrayPopAt(T[] arr)
    void ArrayCopy(T[] dest, T[] src)
    int SizeOfArray(T[] arr)
    void ResizeArray(T[] arr, int sz)
    void OwnArray(T[] arr)
    void DestroyArray(T[] arr)
    
    void printfa(str* format, T[] args)
    void sprintfa(str* buf, str* format, T[] args)
    
    T Min(T arg1, T arg2, ...T rest)
    T Max(T arg1, T arg2, ...T rest)
    T Choose(T arg1, ...T rest)

    This means that the type T must match other occurrences of T throughout the entire signature, given the types of the parameters used by the callsite. For example, this code no longer compiles:

    printfa("hello %d", 1) // Second param is not an array
    Object objects[] = {new Object()};
    ArrayPushBack(objects, 1) // Second param is not an Object
    int v = ArrayPopBack(objects) // Cannot convert Object to int

    Note: for now, SizeOfArray and ResizeArray still allow char32 for their array parameters, since that is common for string operations and we don't have a formal string type yet.

  • Add garbage collector for automatic memory management d4bc547f8e  

    Objects created by scripts are now automatically deleted when they are no longer reachable from any script.

    This removes needing to manually delete objects you create (either with the delete operator or Free()), and mostly removes any reason to ever call Own().

    See the new "Object Memory Management" section in ZScript_Additions.txt for further details.

  • Arrays now are separately typed from non-arrays cf2769fe95  

    Array types can be declared by adding [].

  • Option 'OLD_ARRAY_TYPECASTING' to use old array type handling d7555bf9e8
  • Add LEGACY_ARRAYS option as more lenient approach to array syntax caeb933574  

    This replaces the OLD_ARRAY_TYPECASTING option with LEGACY_ARRAYS. It can be set to on, off, or warn, and defaults to warn. This option supports usage of deprecated syntax for arrays. This will continue to work:

    int arr = {1, 2};
    Trace(arr[0]);
    
    • by default, this will warn that int[] arr is the preferred syntax
    • legacy arrays syntax is currently not allowed for objects that must be free'd, such as custom classes or bitmap (but, for example, lweapon is fine)

     

    Additionally but independent of this option, parameter types are cast to/from arrays when resolving a function call. There was an existing feature that selects the function that required the fewest type casts, and this taps into that. For example, this code works:

    void fnArray(int[] arr) {}
    void fnLegacyArray(int arr) {}
    
    ...
    
    int legacy_arr = {1};
    fnArray(arr); // arr is cast to int[]
    int arr = {1};
    fnLegacyArray(arr); // arr is cast to int
    
  • 'TileBlit' and 'ComboBlit', for drawing parts of tiles/combos c874bc20ed
  • Webapp for exploring and sharing ZScript ae2a67e77a  

    https://web.zquestclassic.com/zscript

  • Add bottle cure shield jinx flag (BTF_CURESHIELDJINX) 63d0dba0c5
  • Add Game->Exit(), which closes the program af90766952
  • Add base sprite class 9304859284  

    The following classes now all share a common base class:

    • eweapon
    • lweapon
    • ffc
    • itemsprite
    • npc
    • player

     

    All of these classes can now be assigned to variables of the type sprite. The sprite class contains 40 properties that were duplicated across these classes. Some properties do not work for all classes (like ffc and player), but more support may come later.

  • Show source code context with error messages fb4dbc83fe
  • Add RepairShield function to npc ef15f9019c
  • Support setting Hero->ScriptTile to draw larger than 1x1 7b8530979b  

    Internally, the Hero sprite resets its Extend property every frame, which prevented using ScriptTile in combination with TileWidth and TileHeight. Now, Extend is only reset if ScriptTile is not in use.

  • @Increment annotation for enums 43003ca8c0  

    Allows manually setting a value for the enum to increment by for each value

  • Add @Bitflags enum annotation c089b2af15  

    This annotation turns an enum into a bitflags enum:

    1. Auto-incrementing values starting at 1 and doubling the previous for each new enum member
    2. For type safety, bitwise operations on enum bitflags are only allowed with the same type

     

    For example:

    @Bitflags("int") // "long" is also supported
    enum SomeBitflags
    {
       Fast,
       Big,
       Loud,
    };
    
    @Bitflags("int")
    enum OtherBitflags
    {
       Combo,
       Enemy,
       Weapon,
    };
    
    auto x = Fast | Big; // inferred type is SomeBitflags
    if (x & Enemy) // Errors, scripter accidentally used the wrong enum.
       // ...
    
  • Add sprite::SpawnScreen c9fbd48d7b  

    This is the screen that the sprite spawned on. In a non-scrolling region, this is the same as Game->CurScreen.

  • Support expression in default parameters d2dd3eebf5  

    The default for optional parameters no longer need to be constant. For example, this is now valid:

    void debug(int num, int x = Player->X, int y = Player->Y - 10) {
       // draw num at x, y ...
    }
    
  • Support passing string / boolean to Trace de08c1eb39
  • Persist all reachable objects to save file 8cc79d2490  

    GlobalObject is no longer necessary to persist a custom object to save files. It is now enough to assign it to a global variable or array - as long as it uses the custom object type (rather than int or untyped).

    This includes all nested objects, and any object reachable from an object that was globalized via GlobalObject.

    https://discord.com/channels/876899628556091432/1377446615178281190

  • Screen->ComboData[] to directly read the combodata pointers of the positions on the screen a69021df5d
  • Support Game->LoadBitmapID(RT_*) 134545e1bf  

    The render target constants RT_* (except for RT_CURRENT) now work via Game->LoadBitmapID(). Also mostly all drawing functions now accept bitmaps loaded in this way as parameters.

  • Automatic array/string management; improved internal arrays 4b40449cc8  
    • arrays (which includes strings) are automatically freed by garbage collector when no longer used (if appropriately typed as an array)
    • removed constraints for local arrays (no more Temporary literals cannot be stored!). Can now return local arrays (and strings) from functions
    • internal arrays (like Screen->D[]) can be used like any other array: assign to another variable, get the length with SizeOfArray, use w/ for loops, etc.
    • arrays assigned to a global variable or otherwise reachable from a saved object always persist to the save file
    • references to internal arrays expire when their engine object is destroyed (ex, when a lweapon is destroyed, or when a new screen is loaded); they also don't persist to the sav file (will just load as NULL)
  • Enable JIT script compilation by default 9f80b3d303  

    This makes scripts much more efficient: between 2 - 10x.

    Note: windows 32-bit is not supported.

  • Customizable per-sprite gravity strength and terminal velocity dab1c5d406
  • Support negative indices for internal arrays fae2ad2be6  

    Some internal arrays would bound the index to force it to be valid, while others would instead error and give a default value. Now, indices are never bound, and instead if the index is negative it will "wrap around" to the end of the array, just like all other arrays do.

    Previous behavior is available behind a compat QR.

  • npc->Flags[] array to access more enemy flags 1a38b0065e
  • Add messagedata::Segments[] 036930bbca  

    This exposes to scripts the parsed message string, which includes commands and escaped characters.

  • Update WarpEx to not use weird array parameter 21390ba907
  • Add debug data line mappings to compiler output 9b2cfd68e4  

    With this, any trace or error from a script is now printed with a stack trace, showing what script file and line of code caused it.

  • Add rich debugger c7a2ccbb84  

    See https://docs.zquestclassic.com/zscript/lang/debugger/ for details.

  • Falsy-Coalescing (?:, ?:=) operator 4d0ea0fd73  

    a ?: b == a ? a : b a ?:= b == unless (a) a = b;

  • Audio->GetMusicData("Music Name") 49608e7420
  • ffc->ScreenFFCIndex 17708d545c
  • Access to '*weapon->PierceCount' fb65452a0b
  • subscreendata->Open() / subscreendata->Close() c6bed9186c  

    Directly open an active subscreen, or via this->Close() on an active subscreen script, close one. Equally works on map subscreens. Opening is delayed until the next moment the player could normally open the subscreen themselves.

  • Add FileSystem->LoadFile, document "mode" 11a3b8e3f1

Visual Studio Code Extension

  • Document symbol outline, hover tooltips and "Go to Definition" dbd473b97a  

    This patch greatly enhances the capabilities of the language extension. New features are:

    • A symbol outline of the current script, showing all variables, functions, classes, namespaces, etc.
    • Tooltips on hover, shown if a variable/class/whatever was declared with a comment. This supports markdown
    • "Go to Definition" to jump to where something is defined. You can right-click to see this option, or CTRL/CMD+click on something
  • Support @link tags in hover tooltips 1430272d25  

    Comments may contain inline links to other symbols with the @link tag:

    // Better than {@link counter2} ... {@link counter2|that counter is lame}
    int counter1;
    // This also works as shorthand for links: [counter1]
    int counter2;

    When hovering the mouse over any usage of counter1, the tooltip will render these as clickable links that navigate you to the specified symbol.

  • Support Go To Definition for type of variable declaration 32d372e647
  • Support Go To Definition for includes/imports dffa4cf41a
  • Support Go-To-Definition for enums c3ae6346b1
  • Support Go To Definition for function return type ea021739ac  

    Also support tooltip showing up when hovering over declarations.

  • Support 'Find all references' e15861fc0c  

    For now, this is only able to list all references within the current file.

  • Skip compiler codegen, not needed for extension 02786b32b5
  • Add contextual autocomplete and function signature help 4683653438  

    When typing, VS Code will now suggest relevant variables or functions. This suggestions are contextual, such that typing Screen-> will suggest only things on the Screen object.

    If a function is selected, its parameters will be suggested as a snippet for easier completion.

    Also new is 'function signature help', which allows pressing a keyboard shortcut (default is ctrl/cmd + shift + space) to display a tooltip that describes the parameters of the function under the text cursor.

  • Add document highlight 867e93e3be  

    When selecting a variable or function name, all instances within the current document that refer to the same symbol will be highlighted. Before, it would highlight everything with the same name, even if it was an unrelated variable in a different function / scope.

  • Scan all ZScript files in workspace 1418595b9b  

    This collects all code completion suggestions at start by eagerly processing every ZScript file found in the current workspace.

ZLauncher

  • Add options for window size, and cap max default window size 919bda1567  

    [ZLAUNCH] window_width, window_height in zcl.cfg

    Cap max default size to 2x

Web

  • First pass on wasm JIT backend for web 08254299cb  

    Adds a new backend to convert ZASM to WebAssembly. This also includes some utility methods for analyzing the structure (finding the functions) and control flow of a ZASM script, which was necessary to split ZASM scripts into multiple WebAssembly functions and implement the control flow of a ZASM script into WebAssembly structure control ops.

    Although prime.zs is ~10x faster, scripts from real quests aren't any faster than the normal ZASM interpreter, since a very naive and poorly performing method was used to transform the ZASM control flow graph.

    The utility methods for analyzing ZASM should be useful for improving the x64 backend too, for example, to similarly compile only one function at a time.

  • Support more ZASM ops for wasm JIT 53d5bc9a77
  • Support new SETCMP, GOTOCMP, CALLFUNC, RETURNFUNC ops in wasm 1c190a5a7b
  • Support loading quests from remote url d9d6a5ed42  

    See https://docs.zquestclassic.com/about/how-to-play#alternative-method-play-directly-in-the-browser

Bug Fixes

  • Fairy npc not despawning when picked up ea1be60e0e
  • zfix modulo operator being entirely wrong efe6125234
  • Changer ffcs counting for trigger groups and similar effects (they shouldn't) 7ce5862b67
  • ZScript docs were not being generated for release package a5a9bc81d1
  • Screen->Lit not compiling; now properly returns (and sets) screen's lit state 8f50a32f5a
  • Remove sfx limit (except for fuzz testing) 0c1de2949a
  • Initial path not being set for file dialog 1d08708c9c
  • Pushblocks ignoring the top half of combo solidity 09f9912980
  • Fire level triggers not counting as 'weapon' triggers 5f42bff76e  

    They didn't count for effects such as 'Kill Triggering Weapon'- they do now.

  • Prevent multiple potential crashes from bad string formatting b809aa2aa2
  • The counter percentage bar widget was drawing completely wrong rectangles caa206e9b8
  • Classic / cambria tilesets having a 'pop' in the 'Jump' sfx 7c81dd136b
  • Subscreen selector fitting to item hitboxes is now togglable via QR e7746505b3  

    Subscreen rule, not compat rule

  • Prevent crash from listers using too much memory 853a674810
  • Prevent crash when loading music with non-ascii filenames c6bf33d530
  • Compat issues with quests before 2.53 related to owning mcguffin items a2ea6e441a

Player

  • Cheats menu being greyed out when it shouldn't be b0db6567a3
  • Use more performant throttleFPS instead of rest in system menu 4c9ace43bf
  • Only assign save path just before actually writing to disk 17ba9ef42e
  • Prevent calling DMap script twice in scrolling DMap warp 6fc179786f
  • Not showing error dialogs in title screen, and unbreak -only switch 949bb6abee
  • Prevent failing to save after continue e2922a7d3b
  • Disable scripts that start with an unknown command 4aa4acd943
  • Check for null when printing ZASM command string arg 6c4d774c56
  • Improve function breakdown in structured ZASM 68259bbf46
  • Handle first command being function call for structured ZASM 69bbf846a2
  • Handle recursive function calls in ZASM cfg creation 1649a62e12
  • Detect dtors as separate functions in structured ZASM 08e17d01de
  • Remember last save slot position when returning to save select screen b05607e2e3
  • Re-optimize when JIT reuses scripts from last load f55cf241f4
  • Invalid optimization on broken SDDDD register d482c135b9
  • Disable propagate_values and dead_code passes for now cca0aaf0d6  

    These are likely to have a few edge cases remaining.

  • Do not stretch GUI ad7995cf15
  • Skip title screen if specific save slot is given 94f39f26e2
  • Actually stop mp3/ogg, and explicitly stop title music c3f7ec46fd  

    The titlescreen music would restart in the file select screen if the Sound dialog was opened then closed. This was because the volume was set to 0 to fade out, but it was never actually stopped.

    But also, due to a bug ogg and mp3 formats were really just "paused" when told to stop, so setting the volume afterwards would result in resuming music that was meant to be over.

  • Inline function optimization handles PEEK correctly a3d768e8f3
  • Various fixes to optimizer that broke crucible quest 47ca63d081  
    • ignore QUIT in inline opt
    • handle POPARGS in inline opt
    • add missing register dependencies for multiple commands
  • Inline function optimization handles PUSHARGSR correctly ffd3fe1fec
  • Various slope improvements, like fixing ffc slopes a93568375a
  • Save select screen not showing new hp after save->reset e91c347a89
  • Load default quest for sfx when loading replay 0586712dff  

    Quests before custom sfx rely on the default quest providing sfx, but that wasn't being loaded when playing back a replay. So it would either use whatever the last quest loaded, or have nothing, which was the case for the replay test script.

  • Bug in dead code optimizer when register is both read and written to 2ed2cd56dc
  • Passageways can have their own midi music 97a0c0130a
  • Shadows for rocks and boulders not drawing dc7454ec5d
  • Ensure enemy projectiles spawn at center of hitbox 3a60859a38
  • Ignore conveyors when rafting 5167be5988
  • Pushblocks with non-push flags placed on them were leaving trails of that flag fa2c337583
  • Layers not showing revealed secrets in map view 2502d11cd1
  • 'Platform' ffcs teleporting the player as the screen loads 364a014f7f
  • Game time shows in-game, even when you've 'cheated' 01614ff3cb
  • Inline function optimization handles LOAD correctly 0c8cc86242
  • Apply switch state when checking bordering screens 3967f0ebfc  

    For example, the smart scrolling feature which prevents scrolling when detecting solid combos on the next screen was not considering the state of level or global switches.

  • Subscreen 'Sys Colors' displaying entirely wrongly 226cc65c8f
  • Bottle flag 'Cure Shield Jinx' not working when used manually 35095ceae9
  • Issues with sideview "gravity falling" pushblocks b300fcd821
  • armos/graves not activating properly from Large Hitbox player 1b4fd9b507
  • Generic scripts wrongly stopping on F6->Continue ba4c6cdaff
  • Prevent rare case where sprite deletion is delayed a frame b727715fd4
  • Liquid combo passive damage logic 82d06203d9  

    If the required itemclass was set to 0, but the required level was set >0, would wrongly still require the item (when item class 0 should be (None) for this combo) Also, the hit sound was sometimes being ignored, and damage events were not being emitted.

  • 'Show Hitbox' cheat hitboxes being slightly misaligned cb6a74092a
  • Melee weapon hitboxes lingering forever based on 'Live One Extra Frame' rule 9c7185b098
  • Show cheat hitboxes for invisible enemies c3c6ac9384
  • Graphical errors in older quests 927154ee34  

    Many older quests were incorrectly drawing the player, held items, or some enemies and weapons over the subscreen.

    Regressed in 2.55 alpha 120 (93f25b690).

  • Prevent crash when combos trigger bbf9ecb0cb  

    Regressed in 2.55.13.

  • 0-damage brang/hshot items not obeying script-changed damage values 9eaa5f46c3  

    If a script changed the damage of the weapon but not the item, enemies who don't have "Damaged by Power 0 Weapons" checked would take the ITEM's damage amount rather than the WEAPON's. This also affected generic scripts changing the damage in an enemy hit event.

  • Stunned hero no longer stops dead in his tracks on ice f564449997  

    The ice momentum now continues while stunned (as though you were pressing no inputs)

  • 'slashable' combos (tall grass, etc) wrongly 'cutting' via triggers tab 6c94c88acd  

    Due to some old half-finished code, slashables were responding to all weapons set in their combo triggers tab, even with ->ComboType Effects not checked. This behavior has been fixed, now requiring ->ComboType Effects to trigger.

    Old quests loaded will automatically update any affected combos to behave as they did previously.

  • Hero sometimes drowning when drown QR is off fc19bb7b67
  • Newer Hero Movement buggy collision re: damage combos along the top of the screen 4a1cacf4a3  

    Hitting the corner of any solid horizontally was wrongly checking the TOP of the screen for damage combos.

  • Statue shooters / spintiles / etc not working properly with triggers 4a03ce9b26  

    triggers changing combos wasn't calling screen_combo_modify_preroutine()/postroutine()

  • Spinning Tiles not becoming the next combo df08eff634  

    No idea when this initially "broke", or if it ever worked at all, but the help text says it is supposed to, so fixed it with a compat rule.

  • Prevent soft-lock in whirlwind over water 4a7e6da589  

    This regressed in 2.55.13 (b27da2ea2).

Editor

  • Missing rclick menu separators 1b0b0341c4
  • Test init data not being applied correctly c599dfc30d
  • Handle quest path/title with spaces in package export 11b09ef8c7
  • Handle error instead of crashing if package export fails e26e02c9e6
  • 'Notes' and 'Browse Notes' not having menu buttons 5c338087d8
  • Upgrade tile 'move' code, more things now update on moving tiles 5c29d6f4e6
  • Upgrade combo 'move' code, more things now update on moving combos, add Combo overwrite warnings e8d903186f
  • Crash on moving combos in quests with many maps/screens 80af019ef4
  • Improve efficiency of combo moving + fix crash + fix 'undo' combo move 4efe6b07df
  • Improve efficiency of tile moving + fix 'undo' tile move 7b26369e09
  • Memory issue when moving/inserting tiles/combos 3c72e37128
  • Arrow buttons above combo columns sometimes not working properly 1af434da4a
  • 3-stair warp dialog not properly listing catchall purpose 6ab8d137e9
  • Buffer overflow in info editor dialog 63b6cb23f3
  • Reduce latency on combo page paste when ComboProtection is off 5fd5fa503e
  • Prevent crash when assigning global scripts 143e6836c6
  • Delete the initial screen from default.qst 3b7ed5186d
  • Prevent another crash when assigning global init script aa28815b4e
  • Draw eyeball combos correctly in compact mode and when zoomed out 3f8e849e8d
  • Add latest fields to .znpc for enemy save/load 0f15969f6c
  • Fix tile protection for darknut, gleeok, ganon, and patra enemies 74e0347de2
  • Combo editor triggers -> Level Palette now has hex/decimal swapping button dc8d75038c
  • Aliases with layers set not placing correctly when zoomed out 83d31d5a54
  • Holding 'shift' after already starting to drag an ffc/warpsquare/etc not changing to more granular control 50678480ce
  • Subscreen TileBlock Wizard not saving Width/Height values properly c8eeddfdf4
  • Prevent long label from visually breaking combo editor 5a186fb2a9
  • Don't show compat QR confirmation when creating new quest 79b59ca0f8  

    When creating a new quest from an older tileset, don't show a confusing confirmation dialog about disabling compat QRs. It won't hurt a new quest to disable these QRs, and this dialog is likely to confuse new users.

  • Prevent screen palette truncating to byte (0xFF) ab607a9fe2
  • Show correct combos from adjacent screens 45ac1ee719  

    When the screen editor displays combos from adjacent screens, it was randomly showing the wrong combos.

    Regressed in 2.55 alpha 109 (be515839b).

  • Visual bug with Lister dialog preview size f318313547
  • Naming of tile variables in enemy lister info 0eb511287d
  • Set CSet to 2 when loading new quest e587bafe06

ZScript Standard Library (std.zh)

  • Clean up some missing function returns ef52113252
  • Use template for Cond to support arrays af4293cd68  

    Also deprecate and suggest using ternary expressions.

  • Set MAX_DEFENSE to correct value 60645cedc1  

    It should be 41, but it was 42.

ZScript

  • Errors related to breaks in infinite loops ccf9959570
  • Issue with global variables sometimes not initializing properly 8721621154
  • Label error bug with while(true) and 'break;' bfef7fd445
  • Case-range backwards check b3fb9bc308
  • Missed handling arrays for unused var trimming 8d2ddc6f90
  • Clear script data when reassigning script 03ce2a4f66  

    Previously, only FFCs properly reset their state when changing their script. All others would retain their state, so would instantly do all the wrong things.

  • Exit with correct status for JIT on QUIT 3a48a0aea4
  • Consider PEEK when finding function calls for structured ZASM c45c5f5e7d  

    The structured ZASM builder assumed all function calls are followed by POP D4 in older scripts. However, if POP D4 is followed by PUSH D4 then the compiler replaces it with PEEK D4. This oversight missed these function calls, which broke the JIT compiler and ZASM optimizations for newer 2.55 compiled scripts.

  • Use correct config section for optimize_zasm 694d589f6f  

    The base config was using the wrong value, so it was still always on.

  • Handle WAITX not actually yielding in JIT compilers 6e95932c2f  

    WAITFRAMESR D2 does nothing when D2 is 0, but the JIT compilers assume all wait commands should yield. Now they check if waiting actually occurs.

  • X64 JIT compiles STACKWRITEAT correctly 5f8f9d1246
  • Invalid compiler output from removing unused variables d8123f886f  

    The compiler has a pass to remove unused variables from taking up a position on the stack. However, a logic error made it so the wrong scopes would have their stack variables repositioned, which resulted in multiple variables sharing the same stack position, and breaking the script.

  • Parser bad optimization edge-case 978ab1b634
  • Parser failing to properly initialize some variables b93b1e2249
  • Bad optimization causing global vars to sometimes read incorrectly b000fc9e2f
  • Socket arrays sometimes going invalid? 12e3b9a92a  

    Patched the issue here, not the cause. Not sure what caused it to sometimes go invalid, but a validity check seems sane.

  • Derive language runtime version from compiled scripts a772dd8734  

    The script engine checks the version a script was compiled in to vary some behavior. Previously this version was set to the section version in the qst file format, but that is updated even if scripts were not re-compiled. Now we look directly at the script metadata to set this version. This avoids issues with saving a quest in a new version without a recompile.

  • Don't only show singular deprecation warnings 88898e22f2
  • Handle non-global objects correctly when reloading game f93172d335
  • Allow simple types to match a template array type, for now 08756b8cb1
  • Hero->Warp() using current screen's warp return square value 1f010f2d65
  • Stack offset issue when 'return'ing inside a 'loop()' dc6c35037e
  • Not correctly removing stale pointers on reload 4bd0e54125
  • Exit process when preprocessor recursion limit is reached 58aaefd3a3
  • Object fields not being available in dtor 7feb9afdda  

    This regressed because of the recent GC changes.

  • Compiler crashing on for-each loops b00f59aadb  

    This regressed because of the recent error locations refactor.

  • Some bindings ZASM using wrong literal values 975cf9c604
  • loop()s not having location metadata associated with their identifier 68a5f70c82
  • 'hero' and 'link' script types not compiling 4ce3a21862
  • Code gen for range loop using wrong op 2133615649
  • OwnArray() not working properly at all d706df9038
  • Code blocks sometimes not removing object references 2413e5ed84
  • Crash from metadata of var inside if statement 54cb5c3ac6
  • Continue generating editor metadata after (most) compile errors 3d5912f157
  • Generate metadata for code even if optimized away 8defe2955b
  • Scope error when using for (...){} else {} f43e469073
  • Prevent bogus "invalid object pointer" caused by uninitialized memory 9db7d34032
  • Remove a bunch of unnecessary zprints 1e1000c99f
  • Make npcdata->Flags a bool array, remove ->Flags2 ec60344a6b  

    npcdata->Flags and npcdata->Flags2 are undocumented and broken tools for accessing the internal flag of npcdata. They tried to split 64 possible flags over two integer values, but since they aren't "long" ints it didn't work. It is now a bool array.

  • Pop parameters for internal functions in fewer commands 2ea65eef2d
  • Typo in Region->GetScreenForComboPos 93238598d4
  • For-each loop compile issue when iterating over 'const' arrays a7945bb456
  • Game->GameOverScreen[]/Gam->GameOverStrings[] not compiling in 3.0 4f80edc073
  • Deprecation warnings for functions not giving 'INFO:' text 4a89897b67
  • Prevent crash when processing for-loop metadata 235ad808bf
  • Use lexical scoping for namespace compiler options 215607727e  

    Previously, namespaces would ignore options defined in the file scope. Also, options defined in one namespace block would be applied to every namespace block of the same name.

    See https://discord.com/channels/876899628556091432/1243749050616905768.

  • Internal bitmaps from Game->LoadBitmapID() now work with Blit 7787176771
  • Screen->DrawLight functions now respect Screen->DrawOrigin ae5a36c6a7  

    These functions did not add the playing field offset, like other draw functions do. Now they respect Screen->DrawOrigin, and use SPLAYER_DARKROOM_UNDER for the draw timing.

    Old behavior is behind the compat QR Scripts Screen->DrawLight Functions Have No Offset.

  • Use correct id for eweapon::TotalDYOffset 9fb331c9d9
  • Suspending ffc scripts no longer suspends screen scripts 723d6e040d
  • For JIT, prevent running script from changing itself e17575e4a2  

    It's forbidden for a script to directly change its own Script variable, but when JIT is enabled that check was missing and the result was a crash.

  • Produce correct codegen for objects with default constructors 99a548a524  

    Creating an custom object inside another's constructor generate incorrect code when the second class has a default (or empty) constructor.

    For example, this code would error and not set the b variable on f.

    class foo
    {
       bar b;
       foo()
       {
           b = new bar();
       }
    }
    
    class bar
    {
       bar()
       {
       }
    }
    
    foo f = new foo();
    
  • Make owned objects live as long as the sprite owner 104fc490ea  

    The Own functions on sprite objects (npc, ffc, itemsprite, weapons) are documented as assigning the object's owner to the sprite. However, they were actually being "owned" by the sprite's script, so in the case where a script ends before a sprite is destroyed, the object lost its owner a little earlier than expected.

  • Game->LevelStates[] and Game->GlobalStates[] actually toggle switches on-screen c0df8c0d90
  • Return invalid mapdata when Game->LoadTempScreen, etc. fail 2d76d115cd  

    These methods were actually returning the first canonical (id 0) when the input is out-of-bounds. Now, they return an invalid mapdata.

  • Log error if file fails to open 15c711a2cf
  • Prevent compiler crash when parsing long decimals ab12873514  

    In some places, the compiler would crash if parsing a number with more than 4 decimal positions.

  • npcdata->InitD[] / WeaponInitD[] being *10000 4541c666fa
  • Class destructors failing to run fully when calling user functions 33c22418fc
  • Some included headers using bad DrawCombo frame parameter 93f6ace5a7  

    this fixes combo draws not animating properly in ghost, tango, and EmilyMisc.zh

  • Add newlines missing in some error messages dc8ee68c9c
  • Update door combos when writing to mapdata::Door b6f369d2e7
  • Add getters for ffc::LastChangerX and ffc::LastChangerY de854f2a55

Visual Studio Code Extension

  • Character literals not highlighting properly 5dc7bd7c0e
  • 'AlwaysRunEndpoint' annotation missing syntax highlighting b5b8ef720c
  • 'loop' keyword missing highlighting, add range operators to operator list df11ee40f1
  • Invalid uri on windows for links in hover tooltip 179d55946c
  • Increase max buffer size for ZScript process, which was breaking editor for large scripts 2169c67a36
  • Show error message when default include file does not exist d19b885857
  • Correctly highlight half-open ranges 2d876df1a2

Web

  • Improve sfx on title screen by yielding during quest load 424f6200c2
  • Handle reaching end of script in wasm JIT eb3dc8a7a0
  • Handle CMP_BOOL in JIT wasm 35fc59b6b3
  • Skip titlescreen for quick open links 840e2ef7b2
  • Disable broken parallel processing for ZASM opt cc0518ae6d
  • Avoid performance hit by disabling info bitmap 2a6812a96b
  • Packaged quests not loading correctly 49b71a2a1f
  • Disable text selection in Safari dd4d5a5cce
  • Prevent hang when attached folder is deleted f155adeff9
  • List default controls relevant to detected keyboard layout c48d4f2fe4
  • Prevent backspace randomly inserting characters 0cb58f500b

Documentation

  • Create https://docs.zquestclassic.com ce839d1e8d  

    This is a new website for documentation. It's currently mostly just reference docs for ZScript, but soon it will also have tutorials and documentation for the editor.

  • Add SCC tutorial a731f1d2c0
  • Remove ghost, tango doc sites from release package 5fd2ed7ce1
  • Remove zasm_registers.txt from release package 63984595c8
  • Add new ZScript language documentation e1cfeefd1a
  • Update docs related to generic script events d517ebf642
  • Mention loading functions at header of each class 9d3693b6a5  

    no notes were added mentioning class constructors, as they simply are in the constructors list already.

  • Document values for Game->GlobalStates[] 0e40c8fc18
  • Add "Using a tileset" tutorial 3cdbbe32f4

Build

  • Include logo and title assets in web data file 9e4f5313f5
  • Add default file for compiler "signature" d53db7b6f1  

    This is to make the build just work in a clean checkout until I get around to removing this pointless thing altogether.

  • Fix typo in building.md for cmake version aa460db5ab
  • Use better library for json

      Relevant changes:

    • ci: update to macos-13 in other places too 6bb570d372
  • Update fmtlib to 10.2.1 11b834b35e
  • Update building.md for Linux f00d2f0ace
  • Pin poolSTL dependency to specific commit 1a347f264b
  • Fix gcc compilation issues 7cfee7439c
  • Only depend on .git/refs/tags if present bd8e3c8f53
  • [linux] do not disable allegro5 png, which broke the title screen logo c0553e6a98
  • Update fmtlib to 11.2.0 d808c0b5ef
  • Add WANT_NFD cmake option 4b75a51c00
  • Enable unused parameters diagnostic as error 7aeeb0e47a
  • Upgrade sentry to 0.13.8 e57dff45d7

Web

Refactors

  • Menus (new sleeker look, much cleaner backend) 03339654bb
  • Share common allegro app setup 05eb72d5b6
  • Load text files more efficiently 0964f74814
  • Remove scary and now pointless warnings when toggling fullscreen 75f9d356a1
  • Use enums instead of defines for many flag values 806180beab
  • Combine misc attributes for guys into array 4e949df181
  • Use vector for storing FFCs c1273e1491  

    Previously, every screen allocated memory to hold the maximum number of FFCs (2.55 alpha 112 bumped this from 32 to 128), which took ~43 KB per screen, even if no FFCs were used. Now screens only allocate as many FFCs as they need.

    For a quest that uses no FFCs at all, this saves ~5 MB of memory per map. For Yuurand, total memory usage on startup went from 1.3 GB to 800 MB.

  • Consistently use "Hero" instead of "Player" to refer to the playable character 3e3989cdb5
  • Move Hero extern to header ef61b61363
  • Move particles extern to header 92136e1c93
  • Remove module system (zinfo has replaced it) 3f0f249761
  • Rewrite string message parsing and renderer 71b272aee9  
    • Completely rewrite the string message parser / renderer - this will make it possible to add more advanced SCC features in the future.
    • Executing a SCC no longer takes a frame per command.
    • Use the same code for parsing a message string in the player and in the editor - this fixes a handful of differences w/ word wrapping that the player handled poorly.

     

    https://discord.com/channels/876899628556091432/1277878877057978460

  • Improve syntax and encoding of message strings 8c038be724  

    Message strings now use an improved syntax that is more readable, supports negative arguments, and is less error prone.

    Previous:

    It's dangerous to go alone! \1\2\3Take this!

    New:

    It's dangerous to go alone! \TextColor\2\3\ Take this!

    Additionally, message strings no longer use a binary encoding to store SCCs, but instead now use plain ASCII. Scripts that require the old binary encoding should use the compat QR.

    See https://docs.zquestclassic.com/tutorials/message_strings for more.

  • Update old getnumber dialogs b418222d8d
  • Create display window in consistent manner for every app ec4f1e0973
  • [mac] unify F-keys for reset/quit 17d76f12b6  

    Previously on Mac, reset/quit were mapped to different keys than on other platforms because historically F9/10 were reserved by the OS. However, that is no longer the case on modern Macs.

    These function keys on Mac now match other platforms:

    • Reset is now F9 (was F7)
    • Quit is now F10 (was F8)
    • Screensaver and Palette Toggle have been moved back to F7 and F8, respectively
  • Speed up subscreen draws by simplifying string operations ec323637f7

Player

  • Add null JIT backend ec0a84ab43
  • Move debug ZASM writing to new -extract-ZASM command 847ab88e96  

    This allows for all scripts in a qst to be written to disk, instead of only the ones that happen to execute.

  • Use common structured ZASM utilities in jit_x64.cpp c40c79a067
  • Simplify how structured ZASM finds functions 46bc924eda
  • Split some ZASM opts into separate script-level pass 3f4f964dcd
  • Assume modern function calls in ZASM optimization passes e260ce752e
  • Move get_register_dependencies to zasm_table.cpp 13b6a599c6
  • Remove music buffer setting 572f445148  

    This only applied to it/xm/s3m/mod music. There's no need to expose this to users. Instead, always use 128KB as a buffer size.

  • Add get_command_implicit_dependencies in zasm_table.cpp 9e4a41e07f
  • Add get_register_ref_dependency in zasm_table.cpp ced4dbad84  

    Also run propagate_values after the comparison opt passes, as it was accidentally skipping some optimizations due to the comparisons passes assuming D2 is being compared.

  • Simplify ZASM simulation and always simulate stack 37d86217db
  • Optimize ZASM scripts in parallel 9ae7f4e860
  • Improve handling of bugged SDDDD by fixing it, instead of deopting df037da33f
  • Reduce duplicated code for trigger conditionals

      Relevant changes:

    • refactor(zc): reduce duplicated code for trigger results f20ddc1b49
  • Clean up jinx handling cfe48cd7b0
  • Deduplicate enemy code reading of SIZEflags 92bb2cc6ad
  • Remove old movement functions c5b8a0e17d
  • Use transulency table cache for all fade/lighting 284fc7567d
  • Turn off replay_debug by default 8629e181d7  

    This makes replay files significantly smaller by disabling debug mode, which stores a hash for every graphics frame in the replay file. This is no longer needed for replays recorded by players so it's time to disable it.

Editor

  • Clean up Tile/Side/Ring warp dialogs 2637fc6ace
  • Re-organize the combo editor 'Triggers' tab 53310a2541
  • Redesign enemy editor using new GUI e335517596
  • Upgrade enemy editor's enemy selector to new GUI b7e767fd40
  • Remove the Misc[] dialog as it was unused 49c6f2e4f9
  • Upgrade screen enemy selector to new GUI 54498fae33
  • Upgrade midi editor to new GUI e472b5f1a0
  • Upgrade sfx editor to new GUI ccdde8a650
  • Upgrade map styles editor to new GUI 031767ec0e
  • In enemy editor, read defense names from zinfo 8cde41f2ec
  • Remove classic_zquest.dat, load assets from new assets/editor folder 5551216eb2
  • Clean up Quest->Audio->MIDIs lister c4a6d8b720  

    Empty MIDIs now show as zzUntitled, to help support alphabetized sorting.

  • Rename Fire Levels to Burning in combo triggers tab d454c4abe0
  • Upgrade sprite data list dialog 383b5d34a6
  • Hero editor now uses zcgui 9fa5643029
  • Redesign ffc editor fdd6917e77
  • Format map, screen locations more consistently d653e722b4  
    • Format map + screen pairs using a common format: decimal for map, hex with a 0x prefix for screen, and spaces for legibility. Example: 19 : 0x5A.
    • Fix an issue in quest report tools that incorrectly used hex to format the map component.

ZScript Standard Library (std.zh)

  • Remove instances of deprecated functions 331bbd4e39
  • Make every std file compile individually 6de1bb98b4
  • Move some constants from std to bindings, and add more doc comments 45d9718e1e

ZScript

  • Internal function aliases, internal constexpr functions 17e03bc814
  • Use alias name in comments, update expected ZScript b0af4b4b83
  • Reserve 'constexpr' token 0cb3519ea3
  • Clean up ScriptEngineData for all script types 584bea1321
  • Clean up generic script indexing a27241f734
  • Optimize bool ops a lot c8fae535d2
  • optimize sections of zasm that are run only for their side-effects d253cbb843
  • Clean up getStackOffset(Datum) code 3cdf73853f
  • Label opcode register args as R/W/RW/unused 40e805b559
  • Label some opcode properties with flags c11ec71723
  • Use common UserDataContainer for most user data ba6e421d92
  • Standardize script object management be20f347b6  

    This keeps script-created objects in the same map, gives all objects a unique id, and implements allocation and retrieval for any object type using the same methods. This reduces some duplicated code, and should help with implementation of a potential garbage collector feature.

    Bitmap objects are a bit special, and still need to be refactored.

  • Migrate user_bitmap to script object system 68329daf9f  

    Incidently, this increases the maximum number of user bitmaps to 256.

  • Move ZASM table and serialization to shared lib c483f611c8
  • Remove separate ZASM defines for compiler bcd0795391
  • Improve location of many error messages 52949459f6
  • Move internal symbols to new binding .zh files 011539980b  

    Internal symbols were defined in .cpp files, but now they are defined in .zs files with a new internal keyword and @ZASM doc comments. These files live in bindings, and are automatically included for every compilation.

    This should simplify the process of adding new internal symbols. It also enables viewing documentation of any internal symbol in the VS Code extension (w/ a hover tooltip), and all the documentation we have for internal functions and variables has been inserted as comments in the binding files.

    This also deprecates functions that create an object of internal types, like Game->CreateBitmap(width, height) - and replaces with normal constructors - new bitmap(width, height).

  • Remove library symbol cpp files 76a67b3714
  • Remove internal class type b760782751
  • Array literals better deduce their element types 3717da2936
  • Type-safe opcode classes and use ZASM table for stringification 75dc4d745e
  • Separate ZASM code from script data 75f981f571
  • Make all command strings match enum name 08e0c08e56  

    This normalizes all the string names for commands to be the same as the enum name used in code, and rewrites get_script_command to be an explicit mapping of this string representation and the enum value. These not matching was confusing, and was a potential source of future bugs.

  • Remove unused features from ZScriptArray c09b581332  

    Various things are just a wrapper around what std::vector does, and we don't need dimensions, a template, or a custom iterator.

  • Remove duplicated function deallocateZScriptArray d061e3c552
  • Add -json switch to parser, use stderr for logging 3be9b16e8a
  • Add errors and warnings to json output as diagnostics 6ae06e15d7
  • Improve validation of file paths 0480ad0349  
    • .. is now allowed in paths, as long as it doesn't reach above the quest's "Files" folder
    • more specific error messages when path is invalid
    • check for illegal filenames
    • general clean up of path validation code
  • Remove Game->Misc,Misc2,Misc3,STD,Ghost,Tango arrays 5c64321ee1  

    These have been removed from ZScript. Additionally their implementations are removed too, since no quests ever used them.

  • Remove unused getters/setters from npcdata a7fbbb5cc2
  • Simplify ltou, utol and convcase 7aabd90782  

    These functions returned false if the string given is empty. That's not useful, so now they longer return anything.

  • Remove unnecessary Debug-> "typecast" functions 18c2b4c49e
  • Remove many unused Game-> functions 7948da864c  

    All of the following functions were found to not be used in any published quests or scripts. Since they have all been deprecated (via Screen-> or mapadata), they have been removed.

    • GetScreenEnemy
    • SetScreenEnemy
    • GetScreenDoor
    • SetScreenDoor
    • SetScreenGuy
    • GetScreenGuy
    • SetScreenString
    • GetScreenString
    • SetScreenRoomType
    • GetScreenRoomType
    • SetScreenEntryX
    • GetScreenEntryX
    • SetScreenEntryY
    • GetScreenEntryY
    • SetScreenItem
    • GetScreenItem
    • SetScreenUndercombo
    • GetScreenUndercombo
    • SetScreenUnderCSet
    • GetScreenUnderCSet
    • SetScreenCatchall
    • GetScreenCatchall
    • SetScreenLayerOpacity
    • GetScreenLayerOpacity
    • SetScreenSecretCombo
    • GetScreenSecretCombo
    • SetScreenSecretCSet
    • GetScreenSecretCSet
    • SetScreenSecretFlag
    • GetScreenSecretFlag
    • SetScreenLayerMap
    • GetScreenLayerMap
    • SetScreenLayerScreen
    • GetScreenLayerScreen
    • SetScreenPath
    • GetScreenPath
    • SetScreenWarpReturnX
    • GetScreenWarpReturnX
    • SetScreenWarpReturnY
    • GetScreenWarpReturnY
    • GetScreenEFlags
  • Improve placement of errors/warnings on function calls 9eedc19110  

    Errors/warnings from using unknown or deprecated functions now attach to the function name, rather than the entire call expression.

  • Remove A registers 2c8e6a1ecd  

    The "A" registers are two old registers that were never used in any quests. The only way to access them in recent builds has been the FFC GetFFCInitA / SetFFCInitA, but no published quest has ever used them.

    Now the ffc and item editors no longer display these two "A" register fields, and internally many other things handling these registers have been deleted.

  • Make ComboAt internal as an optimization 777571531c
  • Tidy up std, move many enum/constants to bindings 45b9f17949  

    Many constants are now named enums, and moved from std to binding files (which are imported automatically). This allows these values to be used with internal bindings (like Game->) without importing std; and improves documentation by giving everything a reference-able name.

    Also did a large general clean up of documentation comments, and made sure every internal function/variable documents what enum applies to it.

    Removed many unused or unimplemented features.

  • Remove HEADER_GUARD (allow and ignore duplicate imports) 626c877724
  • Prevent parsing same files multiple times 20885219b6  

    Before, every import would parse the file it included. Now, a cache is used so every file is only parsed once. This reduces compiler times (for example: compiling the binding files went from ~300ms to ~200ms).

  • Remove WarpReturnC 0f4e5290cb
  • Deprecate WrapAngle (use WrapRadians instead) 786f3b248d
  • Emit shared ZASM for scripts 51ec0e0a51  

    Previously each compiled script resulted in a separate chunk of ZASM for just the code it used. This resulted in large amounts of duplicated ZASM instructions across all scripts. Now, the ZScript compiler uses the same chunk of ZASM for all scripts.

    Compiling Yuurand's scripts went from 4m ZASM commands to 1.87m.

  • Remove separate "script UID" for sprites 02028b2077  

    Every sprite object has an internal engine ID, but for some scripting features a separate "script UID" was used. Features such as ->HitBy, ->ParentUID used this - and Screen->LoadNPCByUID (etc.) existed to translate to the actual engine ID. These are relevant to eweapon, lweapon and npc sprites.

    Now, all these features just use the engine ID, and "script UID" is no longer a separate thing.

  • Print context alongside script runtime errors b7829c0f8e  

    When a script does something that results in an error, a message is logged to the console that usually mentions the ZScript source variable or function where the problem occurred. This was usually right, but sometimes would mention the wrong thing.

    Some automation is added to more consistently print the correct variable or function name when encountering an error. In addition, potentially multiple bits of context may now print alongside error messages (one or all of: function, variable, or the name of a specific parameter).

  • Remove almost all of Debug-> 418b016fab  

    The only useful thing here is Debug->Testing, which is now deprecated in favor of the newly added Game->Testing.

  • Use common abstraction for arrays df3ce2079c  

    Built-in arrays (such as Screen->State[]) are now implemented using a new shared abstraction.

    • improves maintainability of arrays
    • consistent application of index/value bounds (this was often wrong and many issues are now resolved)
    • enables new features in the future (such as iterating built-in arrays)

     

    https://discord.com/channels/876899628556091432/1382495697907093574

  • Simplify ownership of JIT script handles e44642dc36
  • Improve stack overflow error behavior dcac26d531  

    Previously, if a script used too many stack variables (typically by doing lots of recursion), the engine would (sometimes) emit a warning, "wrap around" the stack pointer, and continue executing the script. However, that results in very buggy and random behavior, and is never recoverable.

    Now when the stack overflows, the script is stopped.

  • Increase stack from 1 KB to 5 KB b118e9fc1a
  • Limit max nested function calls to 1024 37a0a4f13c
  • Soft-deprecate some duplicate variables 00f762a12e  

    Some variables access the same data. All but one of these are now soft-deprecated (compiler won't complain, but docs will suggest not using them).

    • deprecate npc/npcdata/itemsprite/itemdata Family (prefer Type)
    • deprecate lweapon/eweapon ID and Family (prefer Type)
  • For x64 JIT, compile each function separately daa1161618  

    Instead of compiling the entire ZASM chunk at once, compile only one function at a time, and only the "hot" ones. This greatly reduces the amount of memory needed to compile scripts, and does not waste any time compiling unused code.

  • Always return 0 for out-of-bounds access for internal arrays e323678cb3  

    Some internal arrays would return non-zero values if the index used was invalid. Now, all return zero.

    Previous behavior is available behind a compat QR.

  • For x64 JIT, use smarter register allocation 68087da593  

    Instead of reading / writing to memory within every command, the x64 JIT compiler now attempts to keep values used across multiple commands cached in registers, only writing back to memory when necessary.

    This makes the compiled code ~40% faster, and makes compilation take ~44% less time.

  • Move Own functions to base sprite class bfb37ca568
  • Deprecate QuitNoKill 32dbbc501b
  • Remove unused "ignore/catch" compiler directive fc12c12651
  • Remove multiple compat compiler settings 725b3f3a33  

    The following compat compiler settings have been removed in order to simplify the compiler. They don't seem to be necessary to support any popular scripts, and sometimes resulted in bugs when users inadvertently had them enabled.

    • 2.50 division truncation
    • 2.50 value for 'true' is 0.0001
    • Binary operations use true 32-bit int
    • True MAX_INT sizing (smaller max int sizes no longer supported)
    • Short-circuit boolean operations (non-short circuiting no longer supported)
  • repeat(N) now acts like loop(0=..N) 1ec6f924f2
  • Change Screen/mapdata->Tile/SideWarpType[] to enum type 8e6839aeab  

    This will require using the correct constants to assign to these, but also will make them return the correct type for use with ex. WarpEx()

Visual Studio Code Extension

  • Use new -json ZScript option for diagnostics 1143e74802
  • Improve symbol id generation used for metadata 175bf49720
  • Add job pool, improve script processing 6e70798b29

ZUpdater

  • Disable on mac, linux. remove python dependency 6db84e95dc

Tests

  • Save replay result file when starting replay cb2e4b0d37
  • Fix get_recent_release_tag method 3b24464b14
  • Update 'armos.zs' expected ZASM 8ccc152f66
  • Extract snapshot testing code to base class d9d839b21e
  • Add snapshot tests for x64 JIT 07a6ef7137
  • Fail replay test if JIT cannot compile a script 1bf248ab2a
  • Fail on abort in web replay tests 2b643c358e
  • Stop on fatal errors in run_web_version.js bafc72ebae
  • Fix test_jit.py not looking in the right folder anymore 44227cd6e3
  • Add "frames" and "length" meta fields to zplay 93e77ddf79
  • Use "latest" version for all playground.qst replays 3c80d24394  

    These replays should be trivial to update as needed, and using no replay compat code makes them far more useful for verifying specific features.

  • Add test_optimize_zasm.py and update_snapshots.py 6b8053c89f
  • Move snapshot files to common folder 47eb8e7451
  • Hash JIT output for all but playground.qst 8a28eff6bb
  • Add scripts/run_for_every_qst.py, for running a command against every qst in the database 0eb93f48d2
  • Add replay test for class ctor/dtor 57c8cc5e1a
  • Fix different outputs for JIT snapshots 179f968587
  • Define calling convention for JIT regression tests 03e3f08718
  • Add playground_exstate.zplay and playground_large_animations.zplay d61aeb1bc3
  • Add crucible_quest.zplay 5dd7d4c231
  • Add combo_rotator.zplay 543bcfb5ff  

    This is the first of more planned script replay tests, which along with the playground.qst replays will be re-compiled with the latest ZScript in CI and their replays re-verified. Should result in better test coverage for newer compiler features.

  • Fix crucible_quest.zplay from recent slope refactor 3a3dba0d00
  • Make the editor File->New test do what it says it does 3314b4ef0b
  • Use original qst for combo rotator replay b093e59c68
  • Update crucible_quest.zplay for 5732b53 798646bc47
  • Add local web app for running replay tests bd16f16e03
  • Move build archive operations to archive.py 144ec7f337  

    This greatly cleans up bisect_builds.py, which was doing a lot. Now a new tool scripts/archive.py is responsible for downloading any build - or building from source, as needed.

  • Avoid enumerating s3 bucket just to download single version e1b37622be
  • Use new archive download for run_replay_tests.py f2eaaf7ec7  

    This removes the old download flow that required a github api key to get a baseline build for a compare report.

  • Move github related functions to github_helpers.py deb47752d3
  • Use requirements.txt for python deps 61941b504c
  • Extract core replay runner to replays.py a2ab3ac30a
  • Format Python using Black c54f261959
  • Sort Python imports using isort 2cabfdb7c0
  • Update expected ZASM from recent changes ed025a9724
  • Refactor how known replay failures are handled 85f745323c
  • Import Path directly 2fd2403216
  • Remove solid.zplay 2b3acd7420
  • Add playground_bitmap_credits.zplay d6b398ad43
  • Make some test scripts emit no warnings 6720fc50e9
  • Update test scripts for new array syntax 873e7ecd64
  • Add item_spawns_cloud.zplay 0ab66ae79b
  • Add crucible_quest_short_1.zplay f7650745d9
  • Add snapshot test for compiling the ZScript database 46e71c1d8f
  • Use truecolor bitmap for gfx frame hash bd2cf5c9be
  • Add "auto" script tests; reorganize and document playground quest 99a867ad32
  • Add SCC replay test cfe187b588
  • Add scripts/replay_uploads.py for downloading and running uploaded replays 49b3d60e07
  • Add Database class to nicely automate downloading the database for local use 3af230f63f
  • Add terror_of_necromancy_demo5.qst replays 4d652888b6

Visual Studio Code Extension

  • Add tests for 2.55 and 3.0 c9334a3811  

    Also:

    • On Mac, can now use path to .app bundle as installation folder
    • For 2.55, fix bug where parser errors underlined the entire line

Misc.

  • Ignore fixup commits in git hook 6447981462
  • Use better examples for commit messages 46af4f0af8
  • Version refactor b49ae14d62  

    Switch from "alpha/beta/gamma/final" to simpler "stable/nightly" versioning, and adopt a semver-like version string. See docs/versioning.md for more.

    Also, greatly automate the version bumping process. Simply select stable or nightly in GitHub action, and release scripts handle selecting the next version number accordingly.

  • Link to website in generated changelog c72db74777
  • Use correct .sav path for -standalone mode 742115e113
  • Remove whistle delay for new replays 9bf0e2a7b5
  • Minor replay/debug improvements 4fe60ce1f8
  • Add jit_runtime_debug.py for debugging JIT bugs 781ffbc008
  • Remove noisy allocation logs 6319e54acc
  • eweapon Rocks no longer hardcoded to die on solids 20e5b2415b  

    Instead, they obey the weapon flag for breaking on solids, allowing rocks that either break or not.

  • Auto-generate 'include/bindings/qrs.zh' from source code 93f82434ea
  • Add horizontal scrolling panes c9a009b60b
  • Add "spreading fire" to 'trigger_example.qst' a755adb086

Player

  • Support "latest" for version field in zplay dcaf7f925e
  • Disable ZASM optimization until reported issues with tango are fixed c3b7e1ba25
  • Update MIDI Info dialog 1926d732e6
  • Update goto cheat dialog 09d6d254f5
  • Update 'ZC > Quest Info' dialog e72ed380b1
  • Update 'Screen Saver' dialog, let screensaver take arbitrary seconds value 46f6a1c476

ZScript Standard Library (std.zh)

  • Update headers and bindings with array typing b23b23484e

ZScript

  • Optimize '!' operator cb8cbe0388
  • More parser optimizations 900178b730
  • Optimize multiple consecutive PUSH opcodes dc6d9e49ef
  • Add ZASM comments to parser output 407bcf258d
  • Add more ZASM comments 4b1dd09883
  • CALLFUNC/RETURNFUNC for optimized function call/return 5aa14b3355
  • New 'ReturnVisitor' pass errors on functions missing 'return' statements 5cc8fb151d
  • Code reachability optimizations 17ae5ad31f
  • More small ZASM optimizations 76f86d2a7e
  • Add compile option for missing return error 18275ed760
  • Treat empty functions like prototype functions 433581fe73  

    This can be a heavy optimization for empty constructors/destructors.

  • Make some more internal functions constexpr 21cdf3c04b
  • Optimize 'STORED' followed by 'LOADD', and add 'STOREDV' 6fce115646
  • Optimize standing-statement x++,x-- to ++x,--x 5b62f2f5c4
  • Optimizations related to function call parameters, unused function params d79b131ab7
  • Range loop cleanup 9841db7d55
  • Optimize variables initialized to 0 f20abd31d0
  • Clean up unused variables f3a0991d62
  • Internal label errors now prevent compile beb7671129
  • Compare related optimizations 3a0d346dc7
  • Allow 3-arg opcodes, move ZASM tables to remove duplication 0c3e0823b2
  • Optimize comparisons to run when used, add CMP_BOOL flag for boolean-equality comparisons aa9bf8ebba
  • Support CMP_BOOL in x64 JIT accf84bf07
  • Add Region in anticipation of z3 scrolling f87c20d08a  

    To enable scripts to work in 2.55 and in a future release with z3 scrolling, we are adding a non-functional Region:

    • Region->Width: width in pixels (today, always 256)
    • Region->Height: height in pixels (176)
    • Region->ScreenWidth: width in screens (1)
    • Region->ScreenHeight: height in screens (1)
    • Region->NumCombos: number of combo positions (176)
    • Region->ID: region id (0 - meaning just a normal 1x1 area)
    • Region->OriginScreen: top-left screen in the region
    • Region->GetScreenForComboPos(int pos): given a combo position, returns the screen index associated with it
    • Region->TriggerSecrets(int screen_index): trigger secrets for given screen. The screen must be in the region

     

    For example, if a script uses Region->NumCombos instead of 176 to iterate all the combos in the current area, it will work in both regions and non-regions. Additionally you should use ComboAt(x, y) rather than anything else to translate between pixel coordinates and a combo position.

  • Optimize PEEK in x64 and wasm JIT 0ff7dee9ef
  • Use faster LOAD/STORE instead of LOADD/STORED in compiler e8b3be6fd8
  • Remove SRAM feature 22a9c67341  

    SRAM continually has caused issues with new updates and has fallen severely behind. As it was originally implemented, it does not work well.

Visual Studio Code Extension

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment