OpenNox

An opensource implementation of Nox game engine.

★ What’s new in the latest release ★

OpenNox logo OpenNox logo

Sections

Support

To get support, feel free to open issue report in our GitHub repository.

Alternatively, you can always find us on the Discord and Matrix.

This project is developed by the community, consider supporting us on OpenCollective or Patreon.

Contributions

Feel free to contribute to this documentation by just clicking the button displayed on top right of each page.

For contributing to OpenNox project itself, see the main repository.

License

This project (OpenNox) is an unofficial community collaboration project for preservation, modding and compatibility purposes. This project has no direct affiliation with Electronic Arts Inc. and/or the “Nox” brand. “Nox” is an Electronic Arts Inc. brand. All Rights Reserved.

No assets, texts, artwork or other media from the original game(s) is included in this project. We do not condone piracy in any way, shape or form and encourage users to legally own the original game.

The video game “Nox” is copyright © 2000 Westwood Studios. All Rights Reserved. Westwood Studios is a trademark or registered trademark of Electronic Arts in the U.S. and/or other countries. All rights reserved.

If not specified otherwise, the source code is licenced under the GNU General Public License version 3. Please see the accompanying LICENSE file.

OpenNox logo created by @CCHyper under CC0 license.

OpenNox project additionally follows C&C Remastered Modding guideline. All changes to the project MUST follow these rules.

Подразделы OpenNox

OpenNox

Информация про движек OpenNox.

Подразделы OpenNox

Что нового

This page shows what’s new in the latest OpenNox release.

Bug A well-known issue affecting specific version.

Breaking A change that requires action by you after upgrading.

Change A change in default behavior that may requires action by you if you want to revert it.

Experiment An experimental change that may be removed or changed completely in the future.

New Marks new behavior you might find interesting or comes configurable.

Fix A fix of a bug or regression.


1.8.11 (2022-06-29)

Known issues

  • Bug Game may crash or break save file in solo when encountering invisible NPCs.
  • Bug Multiplayer is unstable. Client may fail to connect to servers.

New

  • New Preparations to make more spells moddable.
  • New Hidden Death spell now correctly draws spinning skull on monsters.
  • New Allow using two more effects from scripts: ENERGY_BOLT and PLASMA.
  • New Lots of internal changes related to color handling.
  • New Allow force-switching maps in more cases.
  • New Stretch image option is now persisted.

Fixes

  • Fix Potential crash when loading certain maps.
  • Fix Downloading maps via Nox protocol.
  • Fix Incorrect rendering of the observer effect.
  • Fix Rendering of abilities panel when player dies.
  • Fix Obliteration spell effect.
  • Fix Minimap rendering.
  • Fix Parsing of network filters from the config.
  • Fix Transparent color not rendering correctly in some GUI elements.
  • Fix Correctly override background color in GUI.
  • Fix Crash when reading gamma on the server.
  • Fix Server requiring audio/video libs.
  • Fix Text message when switching maps.
  • Fix GREEN_BOLT effect when called from a script.
  • Fix Build now doesn’t require Git.

1.8.10 (2022-05-30)

  • Change First release as an open source project!
  • New Significant cleanup of the codebase.
  • New Fix long-standing bug for rendering lights in high-res.
  • New Long-awaited support for movie playback.
  • New Reworked most of the rendering code.
  • New Allow console commands in Quest.
  • New Use shaders for gamma control. Should work more reliably.
  • New Send server resolution and player list to the lobby.
  • New Allow overriding and initial modding support for spells.
  • New Allow getting all spells, including hidden ones via cheat spells all.
  • New Allow removing summon limit via cheat summon.nolimit.
  • New Support XDG paths on Linux.
  • Fix Correctly handle goto console command.
  • Fix Minor physics deviation compared to vanilla.
  • Fix Teams creation in Quest.
  • Fix Reading gamma settings from config.
  • Experiment Support for loading campaign in multiplayer.

1.8.9 (2022-03-04)

  • Change OpenNox will now use the new lobby server and fallback to XWIS if no servers were found.
  • New Ping will now be shown in servers list for servers that support it.
  • New Server discovery was optimized and is now faster.
  • New Implemented a tiny builtin SSH remote console. Telnet support removed.
  • New Game load/save was optimized and works faster now.
  • Fix Not being able to connect to non-OpenNox servers.
  • Fix Spawned creatures being stuck when damaged.
  • Fix Magic missiles targeting dead entities.
  • Fix Energy bolt not working properly in traps.
  • Fix UI no longer freezes when discovering game servers.
  • Fix Player names not being shown in scores table.
  • Fix Sorting in the character list.

1.8.8 (2022-01-31)

  • New Notify if OpenNox update is available.
  • New Server: add metrics for monitoring.
  • Fix Jumping no longer prevents from taking damage from lava.
  • Fix Do not announce Solo Quest games online.
  • Fix Team colors (regression from v1.8.7).
  • Fix Correctly set config dir for Snap.

1.8.7 (2022-01-21)

  • New Support loading of TrueType and OpenType fonts.
  • New Automatically fix Russian translation and font files.
  • New A ton of internal changes and cleanup.
  • Fix Creatures and NPCs with ranging attack trying to fight melee only.
  • Fix Server API being stuck than there are no players on the server.
  • Fix Crash when falling into a pit.
  • Fix AI debug logging.

1.8.6 (2021-12-18)

  • New Release OpenNox for Linux on Snapcraft.
  • New Reading game files is now safer and more extendable.
  • New Preparations for saving and replaying Nox matches.
  • New Preparations for rendering TTF fonts in game engine.
  • New E2E mode now allows recording player input directly (to reproduce bugs).
  • New Safer and faster sprite rendering.
  • New Initial work on rendering map previews.
  • New A lot of internal refactorings and improvements.
  • New Allow configuring manual spell cast timeout.
  • New Allow binding any keys with bind command.
  • New cheat spawn command to spawn items and monsters.
  • Fix Safer GUI code, preventing a major memory corruption.
  • Fix Races in the audio playback.
  • Fix Potential fix for native map downloads.
  • Fix Crashes when playing on broken maps.

1.8.5 (2021-10-31)

  • New Add more resolution options for both regular and HD version.
  • New Move screen resolution to opennox.yml config.
  • Fix Instant victory if player commits a suicide in Arena.
  • Fix Properly propagate closed and private game flags to XWIS.
  • Fix It was possible to join closed games.
  • Fix Map filtering by game type.
  • Fix cheat health and cheat mana now work properly without arguments.

1.8.4 (2021-10-31)

  • New Better performance for particle effects.
  • New Allow using emotes in campaign.
  • New cheat sage command that gives all spells and scrolls, but doesn’t make you invincible.
  • New cheat spells command that only gives all spells for your class.
  • New cheat scrolls command that only gives all best scrolls.
  • New cheat god (as opposed to set god) that only makes you invincible, but won’t give any spells.
  • Fix Set time limit for new key bindings to prevent the same action from executing to fast.
  • Fix Lightning spells were not hitting multiple targets as they should.
  • Fix Controlled creatures disappearing on map switch.
  • Fix Effects from Protection spells were played incorrectly.
  • Fix Random “you cannot wear this” messages when switching equipment.
  • Fix Allow really large amount of gold in cheat gold.
  • Fix Announcing Solo games to online lobby.
  • Fix Using relative paths in config.
  • Fix Better protection from potential memory leaks.
  • Fix Crash when reading maps that use the new Panic’s script compiler.
  • Fix Multiple other crashes.

1.8.3 (2021-10-06)

  • New Integrated the new (simple) server control panel.
  • Fix Saving complex input bindings to the config.
  • Fix Wrong interpretation of XWIS option in the new config.
  • Fix Possible crashes for maps using new memhacks compiler.

1.8.2 (2021-10-02)

  • New Write opennox.yml config with all extended options.
  • New Allow changing game data dir via the opennox.yml config.
  • Fix Player names being stuck as online in dedicated server.
  • Fix Mouse movement on low sensitivity settings.
  • Fix Assigning keyboard keys instead of mouse for movement.

1.8.1 (2021-10-01)

  • Fix Back walls rendering in high-resolution mode.
  • Fix Center in-game menu in high-resolution mode.
  • Fix Possible crash after running for some time.

1.8.0 (2021-09-29)

New

  • New High-resolution support (up to 4K)! You’ll need to run opennox-hd.exe for it.
  • New A lot faster OpenGL-based rendering (partially offloaded to GPU).
  • New Add cheat charm.all to charm any creature (including humanoids).
  • New Automated end-to-end testing mode, see opennox-e2e for details.
  • New Simple HTTP-based Server API for controlling game servers.
  • New Allow disabling image smoothing in the video options.
  • New Allow enabling image stretching in the video options.
  • New Other minor optimizations.

Fixes

  • Fix Bug with creatures being “deaf” (not reacting to footsteps, etc).
  • Fix Properly show the last character in long server names.
  • Fix Error when manually saving player in online games.
  • Fix Banish of captured creatures (like vampire bats) leading to scripts being stuck.
  • Fix Properly forward ports when server port is changed via a flag.
  • Fix Disabling soft shadows via -soft flag.
  • Fix LUA scripts when reloading the same map from the console.
  • Fix Nox Reloaded failing to join OpenNox Quest games.
  • Fix OpenNox changing user.rul file permissions.
  • Fix Potential crash on hosting Quest games.
  • Fix Potential crash when leaving the game.
  • Fix Crash when opening advanced server setting without admin rights.

1.7.1 (2021-07-19)

  • Fix Hide OS mouse cursor in windowed mode as well.
  • Fix Rename “Back” button in input config menu to “Accept”.
  • Fix Prevent crash on audio errors.
  • Fix Avoid collision of new health and mana cheats with old ones.

1.7.0 (2021-07-16)

  • Change Completely reworked input and present pipelines.
  • New Manual spell casting. Bind keys to individual spell gestures and become a real wizard/conjurer!
  • New Gamma and mouse sensitivity sliders were added to the options menu.
  • New Wide-screen 16:9 resolutions are now available. Older 4:3 resolutions are still supported via config.
  • New Added key bindings for:
    • Switching to a specific spell slot.
    • Switching to a specific trap slot.
    • Dropping a trap from your inventory.
    • Controlling spawned creature behavior.
    • Accepting item buy/sell/drop.
  • Breaking set allow.all was renamed to cheat equip.all
  • Breaking set mana was renamed to cheat mana
  • Breaking set health was renamed to cheat health
  • Fix Input sensitivity should now work correctly in fullscreen mode.
  • Fix Gamma setting in the config is now respected.
  • Fix Stretched video setting in the config is now respected.

