Synchrony

Synchrony is a work-in-progress reimplementation of Crypt of the NecroDancer that adds online multiplayer support and an extensive Lua-based modding API.

Stable build (v0.35)

Download: Windows | macOS | Linux
Last update:

Development build

Download: Windows | macOS | Linux
Last update:

Join our Discord community for mods, announcements, online multiplayer sessions!

Changelog

v0.5 (2020-10-29)

(Full changelog coming soon)

  • Added spectator mode for online sessions
  • Added late-joining and re-joining for online sessions
  • Added local co-op for both local and online sessions
  • Added most weapons, shovels and torches, as well as some headgear, boots and charms
  • Added behavior for all remaining Zone 1 enemies
  • Added functionality for Zone 1's traps and tiles
  • Implemented a full Lua modding API, including a mod loader to create and load packaged mods

v0.4 (2019-09-24)

Multiplayer

  • Added Steam integration for online multiplayer
    • Create public, friends-only or private lobbies, join friends using the Steam client or use the game browser to find a match
    • NecroNecro automatically connects to the Steam client on startup
    • Direct IP connection multiplayer servers are still available, and can now be hosted and joined on non-default UDP ports

Gameplay

  • Added the Fireball spell
  • Added Minotaur behavior
  • Added Red Dragon behavior
  • Added Armadillo behavior
  • Added Zombie behavior
  • Levels in All-Zones runs now play their respective song
  • Changed the default camera mode to center on the local player at a fixed zoom level, instead of panning and zooming out to show all characters

Menus & User Interface

  • Added spell slots to the heads-up display
  • Added "Change Soundtrack" menu

Bugfixes

  • Fixed binding menu controls and movement directions to the same keys not being allowed
  • Fixed blood damage causing the groove chain to be dropped
  • Fixed characters occasionally getting stuck in remote data awaiting mode
  • Fixed error when spawning a swipe outside of beat processing
  • Fixed exit stairs screen fade-out effect cutting off in custom dungeons
  • Fixed exit stairs screen fade-out not animating correctly in online games
  • Fixed Ghosts and Bats bouncing on movement failure
  • Fixed Ghosts ceasing to move when player idles
  • Fixed inactive entities performing AI actions
  • Fixed key bindings not saving correctly
  • Fixed local player's latency not displaying correctly
  • Fixed message boxes not being dismissed when pressing Escape
  • Fixed non-directional attacks resulting in right-oriented damage
  • Fixed non-looping music restarting when unpausing after the song ended
  • Fixed tiles in custom dungeons being shifted horizontally by one column
  • Fixed procedural dungeons not being regenerated when returning to lobby
  • Fixed previous position not resetting on non-movement directional actions
    • This is known as the "prevpos" bug in the reference implementation, and may be toggleable in the future via a compatibility flag
  • Fixed snapshot rollback errors when experiencing poor network connectivity
  • Fixed space being one pixel too wide in small font
  • Fixed user interface scale factor incorrectly defaulting to 1 instead of 2
  • Fixed Whip weapons dealing directionally incorrect damage

