Skip to content

Introduction

szapp edited this page Jan 16, 2020 · 3 revisions

Modifications of the video games Gothic and Gothic 2 Night of the Raven have succeeded to impress for well over a decade. Graphical changes to the games may be deployed as modular patches running independently side-by-side. Other aspects of the games, such as the story, however, can only be replaced as a whole. This is due to the compiled formats in which these resources are collected. This has limited such modifications of the games to be exclusive in form of separate self-contained "games". To the frustration of many players, combining their favorite mods is not possible. Even the smallest improvement or bug fix of the original games demands an entirely independent "mod" incompatible with any other mods.

Ninja lifts this constraint by extending the scope of the aforementioned modular patches to any aspect of the game, instead of only mere graphical enhancements. This empowers them to the extent of mods, while retaining their modular behavior. Different from mods, they may be stacked and combined at will, enriching the modding landscape for players and raising it to a new level. Nevertheless, they are not to be understood to replace mods, but to complement them with small, independent features and enhancements.

This chapter aims to explain the problem that Ninja is solving.

Virtual Disk File System (VDFS)

Although the VDFS is explained in more detail elsewhere, this section serves to give a rough understanding about its functionality with respect to file preference.

All resources (e.g. textures, models, sounds) for the game are stored in VDF volumes, i.e. VDF files, in the Data directory. There are also MOD files that are typically in the subdirectory named ModVDF, but these MOD files are not important here. The volumes are containers for the resources, associated with a timestamp. They are loaded by Gothic in order of their timestamps where resources in later volumes take precedence and "override" any "older" ones. Should a file example.tex exist both in the volumes volumeA.vdf (timestamp 2010-01-01) and volumeB.vdf (timestamp 2019-01-01), it will be loaded from the volume with the later timestamp, i.e. volumeB.vdf.

This behavior is used to patch individual resources, by creating a VDF with a newer timestamp that contains the resource to change. In the previous example, the texture example.tex in volumeB.vdf might be a reworked version of the original example.tex from volumeA.vdf, which would then be displayed in the world everywhere in place of the original one. This technique has been the basis for patches as well as mods.

Formats

Creating a VDF with a newer timestamp allows replacing existing or adding new resources to the game. Although this method is straight forward, not all types of resources may be targeted individually. Here, the different resource types are divided into what we will call single-file formats and collected-file formats. As the names suggest, single-file resources can be individually replaced, while resources that are collected into one (virtual) file can only be replaced as a whole and overriding of individual parts is not possible. Below, only a list of the most commonly used file formats is given. More detailed information about the individual formats is available in the ZenGin documentation of the mod-kit and is beyond the scope of this documentation.

Single File Formats

While several files of same type are not aggregated into one file, most of them are, nevertheless, expected in compiled form. All these listed types of files can and are patched in a modular way already without the need for Ninja.

  • Textures (TEX)
  • Models (MRM, MSH)
  • Worlds (ZEN)
  • Animations (MAN, MDH, MDM, MMB, MDL)
  • Sounds/Speech (WAV)

Collected File Formats

The following files are compiled collections of their uncompiled counterparts. For this reason, their individual components cannot be overridden but only the entirety of the collection, i.e. the whole file. It is those file types for which Ninja offers solutions.

  • Scripts (DAT)
  • Animations (MDS/MSB)
  • Output Units (BIN/CSL)

Limitations to Overcome

The collected-file formats pose a problem when only a specific component should be changed or a new one should be added.

Scripts

When scripts are parsed they are saved collectively into one DAT file. Gothic is only able to load one such file and is not able to combine multiple files in any way. Replacing this file in a patch in order to add new script features also replaces compiled scripts from the underlying mod, which will thus cease to exist. Gothic cannot load more than one DAT file, because once compiled, any references within the scripts are resolved to exact positions within the file. Consequently, in order to make any changes to the scripts they need to be recompiled for Gothic to draw these references anew. Although modifying such a DAT file without de- and re-compiling is technically not entirely impossible, this is not feasible to do dynamically, i.e. on game start.

Animations

While animations are stored independently in their own files, they are defined in MDS files (or their compiled MSB counterparts in Gothic 2) for Gothic to find and refer to them. For each model, Gothic can only read one of these files and cannot append them. Replacing such a file with a patch, replaces any definitions the underlying mod has made. Consequently, the mod will no longer find its new animations and will no longer work properly.

Output Units

Output units (i.e. dialog lines) are defined in OU.bin or OU.csl files. Any dialog line is written at a specific position within these files. Gothic will only load one such file at a time. When replaced by a patch to add new dialog lines, any dialog line from the underlying mod will be lost.


To find out how Ninja lifts this limitations, read on in the chapter Solution.

Introduction
    Virtual Disk File System
    Formats
        Single File Formats
        Collected File Formats
    Limitations to Overcome
        Scripts
        Animations
        Output Units

Solution
    Implementation
    Patch Structure
        VDF File Tree
        VDF Header
    Patch Template
    Patch Validator
    Inter-Game Compatibility

Inject Changes
    Daedalus Scripts
        Overwriting Symbols
            Naming Conventions
            Preserved Symbols
        Initialization Functions
            Init_Global
            Menu Creation
        Ikarus and LeGo
            Initializing LeGo
            Modifications to LeGo
            PermMem and Handles
        Daedalus Hooks
        Inserting NPC
        Disallow Saving
        Helper Symbols
            NINJA_VERSION
            NINJA_MODNAME
            NINJA_PATCHES
            NINJA_ID_PATCHNAME
            NINJA_SYMBOLS_START
            NINJA_SYMBOLS…PATCHNAME
        Common Symbols
        Localization
    Animations and Armor
    Output Units

Other Mechanics
    Remove Invalid NPC
    Safety Checks in Externals
    Preserve Integer Variables
    Detect zSpy
    Incompatibility List for Mods

Technical Details

Applications and Examples
    Add New NPC
    Set AI Variables
    Add New Dialogs
    Add New Spells
    Add New World
    Translation Patch

Debugging
    Console
    Logging

Installation
    Requirements
    Instructions

Troubleshooting
    Is Ninja Active
    Is Patch Loaded
    Error Messages

Download

Checksums
    Setup
    In-Game

Changelog

Support this project  

Acknowledgements

Contact and Discussion

Clone this wiki locally