1.6.1 (2021-06-21)

  • Fix Prevent freeze when closing the game on Windows.
  • Fix Prevent crash in set mana.
  • Fix Prevent crash when switching shield and bow with set allow.all enabled.
  • Fix Ignore item strength requirement when using allow.all.
  • Fix Remove restrictions from cheat gold, so it’s accepted in Quest games.

1.6.0 (2021-06-21)

  • Change Rename project to OpenNox to avoid confusion.
  • New Automatically set Nox data folder. Supports Origin, GoG and Nox Reloaded.
  • New Keep 4:3 aspect ratio when resizing game window.
  • New Toggle fullscreen mode with Alt+Enter.
  • New Add set health and set mana cheats.
  • New Add set allow.all cheat to remove item class restrictions.
  • New Allow customizing gamedata.bin values without encoding it. See gamedata-sample.yml.
  • New LUA now supports trigger events as well as player join/leave events.
  • Fix Detonate traps spell will no longer freeze the game.
  • Fix Fullscreen mode will now be saved correctly.
  • Fix Warriors should now be able to scroll weapons with mouse wheel in multiplayer as well.

1.5.0 (2021-06-06)

  • New Automatically open/forward ports when hosting a game (no need to configure firewall).
  • New Blazing-fast map downloads. Both client and the server should use this version.
  • New Maps will now be transferred with other related files when possible (.txt, .rul, .lua, .png).
  • Fix Fixed the bug that prevented warriors from scrolling weapons with mouse wheel.
  • Experiment Experimental support for LUA map scripts.

1.4.0 (2021-05-19)

  • New First public release!
  • New Compatible with Nox Reloaded.
  • New Native SDL and OpenAL support (no workarounds required for Win10, streaming, etc).
  • New Builtin XWIS integration. No need for account in order to host or join games.
  • New More Nox Quest options (skip levels, keep portal forever, etc).
  • New Native Linux build (no Wine).
  • New Dedicated “headless” server.
  • Experiment Gamepad support.

Features

Vanilla features

All vanilla features are supported. You should be able to complete the campaign and play online with OpenNox.

If something doesn’t work, please file an issue.

Compatibility

OpenNox will work out-of-the-box on any recent Windows version. This includes proper graphics and online multiplayer.

OpenNox also works natively on Linux, including Steam Deck.

OpenNox doesn’t provide Nox assets. You must own a copy of the original game and have it installed in order to run it. OpenNox will attempt to find Nox installation automatically.

OpenNox is able to connect to vanilla Nox servers, as well as vanilla Nox clients are able to connect to OpenNox servers. This is only true for regular version of OpenNox. OpenNox HD will refuse to connect with non-HD (legacy) players.

Graphics

OpenNox can load vanilla Nox content and should work on any recent Windows and Linux versions with no graphical issues.

Additionally, OpenNox provides an HD version, which allows using display resolutions up to 4K. OpenNox HD will refuse connections from non-HD/legacy version and from vanilla Nox, because fairness considerations.

OpenNox supports custom TTF and OTF fonts to replace vanilla raster fonts.

Multiplayer

Vanilla Nox distinguishes between online and LAN multiplayer. It uses XWIS server and requires login/password for it.

OpenNox combines both online and LAN games into a single list. It doesn’t require XWIS password, while still able to join XWIS servers.

OpenNox also attempts to automatically forward ports, when hosting a game online. This requires UPnP to be enabled on your router (which is enabled by default in most cases).

There is an initial work done for supporting playing solo campaign in multiplayer.

Server

OpenNox provides a headless dedicated server both for Linux and Windows.

OpenNox servers expose a simple HTTP API for getting server information, which allows easy integration with websites, Discord bots, etc. The same API provides a simple Web control panel for the server.

Game

OpenNox improves a few aspects of the game to make it more convenient to players, or to provide more options.

Apart from a simpler online games list, automatic port-forwarding and more graphical options, OpenNox additionally provides:

Modding

OpenNox aims to greatly improve modding support. It is still a work-in-progress, but there are a few improvements already implemented:

Подразделы Установка

Подразделы Install on Linux

Appimage release

Package information

Appimage is a portable packaging format designed to simplify user interaction with software by removing the need to install it as a package or install its dependencies.

32 bit Appimage packages are provided since v1.8.12-alpha9 (25 Aug 2023).

The Appimage contains all 3 executables: non-hd client, hd client and dedicated server.

The Appimage release is not portable by default – it overrides config location and data location to use user’s home folder conforming to Freedesktop standard “XDG Base Directory Specification v0.8”. This is done specifically to allow making packages out of this AppImage and to allow direct system installation (in /usr/local/bin for example).

Paths used by the Appimage release

Please note, that $HOME is either user’s home or a portable home, depending on how you install OpenNox.

  • Game files are expected to be in this directory: $HOME/.local/share/opennox
  • Game configuration files are expected to be in this directory: $HOME/.config/opennox
  • Game logs will be put into this directory: $HOME/.local/state/opennox

Prerequisites

Внимание

OpenNox is not a full game. It requires game content files of the original Nox installation!

See GoG for purchase options. Original CD should work as well.

Most probably, you are using 64 bit distribution of Linux. To use OpenNox you have to enable i386 architecture and install these packages:

  • libc6:i386
  • libfuse2:i386
  • zlib1g:i386

Make sure you have 32 bit version of your graphics drivers installed to provide libgl1:i386.

On 32 bit distributions you probably have everything installed already.

Installation process (standard usage)

  1. Download the Appimage file from the Opennox releases page. Put it anywhere you think is appropriate and mark it as executable.
  2. Copy Nox content files into the $HOME/.local/share/opennox folder. Alternatively, you can install Nox into this folder.
  3. (Optional) If you are migrating from binary release, please put opennox.yml into $HOME/.config/opennox folder.

Installation process (portable)

  1. Download the Appimage file from the Opennox releases page. Put it anywhere you think is appropriate and mark it as executable.
  2. Create portable home folder for the Appimage by running it with parameter –appimage-portable-home or by creating a folder with the same name as the Appimage and “.home” appended to the end. If Appimage file is opennox-bundle-i386.AppImage, then portable home folder must be named opennox-bundle-i386.AppImage.home.
  3. Copy Nox content files into the .local/share/opennox folder inside the portable home folder you had created in step 2.
  4. (Optional) If you are migrating from binary release, please put opennox.yml into the .config/opennox folder inside the portable home folder you had created in step 2.

Running the Appimage

Appimage release always checks the first parameter to decide which executable to run.

  • To run OpenNox (legacy version), simply run the Appimage file.
  • To run OpenNox HD, run the Appimage file with “hd” parameter as the first parameter.
  • To run OpenNox dedicated server, run the Appimage file with “server” parameter as the first parameter.
  • To get help about this Appimage release, run the Appimage file with “help” parameter as the first parameter. The help explains how to use Appimage and where files should be placed.

Troubleshooting

OpenNox doesn’t start

  • Try starting OpenNox from the terminal. Check if there are any error messages there.
  • Make sure you have Nox game files in $HOME/.local/share/opennox folder.

If nothing helps, please contact us on OpenNox Discord in #feedback channel and share the opennox.log located in the .local/state/opennox folder.

Can’t connect to a server: Version mismatch

HD and legacy versions won’t join servers of the opposite version.

Most online servers still run legacy version, so if you want to join them, you must run legacy version of OpenNox as well.

Binary archive release

Release information

This release is just OpenNox binaries packed into tar.gz archive.

Prerequisites

Внимание

OpenNox is not a full game. It requires game content files of the original Nox installation!

See GoG for purchase options. Original CD should work as well.

To run OpenNox you will need to install this dependencies:

  • libc6:i386
  • libopenal1:i386
  • libsdl2-2.0-0:i386

Make sure you have 32 bit version of your graphics drivers installed to provide libgl1:i386.

Installation process (portable)

  1. Download the tag.gz file from the Opennox releases page.
  2. Unpack tar.gz archive contents into Nox installation folder.
  3. Mark files opennox, opennox-hd and opennox-server as executable.

Installation process (non-portable)

  1. Download the tag.gz file from the Opennox releases page.
  2. Unpack tar.gz archive contents into folder of your choice.
  3. Mark files opennox, opennox-hd and opennox-server as executable.
  4. Copy Nox content files into your $HOME/Nox folder. Alternatively, you can install Nox into this folder.

Running the game

You need to create launchers yourself for executables you want to run.

Please note, that working directory must be set to the Nox installation folder.

Running from terminal

Информация

Navigate to the Nox installation folder, before running any of these commands.

To run OpenNox Non-HD (legacy), issue this command:

opennox

To run OpenNox HD, issue this command:

opennox-hd

To run OpenNox dedicated server, issue this command:

opennox-server
Информация

If you placed binaries not Nox installation folder, you have to provide a full or relative path to the binary.

Troubleshooting

OpenNox doesn’t start

  • Try starting OpenNox from the terminal. Check if there are any error messages there.
  • Make sure you have put binaries into your Nox installation folder or have game files in the $HOME/Nox directory or in the place specified in opennox.yml (which can be either in $HOME/.config/opennox or in the working directory used to call binaries from):
game:
  data: /home/user/some/path/to/Nox

Change this path manually to a folder where your copy of Nox is installed, if necessary. Restart OpenNox.

If nothing helps, please contact us on OpenNox Discord in #feedback channel and share the opennox.log located in the $HOME/snap/opennox/common/logs folder.

Can’t connect to a server: Version mismatch

HD and legacy versions won’t join servers of the opposite version.

Most online servers still run legacy version, so if you want to join them, you must run legacy version of OpenNox as well.

Flatpak release

Package information

Flatpak is a packaging format designed to simplify user interaction with software by removing the need to install its dependencies.

Flatpak package is provided since v1.8.12-dev (0a8352c) (13 Jan 2023).

Flatpak package supplies only 2 executables: non-hd client and hd client.

Prerequisites

Внимание

OpenNox is not a full game. It requires game content files of the original Nox installation!

See GoG for purchase options. Original CD should work as well.

You will need Flatpak installed.

Installation process

  1. Follow installation instructions on Flathub
  2. Copy Nox content files into your $HOME/Nox folder. Alternatively, you can install Nox into this folder.

Running the game

After installing you should get two launchers in your applications menu: OpenNox and OpenNox HD. Run the one you need.

Running from terminal

To run OpenNox Non-HD (legacy) issue this command:

flatpak run io.github.noxworld_dev.OpenNox

To run OpenNox HD issue this command:

flatpak run --command=opennox-hd io.github.noxworld_dev.OpenNox

Troubleshooting