Modding

  • Added support for registering custom entity types in Lua
    • Template entities allow for the simplified registration of enemies, items and playable characters using a necrodancer.xml-like table structure, with optional component modifiers applied afterwards
    • Entities can also be created manually for full control over the used components, bypassing the internal XML-to-ECS mapping functions entirely
  • Added support for animation variants
    • Added directional versions of normal and tell animations
  • Added support for object-timed (offBeat) animations, running on the object's action timer instead of the song beat
    • At the end of the object-timed animation, the frames can be looped, the last frame can be sustained, or a lower-priority animation can be used as a fallback
  • Added Damage.inflict function, replacing Character.attack
  • Split previousPosition into logical and visual previous position
    • The previous position for movement animations of character sprites is now stored in hopTween
  • Added objectFacing event, fired whenever the direction of an object changes (such as when moving or turning around), even for entities without a facingDirection component
  • Added objectMoveFail event and INVALID action result, allowing enemy movement failures to be handled without triggering on transient movement failures (re-queued movement)
  • Added field active to component gameObject, replacing the former tangibility component
  • Added various components:
    • aiLinearFollowFacingDirection: causes the linear AI's direction to be set to the entity's facing direction
    • actionDelay: enforces a delay before executing certain actions
    • autoCast and related components: performs actions automatically upon the nearest target entity entering a specific range
    • beatDelayBypass: allows an entity to bypass the beat delay for specific actions
    • moveOverride and related components: controls whether the entity is "charging" in a specific direction, and initiates such a charge automatically if the target entity is in range
    • resetBeatDelayOnMoveFail: resets the beat delay when the entity's movement fails
    • turnOnMoveFail: causes an entity to face the opposite direction when its movement fails
    • spell and related components: represents a reusable item that creates one or more spellcast entites upon activation
    • spellcast and related components: indicates that the entity is spawned upon the activation of a spell, causing a variety of possible effects on the caster or nearby enites and tiles
  • Added X and Y scale factors to Swipe entity
  • Added support for cross-module event registration calls at load-time
  • Added LineOfSight module, implementing Bresenham's line drawing algorithm to perform line-of-sight checks for collisions with solid tiles and/or entities
  • Added function Player.getPlayableCharacterTypes
  • Added function AnimationTimer.getAnimationFactor
  • Added functions Inventory.getItemInSlot and Inventory.getItemsInSlot
  • Added Lua Table Notation serializer, replacing Serpent
  • Added selectableIf menu entry key to conditionally control selectability
  • Added hideIfDisabled menu entry key to hide disabled menu entries
  • Added entity existence checks to ECS accessors, catching use-after-delete errors
  • Added support for specifying a separate hit sound for suppressed damage
  • Added support for reading/writing arrays and maps from/to the config file
  • Added attributes parameter to Object.spawn
  • Added support for variable item capacities per inventory slot
  • Added configuration entries wos.game.assets.autoReload.delay.* for asset auto-reload event coalescence
    • NecroNecro now waits until the application has finished writing to changed files before reloading them to avoid reading corrupted or incomplete files
    • On Windows, this check is approximated by waiting until no more file write events are fired for a short amount of time
  • Added configuration entry wos.game.graphics.filterTextures for controlling whether textures should be linearly interpolated
  • Added configuration entries wos.game.debug.logging.* for controlling logging verbosity and the log file name
  • Added spawn debug command to create entities (single-player only)
  • Added char debug command for changing the player's character class
  • Added watch.add, watch.remove and watch.clear debug commands for visually debugging field values on entities and components
    • Use F1 to enable the debug overlay and press Shift-F1 to cycle to the watch overlay mode
  • Added parameter info to comments for kill and death object events
  • Changed inventory code to store items in the order they were picked up
  • Changed rollback snapshot indices to correspond exactly to beat index
  • Entity despawns are now deferred to the end of the current beat, instead of being performed immediately

Modding Bugfixes

  • Fixed Action.isOrthogonalDirection and Action.isDiagonalDirection returning incorrect results
  • Fixed Action.isResultSuccessful returning incorrect value for FAIL
  • Fixed Action.rotateDirection interpreting non-directional inputs as RIGHT
  • Fixed penetration field not being populated in damage event parameters
  • Fixed entity schema loader not cleaning up unused entities and components
  • Fixed error when accessing mutable fields of prototype entities
  • Fixed beat delay induced during an action not applying to requeued enemies
  • Fixed beat delay not resetting after performing special action
  • Fixed non-zero beat delay being reset at the end of an action
  • Fixed incorrectly negated menu entry visibility condition

v0.3 (2019-03-21)

Gameplay

  • Added All-Zones Mode
    • Dungeons are generated procedurally using a random seed
    • Based on Mendayen's ndref project
    • Procedural dungeons highly resemble those generated by the original game
  • Added Seeded All-Zones Mode
    • Specific procedural dungeons can be played by entering a seed
    • Seeds are compatible with the original game, resulting in (nearly) the same dungeons
  • Added lighting system
    • Added torch items which provide wall-penetrating light around the player
    • Added wall torches which light up areas within the player's field of view
  • Added usable exit stairs
    • Locked stairs must be unlocked by defeating miniboss first
    • Step on unlocked stairs to proceed to the next level
    • Stairs grant immunity to damage and coin multiplier loss
  • Added monkey behavior
    • Monkeys can move onto the player and grab them
    • Monkeys are knocked back when they take damage
  • Added ghost behavior
    • Ghosts fade out, stand still and become unattackable when the nearest player approaches them
    • When the nearest player moves away from the ghost, it becomes corporeal, seeking out and attacking the player
  • Added green dragon behavior
    • Dragons seek out the player, destroying walls within their path
  • Added screen flashes when unlocking exit stairs or taking damage
  • Added attack pattern for whip weapons
  • Added different pickup sound for weapons
  • Added boss walls