OpenNox doesn’t start

  • Try starting OpenNox from the terminal. Check if there are any error messages there.
  • Make sure you have Nox game files in $HOME/Nox or in the place specified in $HOME/opennox.yml:
game:
  data: /home/user/some/path/to/Nox

Change this path manually to a folder where your copy of Nox is installed, if necessary. Restart OpenNox.

If nothing helps, please contact us on OpenNox Discord in #feedback channel and share the opennox.log located in the logs folder, which is located either in your home folder or in OpenNox working directory.

Can’t connect to a server: Version mismatch

HD and legacy versions won’t join servers of the opposite version.

Most online servers still run legacy version, so if you want to join them, you must run legacy version of OpenNox as well.

Snap release

Package information

Snap is a packaging format designed to simplify user interaction with software by removing the need to install its dependencies.

Snap package is provided since v1.8.6 (19 Dec 2021).

Snap package supplies all 3 executables: non-hd client, hd client and dedicated server.

Prerequisites

Внимание

OpenNox is not a full game. It requires game content files of the original Nox installation!

See GoG for purchase options. Original CD should work as well.

You will need snapd installed.

Installation process

  1. Follow installation instructions on Snapcraft
  2. Copy Nox content files into your $HOME/Nox folder. Alternatively, you can install Nox into this folder.

Running the game

After installing you should get two launchers in your applications menu: OpenNox and OpenNox HD. Run the one you need.

Running from terminal

To run OpenNox Non-HD (legacy), issue this command:

snap run opennox

To run OpenNox HD, issue this command:

snap run opennox.hd

To run OpenNox dedicated server, issue this command:

snap run opennox.server

Troubleshooting

OpenNox doesn’t start

  • Try starting OpenNox from the terminal. Check if there are any error messages there.
  • Make sure you have Nox game files in $HOME/Nox or in the place specified in $HOME/opennox.yml:
game:
  data: /home/user/some/path/to/Nox

Change this path manually to a folder where your copy of Nox is installed, if necessary. Restart OpenNox.

If nothing helps, please contact us on OpenNox Discord in #feedback channel and share the opennox.log located in the $HOME/snap/opennox/common/logs folder.

Can’t connect to a server: Version mismatch

HD and legacy versions won’t join servers of the opposite version.

Most online servers still run legacy version, so if you want to join them, you must run legacy version of OpenNox as well.

Установка на Windows

Установка

Внимание

OpenNox не является отдельной игрой. Он требует установки оригинала Nox!

См. GoG или Origin для покупки. Оригинальный CD так же должен сработать.

  1. Установить оригинальный Nox. Предпочтительно, вне папки “Program Files”.
  2. Скачать последний установщик OpenNox. Использовать файл .exe для Windows.
  3. Установить его в любую директорию (отдельно от директории оригинального Nox).

Запуск

HD версия

  1. Перейти в директору где установлен OpenNox.
  2. Сделать ярлык на opennox-hd.exe.
  3. Запустить его!
Информация

HD версия не будет подключаться к публичным серверам старого Nox или OpenNox legacy!

Это сделано для обеспечения честности, т.к. не все игроки используют OpenNox HD и не видят так же далеко как в HD. Вы все ещё можете создать свой сервер для того чтобы играть с друзьями в HD версию.

Legacy версия

  1. Перейти в директору где установлен OpenNox.
  2. Сделать ярлык на opennox.exe.
  3. Запустить его!
Информация

Legacy версия не будет подключаться к публичным HD серверам!

Удостоверьтесь что использует версия совместимая с сервером при игре по сети (HD или совместимая).

Устранение проблем

OpenNox не запускается

Во первых, можно попробовать запустить OpenNox с правами администратора. Если это сработало, значит Nox установлен в защищенную директорию вроде “Program Files” что вызывает проблемы с доступом. Удалите папку OpenNox, переустановите Nox в другую директорию и установите OpenNox снова.

Если это не помогло, откройте opennox.yml (в директории куда установлен OpenNox) с помощью текстового редактора (Notepad++ это лучший вариант). Найдите секцию похожую на:

game:
  data: C:\Games\Nox

Измените путь в файле на папку куда установлена копия Nox. Перезапустите OpenNox.

Если это тоже не сработало, пожалуйста обратитесь за помощью в OpenNox Discord в канал #feedback. Так же поможет если вы приложите файл opennox.log который находиться в капке log в директории OpenNox.

Can’t connect to a server: Version mismatch

Как было указано в документации по установке, HD и legacy версии не будут присоединяться к серверам друг друга.

Большинство публичных серверов до сих пор используют legacy версию, по этому если вы хотите присоединиться к ним, вам необходимо использовать legacy версию OpenNox. Удостоверьтесь что используете правильную версию когда пробуете присоединиться к серверу.

Install on Steam Deck

Заметка

This guide is based on Linux installation guide.

Specific Steam Deck guide will be provided in the future as well.

Installing

Внимание

OpenNox is not a standalone game. It requires a copy of original Nox installed!

See GoG for purchase options.

  1. Install original Nox from GoG (via Lutris or Heroic).
  2. Install OpenNox via Flatpak.

Playing

HD version

Installation should create a “OpenNox HD” shortcut in the start menu. Alternatively: run opennox-hd binary from terminal.

Информация

HD version will not join public legacy servers!

This is done for fairness reasons, since not everyone runs OpenNox in HD. You can still host your own server for your friends to join.

Legacy version

Installation should create a “OpenNox” shortcut in the start menu. Alternatively: run opennox binary from terminal.

Информация

Legacy version will not join HD servers.

Make sure to run the same version as the server when playing online.

Troubleshooting

OpenNox doesn’t start

Try starting opennox from the terminal. Check if there are any error messages there.

If it doesn’t help, open opennox.yml in OpenNox installation directory in a text editor. Find section similar to this:

game:
  data: /home/user/some/path/to/Nox

Change the path manually to a folder where your copy of Nox is installed. Restart OpenNox.

If it still doesn’t work, please ping us on OpenNox Discord in #feedback channel. It will help if you share opennox.log located in log folder in OpenNox install directory.

Can’t connect to a server: Version mismatch

As was explained in the installation section, HD and legacy versions won’t join servers of the opposite version.

Most online servers still run legacy version, so if you want to join them, you must run legacy version of OpenNox as well. Make sure to try a correct version when joining a server.

Подразделы Игра

Nox Quest

OpenNox provides more commands for Nox Quest game mode.

Originally, Nox Quest:

  • Prevents players to skip levels if they haven’t completed them already
  • Skips only 5 levels at a time.
  • Disables the portal after level 20.
  • Even if portal cutoff is increased to more than 20, it won’t teleport to next levels.

To solve all of this, you can run (in the game console; F1):

racoiaws
set quest warp.allow
set quest warp.inc 10
set quest warp.inf

For more detailed description of commands, read on.

warp.allow

This option disables the requirement to complete a certain Quest level before accessing the portal.

Example:

# always allow to pass through the portal
set quest warp.allow
set quest warp.allow 1

# original Nox behavior
set quest warp.allow 0

warp.inc

Changes the number of levels that the portal skips at a time.

Example:

# portal will only skip one level instead of 5
set quest warp.inc 1
# skip 20 levels
set quest warp.inc 20

# original Nox behavior
set quest warp.allow 5

warp.inf

Allows the portal to work indefinitely instead of shutting down at level 20.

Example:

# portal will always be enabled
set quest warp.inf
set quest warp.inf 1

# original Nox behavior
set quest warp.inf 0

level.inc

Changes the number of levels that will be skipped on the stage completion. In other words, how quickly the levels will increase when you complete a Quest level.

This allows to ramp up difficulty much faster without affecting other Quest rules.

Example:

# completing level 5 will lead to level 7 (+2) instead of 6 (+1)
set quest level.inc 2

# original Nox behavior
set quest level.inc 1

Multiplayer campaign

Внимание

This mode is highly experimental! You will encounter bugs.

You must restart the game after playing in this mode. Otherwise, game session and the menu will likely be broken.

Starting campaign in multiplayer

  1. Host regular Quest game.
  2. Wait for all players to join.
  3. Open game console with F1 and type racoiaws (enables console commands).
  4. Disable map restrictions: set maps allow.all.
  5. Load desired campaign: load wiz01a (for Wizard), load con01a (for Conjurer), load war01a (for Warrior).
  6. Enjoy!

Known issues

  • Game saves won’t work. All your progress for this session will be lost. Use load to jump to other chapters.
  • Players likely won’t be able to reconnect. Full game restart is required (for both client and server!).
  • Other players can run around during cutscenes. If you break them - you’ll have to restart the map.
  • Death of any player will trigger the death screen and stop the campaign.

Useful commands

  • Teleport P2 to P1: tp (or tp 0).
  • Teleport P1 to P2: tpto (or tpto 0).
  • Unfreeze P1 after broken cutscene: unstuck.

Use SSH remote console to copy-paste commands.

Ручной каст заклинаний

Surprisingly, vanilla Nox has a hidden feature that allows casting spells manually by pressing one of 9 phoneme/gesture keys in the right order to cast specific spells. It is similar to the way spell casting works in Magicka.

OpenNox restores this feature by default. Manually casting each spell is challenging, thus we think that it doesn’t give any advantage in multiplayer (actually the opposite), so can be enabled safely.

All that needs to be done to use it to set hotkeys in OpenNox input options. There are 8 main phonemes, plus a special “end” phoneme to finish and cast the spell.

It’s typical to use numpad keys for phonemes where 5 or Enter is an “end” phoneme, and actual phonemes occupy other number keys:

Manual casting gestures layout Manual casting gestures layout

Manual casting key bindings Manual casting key bindings

Another typical layout is to use QWER-ASDF block for 8 phonemes and set “end” to any key that is close enough.

For more details, see this post.

Подразделы Хостинг

Хостинг через клиент

The simplest way to host Nox game is via OpenNox game client.

Run OpenNox or OpenNoxHD, go to “Network”, and host the game. Simple as that!

OpenNox will automatically register the game online (for both OpenNox and Nox Reloaded).

It will also attempt to automatically open ports for the game (via UPnP on your router).

Информация

Servers hosted with OpenNoxHD version will not allow non-HD clients!

This is done for fairness reasons. Since not everyone runs OpenNox in HD, it will significantly limit their vision distance, giving too much advantage to HD players.

Хостинг выделенного сервера

OpenNox also ships with the opennox-server binary which can be used to run as a dedicated server.

Also, Docker images are available for the server.

When hosting a dedicated server, it’s important to consider remote console and/or HTTP API to control the server remotely.

Внимание

We got quite a few bug reports about dedicated server freezing.

Thus, we do not recommend running dedicated server at this stage.

Удаленный доступ через SSH

Vanilla Nox supported a telnet-based remote console (RCON) which allowed controlling Nox server remotely.

OpenNox has dropped telnet support in favor of SSH-based remote console.

Информация

OpenNox only emulates SSH protocol. It does not allow accessing the host machine via SSH.

To enable RCON, OpenNox must be started with an additional argument:

opennox --rcon=:18522 --rcon-pass=my-secret-password

This will allow SSH connections on port 18522 with a password my-secret-password:

ssh -p 18522 127.0.0.1

See this tutorial

ssh -p 18522 127.0.0.1

Or install PuTTY and connect to 127.0.0.1:18522 with any username and password my-secret-password.

  /888888                                /88   /88           /88   /88
 /88__  88                              | 888 | 88          | 88  / 88
| 88  \ 88  /888888   /888888  /8888888 | 8888| 88  /888888 |  88/ 88/
| 88  | 88 /88__  88 /88__  88| 88__  88| 88 88 88 /88__  88 \  8888/
| 88  | 88| 88  \ 88| 88888888| 88  \ 88| 88  8888| 88  \ 88  >88  88
| 88  | 88| 88  | 88| 88_____/| 88  | 88| 88\  888| 88  | 88 /88/\  88
|  888888/| 8888888/|  8888888| 88  | 88| 88 \  88|  888888/| 88  \ 88
 \______/ | 88____/  \_______/|__/  |__/|__/  \__/ \______/ |__/  |__/
          | 88
          | 88        Version: v1.9.x (xxxxxxxxx)
          |__/

user@opennox:~$

From here, all console commands will work the same way as via in-game console. A good starting point is a help command.

HTTP API для сервера

Server info

GET /api/v0/game/info

Or in terms of curl:

curl 'http://127.0.0.1:18580/api/v0/game/info'

Example response:

{
  "name":"OpenNox",
  "map":"estate",
  "mode":"arena",
  "vers":"v1.8.0",
  "players":{
    "cur":1,
    "max":32,
    "list":[
      {
        "name":"Jack",
        "class":"wizard"
      }
    ]
  }
}

Setting the token

You need to run the server with NOX_API_TOKEN=<some-random-string> to allow using control APIs.

Внимание

You must set token to something complex. Otherwise, someone can get full control of your server!

All examples below assume NOX_API_TOKEN=xyz.

Change map

POST /api/v0/game/map
X-Token: xyz

estate

Or in terms of curl:

curl -X POST -H 'X-Token: xyz' -d 'estate' 'http://127.0.0.1:18580/api/v0/game/map'

Run console command

POST /api/v0/game/cmd
X-Token: xyz

load estate

Or in terms of curl:

curl -X POST -H 'X-Token: xyz' -d 'load estate' 'http://127.0.0.1:18580/api/v0/game/cmd'

Run NS script

POST /api/v0/game/eval
X-Token: xyz

ns4.CreateObject("RedApple", ns4.GetHost().Unit().Pos())

Or in terms of curl:

curl -X POST -H 'X-Token: xyz' -d 'ns4.CreateObject("RedApple", ns4.GetHost().Unit().Pos())' 'http://127.0.0.1:18580/api/v0/game/eval'

Run LUA script

POST /api/v0/game/lua
X-Token: xyz

p = Nox.Players[1];
apple = Nox.ObjectType("RedApple");
apple:Create(p);

Or in terms of curl:

curl -X POST -H 'X-Token: xyz' -d 'p = Nox.Players[1]; apple = Nox.ObjectType("RedApple"); apple:Create(p)' 'http://127.0.0.1:18580/api/v0/game/lua'

Подразделы Модификация

Настройка игрового баланса

Классический Nox хранит параметры игрового баланса в закодированном файле gamedata.bin.

OpenNox позволяет переопределять значения указанные в этом файле теми, что записаны в текстовом файле gamedata.yml.

Для пробы скопируйте gamedata.yml в папку с установкой Nox (не в папку OpenNox!). После этого, вы можете редактировать этот файл с помощью любого текстового редактора (Notepad++ рекомендуется для Windows пользователей).

Изменение заклинаний

Vanilla Nox stores spell configs in three different places:

  • As a section in thing.bin file
  • Balance file
  • Built into the engine

The engine defines a list of all supported spell IDs (e.g. SPELL_BLINK) and the effect associated with it.

The thing.bin then lists spells that should be enabled in the game (by ID) and additionally configures them. Unfortunately, this configuration is quite limited.

The balance file may additionally tune per-level spell parameters, or special parameters that are unique to certain spells.

OpenNox extends this system and allows using spells.yml file to configure new spell parameters, as well as old ones in one place.

Note: this modding feature is still in development. Not all the config options for spells are available in spells.yml. We will keep adding new ones in each version of OpenNox.

Generating base spells.yml file

Since this feature is in the development, it is strongly advised to generate a fresh spells.yml based on the latest OpenNox version and your Nox game data.

This can be done by running OpenNox with NOX_DUMP_SPELLS=true environment variable.

On Linux:

NOX_DUMP_SPELLS=true opennox

On Windows (via cmd.exe):

set NOX_DUMP_SPELLS="true"
opennox.exe

This should create a spells.yml in Nox game data directory (not OpenNox directory!).

Alternatively, you could copy the spells.yml file to your Nox game directory. Be aware that the sample file might be old and won’t list all options available in the engine.

Modifying spells.yml

Note that modifying spells.yml currently requires OpenNox restart.

Usually, the spell section will look like this:

name: SPELL_BLINK
icon:
  ind: 131860
icon_enabled:
  ind: 131938
mana_cost: 10
price: 3000
flags:
- 1
- MOBS_CAN_CAST
- 128
- 1024
- CAN_COUNTER
- CANT_HOLD_CROWN
- 1048576
- CLASS_ANY
- 2147483648
phonemes: [cha, et, un]
title: thing.db:Blink
desc: thing.db:SPELL_BLINK_DESC
cast_sound: BlinkCast
---

Where:

  • name - specifies spell ID to use; if effect is not set, this also determines the spell effect
  • effect - specifies spell ID which will control the actual effect of the spell; see adding spells
  • icon.ind - the sprite index from video.bag that is used as a spell icon
  • icon_enabled.ind - same as icon.ind, but for enabled spell icon
  • mana_cost - mana cost of the spell
  • price - base spell book price; Quest uses an additional multiplier for this price
  • flags - different flags that controls which category spell belongs to, what it can target, etc
  • phonemes - a unique list of spell phonemes/gestures that invoke this spell; see spell casting
  • title - a string ID for the spell title
  • desc - a string ID for the spell description
  • cast_sound - a sound for casing a spell
  • on_sound - a sound for enabling a spell
  • off_sound - a sound for disabling a spell

These are the only parameters that can be originally controlled via thing.bin, and was ported to spells.yml.

Apart from these, OpenNox provides more options for certain spells. For example, SPELL_MAGIC_MISSILE has a new section:

missiles:
  spread: 16
  projectile: MagicMissile
  vel_mult: 0.1
  offset: 4
  speed_rnd_min: 0.80000001
  speed_rnd_max: 1.2
  search_dist: 600

Here, a count parameter is omitted, because it is usually controlled via balance file (see MagicMissileCount). Specifying it here will override balance data.

When a special section like missiles this is present, all parameters in there can be controlled individually for each spell level:

missiles:
  # default parameters for all levels
  spread: 16
  projectile: MagicMissile
  vel_mult: 0.1
  offset: 4
  speed_rnd_min: 0.80000001
  speed_rnd_max: 1.2
  search_dist: 600
  # per-level configs
  levels:
    # levels 1-3: copied from balance file
    - count: 1
    - count: 2
    - count: 3
    # level 4: same number of missiles as lvl3, but longer homing distance
    - count: 3
      search_dist: 800
    # level 5: make it ultimate: more missiles, longer distance, faster missiles
    - count: 10
      speed_rnd_min: 1.0
      speed_rnd_max: 2.0
      search_dist: 800

Spell flags

Not all flags are completely understood at this point. So we recommend to see what flags are set for existing spells and experiment by setting/unsetting them in your mod.

Names of the spell flags provided below may change in a freshly-generated spells.yml, but OpenNox will still support old names as well.

Player class flags:

  • CLASS_ANY - spell can be used by any magic class (Conjurer and Wizard)
  • CLASS_WIZARD - spell can only be used by Wizard
  • CLASS_CONJURER - spell can only be used by Conjurer
  • Setting none of these flags will effectively hide the spell.

Targeting flags

  • TARGETED - spell is homing
  • AT_LOCATION - spell can be cast at a point
  • CANT_TARGET_SELF - spell cannot be targeted at the character

Cast flags:

  • NO_MANA - spell doesn’t require mana
  • NO_TRAP - spell can’t be used in traps
  • INSTANT - spell is instant
  • DURATION - spell is duration-based
  • OFFENSIVE - spell is offensive
  • DEFENSIVE - spell is defensive
  • CAN_COUNTER - spell can be countered
  • MOBS_CAN_CAST - mobs are allowed to use this spell
  • CANT_HOLD_CROWN - spell can’t be cast when holding a flag/crown/ball

Special flags

  • SUMMON_SPELL - this is the base Summon Creature spell
  • SUMMON_CREATURE - this is Summon for a specific creature
  • MARK_SPELL - this is the base Mark Location spell
  • MARK_NUMBER - this is Mark Location with a specific number
  • GOTO_MARK_SPELL - this is the base Go To Mark spell
  • GOTO_MARK_NUMBER - this is Go To Mark with a specific number

There are some flags that don’t have names, which means we are not sure of its effect.

Adding new spells

Currently, adding new spells in OpenNox is not supported.

Having said that it is possible to replace unused spell slots that already exist in the game.

In spell section there’s a name parameter that defines the slot that the spell uses and effect for the engine to know which effect to run.

Usually these two IDs are the same (or effect is empty and derived from name), but these fields can be used to replace unused spell IDs with custom ones.

For example, there’s SPELL_PHANTOM which doesn’t appear in the game and has no effect in the engine. This gives us a free spell slot to use. Let’s replace it with a custom magic missiles (SPELL_MAGIC_MISSILE) variant. For this we need to set name: SPELL_PHANTOM (or find existing section with it) to specify which slot we are using, and set effect: SPELL_MAGIC_MISSILE for the engine to know which logic to use for it. The result should look like this:

name: SPELL_PHANTOM # replacing Phantom spell slot
effect: SPELL_MAGIC_MISSILE # but effect is based on Magic Missiles
phonemes: [un, ro, do] # phonemes must be unique, so we keep ones from Phantom
# the rest is copied from Missiles and modified
icon:
  ind: 18248
icon_enabled:
  ind: 131967