Menus & User Interface

  • Added game mode selection menu to lobby
  • Added 'quick restart' hotkey
  • Added game controls configuration menu
  • The chat box can now be opened from the pause menu

Bugfixes

  • Fixed players not being able to move on the very first beat of a song
  • Fixed coin multiplier loss when standing still at the beginning of a level
  • Fixed decorated Zone 4 walls missing their texture
  • Fixed sound groups sometimes repeatedly playing the same sound
  • Fixed HUD scaling not applying correctly
  • Fixed the session's first input frame sometimes being reported incorrectly
  • Fixed incorrect swipe creation order for entities with a base attack
  • Fixed incorrect swipe offset at modified camera zoom levels
  • Fixed character heads becoming temporarily detached on level transition
  • Fixed item pickup HUD animation repeating after level transition
  • Fixed chat box opening when pressing chat key while entering text in a menu
  • Fixed non-host clients being able to open dungeon selector in lobby
  • Fixed occasional 'Inconsistent snapshot' error on level transition
  • Fixed animation timer continuing to run when the game is paused
  • Fixed game content directory sometimes being misdetected
  • Fixed incorrect 'Unpausing in' countdown when rapidly pausing/unpausing
  • Fixed whole player list being sent unnecessarily often in multiplayer, causing high bandwidth usage
  • Fixed sprite animations frames being recomputed unnecessarily often, causing slowdowns
  • Fixed client to server data transfers not being cancelable

Modding

  • Added functions to Graphics module for drawing rotated boxes and sprites
  • Added Color module for manipulating integer colors
    • Reworked most graphics functions to accept integer colors in addition to tables
  • Added depth sorting/Z-order for sprites
  • Replaced opacity field with color in sprite component
    • This allows sprites to be darkened or tinted
  • Added visionRaycast component
  • Added stasis component for characters
  • Added weapon material components
  • Added generic fade in/out effect component for sprites
  • Changed lobby renderer to use bestiary images
    • Removed now obsolete lobby.png image from assets
  • Added animateObjects event for applying object animations
  • Split enemyActions step into separate targeting and AI actions steps
  • Split HUD module into element-specific sub-modules
  • Added support for partial network data transfers
    • This allows only part of a resource to be updated, such as one level of a dungeon
  • Added common removeItem event for both dropped and destroyed items
  • Added tileChange object event
    • Fired when the tile beneath an object changes
  • Added support for passing nil key to enum selectors, accessing all entries
  • Added support for custom reliable ordering channels to network layer
  • Added function TileTypes.getCrackedTileID
  • Added various associative table helper functions to Utilities module
    • Utilities.getKeyList: returns a list of keys in an associative table, discarding values
    • Utilities.getValueList: returns a list of values in an associative table, discarding keys
    • Utilities.getKeyValueList: returns two correlated lists of keys and values of an associative table
    • Utilities.setKeyAtPath: modifies a table by recursively following a list of keys
  • Added FileIO.exists function to check for the existence of a resource
  • Added optional destination, offset and size arguments to Array.copy
  • Added id key to arrays, to retrieve the ID for native code interoperation
  • Added startsWith and endsWith functions to StringUtilities module
  • Added simple query string parser/builder to StringUtilities module
  • Added StringPool module for dynamically mapping strings to integers
  • Added Bitmap module for manipulating images
  • Added virtual Lua resource provider
    • This enables the procedural generation of assets, such as images
    • Added CropImage virtual resource
  • Added functions to Input module to poll for vertical/horizontal mouse scrolling
  • Added error logging and more informative error message on level load failure
  • Added light map debugger to debug overlay (F1)
  • Reworked internal level format and level loader
    • Added LevelUtils module for manipulating levels in the internal format
  • Move Colors module from config to render package
  • Reworked movement animation/tweening code
    • Added support for starting animations before an entity's AI is executed
  • Added function to look up player character type by XML ID
  • Added bestiary images for all playable characters and some enemies

Modding Bugfixes

  • Fixed global variables resetting upon full script reload
  • Fixed event selectors failing to update after full script reloads
  • Fixed key suppression being case sensitive
  • Fixed global random number generator (math.random) not being seeded on session start
  • Fixed stack overflow freezing the game for longer than necessary
  • Fixed duplicate 'unknown tile ID' log warnings when loading dungeons
  • Fixed error in mouse button check functions
  • Fixed debug hotkey for content reload using incorrect entity namespace
  • Fixed incorrect array copy offsets for multibyte data types
  • Fixed entries in configuration file being ordered incorrectly
  • Fixed network transfers sometimes being delivered in the wrong order
  • Fixed potential name conflict with generated entity schema, interfering with live reloading