mana_cost: 50
price: 5000
flags:
  - AT_LOCATION
  - MOBS_CAN_CAST
  - OFFENSIVE
  - CAN_COUNTER
  - CANT_TARGET_SELF
  - CLASS_WIZARD
  - 536870912
  - 1073741824
title: thing.db:MissilesOfMagic
desc: thing.db:SPELL_MAGIC_MISSILE_DESC
cast_sound: MagicMissileCast
missiles:
  count: 5
  spread: 30
  projectile: MagicMissile
  vel_mult: 0.1
  offset: 4
  speed_rnd_min: 0.1
  speed_rnd_max: 0.3
  search_dist: 800
---

Замена изображений

The main build supports a way to replace sprites used by the game.

For it to work, you may first need to get original sprites:

cd Nox
noxtools videobag extract -z --out ./video.bag.zip

Find sprites that you want to replace and put them into Nox/images (create if not exists). Make the changes to the sprite in this directory and run the game to test it.

Note that it will ONLY work with this Nox version. Original Nox, GoG version or Nox Reloaded doesn’t support this.

Adjusting sprite offsets

If you decide to change the sprite significantly, e.g. changing its size or completely redrawing the image, you may need to change the sprite offset used by the engine.

First, get the original sprite metadata:

cd Nox
noxtools videobag extract -z --out ./video.bag.zip --json

Now this archive will contain .json files that correspond to each sprite. Copy selected ones to Nox/images, adjust the offsets using the text editor and check them in game.

Изменение перевода

Most of the text used in Nox is stored in the CSF files which are encoded and are hard to modify.

This build provides an easier way to customize those texts.

First, decode the original file:

noxtools strings csf2json nox.csf

This will produce nox.csf.json file that you can modify with a regular text editor. The build will automatically use this file instead of the original nox.csf.

The nox.csf.json file will consist of sections similar to this:

    {
      "id": "ParseCmd.c:exithelp",
      "vals": [
        {
          "str": "Exit the game to Main Menu."
        }
      ]
    }

For translation Nox texts to a different language (or changing existing texts), you need to keep the id field, but translate all str fields.

For adding custom strings, you need to add a new section with a unique id add at least one str. Then you should be able to use this new id in your map or mod.

Подразделы Scripts

NoxScript

OpenNox implements a new more powerful version of NoxScript runtime.

It can be used to make new generation of maps, as well as some full-featured mods in the future.

See NoxScript quickstart if you want to try it.

Скрипты LUA

OpenNox implements an experimental LUA map script runtime.

Заметка

LUA scripts are deprecated. Consider using new NoxScript runtime.

Quickstart

To create a LUA map script, put <mapname>.lua file in the map’s directory.

For example:

maps/
  estate/
    estate.map
    estate.nxz
    estate.lua

You also need to request a specific version of the scripting API that you want to use:

Nox = require("Nox.Map.Script.v0")

Now you are ready to write some magic Nox scripts!

It is also possible to add more LUA files, for example:

maps/
  estate/
    estate.map
    estate.lua
    other_file.lua

And use require to load it:

other_file = require("other_file")

Debugging with the in-game console

You can access script variables for debugging using Nox console.

First, you should enable cheats (racoiaws), and the prefix all you commands with lua .

For example:

lua p = Nox.Players.host
lua print(p)

Timers

Timers allow to trigger some LUA function at a later time.

Frame timer

This timer will call a given function after N game frames (server ticks).

function MyFunc()
    print("trigger!")
end
Nox.FrameTimer(60, MyFunc)

Seconds timer

This timer will call a given function after N in-game seconds pass.

function MyFunc()
    print("trigger!")
end
Nox.SecondTimer(10, MyFunc)

Walls

Walls in Nox are positioned on a regular grid. Thus, walls can be addressed by those grid positions. If walls are marked as scriptable in the editor, it will be possible to enable (close) and disable (open) them.

  • Wall(xi,yi) - get a wall by its grid coordinates.
  • WallAt(x,y) - get a wall at exact real coordinates (not grid ones).
  • WallNear(x,y) - get a wall near specific real coordinates (not grid ones).
  • WallNear(obj) - get a wall near a specific object or waypoint.
  • WallGroup(id) - finds a wall group by the ID.

Wall object

This object represents a single wall on the map.

  • w.xi - returns X grid coordinate of the wall.
  • w.yi - returns Y grid coordinate of the wall.
  • w.x - returns real X coordinate of the wall.
  • w.y - returns real Y coordinate of the wall.
  • w.enabled - checks if the wall is enabled (closed) or sets the enabled state.
  • w:Pos() - returns wall’s real position as a pair of X,Y coordinates.
  • w:Toggle() - toggles the wall’s state (opened/closed).
  • w:Break() - break this wall (must be set as breakable).

WallGroup

This object represents a group of one or more walls on the map.

  • w.id - returns ID of this wall group.
  • w:Toggle() - toggles walls state (opened/closed).
  • w:Break() - break these walls (must be set as breakable).

Examples

Open secret wall near the player (must be really close):

local p = Nox.Players.host
Nox.WallNear(p).enabled = false

Break a wall group with ID MyGroup on the map:

local g = Nox.WallGroup("MyGroup")
g:Break()

Players

This section describes player-related objects and functions.

Players meta-class

Players list can be accessed via Nox.Players meta-class.

  • Players() - returns current list of players as LUA array.
  • Players[i] - returns a player by index i.
  • Players:Print(text) - prints a text message to all players.
  • Players:Blind() - blinds all players (fades the screen to black).
  • Players:Blind(false) - unblinds all players (fade back to normal).

Player object

Player object includes information about human-controlled player, as well as a unit he controls.

  • p.name - returns player’s name.
  • p.host - checks if player is a host.
  • p.unit - returns player’s unit, if any.
  • p.x - gets or sets player’s unit X coordinate.
  • p.y - gets or sets player’s unit Y coordinate.
  • p:Pos() - returns player’s unit position as a pair of X,Y coordinates.
  • p:SetPos(x,y) - instantly moves player’s unit to given coordinates.
  • p:SetPos(obj) - instantly moves player’s unit to a given object or waypoint.
  • p:Print(text) - prints a text message to the player.
  • p:Blind() - blinds player (fades the screen to black).
  • p:Blind(false) - unblinds player (fade back to normal).

Examples

Iterating over all players:

local players = Nox.Players()
for i,p in ipairs(players) do
    print(p)
end

Getting the first player:

local p = Nox.Players[1]
print(p)

Getting the host player:

local p = Nox.Players.host
print(p)

Getting player’s name:

local p = Nox.Players.host
print(p.name)

Checking if player is a host:

local p = Nox.Players[1]
if p.host then
    print("it's the host!")
end

Blind everyone:

Nox.Players:Blind()

Blind everyone except the host:

local players = Nox.Players()
for i,p in ipairs(players) do
    if not p.host then
        p:Blind()
    end
end

Objects

This section describes different object present in game.

ObjectType

Object type describes a “prototype” of an object that can be spawned in-game.

  • Nox.ObjectType(id) - find an object type by ID.
  • t.id - returns object type ID.
  • t:Create(x,y) - creates a new object instance at given coordinates.
  • t:Create(obj) - creates a new object instance at the position of another object or waypoint.

Object instance

  • Nox.Object(id) - find an object by ID.
  • v.id - returns object’s ID, if any.
  • v.owner - returns or sets object’s owner.
  • v.x - gets or sets object’s X coordinate.
  • v.y - gets or sets object’s Y coordinate.
  • v.z - gets or sets object’s Z coordinate.
  • v.enabled - checks if object is enabled or sets the enabled state.
  • v:Pos() - returns object’s position as a pair of X,Y coordinates.
  • v:SetPos(x,y) - instantly moves object to given coordinates.
  • v:SetPos(obj) - instantly moves object to another object or waypoint.
  • v:SetOwner(obj) - sets object owner; same as v.owner, but allow chaining.
  • v:Delete() - permanently delete object from the map.
  • v:Toggle() - toggles object’s enabled state.

Unit object

Unit extends the generic object, so everything that can be done with object can be done with a unit.

  • v.health - current health of the unit.
  • v.max_health - max health of the unit.
  • v.mana - current mana of the unit.
  • v.max_mana - max mana of the unit.
  • v:Freeze() - freezes the unit in place.
  • v:Wander() - make the unit wander around.
  • v:Return() - make the unit return to its starting position.
  • v:Idle() - make the unit idle.
  • v:Guard() - make the unit guard position.
  • v:Hunt() - make the unit hunt for enemies.
  • v:LookAt(x,y) - make the unit look at certain position.
  • v:LookAt(obj) - make the unit look at another object or waypoint.
  • v:LookAtDir(dir) - make the unit look in a given direction.
  • v:LookAngle(dir) - make the unit look at a given angle.
  • v:MoveTo(x,y) - make the unit move to certain position.
  • v:MoveTo(obj) - make the unit move to another object or waypoint.
  • v:WalkTo(x,y) - make the unit walk to certain position.
  • v:WalkTo(obj) - make the unit walk to another object or waypoint.
  • v:Follow(obj) - make the unit follow another object.
  • v:Attack(obj) - make the unit attack another object.
  • v:HitMelee(x,y) - make the unit hit melee a certain position.
  • v:HitMelee(obj) - make the unit hit melee another object or waypoint.
  • v:HitRanged(x,y) - make the unit hit ranged a certain position.
  • v:HitRanged(obj) - make the unit hit ranged another object or waypoint.

Examples

Teleport player 10 pixels right:

p = Nox.Players.host
x, y = p:Pos()
x = x + 10
p:SetPos(x,y)

Teleport player 1 to player 2:

p1 = Nox.Players[1]
p2 = Nox.Players[2]
p1:SetPos(p2)

Spawn 10 apples near the player:

apple = Nox.ObjectType("RedApple")
p = Nox.Players.host
for i = 1,10 do
    apple:Create(p)
end

Spawn Mimic near the player and make him friendly:

mimic = Nox.ObjectType("Mimic")
p = Nox.Players.host
mimic:Create(p):SetOwner(p)

Spawn 2 Beholders and make them follow the player:

beholder = Nox.ObjectType("Beholder")
p = Nox.Players.host
arr = {}
for i = 1,2 do
    arr[i] = beholder:Create(p)
end
squad = Nox.ObjectGroup(unpack(arr))
squad:SetOwner(p)
squad:Follow(p)

Make a train of 5 Bombers that follow each other and the player:

function trainFollow()
    p:Print("Bomber train!")
    prev = p
    for i, b in ipairs(bombers) do
        b:Follow(prev)
        prev = b
    end
end

function makeTrain()
    bomber = Nox.ObjectType("Bomber")
    p = Nox.Players.host
    bombers = {}
    for i = 1,5 do
        bombers[i] = bomber:Create(p)
    end
    train = Nox.ObjectGroup(unpack(bombers))
    train:SetOwner(p)
    -- give them a frame or two to appear
    Nox.FrameTimer(2, trainFollow)
end

makeTrain()

Разработка

Информация про движек OpenNox.

Подразделы Разработка

Консоль OpenNox

Enabling all commands

By default, Nox and OpenNox start with most commands disabled. This is done to prevent cheating in campaign. Most commands will not work in multiplayer, unless you are a server admin/host.

To enable all commands, open the console (F1 by default) and type:

racoiaws

Remote console

OpenNox does not support original RCON protocol.

Instead, it implements remote console via a builtin SSH server.

List commands

To get a list of all available commands, use help.

Here’s the list of the most interesting ones.

image

Take a screenshot and save it as a PNG image.

image

show

This command contains various helpers for debugging.

Available sub-commands:

  • show bindings - show console bindings (macros).
  • show extents - show names and sizes for all object on the screen.
  • show ai - show AI paths and print all AI decisions to console.
  • show gui - shows or hides graphical user interface.

list

This command list various in-game spells, items, monsters, maps and players.

These commands print item IDs that can be the used with spawn command.

Available sub-commands:

  • list staffs - list all staffs and wands.
  • list armor - list all armor.
  • list weapons - list all weapons.
  • list food - list all consumables.
  • list monsters - list all monsters and NPCs.
  • list spells - list all spells.
  • list maps - list all maps.
  • list users - list all players.

load

This command switches current game map to the one specified:

load wiz01a

In vanilla Nox, not all maps can usually be loaded. For example, it’s impossible to load campaign maps in multiplayer. OpenNox allows removing those restrictions via set maps allow.all.

set god

A vanilla cheat for invulnerability, all spells and infinite mana.

set god

To disable:

unset god

Note that using this cheat will cause the character to learn all spells up to the maximal level. This cannot be reversed, even if the cheat is disabled. See cheat god if you only need invulnerability and infinite mana.

set quest

These commands allow more controls for Nox Quest game mode. See this page for details.

set maps

These commands allow more controls for game map loading.

  • set maps allow.all - disable game mode checks when loading the map; allows loading campaign in multiplayer, etc

cheat god

A cheat for invulnerability and infinite mana.

cheat god

To disable:

cheat god 0

For additionally getting all spells see cheat sage, or set god.

cheat sage

A cheat for getting all class spells, scrolls and/or abilities.

cheat sage

To disable:

cheat sage 0

cheat spells

A cheat for getting all spells.

For getting class spells:

cheat spells

For getting class spells with a specific spell level:

cheat spells 3

To get all spells, even hidden ones:

cheat spells all

cheat scrolls

A cheat for getting all beat scrolls.

cheat scrolls

To disable:

cheat scrolls 0

cheat goto

Teleport to given coordinates or a waypoint.

For teleporting to coordinates (X, Y):

cheat goto 1000 2000

For teleporting to a waypoint:

cheat goto MyWaypoint

cheat spawn

Spawn a given item or monster at the player’s position.

Command accepts IDs returned by the list command.

cheat spawn OblivionOrb
cheat spawn Mimic

It is also possible to specify a number of items to spawn:

cheat spawn RedApple 5

cheat gold

Adds specified amount of gold to all players.

cheat gold 10000

cheat health

Sets or restores health for the character.

Without arguments, command will restore health to maximum:

cheat health

You can also specify desired health value:

cheat health 999

cheat mana

Sets or restores mana for the character.

Without arguments, command will restore mana to maximum:

cheat mana

You can also specify desired mana value:

cheat mana 999

cheat equip.all

Removes equipment requirements from all items. In other words, any class can equip and use any armor/weapons.

cheat equip.all

To disable it:

cheat equip.all 0

cheat charm.all

Allows charming any hostile creatures and NPCs (including scripted ones, humanoids, etc).

cheat charm.all

To disable it:

cheat charm.all 0

cheat summon.nolimit

Внимание

The game may become unstable and crash, when using this command!

Remove the limit for the number of summoned creatures.

cheat summon.nolimit

To disable it:

cheat summon.nolimit 0

lua

This commands runs given LUA code.

For example, to replicate cheat spawn RedApple with LUA:

apple = Nox.ObjectType("RedApple")
p = Nox.Players.host
apple:Create(p)

In the console, each line must start with lua command:

lua apple = Nox.ObjectType("RedApple")
lua p = Nox.Players.host
lua apple:Create(p)

Notice that variables defined in one lua commands can be used in other ones.

It’s also possible to write a multi-line command in a single line:

apple = Nox.ObjectType("RedApple"); p = Nox.Players.host; apple:Create(p)

or

Nox.ObjectType("RedApple"):Create(Nox.Players.host)

For more information about LUA scripting, see this page.

NoxScript

Данная документация покрывает движек NoxScript реализованный в OpenNox.

Runtimes

На данный момент, список поддерживаемых скриптовых движков включает:

Для быстрого ознакомления с NoxScript, см как начать.

Некоторые из вопросов могут быть уже покрыты в Q&A. Так же доступны примеры.

Если вопросы не нашли ответа, можно задать их здесь или в нашем Discord.

Подразделы NoxScript

Как начать

Это руководство поможет создать ваш первый скрипт используя интерфейс скриптов OpenNox на языке Go.

Первые шаги

Заметка

Удостовертесь что у вас установлен OpenNox. Оригинальный Nox, Reloaded или иная версия не будут работать!

Чтобы создать ваш первый скрипт, скопируйте существующую папку одной из карт, либо создайте новую карту в редакторе. Если карта была скопирована, удостоверьтесь что файл карты внутри папки тоже был переименован.

Затем, создайте следующие файлы в папке карты:

script.go (любое имя с *.go будет работать):

package <mapname>
	
func init() {
	println("hello!")
}

go.mod:

module <mapname>

go 1.22

К примеру, оригинальная карта:

maps/
  estate/
    estate.map
    estate.nxz

И скопированная, включая новые файлы:

maps/
  example/
    example.map
    example.nxz
    script.go
    go.mod

В файле script.go:

package example

func init() {
	println("hello!")
}

В файле go.mod:

module example

go 1.22

Готово! Теперь запустите карту в OpenNox, откройте консоль и вы должны увидеть там сообщение hello!.

Информация

Вам не нужно устанавливать Go или какой-либо другой компилятор чтобы писать скрипты для OpenNox.

Тем не менее, правильная настройка Go поможет включить поддержку IDE, проверку типов в скриптах, автодополнение и т.д. По этому, мы крайне советуем это сделать.

Полная настройка

Для полной настройки нам понадобиться:

  1. Go 1.20+ (для проверки типов, работы с зависимостями)
  2. Git (для Windows)
  3. GoPls (для интеграции с VSCode)
  4. VSCode (сама IDE)
  5. Расширение Go для VSCode (включает документацию для gopls)

Когда все установлено, мы можем создать новый проект. Для это нужно:

  1. Скопировать существующую карту или создать новую через редактор карт.
  2. Открыть папку карты через VSCode.
  3. Открыть терминал (Terminal -> New Terminal в верхнем меню VSCode).
  4. go mod init <mapname> (например go mod init example). Это создаст готовый go.mod.
  5. Создать новый Go файл, например script.go с package <mapname> (например package example).
  6. Добавить какой-либо код в этот файл, например func init() { println("hello!") }.
  7. Сохранить все файлы, запустить OpenNox и проверить карту.

Скриптовые движки

Существует несколько доступных версий скриптовых движков (полный список здесь), к примеру:

Скриптовые движки работают следующим образом: обычно один из движков явлется остновным (NS4 в данном случае), который предоставляет весь функционал доступный в OpenNox. Остальные движки являются лишь слоем поверх него. Тем не менее эти слои важны! Они предоставляют уже знакомый интерфейс для разработчиков карт (например NS3 или EUD).

Благодаря этому, полность безопастно использовать несколько движков в одной карте. Если есть опыт в NS3 - лучше начать с него. Если вы только начинаете разбираться с Nox скриптами - выбирайте последний NS движек (NS4).

Ссылки выше ссылаются на документацию языка Go для каждого из движков - это основной источник документации
по функциям и классам доступным в каждом из движков. Это руководство даст лишь базовое знание про настройку скриптов.

Использование движков

Тогда, как использовать эти движки?

Если вы пропустили полную настройку, то для это нужно лишь добавить import в Go файл и использовать его:

package example

import (
    "fmt"
    
    "github.com/noxworld-dev/noxscript/ns/v4"
)

func OnFrame() {
	fmt.Println("players:", len(ns.Players()))
}

Несколько моментов которые стоит отметить:

  • Мы подключили стандартный пакет Go fmt используемы для вывода в консоль. Вы можете свободно использовать и другие стандартные Go пакеты.
  • Мы подключили NS через github.com/.../ns/v4, но мы ссылаемся на него как ns.* (например в ns.Players). Суффикс v4 является версией пакета.
  • Функция OnFrame будет вызываться OpenNox каждый кадр (или “тик сервера”). Так что мы должны увидеть множество сообщений в консоли!

Это все что нужно знать чтобы использовать один из движков. Но что если мы хотим использовать и NS3 и NS4, к примеру?

Подключение обоих пакетов не сработает - ведь у них одинаковое имя. Так что мы присвоим псевдоним для каждой версии:

package example

import (
    "fmt"
    
    ns3 "github.com/noxworld-dev/noxscript/ns/v3"
    ns4 "github.com/noxworld-dev/noxscript/ns/v4"
)

func OnFrame() {
	fmt.Println("players:", len(ns4.Players()))
	fmt.Println("talking:", ns3.IsTalking())
}

Если вы привыкли к NoxScript 3 и не хотите указывать ns. или ns3. повсюду, можно так же указать псевдоним как точку:

package example

import (
    "fmt"
    
    . "github.com/noxworld-dev/noxscript/ns/v3"
    ns4 "github.com/noxworld-dev/noxscript/ns/v4"
)

func OnFrame() {
	fmt.Println("players:", len(ns4.Players()))
	fmt.Println("talking:", IsTalking())
}

Можно заметить что мы вызываем IsTalking без префикса ns3. Это, тем не менее, не типично для Go, т.к. из кода не понятно объявлена ли функция IsTalking в карте или в другом пакете.

Теперь, возвращаясь к полной настройке IDE, вы могли заметить что импорты не были опознаны. Это происходит потому что нам нужно обновить зависимости проекта в go.mod. Мы можем сделать это двумя способами:

  • go mod tidy в терминале (требует Git).
  • Либо навести мышку на нераспознанное имя импорта, выбрать Quick fix..., и далее go get ....