v0.2 (2018-10-29)

Gameplay

  • Added enemy attacks
  • Added enemy health bars
  • Added enemy movement priorities
  • Added silhouettes for entities outside the player's field of view
  • Added coin multiplier
  • Added item pickups and equipment HUD
  • Added weapons
  • Added tile digging
    • Implemented shovels of differing strength
    • Special shovel effects are not implemented yet
  • Added playable characters other than Cadence
    • Each character spawns with their default starting items and health
    • No character-specific gameplay effects yet
  • Added various sound effects
    • Hurt and death sounds for enemies and players
    • Attack sounds for enemies
    • Dig sounds for players
  • Added AI for some enemies
    • Skeletons
    • Slimes
    • Bats
  • Added attack patterns and swipes for some weapons
    • Daggers
    • Broadswords
    • Longswords
  • Added sprite mirroring for moving characters

Multiplayer

  • Added movement animation smoothing for online sessions

Menus & User Interface

  • Added dungeon selection list
    • This replaces the "Enter dungeon name" dialog
    • Dungeon selector now opens automatically when trying to start a game with no dungeon selected
  • Added character sprite preview to lobby

Bugfixes

  • Fixed animations not being cached correctly
  • Fixed animations sometimes not working on the first beat of the song
  • Fixed movement animation re-playing when performing stand-still action
  • Fixed enemies not requeueing after failed movement
  • Fixed error when an enemy failed to find a target
  • Fixed error when loading a level containing doors or wires
  • Fixed error when picking up certain item combinations
  • Fixed incorrect stack trace depth on read-only entity field write error
  • Fixed incorrect vertical camera offset
  • Fixed uninitialized spritesheets rendering with garbled textures
  • Fixed pause menu not closing when host restarts the run
  • Fixed single player mode setting online name to "Player"
  • Fixed objects drawing over walls in the same row
  • Fixed some enemy sprites incorrectly rendering horizontally mirrored
  • Fixed inaccurate character bounce animation

Modding

  • Added support for load-time require calls across scripts
  • Added object event forwarding to all held items
    • Event handlers for all involved entities are merged, then evaluated in priority order
  • Added customized error stack traces
    • Event handlers in the stack trace now display their names, instead of line numbers
    • Event selectors now display the name of the event
    • Calls to xpcall in the context of event handling are now hidden from the stack trace
  • Added initial support for level transitions
    • Currently implemented as a debug command: press F4 and enter level(2)
  • Added support for cross-beat animation timing
  • Added partial support for drawing rotated sprites
  • Added generic enemy AI handler and implement basicSeek using it
  • Added sound groups and rollback handling for sound effects
  • Added experimental support for specifying numeric ordering for event handlers
    • Event handler order is specified using the priority field in the key parameter
    • This feature is experimental and its exact functionality may change in the future
  • Added beat synchronization functionality
    • This lets the host ensure that all players caught up to each other before switching levels
    • Currently, a beat sync request stops all game logic and can only be lifted via level change
  • Added Random module containing pseudo-random noise functions
    • Rewrote noise functions in C++ to improve performance and prevent possible desyncs
  • Disabled the debug reset hotkey (F2) by default
    • It can be enabled or changed in config.json (wos.game.debug.reset)
  • Removed intermediate character 'controller' entities
  • Removed beat bar entities
  • Changed dbg functions to also work in release mode
  • Changed debug commands (F4) to be accessible without the c. prefix
  • Split Game module into Input, Rollback and LevelEvents modules
  • Split Audio module into Sound and Music modules
  • Moved string conversion functions to StringUtilities module
  • Moved/renamed enum Character.ActionResult to Action.Result
  • Extracted bit manipulation functions into new module BitUtilities

Modding Bugfixes

  • Fixed auto-reload throwing an error when modifying non-script file
  • Fixed cross-module references causing scripts to load multiple times
  • Fixed error when deserializing tables with keys containing keywords
  • Fixed error when enabling the debug profiler (F6)
  • Fixed player actions ignoring beat delay
  • Fixed utils.deepCopy not supporting cyclic tables

v0.1 (2018-09-05)

  • Initial private release