В обоих случаях зависимости должны загрузиться (то есть тот NS движек который вы выбрали) и добавиться в go.mod.

Теперь автодополнение должно работать корректно для пакетов движка.

Обновление движков

Скриптовые движки периодически обновляются в OpenNox чтобы добавить новые возможности или исправить ошибки.

Это делаться автоматически, новый релиз OpenNox подключит новый движек без каких либо действий со стороны разработчика карт.

Тем не менее, IDE не будет распознавать новые функции движка до тех пор пока они не обновяться в проекте карты.

Самый простой способ обновить это открыть файл go.mod в папке карты и найти строку с движком который нужно обновить:

require (
    github.com/noxworld-dev/noxscript/ns/v4 v4.3.0
    // ... other lines
)

Просто обновите версию в нем, и запустите go mod tidy. Полный список версий доступен при нажатии на версию в документации пакета скриптов а так же на GitHub.

Пакеты

Теперь мы знаем как подключить движки скриптов и запускать скрипты. Как же лучше структурировать код?

В Go, единичным проектом является “пакет” (package): директория с одним или несколькими Go файлами. Имена самих Go файлов не имеют значения, единственное требование это то что все файлы в директории должны иметь одинаковую строку package в начале файла. OpenNox так же добавляет ещё одно ограничение: package должен совпадать с именем карты.

В остальном, организация кода полностью зависит от вас. Все функции и переменные обхявленные в одном файле доступны во всех других файлах в этой директории.

Как я могу …

Это руководство лишь поверхностно, в паре шагов показывает как работать со скриптами.

Если вы уже знакомы с оригинальным NoxScript 3, стоит просмотреть руководство по миграции для NS3.

Возможно вам так же интересно поближе познакомиться с языком Go. Язык очень простой, по этому это не должно составить труда. Интерактивный Go тур является хорошим местом чтобы начать.

Некоторые из вопросов могут быть уже покрыты в Q&A. Так же доступны примеры.

Если вопросы не нашли ответа, можно задать их здесь или в нашем Discord.

Примеры

На этой странице приведен список примеров скриптов для OpenNox.

НазваниеДвижекКомментарии
КомпанияNS3Скрипты компании переведеныне в NS3
Ephreaym/Nox-AI-scriptNS4Боты для Arena и CTF от @Ephreaym
mogushanNS4Пример боя с боссом от @dennwc и Garett
NoxWorldNS4Карты и скрипты для NoxWorld: Сервер Nox с открытым миром

NoxScript 4

Reference

Here you can find a full list of functions provided by NS4 runtime.

NS4 runtime

This is the current script runtime in OpenNox based on Go programming language.

See quickstart for a tour, or see NS3 for conversion from vanilla scripts and some history.

Подразделы NoxScript 4

Миграция с NS3

NS4 provides the same functionality as NS3, but uses object-oriented approach. It also supports a few unique features which are not available in NS3.

Changes

Objects

The ns3.ObjectID is replaced with ns4.Obj type. The main difference is that ns4.Obj is opaque and can no longer be used or stored as an integer.

It is possible to convert ns4.Obj to/from ns3.ObjectID using the following code:

ns4.AsObj(obj)
ns3.ObjectID(obj.ObjScriptID())

Similar functions are available for ns4.ObjGroup and ns3.ObjectGroupID:

ns4.AsObjGroup(group)
ns3.ObjectGroupID(group.ObjGroupScriptID())

Most object-specific functions are now available on the object itself, instead of a top-level library function:

obj.Enable(false)
obj.Delete()
ns3.ObjectOff(obj)
ns3.Delete(obj)

Object position is now available as a point type, instead of separate X and Y coordinates:

pos := obj.Pos()
x, y := pos.X, pos.Y
x, y := ns3.GetObjectX(obj), ns3.GetObjectY(obj)

Most functions can now accept this new position type instead of a coordinate pair:

pos := obj.Pos()
obj2.HitMelee(pos)
x, y := ns3.GetObjectX(obj), ns3.GetObjectY(obj)
ns3.HitLocation(obj2, x, y)

Position can also be constructed from X and Y values:

obj.HitMelee(ns4.Ptf(10, 20))
ns3.HitLocation(obj, 10, 20)

Waypoints

Similar to objects, waypoints are also represented with opaque ns4.WaypointObj type.

Conversion to/from ns3.WaypointID is still available:

ns4.AsWaypoint(wp)
ns3.WaypointID(wp.WaypointScriptID())

Waypoints now also have methods instead of top-level library functions:

wp.Enable(false)
ns3.WaypointOff(wp)

Position is also returned as a point data type:

pos := wp.Pos()
x, y := pos.X, pos.Y
x, y := ns3.GetWaypointX(obj), ns3.GetWaypointY(obj)

This, in turn, allows using any type that has Pos() method (also known as ns4.Positioner) in places where position is expected:

ns4.CreateObject("Beholder", ns4.Ptf(10, 20))
ns4.CreateObject("Beholder", ns4.GetHost())
ns4.CreateObject("Beholder", ns4.Waypoint("Spot"))
ns3.CreateObject("Beholder", ns3.Waypoint("Spot"))

NoxScript 3

Reference

Here you can find a full list of functions provided by NS3 runtime.

History

Vanilla Nox has its own script runtime based on compiled source files. Since original Nox editor was never released, community recreated the script compiler from scratch.

Since there’s no official version, the scripts had different dialects, one of the latest is known as NoxScript 3.

There’s also a Panic’s EUD compiler that uses memory manipulation to extend script functionality.

OpenNox supports vanilla scripts with no changes required. Additionally, it implements a more advanced script runtime.

New runtime

To make the transition to the new script runtime smoother, OpenNox provides a compatibility layer for NoxScript 3.

The idea is that all the functions from NoxScript 3 should work exactly the same, accept same arguments, etc. This way all existing functions can be copied with almost no changes (only syntax will vary).

To avoid confusion, we usually refer to vanilla scripts as “NoxScript 3”, while the new compatibility layer is called NS3.

If you have existing scripts you want to migrate, see our migration guide.

Otherwise, it’s better to start directly from the NS4, which is our current script version.

Подразделы NoxScript 3

Миграция с оригинала

Это руководство поможет перенести существующие NoxScript 3 карты на NS3 в OpenNox.

В этом руководстве мы будем называть оригинальные скрипты Nox как “NoxScript 3”, в то время как “NS3” будет обозначать новые Go скипты для OpenNox.

Зачем?

Первый логичный вопрос: зачем? OpenNox хорошо работает с NoxScript 3 скриптами.

Есть пара причин перейти на скрипты OpenNox:

  • NoxScript 3 ограничен ровно тем что оригинальный Nox движек открывает. Возможностей не много. И никаких обновлений не будет.
  • NS3 в OpenNox является прямой заменой. Абсолютно те же функции доступны в нем.
  • Мы предоставляем инструмены для перевода 90% кода скрипта автоматически. Только мелкие правки необходимы.
  • NS4 (и далее) будут иметь всё больше и больше возможностей в будущем, включая поддержку модов.
  • Не нужен отдельный компилятор скриптов. Скрипты запускаются напрямую из кода.
  • Более полная система типов: настоящие массивы, словари (map), стркутуры, классы.
  • Доступны библиотеки: работа со строками, полная поддержка UTF8, математика, сортировка, и т.д.
  • Лучшая производительность: все библиотеки скомпилированы в OpenNox и запускаются нативно.
  • Лучшая отладка: если скрипт “падает”, выведется трасировка. Скрипты так же могут самостоятельно справиться с ошибкой!
  • Язык Go используемый в скриптах так же используется в самом OpenNox. Возможно однажды будет желание присоединиться?

Было бы несправедливо не упоминуть про недостатки:

  • Скрипты работают только в OpenNox.
  • Нужно изучить новый язык для скриптов.
  • Скриптам возможно необходимо делать больше для правильного сохранения/загрузки.

Если вы знакомы с EUD компилятором от Panic и возможно рассматривали его, см это руководство.

In general, we believe that OpenNox is the future of Nox modding, thus porting your map may give it an entirely new life!

How?

There are two path currently: converting the compiled script from the map or converting the source.

Converting the map script

You’ll need a recent noxtools installed (assuming you have Go 1.20+ installed):

go install github.com/noxworld-dev/opennox-lib/cmd/noxtools@latest

From the map directory:

noxscript ns decomp <mapname>.map

It will print a decompiled source code converted to Go and NS3 runtime.

Because of the limitation of Nox script assembly:

  • All variable names will be lost.
  • Some control flow may be replaced with goto.

But after fixing these issues, you should be ready to go!

Converting the source

TODO: Add a guide for using cxgo to automate it.

Currently, you’ll have to manually convert the source. Until we automate it as well, please consider converting the extracted map script, as shown above.

NoxScript 3 is similar to C, which has a lot in common with Go. However, Go syntax is slightly different in regard to types.

Conversion steps will include:

  • Swapping argument and variable names with types: int a -> a int.
  • Adding either var or const to variable definitions: int a -> var a int.
  • Moving function return type to the end: int foo() -> func foo() int.
  • Moving { to the previous line. E.g. func foo()\n{ -> func foo() {. Same for if, else, for.
  • Adding { ... } to if and else which do not have them: if (1) foo() -> if (1) { foo() }.
  • Removing void from returns.
  • Fixing variable types (Go doesn’t allow implicit type conversion).

After this, add the following header to your file:

package example

import (    
    . "github.com/noxworld-dev/noxscript/ns/v3"
)

Dot import should automatically resolve all references to NS3 functions.

After conversion

Limitations

There are some temporary limitations you should be aware of:

  • Timers will stop each time the map is reloaded. You’ll need to restart them from the script.
  • All callbacks will reset when map is reloaded. You’ll need to set them again from the script.

These issues will be resolved eventually.

New: Syntax

We highly recommend checking our Go tour to get familiar with the syntax, but we’ll give a short recap here.

File structure

All files must start with package <mapname>:

package example

It can be followed by one or more package imports:

import "fmt"
import "strconv"
// it is typical to group them:
import (
	"fmt"
	"strconv"
)

Then global variables and/or functions follow. Order of declarations doesn’t matter.

Variables and types

Most notable syntax distinction: in Go, the type name is on the right side, instead of on the left as in NoxScript 3:

var x int
int x;

Note that ; is no longer needed, and variable declaration must start with var (or const).

There’s a very good reason why types are on the right: it makes reading complex types more natural. Just read them left to right!

For example, array: var x [3][2]int simply reads left to right as “array of 3 elements, each containing 2 int values”. Much better than a random order of int x[2][3];.

Same for pointers: *[2]int reads “pointer to an array of 2 ints”. Compare it to int* x[2];.

Functions

Function declarations are also different:

  • They must start with func.
  • Types for arguments are on the right.
  • Return type is after the arguments.
  • Void return type must be omitted.
  • The opening { must be on the same line as the function header.
  • Arguments with the same types can be grouped.
  • Multiple returns are supported.
func foo(a int) {
}

func bar(x, y int, s string) int {
}
void foo(int a)
{
}

int bar(int x, int y, string s)
{
}

Control flow

All control flow structures require the opening { to be on the same line, for example:

if (x) { foo() }

if (y) {
    bar()
}
if (x) foo();

if (y)
{
    bar();
}

The () in the condition is also optional:

if x { foo() }

if y {
    bar()
}
if (x) foo();

if (y)
{
    bar();
}

Same rules for { apply for else:

if x {
    foo()
} else {
    bar()
}
if (x) foo()
else bar()

Loops

Loops must not include ( and have same rules in regard to {:

var i int
for i = 0; i < 10; i++ {
}
int i;
for (i = 0; i < 10; i++)
{
}

Loop that use while must use for keyword:

for x {
}
while (x)
{
}

New: Core types

In original NoxScript 3, there were only a few types available: int, float, string, object.

In NS3 the list is much longer: bool, int, uint, float32 (analog of float), string, any, etc. The object type is replaced with more specific types from NS3 package: ObjectID, ObjectGroupID, WaypointID, etc.

An important distinction is that Go doesn’t allow implicit type conversion. For example, in NoxScript it was okay to have an int variable and put an object there. In NS3, this is requires an explicit type conversion: int(x). But, of course, it’s better to have correct types for your variables.

Another distinction of NS3 is the support of direct conversions between int and float. It is done the same way: int(x) or float32(x).

Converting between int and string is supported via IntToString, but it’s better to use Go’s standard library instead: strconv.Itoa.

It also supports conversion from string to int via Go’s standard library: strconv.Atoi. Note, that this function may return an error, which you are free to ignore (with _):

x, _ := strconv.Atoi("1")

New: Strings

NoxScript 3 had a limitation that a frequent + operation on strings overflows a string table.

There’s no such limitation in NS3: any number of strings can be created.

Printing to strings is also supported with Go’s fmt.Sprintf:

s := fmt.Sprintf("Hello player %d!", n)

There are quite a few more string functions available in strings, https://pkg.go.dev/strconv and unicode packages.

Even though strings can be created with + and individual bytes can be accessed with s[i], strings are immutable in Go! This means, once created, they cannot be edited, only new ones can be created. If you need to change a few characters, consider converting to byte array, making changes, and converting back:

s := "Gello"
b := []byte(s) // type: []byte
b[0] = 'H'
s = string(b) // "Hello"

New: Variable type inference

NoxScript 3 requires a type for new variables to be set explicitly. NS3 allows automatic inference of variable type:

a := 10 // int
b := false // bool
x := ns.Object("Bob") // ObjectID
int a = 10; // int
int b = 0; // bool 
int x = Object("Bob"); // object

The := operator does two things: defines a new variable (similar to var) and infers a type for it.

But note that using float values produces a float64 type, not float32:

x := 0.0 // float64!
y := float32(0.0) // float32
x = y // error!

However:

const x = 0.0 // untyped float
var y float32 = x // no error

Constants are “untyped” and infer the type automatically from a variable they assigned to.

New: Range loop

In NS3 a new type of loop is available: for range, which allows to loop over all values in an array.

var arr [3]int
// writing: loop over indexes only
for i := range arr {
    arr[i] = i+1;
}
cnt := 0
// reading: loop over values
for _, v := range arr {
    cnt += v
}
int i;
int arr[3];
int cnt = 0;
for (i = 0; i < 3; i++) // writing
{
    arr[i] = i+1;
}
for (i = 0; i < 3; i++) // reading
{
    cnt += arr[i];
}

New: Dynamic arrays (slices)

In NoxScript 3, only fixed arrays are supported. NS3 has support for Go slices, which are arrays with dynamic length:

var arr []int
for i := 0; i < 3; i++ {
    arr = append(arr, i+1) // adds elements to the end
}
// len(arr) == 3
int i;
int arr[3];
for (i = 0; i < 3; i++)
{
    arr[i] = i+1;
}

New: Structures

NS3 completely supports custom struct types. They are very similar to classes in other programming languages.

Let’s say we want to build an RPG map, and we want to record a new character class for all player units:

type MyUnit struct {
	ID ns.ObjectID // types on the right: field "ID" with type "ns.ObjectID"
	Class string
}

func init() {
    unit := ns.Object("Bob")
    // creates a new struct instance, takes pointer to it
    myUnit := &MyUnit{ID: unit, Class:"archer"}
    changeClass(myUnit, "shaman")
}

// changeClass accepts a pointer to struct be able to change fields.
// Removing the pointer will make a copy of the struct for this function!
func changeClass(unit *MyUnit, cl string) {
    unit.Class = cl
}

The changeClass function can also be rewritten as a method on MyUnit struct:

type MyUnit struct {
	ID ns.ObjectID // types on the right: field "ID" with type "ns.ObjectID"
	Class string
}

// changeClass is a method on MyUnit struct pointer.
// Removing the pointer will make a copy of the struct for this function!
func (u *MyUnit) changeClass(cl string) {
    u.Class = cl
}

func init() {
    unit := ns.Object("Bob")
    myUnit := &MyUnit{ID: unit, Class:"archer"}
	// now changeClass is available as a method on the struct instance
    myUnit.changeClass("shaman")
}

For developer coming from C, new structs always have their fields initialized to zero vales.

New: Dictionaries (maps)

NS3 support dictionaries/sets, which are unordered collections of values indexed by a key of any type.

For example, we made a MyUnit struct in the previous example. But how to quickly find MyUnit for ns.ObjectID?

type MyUnit struct {
	ID ns.ObjectID // types on the right: field "ID" with type "ns.ObjectID"
	Class string
}

// mapUnits maps ns.ObjectID to *MyUnit.
// All maps must be created with make before use!
var mapUnits = make(map[ns.ObjectID]*MyUnit)

func init() {
	createMyUnits()
	findAndChangeClass()
}

func createMyUnits() {
    unit := ns.Object("Bob")
    myUnit := &MyUnit{ID: unit, Class:"archer"}
    // add new record to the map, index by ID
    mapUnits[unit] = myUnit
}

func findAndChangeClass() {
    unit := ns.Object("Bob")
	// find by ID
	myUnit := mapUnits[unit]
	if unit == nil {
	    return // not found	
    }
	myUnit.Class = "shaman"
}

Keys can also be deleted from the map:

delete(mapUnits, unit) // delete by unit ID

EUD от Panic'а

History

Vanilla Nox has its own script runtime based on compiled source files. Since original Nox editor was never released, community recreated the script compiler from scratch.

Since there’s no official version, the scripts had different dialects, one of the latest is known as NoxScript 3.

However, the script runtime of Nox was very limited. Eventually the community found a way to inject custom code into the game, which lead to a new kind of map scripts, usually referred as “memhacks”.

Panic’s EUD is the most advanced project of this kind. It uses memory manipulation to implement a lot of new functionality for the scripts.

Unfortunately, memory manipulation usually targets a single binary version (vanilla Nox), and thus cannot run on other versions such as OpenNox. Because of this OpenNox does not support EUD scripts.

New runtime

Even though OpenNox cannot support scripts that use memory manipulation, we still can provide similar functions in out own script runtime. Thus, OpenNox provides a compatibility layer for EUD scripts.

The idea is that all the functions from Panic’s EUD which do not expose the memory directly should work exactly the same, in OpenNox This way all existing functions can be copied with almost no changes (only syntax will vary).

If you have existing scripts you want to migrate, see our migration guide.

Otherwise, it’s better to start directly from the NS4, which is our current script version.

Подразделы EUD от Panic'а

Миграция с EUD

This guide will help migrate existing Panic’s EUD maps to NS3 and EUD layer in OpenNox.

First, it’s important to understand that “memhacks” and direct memory access is technically not possible in OpenNox.

Here are a few reasons why:

  • Memhacks target a specific binary. This means it only works on one Nox version. OpenNox constantly evolves, thus we cannot guarantee any specific memory layout.
  • Memhacks usually inject assembly code that targets a specific CPU architecture (Intel/AMD x86). OpenNox can be potentially compiled for ARM (e.g. MacBooks, Android, RPi), thus script will stop working there.

We attempted to resolve these issues with EUD developer Panic, but we don’t see any willingness for collaboration from his side. If you really want EUD to be supported directly in OpenNox, please reach out to Panic. Resolving these technical challenges is possible, but requires tight collaboration, and will to do so from him, first and foremost.

Why?

First logical question: why bother with converting to OpenNox? EUD works great in original Nox.

A few reasons to migrate to OpenNox scripts:

  • OpenNox is evolving and supports new features that are impossible in vanilla (e.g. HD, better multiplayer, modding, etc).
  • EUD library in OpenNox is a drop-in replacement. Same functions will be supported.
  • NS4 (and beyond) will have even more features going forward.
  • You won’t need a separate script compiler. Scripts are run directly from source.
  • More comprehensive type system: proper arrays, dictionaries (map), structures, classes.
  • A lot more libraries included: string manipulation, full UTF8 support, math, sorting, etc.
  • Better performance: all libraries are compiled into OpenNox and run natively.
  • Better debugging: if script crashes, there’s a stack trace. Scripts can recover from it as well!
  • Go language used in scripts is used in OpenNox itself. Maybe one day you’ll decide to contribute?

In general, we believe that OpenNox is the future of Nox modding, thus porting your map may give it an entirely new life!

How?

At this point, we are still working on improving the EUD compatibility layer, so quite a few functions might still be unavailable. Please talk to us for more details.

In general the conversion process is very similar to the one for converting NS3 source manually. Same changes must be done to the source to align the syntax. We are working on a more automated process.

You need to be aware that all functions using GetMemory and SetMemory must be rewritten in any case. The first thing to do is to check if functions you are using are already available in Panic’s EUD library. If so, updating your EUD script to using these function will help you convert to our EUD library later as well.

We aim to provide a good migration path for well-known EUD libraries, so if you copied code from another EUD project, there’s a high chance we support it in one of the libraries.

Still, if you cannot find anything similar, talk to us. We will help convert your code and include necessary functionality into next OpenNox release.

After conversion

The NS3 guide applies here as well, so make sure to check it out!